All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 55/63] Input: atmel_mxt_ts: Use msecs_to_jiffies() instead of HZ
@ 2019-08-16  8:38 ` Jiada Wang
  0 siblings, 0 replies; 10+ messages in thread
From: Jiada Wang @ 2019-08-16  8:38 UTC (permalink / raw)
  To: nick, dmitry.torokhov; +Cc: linux-input, linux-kernel, jiada_wang, george_davis

From: Dean Jenkins <Dean_Jenkins@mentor.com>

Replace HZ / 10 with msecs_to_jiffies(100) in the
schedule_delayed_work() calls in mxt_fw_work() and
mxt_check_bootloader() because it is cleaner.

Signed-off-by: Dean Jenkins <Dean_Jenkins@mentor.com>
Signed-off-by: Sanjeev Chugh <sanjeev_chugh@mentor.com>
Signed-off-by: George G. Davis <george_davis@mentor.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
 drivers/input/touchscreen/atmel_mxt_ts.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 35d92751e49f..40263ef79e8e 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -842,7 +842,7 @@ static int mxt_check_bootloader(struct mxt_data *data)
 	f->previous = state;
 
 	/* Poll after 0.1s if no interrupt received */
-	schedule_delayed_work(&f->work, HZ / 10);
+	schedule_delayed_work(&f->work, msecs_to_jiffies(100));
 
 	return 0;
 
@@ -3773,7 +3773,7 @@ static int mxt_load_fw(struct device *dev)
 		goto release_firmware;
 
 	/* Poll after 0.1s if no interrupt received */
-	schedule_delayed_work(&data->flash->work, HZ / 10);
+	schedule_delayed_work(&data->flash->work, msecs_to_jiffies(100));
 
 	/* Wait for flash. */
 	ret = mxt_wait_for_completion(data, &data->flash->flash_completion,
-- 
2.19.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 55/63] Input: atmel_mxt_ts: Use msecs_to_jiffies() instead of HZ
@ 2019-08-16  8:38 ` Jiada Wang
  0 siblings, 0 replies; 10+ messages in thread
From: Jiada Wang @ 2019-08-16  8:38 UTC (permalink / raw)
  To: nick, dmitry.torokhov; +Cc: linux-input, linux-kernel, jiada_wang, george_davis

From: Dean Jenkins <Dean_Jenkins@mentor.com>

Replace HZ / 10 with msecs_to_jiffies(100) in the
schedule_delayed_work() calls in mxt_fw_work() and
mxt_check_bootloader() because it is cleaner.

Signed-off-by: Dean Jenkins <Dean_Jenkins@mentor.com>
Signed-off-by: Sanjeev Chugh <sanjeev_chugh@mentor.com>
Signed-off-by: George G. Davis <george_davis@mentor.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
 drivers/input/touchscreen/atmel_mxt_ts.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 35d92751e49f..40263ef79e8e 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -842,7 +842,7 @@ static int mxt_check_bootloader(struct mxt_data *data)
 	f->previous = state;
 
 	/* Poll after 0.1s if no interrupt received */
-	schedule_delayed_work(&f->work, HZ / 10);
+	schedule_delayed_work(&f->work, msecs_to_jiffies(100));
 
 	return 0;
 
@@ -3773,7 +3773,7 @@ static int mxt_load_fw(struct device *dev)
 		goto release_firmware;
 
 	/* Poll after 0.1s if no interrupt received */
-	schedule_delayed_work(&data->flash->work, HZ / 10);
+	schedule_delayed_work(&data->flash->work, msecs_to_jiffies(100));
 
 	/* Wait for flash. */
 	ret = mxt_wait_for_completion(data, &data->flash->flash_completion,
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 56/63] Input: atmel_mxt_ts: Use complete when in_bootloader true
  2019-08-16  8:38 ` Jiada Wang
@ 2019-08-16  8:38   ` Jiada Wang
  -1 siblings, 0 replies; 10+ messages in thread
From: Jiada Wang @ 2019-08-16  8:38 UTC (permalink / raw)
  To: nick, dmitry.torokhov; +Cc: linux-input, linux-kernel, jiada_wang, george_davis

From: Dean Jenkins <Dean_Jenkins@mentor.com>

In mxt_interrupt(), complete(&data->chg_completion) was
called everytime mxt_interrupt() ran which is unnecessary.

mxt_regulator_enable() sets data->in_bootloader to true and
waits for the completion indication for data->chg_completion
to be set by mxt_interrupt().

mxt_interrupt() already has a test for data->in_bootloader
being true so move complete(&data->chg_completion) inside
that test.

Here is some analysis of some old commits relating to the
usage of complete(&data->chg_completion):

e6c4b6160d2 ("Input: atmel_mxt_ts - rename bl_completion to
chg_completion")

This old commit moved the "complete" statement from inside a
test for data->in_bootloader being true to run everytime
mxt_interrupt() executed. It is unclear why this was done.

This new commit reverses that modification back to the original
implementation.

4c814dd5c6ae ("Input: atmel_mxt_ts - make bootloader interrupt
driven")

This old commit modified mxt_load_fw() to no longer use the
data->chg_completion solution so only mxt_regulator_enable()
uses the data->chg_completion solution.

Therefore, only mxt_regulator_enable() now needs to be
supported by the data->chg_completion solution.

Signed-off-by: Dean Jenkins <Dean_Jenkins@mentor.com>
Signed-off-by: Sanjeev Chugh <sanjeev_chugh@mentor.com>
Signed-off-by: George G. Davis <george_davis@mentor.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
 drivers/input/touchscreen/atmel_mxt_ts.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 40263ef79e8e..64a1a6815d56 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -1631,9 +1631,9 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
 	struct mxt_data *data = dev_id;
 	int ret;
 
-	complete(&data->chg_completion);
-
 	if (data->in_bootloader) {
+		complete(&data->chg_completion);
+
 		if (data->flash && &data->flash->work)
 			cancel_delayed_work_sync(&data->flash->work);
 
-- 
2.19.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 56/63] Input: atmel_mxt_ts: Use complete when in_bootloader true
@ 2019-08-16  8:38   ` Jiada Wang
  0 siblings, 0 replies; 10+ messages in thread
From: Jiada Wang @ 2019-08-16  8:38 UTC (permalink / raw)
  To: nick, dmitry.torokhov; +Cc: linux-input, linux-kernel, jiada_wang, george_davis

From: Dean Jenkins <Dean_Jenkins@mentor.com>

In mxt_interrupt(), complete(&data->chg_completion) was
called everytime mxt_interrupt() ran which is unnecessary.

mxt_regulator_enable() sets data->in_bootloader to true and
waits for the completion indication for data->chg_completion
to be set by mxt_interrupt().

mxt_interrupt() already has a test for data->in_bootloader
being true so move complete(&data->chg_completion) inside
that test.

Here is some analysis of some old commits relating to the
usage of complete(&data->chg_completion):

e6c4b6160d2 ("Input: atmel_mxt_ts - rename bl_completion to
chg_completion")

This old commit moved the "complete" statement from inside a
test for data->in_bootloader being true to run everytime
mxt_interrupt() executed. It is unclear why this was done.

This new commit reverses that modification back to the original
implementation.

4c814dd5c6ae ("Input: atmel_mxt_ts - make bootloader interrupt
driven")

This old commit modified mxt_load_fw() to no longer use the
data->chg_completion solution so only mxt_regulator_enable()
uses the data->chg_completion solution.

Therefore, only mxt_regulator_enable() now needs to be
supported by the data->chg_completion solution.

Signed-off-by: Dean Jenkins <Dean_Jenkins@mentor.com>
Signed-off-by: Sanjeev Chugh <sanjeev_chugh@mentor.com>
Signed-off-by: George G. Davis <george_davis@mentor.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
 drivers/input/touchscreen/atmel_mxt_ts.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 40263ef79e8e..64a1a6815d56 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -1631,9 +1631,9 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
 	struct mxt_data *data = dev_id;
 	int ret;
 
-	complete(&data->chg_completion);
-
 	if (data->in_bootloader) {
+		complete(&data->chg_completion);
+
 		if (data->flash && &data->flash->work)
 			cancel_delayed_work_sync(&data->flash->work);
 
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 57/63] input: touchscreen: atmel_mxt_ts: Added sysfs entry for touchscreen status
  2019-08-16  8:38 ` Jiada Wang
@ 2019-08-16  8:38   ` Jiada Wang
  -1 siblings, 0 replies; 10+ messages in thread
From: Jiada Wang @ 2019-08-16  8:38 UTC (permalink / raw)
  To: nick, dmitry.torokhov; +Cc: linux-input, linux-kernel, jiada_wang, george_davis

From: Naveen Chakka <Naveen.Chakka@in.bosch.com>

To know the current communication status of the touch controller during
runtime, sysfs interface is added

sysfs interface: /sys/class/i2c-dev/i2c-*/device/*/touch_dev_stat
Executing the above sysfs interface provides two output values

1)Status of the touch device
	value 0 represents device is inactive
	value 1 represents device is active
2)Error counter
	value represents the number of times device in inactive since last read

Signed-off-by: Naveen Chakka <Naveen.Chakka@in.bosch.com>
Signed-off-by: Sanjeev Chugh <sanjeev_chugh@mentor.com>
Signed-off-by: George G. Davis <george_davis@mentor.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
 drivers/input/touchscreen/atmel_mxt_ts.c | 111 +++++++++++++++++++++--
 1 file changed, 104 insertions(+), 7 deletions(-)

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 64a1a6815d56..234e3031ba42 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -25,6 +25,7 @@
 #include <linux/property.h>
 #include <linux/slab.h>
 #include <linux/gpio/consumer.h>
+#include <linux/timer.h>
 #include <asm/unaligned.h>
 #include <linux/regulator/consumer.h>
 #include <linux/workqueue.h>
@@ -222,6 +223,7 @@ enum t100_type {
 #define MXT_CHG_DELAY	        100	/* msec */
 #define MXT_POWERON_DELAY	150	/* msec */
 #define MXT_BOOTLOADER_WAIT	36E5	/* 1 minute */
+#define MXT_WATCHDOG_TIMEOUT	1000	/* msec */
 
 /* Command to unlock bootloader */
 #define MXT_UNLOCK_CMD_MSB	0xaa
@@ -317,6 +319,12 @@ struct mxt_flash {
 	struct delayed_work work;
 };
 
+struct mxt_statusinfo {
+	bool dev_status;
+	bool intp_triggered;
+	u32 error_count;
+};
+
 /* Each client has this additional data */
 struct mxt_data {
 	struct i2c_client *client;
@@ -373,6 +381,9 @@ struct mxt_data {
 	const char *pcfg_name;
 	const char *input_name;
 	struct mxt_flash *flash;
+	struct work_struct watchdog_work;
+	struct timer_list watchdog_timer;
+	struct mxt_statusinfo mxt_status;
 
 	/* Cached parameters from object table */
 	u16 T5_address;
@@ -1626,11 +1637,30 @@ static int mxt_process_messages(struct mxt_data *data)
 	return total_handled;
 }
 
+static void mxt_start_wd_timer(struct mxt_data *data)
+{
+	mod_timer(&data->watchdog_timer, jiffies +
+			msecs_to_jiffies(MXT_WATCHDOG_TIMEOUT));
+}
+
+static void mxt_stop_wd_timer(struct mxt_data *data)
+{
+	/*
+	 * Ensure we wait until the watchdog timer
+	 * running on a different CPU finishes
+	 */
+	del_timer_sync(&data->watchdog_timer);
+	cancel_work_sync(&data->watchdog_work);
+	del_timer_sync(&data->watchdog_timer);
+}
+
 static irqreturn_t mxt_interrupt(int irq, void *dev_id)
 {
 	struct mxt_data *data = dev_id;
 	int ret;
 
+	data->mxt_status.intp_triggered = true;
+
 	if (data->in_bootloader) {
 		complete(&data->chg_completion);
 
@@ -1638,21 +1668,25 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
 			cancel_delayed_work_sync(&data->flash->work);
 
 		ret = mxt_check_bootloader(data);
-		return IRQ_RETVAL(ret);
+		ret = IRQ_RETVAL(ret);
+		goto exit;
 	}
 
-	if (!data->object_table)
-		return IRQ_HANDLED;
+	if (!data->object_table) {
+		ret = IRQ_HANDLED;
+		goto exit;
+	}
 
 	if (data->T44_address)
 		ret = mxt_process_messages_t44(data);
 	else
 		ret = mxt_process_messages(data);
 
-	if (ret <= 0)
-		return IRQ_NONE;
-	else
-		return IRQ_HANDLED;
+	ret = (ret <= 0) ? IRQ_NONE : IRQ_HANDLED;
+
+exit:
+	data->mxt_status.intp_triggered = false;
+	return ret;
 }
 
 static int mxt_t6_command(struct mxt_data *data, u16 cmd_offset,
@@ -2983,6 +3017,38 @@ static int mxt_bootloader_status(struct mxt_data *data)
 	return 0;
 }
 
+static void mxt_watchdog_timer(struct timer_list *t)
+{
+	struct mxt_data *data = from_timer(data, t, watchdog_timer);
+
+	dev_dbg(&data->client->dev, "%s: Timer triggered\n", __func__);
+
+	if (!work_pending(&data->watchdog_work)) {
+		if (!data->mxt_status.intp_triggered)
+			schedule_work(&data->watchdog_work);
+	}
+
+	mxt_start_wd_timer(data);
+}
+
+static void mxt_watchdog_work(struct work_struct *work)
+{
+	struct mxt_data *data =
+		container_of(work, struct mxt_data, watchdog_work);
+	u16 info_buf;
+	int ret = 0;
+	u8 size = 2;
+
+	ret = __mxt_read_reg(data->client, 0, size, &info_buf);
+
+	if (ret) {
+		data->mxt_status.error_count++;
+		data->mxt_status.dev_status = false;
+	} else {
+		data->mxt_status.dev_status = true;
+	}
+}
+
 static int mxt_initialize(struct mxt_data *data)
 {
 	struct i2c_client *client = data->client;
@@ -4010,6 +4076,22 @@ static const struct attribute_group mxt_fw_attr_group = {
 	.attrs = mxt_fw_attrs,
 };
 
+static ssize_t mxt_touch_device_status(struct device *dev, struct
+				       device_attribute *attr, char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (data->mxt_status.dev_status)
+		data->mxt_status.error_count = 0;
+
+	ret =  snprintf(buf, PAGE_SIZE, "%d %d\n", data->mxt_status.dev_status,
+			data->mxt_status.error_count);
+	/* clear the error counter once it is read */
+	data->mxt_status.error_count = 0;
+	return ret;
+}
+
 static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
 static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
 static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
@@ -4021,6 +4103,7 @@ static DEVICE_ATTR(debug_v2_enable, S_IWUSR | S_IRUSR, NULL,
 		   mxt_debug_v2_enable_store);
 static DEVICE_ATTR(debug_notify, S_IRUGO, mxt_debug_notify_show, NULL);
 static DEVICE_ATTR(t25, 0600, mxt_t25_selftest_show, mxt_t25_selftest_store);
+static DEVICE_ATTR(touch_dev_stat, 0444, mxt_touch_device_status, NULL);
 
 static struct attribute *mxt_attrs[] = {
 	&dev_attr_fw_version.attr,
@@ -4032,6 +4115,7 @@ static struct attribute *mxt_attrs[] = {
 	&dev_attr_debug_v2_enable.attr,
 	&dev_attr_debug_notify.attr,
 	&dev_attr_t25.attr,
+	&dev_attr_touch_dev_stat.attr,
 	NULL
 };
 
@@ -4518,6 +4602,13 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		return error;
 	}
 
+	INIT_WORK(&data->watchdog_work, mxt_watchdog_work);
+
+	/* setup watchdog timer */
+	timer_setup(&data->watchdog_timer, mxt_watchdog_timer, 0);
+
+	mxt_start_wd_timer(data);
+
 	error = mxt_initialize(data);
 	if (error)
 		goto err_free_object;
@@ -4525,8 +4616,11 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	return 0;
 
 err_free_object:
+	cancel_work_sync(&data->watchdog_work);
+	mxt_stop_wd_timer(data);
 	mxt_free_input_device(data);
 	mxt_free_object_table(data);
+	del_timer(&data->watchdog_timer);
 	sysfs_remove_group(&client->dev.kobj, &mxt_fw_attr_group);
 	if (data->reset_gpio) {
 		sysfs_remove_link(&client->dev.kobj, "reset");
@@ -4554,6 +4648,9 @@ static int mxt_remove(struct i2c_client *client)
 	mxt_free_input_device(data);
 	mxt_free_object_table(data);
 
+	cancel_work_sync(&data->watchdog_work);
+	mxt_stop_wd_timer(data);
+
 	return 0;
 }
 
-- 
2.19.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 57/63] input: touchscreen: atmel_mxt_ts: Added sysfs entry for touchscreen status
@ 2019-08-16  8:38   ` Jiada Wang
  0 siblings, 0 replies; 10+ messages in thread
From: Jiada Wang @ 2019-08-16  8:38 UTC (permalink / raw)
  To: nick, dmitry.torokhov; +Cc: linux-input, linux-kernel, jiada_wang, george_davis

From: Naveen Chakka <Naveen.Chakka@in.bosch.com>

To know the current communication status of the touch controller during
runtime, sysfs interface is added

sysfs interface: /sys/class/i2c-dev/i2c-*/device/*/touch_dev_stat
Executing the above sysfs interface provides two output values

1)Status of the touch device
	value 0 represents device is inactive
	value 1 represents device is active
2)Error counter
	value represents the number of times device in inactive since last read

Signed-off-by: Naveen Chakka <Naveen.Chakka@in.bosch.com>
Signed-off-by: Sanjeev Chugh <sanjeev_chugh@mentor.com>
Signed-off-by: George G. Davis <george_davis@mentor.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
 drivers/input/touchscreen/atmel_mxt_ts.c | 111 +++++++++++++++++++++--
 1 file changed, 104 insertions(+), 7 deletions(-)

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 64a1a6815d56..234e3031ba42 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -25,6 +25,7 @@
 #include <linux/property.h>
 #include <linux/slab.h>
 #include <linux/gpio/consumer.h>
+#include <linux/timer.h>
 #include <asm/unaligned.h>
 #include <linux/regulator/consumer.h>
 #include <linux/workqueue.h>
@@ -222,6 +223,7 @@ enum t100_type {
 #define MXT_CHG_DELAY	        100	/* msec */
 #define MXT_POWERON_DELAY	150	/* msec */
 #define MXT_BOOTLOADER_WAIT	36E5	/* 1 minute */
+#define MXT_WATCHDOG_TIMEOUT	1000	/* msec */
 
 /* Command to unlock bootloader */
 #define MXT_UNLOCK_CMD_MSB	0xaa
@@ -317,6 +319,12 @@ struct mxt_flash {
 	struct delayed_work work;
 };
 
+struct mxt_statusinfo {
+	bool dev_status;
+	bool intp_triggered;
+	u32 error_count;
+};
+
 /* Each client has this additional data */
 struct mxt_data {
 	struct i2c_client *client;
@@ -373,6 +381,9 @@ struct mxt_data {
 	const char *pcfg_name;
 	const char *input_name;
 	struct mxt_flash *flash;
+	struct work_struct watchdog_work;
+	struct timer_list watchdog_timer;
+	struct mxt_statusinfo mxt_status;
 
 	/* Cached parameters from object table */
 	u16 T5_address;
@@ -1626,11 +1637,30 @@ static int mxt_process_messages(struct mxt_data *data)
 	return total_handled;
 }
 
+static void mxt_start_wd_timer(struct mxt_data *data)
+{
+	mod_timer(&data->watchdog_timer, jiffies +
+			msecs_to_jiffies(MXT_WATCHDOG_TIMEOUT));
+}
+
+static void mxt_stop_wd_timer(struct mxt_data *data)
+{
+	/*
+	 * Ensure we wait until the watchdog timer
+	 * running on a different CPU finishes
+	 */
+	del_timer_sync(&data->watchdog_timer);
+	cancel_work_sync(&data->watchdog_work);
+	del_timer_sync(&data->watchdog_timer);
+}
+
 static irqreturn_t mxt_interrupt(int irq, void *dev_id)
 {
 	struct mxt_data *data = dev_id;
 	int ret;
 
+	data->mxt_status.intp_triggered = true;
+
 	if (data->in_bootloader) {
 		complete(&data->chg_completion);
 
@@ -1638,21 +1668,25 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
 			cancel_delayed_work_sync(&data->flash->work);
 
 		ret = mxt_check_bootloader(data);
-		return IRQ_RETVAL(ret);
+		ret = IRQ_RETVAL(ret);
+		goto exit;
 	}
 
-	if (!data->object_table)
-		return IRQ_HANDLED;
+	if (!data->object_table) {
+		ret = IRQ_HANDLED;
+		goto exit;
+	}
 
 	if (data->T44_address)
 		ret = mxt_process_messages_t44(data);
 	else
 		ret = mxt_process_messages(data);
 
-	if (ret <= 0)
-		return IRQ_NONE;
-	else
-		return IRQ_HANDLED;
+	ret = (ret <= 0) ? IRQ_NONE : IRQ_HANDLED;
+
+exit:
+	data->mxt_status.intp_triggered = false;
+	return ret;
 }
 
 static int mxt_t6_command(struct mxt_data *data, u16 cmd_offset,
@@ -2983,6 +3017,38 @@ static int mxt_bootloader_status(struct mxt_data *data)
 	return 0;
 }
 
+static void mxt_watchdog_timer(struct timer_list *t)
+{
+	struct mxt_data *data = from_timer(data, t, watchdog_timer);
+
+	dev_dbg(&data->client->dev, "%s: Timer triggered\n", __func__);
+
+	if (!work_pending(&data->watchdog_work)) {
+		if (!data->mxt_status.intp_triggered)
+			schedule_work(&data->watchdog_work);
+	}
+
+	mxt_start_wd_timer(data);
+}
+
+static void mxt_watchdog_work(struct work_struct *work)
+{
+	struct mxt_data *data =
+		container_of(work, struct mxt_data, watchdog_work);
+	u16 info_buf;
+	int ret = 0;
+	u8 size = 2;
+
+	ret = __mxt_read_reg(data->client, 0, size, &info_buf);
+
+	if (ret) {
+		data->mxt_status.error_count++;
+		data->mxt_status.dev_status = false;
+	} else {
+		data->mxt_status.dev_status = true;
+	}
+}
+
 static int mxt_initialize(struct mxt_data *data)
 {
 	struct i2c_client *client = data->client;
@@ -4010,6 +4076,22 @@ static const struct attribute_group mxt_fw_attr_group = {
 	.attrs = mxt_fw_attrs,
 };
 
+static ssize_t mxt_touch_device_status(struct device *dev, struct
+				       device_attribute *attr, char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (data->mxt_status.dev_status)
+		data->mxt_status.error_count = 0;
+
+	ret =  snprintf(buf, PAGE_SIZE, "%d %d\n", data->mxt_status.dev_status,
+			data->mxt_status.error_count);
+	/* clear the error counter once it is read */
+	data->mxt_status.error_count = 0;
+	return ret;
+}
+
 static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
 static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
 static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
@@ -4021,6 +4103,7 @@ static DEVICE_ATTR(debug_v2_enable, S_IWUSR | S_IRUSR, NULL,
 		   mxt_debug_v2_enable_store);
 static DEVICE_ATTR(debug_notify, S_IRUGO, mxt_debug_notify_show, NULL);
 static DEVICE_ATTR(t25, 0600, mxt_t25_selftest_show, mxt_t25_selftest_store);
+static DEVICE_ATTR(touch_dev_stat, 0444, mxt_touch_device_status, NULL);
 
 static struct attribute *mxt_attrs[] = {
 	&dev_attr_fw_version.attr,
@@ -4032,6 +4115,7 @@ static struct attribute *mxt_attrs[] = {
 	&dev_attr_debug_v2_enable.attr,
 	&dev_attr_debug_notify.attr,
 	&dev_attr_t25.attr,
+	&dev_attr_touch_dev_stat.attr,
 	NULL
 };
 
@@ -4518,6 +4602,13 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		return error;
 	}
 
+	INIT_WORK(&data->watchdog_work, mxt_watchdog_work);
+
+	/* setup watchdog timer */
+	timer_setup(&data->watchdog_timer, mxt_watchdog_timer, 0);
+
+	mxt_start_wd_timer(data);
+
 	error = mxt_initialize(data);
 	if (error)
 		goto err_free_object;
@@ -4525,8 +4616,11 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	return 0;
 
 err_free_object:
+	cancel_work_sync(&data->watchdog_work);
+	mxt_stop_wd_timer(data);
 	mxt_free_input_device(data);
 	mxt_free_object_table(data);
+	del_timer(&data->watchdog_timer);
 	sysfs_remove_group(&client->dev.kobj, &mxt_fw_attr_group);
 	if (data->reset_gpio) {
 		sysfs_remove_link(&client->dev.kobj, "reset");
@@ -4554,6 +4648,9 @@ static int mxt_remove(struct i2c_client *client)
 	mxt_free_input_device(data);
 	mxt_free_object_table(data);
 
+	cancel_work_sync(&data->watchdog_work);
+	mxt_stop_wd_timer(data);
+
 	return 0;
 }
 
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 58/63] Input: atmel_mxt_ts: Remove sysfs attributes during driver detach
  2019-08-16  8:38 ` Jiada Wang
@ 2019-08-16  8:38   ` Jiada Wang
  -1 siblings, 0 replies; 10+ messages in thread
From: Jiada Wang @ 2019-08-16  8:38 UTC (permalink / raw)
  To: nick, dmitry.torokhov; +Cc: linux-input, linux-kernel, jiada_wang, george_davis

From: Sanjeev Chugh <Sanjeev_Chugh@mentor.com>

This change prevents a scenario when sysfs attributes for Atmel touch
controller driver are being accessed by userland while touch driver
module unloading has already begun. At present, sysfs attribute files
are created at device probe but they are not removed while driver is
being detached.

This change will prevent calls to generic driver layer when the sysfs
driver attributes files are already deleted. Therefore, kernel will not
attempt to invoke driver routines for showing the sysfs atrributes.

Signed-off-by: Sanjeev Chugh <Sanjeev_Chugh@mentor.com>
Signed-off-by: George G. Davis <george_davis@mentor.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
 drivers/input/touchscreen/atmel_mxt_ts.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 234e3031ba42..431c2c54eab0 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -2255,10 +2255,12 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
 static void mxt_free_input_device(struct mxt_data *data)
 {
 	if (data->input_dev) {
-		struct input_dev *dev = data->input_dev;
+		struct input_dev *input_dev = data->input_dev;
 
 		data->input_dev = NULL;
-		input_unregister_device(dev);
+		sysfs_remove_group(&input_dev->dev.kobj,
+				   &data->gpio_attrs);
+		input_unregister_device(input_dev);
 	}
 }
 
-- 
2.19.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 58/63] Input: atmel_mxt_ts: Remove sysfs attributes during driver detach
@ 2019-08-16  8:38   ` Jiada Wang
  0 siblings, 0 replies; 10+ messages in thread
From: Jiada Wang @ 2019-08-16  8:38 UTC (permalink / raw)
  To: nick, dmitry.torokhov; +Cc: linux-input, linux-kernel, jiada_wang, george_davis

From: Sanjeev Chugh <Sanjeev_Chugh@mentor.com>

This change prevents a scenario when sysfs attributes for Atmel touch
controller driver are being accessed by userland while touch driver
module unloading has already begun. At present, sysfs attribute files
are created at device probe but they are not removed while driver is
being detached.

This change will prevent calls to generic driver layer when the sysfs
driver attributes files are already deleted. Therefore, kernel will not
attempt to invoke driver routines for showing the sysfs atrributes.

Signed-off-by: Sanjeev Chugh <Sanjeev_Chugh@mentor.com>
Signed-off-by: George G. Davis <george_davis@mentor.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
 drivers/input/touchscreen/atmel_mxt_ts.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 234e3031ba42..431c2c54eab0 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -2255,10 +2255,12 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
 static void mxt_free_input_device(struct mxt_data *data)
 {
 	if (data->input_dev) {
-		struct input_dev *dev = data->input_dev;
+		struct input_dev *input_dev = data->input_dev;
 
 		data->input_dev = NULL;
-		input_unregister_device(dev);
+		sysfs_remove_group(&input_dev->dev.kobj,
+				   &data->gpio_attrs);
+		input_unregister_device(input_dev);
 	}
 }
 
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 59/63] Input: atmel_mxt_ts: Prevent crash due to freeing of input device
  2019-08-16  8:38 ` Jiada Wang
@ 2019-08-16  8:38   ` Jiada Wang
  -1 siblings, 0 replies; 10+ messages in thread
From: Jiada Wang @ 2019-08-16  8:38 UTC (permalink / raw)
  To: nick, dmitry.torokhov; +Cc: linux-input, linux-kernel, jiada_wang, george_davis

From: Bhuvanesh Surachari <Bhuvanesh_Surachari@mentor.com>

Move sysfs creation after intializing the input device to
prevent crash due to freeing of input device by function via sysfs.

Signed-off-by: Bhuvanesh Surachari <bhuvanesh_surachari@mentor.com>
Signed-off-by: Sanjeev Chugh <sanjeev_chugh@mentor.com>
Signed-off-by: George G. Davis <george_davis@mentor.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
 drivers/input/touchscreen/atmel_mxt_ts.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 431c2c54eab0..8e95f46a30d7 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -2962,6 +2962,8 @@ static int mxt_initialize_input_device(struct mxt_data *data)
 		goto err_free_mem;
 	}
 
+	data->input_dev = input_dev;
+
 	if (data->gpio_attrs.attrs) {
 		error = sysfs_create_group(&input_dev->dev.kobj,
 					   &data->gpio_attrs);
@@ -2972,11 +2974,10 @@ static int mxt_initialize_input_device(struct mxt_data *data)
 		}
 	}
 
-	data->input_dev = input_dev;
-
 	return 0;
 
 err_free_mem:
+	data->input_dev = NULL;
 	input_free_device(input_dev);
 	return error;
 }
@@ -4597,13 +4598,6 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		msleep(MXT_RESET_TIME);
 	}
 
-	error = sysfs_create_group(&client->dev.kobj, &mxt_fw_attr_group);
-	if (error) {
-		dev_err(&client->dev, "Failure %d creating fw sysfs group\n",
-			error);
-		return error;
-	}
-
 	INIT_WORK(&data->watchdog_work, mxt_watchdog_work);
 
 	/* setup watchdog timer */
@@ -4613,11 +4607,18 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 	error = mxt_initialize(data);
 	if (error)
-		goto err_free_object;
+		goto err_del_wd_timer;
+
+	error = sysfs_create_group(&client->dev.kobj, &mxt_fw_attr_group);
+	if (error) {
+		dev_err(&client->dev, "Failure %d creating fw sysfs group\n",
+			error);
+		goto err_del_wd_timer;
+	}
 
 	return 0;
 
-err_free_object:
+err_del_wd_timer:
 	cancel_work_sync(&data->watchdog_work);
 	mxt_stop_wd_timer(data);
 	mxt_free_input_device(data);
-- 
2.19.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 59/63] Input: atmel_mxt_ts: Prevent crash due to freeing of input device
@ 2019-08-16  8:38   ` Jiada Wang
  0 siblings, 0 replies; 10+ messages in thread
From: Jiada Wang @ 2019-08-16  8:38 UTC (permalink / raw)
  To: nick, dmitry.torokhov; +Cc: linux-input, linux-kernel, jiada_wang, george_davis

From: Bhuvanesh Surachari <Bhuvanesh_Surachari@mentor.com>

Move sysfs creation after intializing the input device to
prevent crash due to freeing of input device by function via sysfs.

Signed-off-by: Bhuvanesh Surachari <bhuvanesh_surachari@mentor.com>
Signed-off-by: Sanjeev Chugh <sanjeev_chugh@mentor.com>
Signed-off-by: George G. Davis <george_davis@mentor.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
 drivers/input/touchscreen/atmel_mxt_ts.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 431c2c54eab0..8e95f46a30d7 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -2962,6 +2962,8 @@ static int mxt_initialize_input_device(struct mxt_data *data)
 		goto err_free_mem;
 	}
 
+	data->input_dev = input_dev;
+
 	if (data->gpio_attrs.attrs) {
 		error = sysfs_create_group(&input_dev->dev.kobj,
 					   &data->gpio_attrs);
@@ -2972,11 +2974,10 @@ static int mxt_initialize_input_device(struct mxt_data *data)
 		}
 	}
 
-	data->input_dev = input_dev;
-
 	return 0;
 
 err_free_mem:
+	data->input_dev = NULL;
 	input_free_device(input_dev);
 	return error;
 }
@@ -4597,13 +4598,6 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		msleep(MXT_RESET_TIME);
 	}
 
-	error = sysfs_create_group(&client->dev.kobj, &mxt_fw_attr_group);
-	if (error) {
-		dev_err(&client->dev, "Failure %d creating fw sysfs group\n",
-			error);
-		return error;
-	}
-
 	INIT_WORK(&data->watchdog_work, mxt_watchdog_work);
 
 	/* setup watchdog timer */
@@ -4613,11 +4607,18 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 	error = mxt_initialize(data);
 	if (error)
-		goto err_free_object;
+		goto err_del_wd_timer;
+
+	error = sysfs_create_group(&client->dev.kobj, &mxt_fw_attr_group);
+	if (error) {
+		dev_err(&client->dev, "Failure %d creating fw sysfs group\n",
+			error);
+		goto err_del_wd_timer;
+	}
 
 	return 0;
 
-err_free_object:
+err_del_wd_timer:
 	cancel_work_sync(&data->watchdog_work);
 	mxt_stop_wd_timer(data);
 	mxt_free_input_device(data);
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2019-08-16  8:40 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-16  8:38 [PATCH v1 55/63] Input: atmel_mxt_ts: Use msecs_to_jiffies() instead of HZ Jiada Wang
2019-08-16  8:38 ` Jiada Wang
2019-08-16  8:38 ` [PATCH v1 56/63] Input: atmel_mxt_ts: Use complete when in_bootloader true Jiada Wang
2019-08-16  8:38   ` Jiada Wang
2019-08-16  8:38 ` [PATCH v1 57/63] input: touchscreen: atmel_mxt_ts: Added sysfs entry for touchscreen status Jiada Wang
2019-08-16  8:38   ` Jiada Wang
2019-08-16  8:38 ` [PATCH v1 58/63] Input: atmel_mxt_ts: Remove sysfs attributes during driver detach Jiada Wang
2019-08-16  8:38   ` Jiada Wang
2019-08-16  8:38 ` [PATCH v1 59/63] Input: atmel_mxt_ts: Prevent crash due to freeing of input device Jiada Wang
2019-08-16  8:38   ` Jiada Wang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.