Linux-ACPI Archive on lore.kernel.org
 help / color / Atom feed
* [PATCHv2 0/7] Support inhibiting input devices
       [not found] <20200506002746.GB89269@dtor-ws>
@ 2020-05-15 16:49 ` Andrzej Pietrasiewicz
  2020-05-15 16:51   ` [PATCHv2 1/7] Input: add input_device_enabled() Andrzej Pietrasiewicz
                     ` (3 more replies)
  0 siblings, 4 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-05-15 16:49 UTC (permalink / raw)
  To: linux-input, linux-acpi, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-tegra, patches, ibm-acpi-devel,
	platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, Andrzej Pietrasiewicz, kernel

Userspace might want to implement a policy to temporarily disregard input
from certain devices, including not treating them as wakeup sources.

An example use case is a laptop, whose keyboard can be folded under the
screen to create tablet-like experience. The user then must hold the laptop
in such a way that it is difficult to avoid pressing the keyboard keys. It
is therefore desirable to temporarily disregard input from the keyboard,
until it is folded back. This obviously is a policy which should be kept
out of the kernel, but the kernel must provide suitable means to implement
such a policy.

Due to interactions with suspend/resume, a helper has been added for drivers
to decide if the device is being used or not (PATCH 1/7) and it has been
applied to relevant drivers (PATCH 2-5/7). Patches 2-5 are only being sent
to relevant mailing lists and maintainers.

PATCH 6/7 adds support for inhibiting input devices, while PATCH 7/7
provides an example how to convert a driver to take advantage of this
new feature. Patch 7/7 is only being sent to input mailing list and
maintainer.

This work is inspired by:

https://chromium.googlesource.com/chromiumos/third_party/kernel/+/45c2d7bb398f74adfae0017e20b224152fde3822

and

https://chromium.googlesource.com/chromiumos/third_party/kernel/+/4ce0e8a3697edb8fd071110b3af65014512061c7

v1..v2:
- added input_device_enabled() helper and used it in drivers (Dmitry)
- the fact of open() and close() being called in inhibit/uninhibit paths has
been emphasized in the commit message of PATCH 6/7 (Dmitry)

Andrzej Pietrasiewicz (5):
  Input: add input_device_enabled()
  Input: use input_device_enabled()
  ACPI: button: Use input_device_enabled() helper
  iio: adc: exynos: Use input_device_enabled()
  platform/x86: thinkpad_acpi: Use input_device_enabled()

Dmitry Torokhov (1):
  Input: elan_i2c: Support inhibiting

Patrik Fimml (1):
  Input: Add "inhibited" property

 drivers/acpi/button.c                       |   8 +-
 drivers/iio/adc/exynos_adc.c                |  11 +-
 drivers/input/input.c                       | 142 ++++++++++++++++++--
 drivers/input/joystick/xpad.c               |   4 +-
 drivers/input/keyboard/ep93xx_keypad.c      |   2 +-
 drivers/input/keyboard/gpio_keys.c          |   4 +-
 drivers/input/keyboard/imx_keypad.c         |   4 +-
 drivers/input/keyboard/ipaq-micro-keys.c    |   2 +-
 drivers/input/keyboard/lpc32xx-keys.c       |   4 +-
 drivers/input/keyboard/pmic8xxx-keypad.c    |   4 +-
 drivers/input/keyboard/pxa27x_keypad.c      |   2 +-
 drivers/input/keyboard/samsung-keypad.c     |   4 +-
 drivers/input/keyboard/spear-keyboard.c     |   8 +-
 drivers/input/keyboard/st-keyscan.c         |   4 +-
 drivers/input/keyboard/tegra-kbc.c          |   4 +-
 drivers/input/misc/drv260x.c                |   4 +-
 drivers/input/misc/drv2665.c                |   4 +-
 drivers/input/misc/drv2667.c                |   4 +-
 drivers/input/misc/gp2ap002a00f.c           |   4 +-
 drivers/input/misc/kxtj9.c                  |   4 +-
 drivers/input/misc/sirfsoc-onkey.c          |   2 +-
 drivers/input/mouse/elan_i2c_core.c         | 112 +++++++++++----
 drivers/input/mouse/navpoint.c              |   4 +-
 drivers/input/touchscreen/ad7879.c          |   6 +-
 drivers/input/touchscreen/atmel_mxt_ts.c    |   4 +-
 drivers/input/touchscreen/auo-pixcir-ts.c   |   8 +-
 drivers/input/touchscreen/bu21029_ts.c      |   4 +-
 drivers/input/touchscreen/chipone_icn8318.c |   4 +-
 drivers/input/touchscreen/cyttsp_core.c     |   4 +-
 drivers/input/touchscreen/eeti_ts.c         |   4 +-
 drivers/input/touchscreen/ektf2127.c        |   4 +-
 drivers/input/touchscreen/imx6ul_tsc.c      |   4 +-
 drivers/input/touchscreen/ipaq-micro-ts.c   |   2 +-
 drivers/input/touchscreen/iqs5xx.c          |   4 +-
 drivers/input/touchscreen/lpc32xx_ts.c      |   4 +-
 drivers/input/touchscreen/melfas_mip4.c     |   4 +-
 drivers/input/touchscreen/mms114.c          |   6 +-
 drivers/input/touchscreen/pixcir_i2c_ts.c   |   8 +-
 drivers/input/touchscreen/ucb1400_ts.c      |   4 +-
 drivers/input/touchscreen/wm97xx-core.c     |  14 +-
 drivers/input/touchscreen/zforce_ts.c       |   8 +-
 drivers/platform/x86/thinkpad_acpi.c        |   4 +-
 include/linux/input.h                       |  10 ++
 43 files changed, 336 insertions(+), 119 deletions(-)


base-commit: 2ef96a5bb12be62ef75b5828c0aab838ebb29cb8
-- 
2.17.1


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

* [PATCHv2 1/7] Input: add input_device_enabled()
  2020-05-15 16:49 ` [PATCHv2 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
@ 2020-05-15 16:51   ` Andrzej Pietrasiewicz
  2020-05-15 16:52   ` [PATCHv2 6/7] Input: Add "inhibited" property Andrzej Pietrasiewicz
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-05-15 16:51 UTC (permalink / raw)
  To: linux-input, linux-acpi, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-tegra, patches, ibm-acpi-devel,
	platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, Andrzej Pietrasiewicz, kernel

A helper function for drivers to decide if the device is used or not.
A lockdep check is introduced as inspecting ->users should be done under
input device's mutex.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/input/input.c | 8 ++++++++
 include/linux/input.h | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index 3cfd2c18eebd..41377bfa142d 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -2127,6 +2127,14 @@ void input_enable_softrepeat(struct input_dev *dev, int delay, int period)
 }
 EXPORT_SYMBOL(input_enable_softrepeat);
 
+bool input_device_enabled(struct input_dev *dev)
+{
+	lockdep_assert_held(&dev->mutex);
+
+	return dev->users > 0;
+}
+EXPORT_SYMBOL_GPL(input_device_enabled);
+
 /**
  * input_register_device - register device with input core
  * @dev: device to be registered
diff --git a/include/linux/input.h b/include/linux/input.h
index 56f2fd32e609..eda4587dba67 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -502,6 +502,8 @@ bool input_match_device_id(const struct input_dev *dev,
 
 void input_enable_softrepeat(struct input_dev *dev, int delay, int period);
 
+bool input_device_enabled(struct input_dev *dev);
+
 extern struct class input_class;
 
 /**
-- 
2.17.1


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

* [PATCHv2 6/7] Input: Add "inhibited" property
  2020-05-15 16:49 ` [PATCHv2 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
  2020-05-15 16:51   ` [PATCHv2 1/7] Input: add input_device_enabled() Andrzej Pietrasiewicz
@ 2020-05-15 16:52   ` Andrzej Pietrasiewicz
  2020-05-15 16:53   ` [PATCHv2 3/7] ACPI: button: Use input_device_enabled() helper Andrzej Pietrasiewicz
  2020-05-15 18:19   ` [PATCHv2 0/7] Support inhibiting input devices Hans de Goede
  3 siblings, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-05-15 16:52 UTC (permalink / raw)
  To: linux-input, linux-acpi, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-tegra, patches, ibm-acpi-devel,
	platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, Andrzej Pietrasiewicz, kernel,
	Patrik Fimml

From: Patrik Fimml <patrikf@chromium.org>

Userspace might want to implement a policy to temporarily disregard input
from certain devices, including not treating them as wakeup sources.

An example use case is a laptop, whose keyboard can be folded under the
screen to create tablet-like experience. The user then must hold the laptop
in such a way that it is difficult to avoid pressing the keyboard keys. It
is therefore desirable to temporarily disregard input from the keyboard,
until it is folded back. This obviously is a policy which should be kept
out of the kernel, but the kernel must provide suitable means to implement
such a policy.

This patch adds a sysfs interface for exactly this purpose.

To implement the said interface it adds an "inhibited" property to struct
input_dev and two optional methods - inhibit() and uninhibit(), and
effectively creates four states a device can be in: closed uninhibited,
closed inhibited, open uninhibited, open inhibited. It also defers calling
driver's ->open() and ->close() to until they are actually needed, e.g. it
makes no sense to prepare the underlying device for generating events
(->open()) if the device is inhibited.

              uninhibit
closed      <------------ closed
uninhibited ------------> inhibited
      | ^     inhibit        | ^
 1st  | |               1st  | |
 open | |               open | |
      | |                    | |
      | | last               | | last
      | | close              | | close
      v |     uninhibit      v |
open        <------------ open
uninhibited ------------> inhibited

The top inhibit/uninhibit transition happens when users == 0.
The bottom inhibit/uninhibit transition happens when users > 0.
The left open/close transition happens when !inhibited.
The right open/close transition happens when inhibited.
Due to all transitions being serialized with dev->mutex, it is impossible
to have "diagonal" transitions between closed uninhibited and open
inhibited or between open uninhibited and closed inhibited.

open() and close() - if provided - are called in both inhibit and uninhibit
paths. Please note that close() does not return a value, so if your driver
might need failing inhibiting, you need to provide inhibit() so that it
returns a value to check.

It is drivers' responsibility to implement their inhibiting capability in
terms of whatever is suitable in their context, be it open/close,
inhibit/uninhibit or a combination of both. The drivers should also ensure
that they properly interact with suspend/resume and PM runtime, because
most likely a side effect of inhibiting a device should be its going into
low power mode. Properly inhibiting a device means to prevent it from being
a wakeup source, so drivers should also take care of that.

Signed-off-by: Patrik Fimml <patrikf@chromium.org>
Co-developed-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/input/input.c | 136 ++++++++++++++++++++++++++++++++++++++----
 include/linux/input.h |   8 +++
 2 files changed, 134 insertions(+), 10 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index 41377bfa142d..5b859a178c11 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -367,8 +367,13 @@ static int input_get_disposition(struct input_dev *dev,
 static void input_handle_event(struct input_dev *dev,
 			       unsigned int type, unsigned int code, int value)
 {
-	int disposition = input_get_disposition(dev, type, code, &value);
+	int disposition;
 
+	/* filter-out events from inhibited devices */
+	if (dev->inhibited)
+		return;
+
+	disposition = input_get_disposition(dev, type, code, &value);
 	if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
 		add_input_randomness(type, code, value);
 
@@ -612,7 +617,7 @@ int input_open_device(struct input_handle *handle)
 
 	handle->open++;
 
-	if (dev->users++) {
+	if (dev->users++ || dev->inhibited) {
 		/*
 		 * Device is already opened, so we can exit immediately and
 		 * report success.
@@ -660,6 +665,14 @@ int input_flush_device(struct input_handle *handle, struct file *file)
 }
 EXPORT_SYMBOL(input_flush_device);
 
+static inline void input_stop(struct input_dev *dev)
+{
+	if (dev->poller)
+		input_dev_poller_stop(dev->poller);
+	if (dev->close)
+		dev->close(dev);
+}
+
 /**
  * input_close_device - close input device
  * @handle: handle through which device is being accessed
@@ -675,13 +688,8 @@ void input_close_device(struct input_handle *handle)
 
 	__input_release_device(handle);
 
-	if (!--dev->users) {
-		if (dev->poller)
-			input_dev_poller_stop(dev->poller);
-
-		if (dev->close)
-			dev->close(dev);
-	}
+	if (!dev->inhibited && !--dev->users)
+		input_stop(dev);
 
 	if (!--handle->open) {
 		/*
@@ -1416,12 +1424,49 @@ static ssize_t input_dev_show_properties(struct device *dev,
 }
 static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL);
 
+static int input_inhibit(struct input_dev *dev);
+static int input_uninhibit(struct input_dev *dev);
+
+static ssize_t inhibited_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct input_dev *input_dev = to_input_dev(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", input_dev->inhibited);
+}
+
+static ssize_t inhibited_store(struct device *dev,
+			       struct device_attribute *attr, const char *buf,
+			       size_t len)
+{
+	struct input_dev *input_dev = to_input_dev(dev);
+	ssize_t rv;
+	bool inhibited;
+
+	if (strtobool(buf, &inhibited))
+		return -EINVAL;
+
+	if (inhibited)
+		rv = input_inhibit(input_dev);
+	else
+		rv = input_uninhibit(input_dev);
+
+	if (rv != 0)
+		return rv;
+
+	return len;
+}
+
+static DEVICE_ATTR_RW(inhibited);
+
 static struct attribute *input_dev_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_phys.attr,
 	&dev_attr_uniq.attr,
 	&dev_attr_modalias.attr,
 	&dev_attr_properties.attr,
+	&dev_attr_inhibited.attr,
 	NULL
 };
 
@@ -1703,6 +1748,77 @@ void input_reset_device(struct input_dev *dev)
 }
 EXPORT_SYMBOL(input_reset_device);
 
+static int input_inhibit(struct input_dev *dev)
+{
+	int ret = 0;
+
+	mutex_lock(&dev->mutex);
+
+	if (dev->inhibited)
+		goto out;
+
+	if (dev->users) {
+		if (dev->inhibit) {
+			ret = dev->inhibit(dev);
+			if (ret)
+				goto out;
+		}
+		input_stop(dev);
+	}
+
+	spin_lock_irq(&dev->event_lock);
+	input_dev_release_keys(dev);
+	input_dev_toggle(dev, false);
+	spin_unlock_irq(&dev->event_lock);
+
+	dev->inhibited = true;
+
+out:
+	mutex_unlock(&dev->mutex);
+	return ret;
+}
+
+static int input_uninhibit(struct input_dev *dev)
+{
+	int ret = 0;
+
+	mutex_lock(&dev->mutex);
+
+	if (!dev->inhibited)
+		goto out;
+
+	if (dev->users) {
+		if (dev->open) {
+			ret = dev->open(dev);
+			if (ret)
+				goto toggle;
+		}
+		if (dev->uninhibit) {
+			ret = dev->uninhibit(dev);
+			if (ret) {
+				if (dev->close)
+					dev->close(dev);
+				goto toggle;
+			}
+		}
+		if (dev->poller)
+			input_dev_poller_start(dev->poller);
+	}
+
+	dev->inhibited = false;
+
+toggle:
+	if (!dev->inhibited) {
+		spin_lock_irq(&dev->event_lock);
+		input_dev_toggle(dev, true);
+		spin_unlock_irq(&dev->event_lock);
+	}
+
+out:
+	mutex_unlock(&dev->mutex);
+	return ret;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int input_dev_suspend(struct device *dev)
 {
@@ -2131,7 +2247,7 @@ bool input_device_enabled(struct input_dev *dev)
 {
 	lockdep_assert_held(&dev->mutex);
 
-	return dev->users > 0;
+	return !dev->inhibited && dev->users > 0;
 }
 EXPORT_SYMBOL_GPL(input_device_enabled);
 
diff --git a/include/linux/input.h b/include/linux/input.h
index eda4587dba67..8d0dcfaeaf6f 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -127,6 +127,9 @@ enum input_clock_type {
  *	and needs not be explicitly unregistered or freed.
  * @timestamp: storage for a timestamp set by input_set_timestamp called
  *  by a driver
+ * @inhibit: makes the device ignore all input
+ * @uninhibit: undoes the effect of inhibit
+ * @inhibited: indicates that the input device is inhibited
  */
 struct input_dev {
 	const char *name;
@@ -201,6 +204,11 @@ struct input_dev {
 	bool devres_managed;
 
 	ktime_t timestamp[INPUT_CLK_MAX];
+
+	int (*inhibit)(struct input_dev *dev);
+	int (*uninhibit)(struct input_dev *dev);
+
+	bool inhibited;
 };
 #define to_input_dev(d) container_of(d, struct input_dev, dev)
 
-- 
2.17.1


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

* [PATCHv2 3/7] ACPI: button: Use input_device_enabled() helper
  2020-05-15 16:49 ` [PATCHv2 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
  2020-05-15 16:51   ` [PATCHv2 1/7] Input: add input_device_enabled() Andrzej Pietrasiewicz
  2020-05-15 16:52   ` [PATCHv2 6/7] Input: Add "inhibited" property Andrzej Pietrasiewicz
@ 2020-05-15 16:53   ` Andrzej Pietrasiewicz
  2020-05-18 12:40     ` Rafael J. Wysocki
  2020-05-15 18:19   ` [PATCHv2 0/7] Support inhibiting input devices Hans de Goede
  3 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-05-15 16:53 UTC (permalink / raw)
  To: linux-input, linux-acpi
  Cc: Rafael J . Wysocki, Len Brown, Andrzej Pietrasiewicz, kernel

A new helper is available, so use it. Inspecting input device's 'users'
member should be done under device's mutex, so add appropriate invocations.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/acpi/button.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 78cfc70cb320..7e081bae48ab 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -411,7 +411,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
 		input = button->input;
 		if (button->type == ACPI_BUTTON_TYPE_LID) {
 			mutex_lock(&button->input->mutex);
-			users = button->input->users;
+			users = input_device_enabled(button->input);
 			mutex_unlock(&button->input->mutex);
 			if (users)
 				acpi_lid_update_state(device, true);
@@ -456,13 +456,17 @@ static int acpi_button_resume(struct device *dev)
 {
 	struct acpi_device *device = to_acpi_device(dev);
 	struct acpi_button *button = acpi_driver_data(device);
+	struct input_dev *input = button->input;
 
 	button->suspended = false;
-	if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users) {
+	mutex_lock(&input->mutex);
+	if (button->type == ACPI_BUTTON_TYPE_LID &&
+	    input_device_enabled(input)) {
 		button->last_state = !!acpi_lid_evaluate_state(device);
 		button->last_time = ktime_get();
 		acpi_lid_initialize_state(device);
 	}
+	mutex_unlock(&input->mutex);
 	return 0;
 }
 #endif
-- 
2.17.1


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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-15 16:49 ` [PATCHv2 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
                     ` (2 preceding siblings ...)
  2020-05-15 16:53   ` [PATCHv2 3/7] ACPI: button: Use input_device_enabled() helper Andrzej Pietrasiewicz
@ 2020-05-15 18:19   ` Hans de Goede
  2020-05-17 22:55     ` Peter Hutterer
  2020-05-18 10:48     ` Andrzej Pietrasiewicz
  3 siblings, 2 replies; 80+ messages in thread
From: Hans de Goede @ 2020-05-15 18:19 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi Andrezj,

On 5/15/20 6:49 PM, Andrzej Pietrasiewicz wrote:
> Userspace might want to implement a policy to temporarily disregard input
> from certain devices, including not treating them as wakeup sources.
> 
> An example use case is a laptop, whose keyboard can be folded under the
> screen to create tablet-like experience. The user then must hold the laptop
> in such a way that it is difficult to avoid pressing the keyboard keys. It
> is therefore desirable to temporarily disregard input from the keyboard,
> until it is folded back. This obviously is a policy which should be kept
> out of the kernel, but the kernel must provide suitable means to implement
> such a policy.

Actually libinput already binds together (inside libinput) SW_TABLET_MODE
generating evdev nodes and e.g. internal keyboards on devices with 360°
hinges for this reason. libinput simply closes the /dev/input/event#
node when folded and re-opens it when the keyboard should become active
again. Thus not only suppresses events but allows e.g. touchpads to
enter runtime suspend mode which saves power. Typically closing the
/dev/input/event# node will also disable the device as wakeup source.

So I wonder what this series actually adds for functionality for
userspace which can not already be achieved this way?

I also noticed that you keep the device open (do not call the
input_device's close callback) when inhibited and just throw away
any events generated. This seems inefficient and may lead to
the internal state getting out of sync. What if a key is pressed
while inhibited and then the device is uninhibited while the key
is still pressed?  Now the press event is lost and userspace
querying the current state will see the pressed key as being
released.

On top of this you add special inhibit and uninhibit callbacks
and implement those for just a few devices. How do these differ
from just closing the device and later opening it again ?

Also using a sysfs property for this is very weird given that the
rest of the evdev interface is using ioctls for everything...

So all in all I see a lot of question marks here and I think we
need to have a detailed discussion about what use-cases this
series tries to enable before moving forward with this.

Regards,

Hans


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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-15 18:19   ` [PATCHv2 0/7] Support inhibiting input devices Hans de Goede
@ 2020-05-17 22:55     ` Peter Hutterer
  2020-05-18  2:40       ` Dmitry Torokhov
  2020-05-18 10:48     ` Andrzej Pietrasiewicz
  1 sibling, 1 reply; 80+ messages in thread
From: Peter Hutterer @ 2020-05-17 22:55 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Andrzej Pietrasiewicz, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

On Fri, May 15, 2020 at 08:19:10PM +0200, Hans de Goede wrote:
> Hi Andrezj,
> 
> On 5/15/20 6:49 PM, Andrzej Pietrasiewicz wrote:
> > Userspace might want to implement a policy to temporarily disregard input
> > from certain devices, including not treating them as wakeup sources.
> > 
> > An example use case is a laptop, whose keyboard can be folded under the
> > screen to create tablet-like experience. The user then must hold the laptop
> > in such a way that it is difficult to avoid pressing the keyboard keys. It
> > is therefore desirable to temporarily disregard input from the keyboard,
> > until it is folded back. This obviously is a policy which should be kept
> > out of the kernel, but the kernel must provide suitable means to implement
> > such a policy.
> 
> Actually libinput already binds together (inside libinput) SW_TABLET_MODE
> generating evdev nodes and e.g. internal keyboards on devices with 360°
> hinges for this reason. libinput simply closes the /dev/input/event#
> node when folded and re-opens it when the keyboard should become active
> again. Thus not only suppresses events but allows e.g. touchpads to
> enter runtime suspend mode which saves power. Typically closing the
> /dev/input/event# node will also disable the device as wakeup source.
> 
> So I wonder what this series actually adds for functionality for
> userspace which can not already be achieved this way?

Thanks Hans. To expand on this:
libinput has heuristics to guess which input devices (keyboards, touchpads)
are built-in ones. When the tablet mode switch is on, we disable these
devices internally (this is not visible to callers), and re-enable it again
later when the tablet mode switch is off again.

This is done for keyboards and touchpads atm (and I think pointing sticks)
and where the heuristics fail we have extra quirks in place. For example
the Lenovo Yogas tend to disable the keyboard mechanically in tablet mode
but buttons (e.g. volume keys) around the screen send events through the
same event node. So on those devices we don't disable the keyboard.

We've had this code for a few years now and the only changes to it have been
the various device quirks for devices that must not suspend the keyboard,
it's otherwise working as expected.

If we ever have a device where we need to disable parts of the keyboard
only, we could address this with EVIOCSMASK but so far that hasn't been
necessary.

I agree with Hans, right now I don't see the usefulness of this new sysfs
toggle. For it to be really useful you'd have to guarantee that it's
available for 100% of the devices and that's IMO unlikely to happen.

Cheers,
   Peter

> I also noticed that you keep the device open (do not call the
> input_device's close callback) when inhibited and just throw away
> any events generated. This seems inefficient and may lead to
> the internal state getting out of sync. What if a key is pressed
> while inhibited and then the device is uninhibited while the key
> is still pressed?  Now the press event is lost and userspace
> querying the current state will see the pressed key as being
> released.
> 
> On top of this you add special inhibit and uninhibit callbacks
> and implement those for just a few devices. How do these differ
> from just closing the device and later opening it again ?
> 
> Also using a sysfs property for this is very weird given that the
> rest of the evdev interface is using ioctls for everything...
> 
> So all in all I see a lot of question marks here and I think we
> need to have a detailed discussion about what use-cases this
> series tries to enable before moving forward with this.
> 
> Regards,
> 
> Hans
> 

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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-17 22:55     ` Peter Hutterer
@ 2020-05-18  2:40       ` Dmitry Torokhov
  2020-05-18  7:36         ` Hans de Goede
  2020-05-22 15:35         ` Andrzej Pietrasiewicz
  0 siblings, 2 replies; 80+ messages in thread
From: Dmitry Torokhov @ 2020-05-18  2:40 UTC (permalink / raw)
  To: Peter Hutterer
  Cc: Hans de Goede, Andrzej Pietrasiewicz, linux-input, linux-acpi,
	linux-iio, linux-arm-kernel, linux-samsung-soc, linux-tegra,
	patches, ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi Hans, Peter,

On Mon, May 18, 2020 at 08:55:10AM +1000, Peter Hutterer wrote:
> On Fri, May 15, 2020 at 08:19:10PM +0200, Hans de Goede wrote:
> > Hi Andrezj,
> > 
> > On 5/15/20 6:49 PM, Andrzej Pietrasiewicz wrote:
> > > Userspace might want to implement a policy to temporarily disregard input
> > > from certain devices, including not treating them as wakeup sources.
> > > 
> > > An example use case is a laptop, whose keyboard can be folded under the
> > > screen to create tablet-like experience. The user then must hold the laptop
> > > in such a way that it is difficult to avoid pressing the keyboard keys. It
> > > is therefore desirable to temporarily disregard input from the keyboard,
> > > until it is folded back. This obviously is a policy which should be kept
> > > out of the kernel, but the kernel must provide suitable means to implement
> > > such a policy.
> > 
> > Actually libinput already binds together (inside libinput) SW_TABLET_MODE
> > generating evdev nodes and e.g. internal keyboards on devices with 360°
> > hinges for this reason. libinput simply closes the /dev/input/event#
> > node when folded and re-opens it when the keyboard should become active
> > again. Thus not only suppresses events but allows e.g. touchpads to
> > enter runtime suspend mode which saves power. Typically closing the
> > /dev/input/event# node will also disable the device as wakeup source.
> > 
> > So I wonder what this series actually adds for functionality for
> > userspace which can not already be achieved this way?
> 
> Thanks Hans. To expand on this:
> libinput has heuristics to guess which input devices (keyboards, touchpads)
> are built-in ones. When the tablet mode switch is on, we disable these
> devices internally (this is not visible to callers), and re-enable it again
> later when the tablet mode switch is off again.

I think that is great that libinput has tried solving this for the
tablet mode, but unfortunately libinput only works for users of
libinput, leaving cases such as:

1. In-kernel input handlers, such as SysRq, VT and others
2. Systems that do not rely on libinput for userspace handing (Android,
Chrome OS)
3. Systems with policies that are more complex than tablet mode only.

Because of libinput's inability to affect the kernel, and the presence
of "always on" input handlers (sysrq, VT keyboard, potentially others),
while libinput may control whether consumers receive events from certain
input devices, it will not allow power savings that an explicit
"inhibit" allows when coming from dedicated power policy manager.

I think pushing policy decisions into a library, and trying to have all
clients agree with it, is much harder and leaks unnecessary knowledge
into quite a few layers. A dedicated power policy manager, that is not
only responsible for input device, but power state of the system as a
whole, is a very viable architecture.

> 
> This is done for keyboards and touchpads atm (and I think pointing sticks)
> and where the heuristics fail we have extra quirks in place. For example
> the Lenovo Yogas tend to disable the keyboard mechanically in tablet mode
> but buttons (e.g. volume keys) around the screen send events through the
> same event node. So on those devices we don't disable the keyboard.
> 
> We've had this code for a few years now and the only changes to it have been
> the various device quirks for devices that must not suspend the keyboard,
> it's otherwise working as expected.
> 
> If we ever have a device where we need to disable parts of the keyboard
> only, we could address this with EVIOCSMASK but so far that hasn't been
> necessary.
> 
> I agree with Hans, right now I don't see the usefulness of this new sysfs
> toggle. For it to be really useful you'd have to guarantee that it's
> available for 100% of the devices and that's IMO unlikely to happen.

The inhibiting of the events works for 100% of input devices, the power
savings work for the ones that implement it. It is responsibility of
folds shipping the systems to make sure drivers they use support inhibit
if they believe it will help their battery life.

> 
> Cheers,
>    Peter
> 
> > I also noticed that you keep the device open (do not call the
> > input_device's close callback) when inhibited and just throw away
> > any events generated. This seems inefficient and may lead to
> > the internal state getting out of sync. What if a key is pressed
> > while inhibited and then the device is uninhibited while the key
> > is still pressed?  Now the press event is lost and userspace
> > querying the current state will see the pressed key as being
> > released.

This is a good point. We should look into signalling that some events
have been dropped (via EV_SYN/SYN_DROPPED) so that clients are aware of
it.

> > 
> > On top of this you add special inhibit and uninhibit callbacks
> > and implement those for just a few devices. How do these differ
> > from just closing the device and later opening it again ?

I believe majority will simply reuse open/close callbacks. In Chrome OS
we have dedicated inhibit/uninhibit, but I would like to allow using
open/close as alternatives.

> > 
> > Also using a sysfs property for this is very weird given that the
> > rest of the evdev interface is using ioctls for everything...

This is not evdev interface, it is at the level above evdev (so that it
can affect all handlers, not only evdev). As such it is not bound by
evdev interface.

Thanks.

-- 
Dmitry

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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-18  2:40       ` Dmitry Torokhov
@ 2020-05-18  7:36         ` Hans de Goede
  2020-05-22 15:35         ` Andrzej Pietrasiewicz
  1 sibling, 0 replies; 80+ messages in thread
From: Hans de Goede @ 2020-05-18  7:36 UTC (permalink / raw)
  To: Dmitry Torokhov, Peter Hutterer
  Cc: Andrzej Pietrasiewicz, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi,

On 5/18/20 4:40 AM, Dmitry Torokhov wrote:
> Hi Hans, Peter,
> 
> On Mon, May 18, 2020 at 08:55:10AM +1000, Peter Hutterer wrote:
>> On Fri, May 15, 2020 at 08:19:10PM +0200, Hans de Goede wrote:
>>> Hi Andrezj,
>>>
>>> On 5/15/20 6:49 PM, Andrzej Pietrasiewicz wrote:
>>>> Userspace might want to implement a policy to temporarily disregard input
>>>> from certain devices, including not treating them as wakeup sources.
>>>>
>>>> An example use case is a laptop, whose keyboard can be folded under the
>>>> screen to create tablet-like experience. The user then must hold the laptop
>>>> in such a way that it is difficult to avoid pressing the keyboard keys. It
>>>> is therefore desirable to temporarily disregard input from the keyboard,
>>>> until it is folded back. This obviously is a policy which should be kept
>>>> out of the kernel, but the kernel must provide suitable means to implement
>>>> such a policy.
>>>
>>> Actually libinput already binds together (inside libinput) SW_TABLET_MODE
>>> generating evdev nodes and e.g. internal keyboards on devices with 360°
>>> hinges for this reason. libinput simply closes the /dev/input/event#
>>> node when folded and re-opens it when the keyboard should become active
>>> again. Thus not only suppresses events but allows e.g. touchpads to
>>> enter runtime suspend mode which saves power. Typically closing the
>>> /dev/input/event# node will also disable the device as wakeup source.
>>>
>>> So I wonder what this series actually adds for functionality for
>>> userspace which can not already be achieved this way?
>>
>> Thanks Hans. To expand on this:
>> libinput has heuristics to guess which input devices (keyboards, touchpads)
>> are built-in ones. When the tablet mode switch is on, we disable these
>> devices internally (this is not visible to callers), and re-enable it again
>> later when the tablet mode switch is off again.
> 
> I think that is great that libinput has tried solving this for the
> tablet mode, but unfortunately libinput only works for users of
> libinput, leaving cases such as:
> 
> 1. In-kernel input handlers, such as SysRq, VT and others
> 2. Systems that do not rely on libinput for userspace handing (Android,
> Chrome OS)
> 3. Systems with policies that are more complex than tablet mode only.
> 
> Because of libinput's inability to affect the kernel, and the presence
> of "always on" input handlers (sysrq, VT keyboard, potentially others),
> while libinput may control whether consumers receive events from certain
> input devices, it will not allow power savings that an explicit
> "inhibit" allows when coming from dedicated power policy manager.

Ok, the sysrq and vt keyboard handlers keeping the device open and thus
make it keep using power is a valid reason for a separate inhibit mechanism.

> I think pushing policy decisions into a library, and trying to have all
> clients agree with it, is much harder and leaks unnecessary knowledge
> into quite a few layers. A dedicated power policy manager, that is not
> only responsible for input device, but power state of the system as a
> whole, is a very viable architecture.

Well AFAIK the kernel-policy has always been to leave policy decisions
up to userspace as much as possible, but this just adds a mechanism to
implement the policy so that is fine.

>> This is done for keyboards and touchpads atm (and I think pointing sticks)
>> and where the heuristics fail we have extra quirks in place. For example
>> the Lenovo Yogas tend to disable the keyboard mechanically in tablet mode
>> but buttons (e.g. volume keys) around the screen send events through the
>> same event node. So on those devices we don't disable the keyboard.
>>
>> We've had this code for a few years now and the only changes to it have been
>> the various device quirks for devices that must not suspend the keyboard,
>> it's otherwise working as expected.
>>
>> If we ever have a device where we need to disable parts of the keyboard
>> only, we could address this with EVIOCSMASK but so far that hasn't been
>> necessary.
>>
>> I agree with Hans, right now I don't see the usefulness of this new sysfs
>> toggle. For it to be really useful you'd have to guarantee that it's
>> available for 100% of the devices and that's IMO unlikely to happen.
> 
> The inhibiting of the events works for 100% of input devices, the power
> savings work for the ones that implement it. It is responsibility of
> folds shipping the systems to make sure drivers they use support inhibit
> if they believe it will help their battery life.
> 
>>
>> Cheers,
>>     Peter
>>
>>> I also noticed that you keep the device open (do not call the
>>> input_device's close callback) when inhibited and just throw away
>>> any events generated. This seems inefficient and may lead to
>>> the internal state getting out of sync. What if a key is pressed
>>> while inhibited and then the device is uninhibited while the key
>>> is still pressed?  Now the press event is lost and userspace
>>> querying the current state will see the pressed key as being
>>> released.
> 
> This is a good point. We should look into signalling that some events
> have been dropped (via EV_SYN/SYN_DROPPED) so that clients are aware of
> it.
> 
>>>
>>> On top of this you add special inhibit and uninhibit callbacks
>>> and implement those for just a few devices. How do these differ
>>> from just closing the device and later opening it again ?
> 
> I believe majority will simply reuse open/close callbacks. In Chrome OS
> we have dedicated inhibit/uninhibit, but I would like to allow using
> open/close as alternatives.

Ack, maybe some driver flag to just call close on inhibit and
open on unhibit (also taking input_device.users into account of course) ?

>>> Also using a sysfs property for this is very weird given that the
>>> rest of the evdev interface is using ioctls for everything...
> 
> This is not evdev interface, it is at the level above evdev (so that it
> can affect all handlers, not only evdev). As such it is not bound by
> evdev interface.

Ok I can see how on some systems the process implementing the policy
of when to inhibit would be separate from the process which has the
device open. But in e.g. the libinput case it would be good if
libinput could activate any potential power-savings by setting
the inhibit flag.

The problem with sysfs interfaces is that they typically require
root rights and that they are not really compatible with FD
passing. libinput runs as a normal user, getting a fd to the
/dev/input/event# node passed by systemd-logind.

As said I can see the reason for wanting a sysfs attribute for
this, can we perhaps have both a sysfs interface and an ioctl?

Note both could share the same boolean in the kernel, it would be
up to userspace to not try and write to both. E.g. chrome-os
would use the sysfs attr, libinput would use the ioctl.

Regards,

Hans


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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-15 18:19   ` [PATCHv2 0/7] Support inhibiting input devices Hans de Goede
  2020-05-17 22:55     ` Peter Hutterer
@ 2020-05-18 10:48     ` Andrzej Pietrasiewicz
  2020-05-18 12:24       ` Hans de Goede
  1 sibling, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-05-18 10:48 UTC (permalink / raw)
  To: Hans de Goede, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi Hans,

W dniu 15.05.2020 o 20:19, Hans de Goede pisze:
> Hi Andrezj,
> 
> On 5/15/20 6:49 PM, Andrzej Pietrasiewicz wrote:
>> Userspace might want to implement a policy to temporarily disregard input
>> from certain devices, including not treating them as wakeup sources.
>>
>> An example use case is a laptop, whose keyboard can be folded under the
>> screen to create tablet-like experience. The user then must hold the laptop
>> in such a way that it is difficult to avoid pressing the keyboard keys. It
>> is therefore desirable to temporarily disregard input from the keyboard,
>> until it is folded back. This obviously is a policy which should be kept
>> out of the kernel, but the kernel must provide suitable means to implement
>> such a policy.
> 
> Actually libinput already binds together (inside libinput) SW_TABLET_MODE
> generating evdev nodes and e.g. internal keyboards on devices with 360°
> hinges for this reason. libinput simply closes the /dev/input/event#
> node when folded and re-opens it when the keyboard should become active
> again. Thus not only suppresses events but allows e.g. touchpads to
> enter runtime suspend mode which saves power. Typically closing the
> /dev/input/event# node will also disable the device as wakeup source.
> 
> So I wonder what this series actually adds for functionality for
> userspace which can not already be achieved this way?
> 
> I also noticed that you keep the device open (do not call the
> input_device's close callback) when inhibited and just throw away

I'm not sure if I understand you correctly, it is called:

+static inline void input_stop(struct input_dev *dev)
+{
+	if (dev->poller)
+		input_dev_poller_stop(dev->poller);
+	if (dev->close)
+		dev->close(dev);
                 ^^^^^^^^^^^^^^^^
+static int input_inhibit(struct input_dev *dev)
+{
+	int ret = 0;
+
+	mutex_lock(&dev->mutex);
+
+	if (dev->inhibited)
+		goto out;
+
+	if (dev->users) {
+		if (dev->inhibit) {
+			ret = dev->inhibit(dev);
+			if (ret)
+				goto out;
+		}
+		input_stop(dev);
                 ^^^^^^^^^^^^^^^^

It will not be called when dev->users is zero, but if it is zero,
then nobody has opened the device yet so there is nothing to close.

Andrzej

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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-18 10:48     ` Andrzej Pietrasiewicz
@ 2020-05-18 12:24       ` Hans de Goede
  2020-05-18 13:49         ` Andrzej Pietrasiewicz
  0 siblings, 1 reply; 80+ messages in thread
From: Hans de Goede @ 2020-05-18 12:24 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi,

On 5/18/20 12:48 PM, Andrzej Pietrasiewicz wrote:
> Hi Hans,
> 
> W dniu 15.05.2020 o 20:19, Hans de Goede pisze:
>> Hi Andrezj,
>>
>> On 5/15/20 6:49 PM, Andrzej Pietrasiewicz wrote:
>>> Userspace might want to implement a policy to temporarily disregard input
>>> from certain devices, including not treating them as wakeup sources.
>>>
>>> An example use case is a laptop, whose keyboard can be folded under the
>>> screen to create tablet-like experience. The user then must hold the laptop
>>> in such a way that it is difficult to avoid pressing the keyboard keys. It
>>> is therefore desirable to temporarily disregard input from the keyboard,
>>> until it is folded back. This obviously is a policy which should be kept
>>> out of the kernel, but the kernel must provide suitable means to implement
>>> such a policy.
>>
>> Actually libinput already binds together (inside libinput) SW_TABLET_MODE
>> generating evdev nodes and e.g. internal keyboards on devices with 360°
>> hinges for this reason. libinput simply closes the /dev/input/event#
>> node when folded and re-opens it when the keyboard should become active
>> again. Thus not only suppresses events but allows e.g. touchpads to
>> enter runtime suspend mode which saves power. Typically closing the
>> /dev/input/event# node will also disable the device as wakeup source.
>>
>> So I wonder what this series actually adds for functionality for
>> userspace which can not already be achieved this way?
>>
>> I also noticed that you keep the device open (do not call the
>> input_device's close callback) when inhibited and just throw away
> 
> I'm not sure if I understand you correctly, it is called:
> 
> +static inline void input_stop(struct input_dev *dev)
> +{
> +    if (dev->poller)
> +        input_dev_poller_stop(dev->poller);
> +    if (dev->close)
> +        dev->close(dev);
>                  ^^^^^^^^^^^^^^^^
> +static int input_inhibit(struct input_dev *dev)
> +{
> +    int ret = 0;
> +
> +    mutex_lock(&dev->mutex);
> +
> +    if (dev->inhibited)
> +        goto out;
> +
> +    if (dev->users) {
> +        if (dev->inhibit) {
> +            ret = dev->inhibit(dev);
> +            if (ret)
> +                goto out;
> +        }
> +        input_stop(dev);
>                  ^^^^^^^^^^^^^^^^
> 
> It will not be called when dev->users is zero, but if it is zero,
> then nobody has opened the device yet so there is nothing to close.

Ah, I missed that.

So if the device implements the inhibit call back then on
inhibit it will get both the inhibit and close callback called?

And what happens if the last user goes away and the device
is not inhibited?

I'm trying to understand here what the difference between the 2
is / what the goal of having a separate inhibit callback ?

IOW is there something which we want to do on close when
the close is being done to inhibit the device, which we do
not want to do on a normal close ?

Regards,

Hans



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

* Re: [PATCHv2 3/7] ACPI: button: Use input_device_enabled() helper
  2020-05-15 16:53   ` [PATCHv2 3/7] ACPI: button: Use input_device_enabled() helper Andrzej Pietrasiewicz
@ 2020-05-18 12:40     ` Rafael J. Wysocki
  0 siblings, 0 replies; 80+ messages in thread
From: Rafael J. Wysocki @ 2020-05-18 12:40 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz; +Cc: linux-input, linux-acpi, Len Brown, kernel

On Friday, May 15, 2020 6:53:27 PM CEST Andrzej Pietrasiewicz wrote:
> A new helper is available, so use it. Inspecting input device's 'users'
> member should be done under device's mutex, so add appropriate invocations.
> 
> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> ---
>  drivers/acpi/button.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> index 78cfc70cb320..7e081bae48ab 100644
> --- a/drivers/acpi/button.c
> +++ b/drivers/acpi/button.c
> @@ -411,7 +411,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
>  		input = button->input;
>  		if (button->type == ACPI_BUTTON_TYPE_LID) {
>  			mutex_lock(&button->input->mutex);
> -			users = button->input->users;
> +			users = input_device_enabled(button->input);
>  			mutex_unlock(&button->input->mutex);
>  			if (users)
>  				acpi_lid_update_state(device, true);
> @@ -456,13 +456,17 @@ static int acpi_button_resume(struct device *dev)
>  {
>  	struct acpi_device *device = to_acpi_device(dev);
>  	struct acpi_button *button = acpi_driver_data(device);
> +	struct input_dev *input = button->input;
>  
>  	button->suspended = false;
> -	if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users) {
> +	mutex_lock(&input->mutex);
> +	if (button->type == ACPI_BUTTON_TYPE_LID &&
> +	    input_device_enabled(input)) {
>  		button->last_state = !!acpi_lid_evaluate_state(device);
>  		button->last_time = ktime_get();
>  		acpi_lid_initialize_state(device);
>  	}
> +	mutex_unlock(&input->mutex);
>  	return 0;
>  }
>  #endif
> 

This appears to conflate a fix (the introduction of the missing mutex locking)
with adding new functionality through input_device_enabled().

Please do the fix separately in advance so it can be backported.

Thanks!




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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-18 12:24       ` Hans de Goede
@ 2020-05-18 13:49         ` Andrzej Pietrasiewicz
  2020-05-18 14:23           ` Hans de Goede
  0 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-05-18 13:49 UTC (permalink / raw)
  To: Hans de Goede, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi Hans,

W dniu 18.05.2020 o 14:24, Hans de Goede pisze:
> Hi,
> 
> On 5/18/20 12:48 PM, Andrzej Pietrasiewicz wrote:
>> Hi Hans,
>>
>> W dniu 15.05.2020 o 20:19, Hans de Goede pisze:
>>> Hi Andrezj,
>>>
>>> On 5/15/20 6:49 PM, Andrzej Pietrasiewicz wrote:
>>>> Userspace might want to implement a policy to temporarily disregard input
>>>> from certain devices, including not treating them as wakeup sources.
>>>>
>>>> An example use case is a laptop, whose keyboard can be folded under the
>>>> screen to create tablet-like experience. The user then must hold the laptop
>>>> in such a way that it is difficult to avoid pressing the keyboard keys. It
>>>> is therefore desirable to temporarily disregard input from the keyboard,
>>>> until it is folded back. This obviously is a policy which should be kept
>>>> out of the kernel, but the kernel must provide suitable means to implement
>>>> such a policy.
>>>
>>> Actually libinput already binds together (inside libinput) SW_TABLET_MODE
>>> generating evdev nodes and e.g. internal keyboards on devices with 360°
>>> hinges for this reason. libinput simply closes the /dev/input/event#
>>> node when folded and re-opens it when the keyboard should become active
>>> again. Thus not only suppresses events but allows e.g. touchpads to
>>> enter runtime suspend mode which saves power. Typically closing the
>>> /dev/input/event# node will also disable the device as wakeup source.
>>>
>>> So I wonder what this series actually adds for functionality for
>>> userspace which can not already be achieved this way?
>>>
>>> I also noticed that you keep the device open (do not call the
>>> input_device's close callback) when inhibited and just throw away
>>
>> I'm not sure if I understand you correctly, it is called:
>>
>> +static inline void input_stop(struct input_dev *dev)
>> +{
>> +    if (dev->poller)
>> +        input_dev_poller_stop(dev->poller);
>> +    if (dev->close)
>> +        dev->close(dev);
>>                  ^^^^^^^^^^^^^^^^
>> +static int input_inhibit(struct input_dev *dev)
>> +{
>> +    int ret = 0;
>> +
>> +    mutex_lock(&dev->mutex);
>> +
>> +    if (dev->inhibited)
>> +        goto out;
>> +
>> +    if (dev->users) {
>> +        if (dev->inhibit) {
>> +            ret = dev->inhibit(dev);
>> +            if (ret)
>> +                goto out;
>> +        }
>> +        input_stop(dev);
>>                  ^^^^^^^^^^^^^^^^
>>
>> It will not be called when dev->users is zero, but if it is zero,
>> then nobody has opened the device yet so there is nothing to close.
> 
> Ah, I missed that.
> 
> So if the device implements the inhibit call back then on
> inhibit it will get both the inhibit and close callback called?
> 

That's right. And conversely, upon uninhibit open() and uninhibit()
callbacks will be invoked. Please note that just as with open()/close(),
providing inhibit()/uninhibit() is optional.

> And what happens if the last user goes away and the device
> is not inhibited?

close() is called as usually.

> 
> I'm trying to understand here what the difference between the 2
> is / what the goal of having a separate inhibit callback ?
> 

Drivers have very different ideas about what it means to suspend/resume
and open/close. The optional inhibit/uninhibit callbacks are meant for
the drivers to know that it is this particular action going on.

For inhibit() there's one more argument: close() does not return a value,
so its meaning is "do some last cleanup" and as such it is not allowed
to fail - whatever its effect is, we must deem it successful. inhibit()
does return a value and so it is allowed to fail.

All in all, it is up to the drivers to decide which callback they
provide. Based on my work so far I would say that there are tens
of simple cases where open() and close() are sufficient, out of total
~400 users of input_allocate_device():

$ git grep "input_allocate_device(" | grep -v ^Documentation | \
cut -f1 -d: | sort | uniq | wc
     390     390   13496

Andrzej

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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-18 13:49         ` Andrzej Pietrasiewicz
@ 2020-05-18 14:23           ` Hans de Goede
  2020-05-19  9:02             ` Andrzej Pietrasiewicz
  0 siblings, 1 reply; 80+ messages in thread
From: Hans de Goede @ 2020-05-18 14:23 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi,

On 5/18/20 3:49 PM, Andrzej Pietrasiewicz wrote:
> Hi Hans,
> 
> W dniu 18.05.2020 o 14:24, Hans de Goede pisze:
>> Hi,
>>
>> On 5/18/20 12:48 PM, Andrzej Pietrasiewicz wrote:
>>> Hi Hans,
>>>
>>> W dniu 15.05.2020 o 20:19, Hans de Goede pisze:
>>>> Hi Andrezj,
>>>>
>>>> On 5/15/20 6:49 PM, Andrzej Pietrasiewicz wrote:
>>>>> Userspace might want to implement a policy to temporarily disregard input
>>>>> from certain devices, including not treating them as wakeup sources.
>>>>>
>>>>> An example use case is a laptop, whose keyboard can be folded under the
>>>>> screen to create tablet-like experience. The user then must hold the laptop
>>>>> in such a way that it is difficult to avoid pressing the keyboard keys. It
>>>>> is therefore desirable to temporarily disregard input from the keyboard,
>>>>> until it is folded back. This obviously is a policy which should be kept
>>>>> out of the kernel, but the kernel must provide suitable means to implement
>>>>> such a policy.
>>>>
>>>> Actually libinput already binds together (inside libinput) SW_TABLET_MODE
>>>> generating evdev nodes and e.g. internal keyboards on devices with 360°
>>>> hinges for this reason. libinput simply closes the /dev/input/event#
>>>> node when folded and re-opens it when the keyboard should become active
>>>> again. Thus not only suppresses events but allows e.g. touchpads to
>>>> enter runtime suspend mode which saves power. Typically closing the
>>>> /dev/input/event# node will also disable the device as wakeup source.
>>>>
>>>> So I wonder what this series actually adds for functionality for
>>>> userspace which can not already be achieved this way?
>>>>
>>>> I also noticed that you keep the device open (do not call the
>>>> input_device's close callback) when inhibited and just throw away
>>>
>>> I'm not sure if I understand you correctly, it is called:
>>>
>>> +static inline void input_stop(struct input_dev *dev)
>>> +{
>>> +    if (dev->poller)
>>> +        input_dev_poller_stop(dev->poller);
>>> +    if (dev->close)
>>> +        dev->close(dev);
>>>                  ^^^^^^^^^^^^^^^^
>>> +static int input_inhibit(struct input_dev *dev)
>>> +{
>>> +    int ret = 0;
>>> +
>>> +    mutex_lock(&dev->mutex);
>>> +
>>> +    if (dev->inhibited)
>>> +        goto out;
>>> +
>>> +    if (dev->users) {
>>> +        if (dev->inhibit) {
>>> +            ret = dev->inhibit(dev);
>>> +            if (ret)
>>> +                goto out;
>>> +        }
>>> +        input_stop(dev);
>>>                  ^^^^^^^^^^^^^^^^
>>>
>>> It will not be called when dev->users is zero, but if it is zero,
>>> then nobody has opened the device yet so there is nothing to close.
>>
>> Ah, I missed that.
>>
>> So if the device implements the inhibit call back then on
>> inhibit it will get both the inhibit and close callback called?
>>
> 
> That's right. And conversely, upon uninhibit open() and uninhibit()
> callbacks will be invoked. Please note that just as with open()/close(),
> providing inhibit()/uninhibit() is optional.

Ack.

>> And what happens if the last user goes away and the device
>> is not inhibited?
> 
> close() is called as usually.

But not inhibit, hmm, see below.

>> I'm trying to understand here what the difference between the 2
>> is / what the goal of having a separate inhibit callback ?
>>
> 
> Drivers have very different ideas about what it means to suspend/resume
> and open/close. The optional inhibit/uninhibit callbacks are meant for
> the drivers to know that it is this particular action going on.

So the inhibit() callback triggers the "suspend" behavior ?
But shouldn't drivers which are capable of suspending the device
always do so on close() ?

Since your current proposal also calls close() on inhibit() I
really see little difference between an inhibit() and the last
user of the device closing it and IMHO unless there is a good
reason to actually differentiate the 2 it would be better
to only stick with the existing close() and in cases where
that does not put the device in a low-power mode yet, fix
the existing close() callback to do the low-power mode
setting instead of adding a new callback.

> For inhibit() there's one more argument: close() does not return a value,
> so its meaning is "do some last cleanup" and as such it is not allowed
> to fail - whatever its effect is, we must deem it successful. inhibit()
> does return a value and so it is allowed to fail.

Well, we could make close() return an error and at least in the inhibit()
case propagate that to userspace. I wonder if userspace is going to
do anything useful with that error though...

In my experience errors during cleanup/shutdown are best logged
(using dev_err) and otherwise ignored, so that we try to clean up
as much possible. Unless the very first step of the shutdown process
fails the device is going to be in some twilight zone state anyways
at this point we might as well try to cleanup as much as possible.

> All in all, it is up to the drivers to decide which callback they
> provide. Based on my work so far I would say that there are tens
> of simple cases where open() and close() are sufficient, out of total
> ~400 users of input_allocate_device():
> 
> $ git grep "input_allocate_device(" | grep -v ^Documentation | \
> cut -f1 -d: | sort | uniq | wc
>      390     390   13496

So can you explain a bit more about the cases where only having
open/close is not sufficient?  So far I have the feeling that
those are all we need and that we really do not need separate
[un]inhibit callbacks.

Regards,

Hans


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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-18 14:23           ` Hans de Goede
@ 2020-05-19  9:02             ` Andrzej Pietrasiewicz
  2020-05-19  9:36               ` Hans de Goede
  0 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-05-19  9:02 UTC (permalink / raw)
  To: Hans de Goede, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi Hans, Hi Dmitry,

W dniu 18.05.2020 o 16:23, Hans de Goede pisze:
> Hi,

<snip>

>>>>>
>>>>> So I wonder what this series actually adds for functionality for
>>>>> userspace which can not already be achieved this way?
>>>>>
>>>>> I also noticed that you keep the device open (do not call the
>>>>> input_device's close callback) when inhibited and just throw away
>>>>
>>>> I'm not sure if I understand you correctly, it is called:
>>>>
>>>> +static inline void input_stop(struct input_dev *dev)
>>>> +{
>>>> +    if (dev->poller)
>>>> +        input_dev_poller_stop(dev->poller);
>>>> +    if (dev->close)
>>>> +        dev->close(dev);
>>>>                  ^^^^^^^^^^^^^^^^
>>>> +static int input_inhibit(struct input_dev *dev)
>>>> +{
>>>> +    int ret = 0;
>>>> +
>>>> +    mutex_lock(&dev->mutex);
>>>> +
>>>> +    if (dev->inhibited)
>>>> +        goto out;
>>>> +
>>>> +    if (dev->users) {
>>>> +        if (dev->inhibit) {
>>>> +            ret = dev->inhibit(dev);
>>>> +            if (ret)
>>>> +                goto out;
>>>> +        }
>>>> +        input_stop(dev);
>>>>                  ^^^^^^^^^^^^^^^^
>>>>
>>>> It will not be called when dev->users is zero, but if it is zero,
>>>> then nobody has opened the device yet so there is nothing to close.
>>>
>>> Ah, I missed that.
>>>
>>> So if the device implements the inhibit call back then on
>>> inhibit it will get both the inhibit and close callback called?
>>>
>>
>> That's right. And conversely, upon uninhibit open() and uninhibit()
>> callbacks will be invoked. Please note that just as with open()/close(),
>> providing inhibit()/uninhibit() is optional.
> 
> Ack.
> 
>>> And what happens if the last user goes away and the device
>>> is not inhibited?
>>
>> close() is called as usually.
> 
> But not inhibit, hmm, see below.
> 
>>> I'm trying to understand here what the difference between the 2
>>> is / what the goal of having a separate inhibit callback ?
>>>
>>
>> Drivers have very different ideas about what it means to suspend/resume
>> and open/close. The optional inhibit/uninhibit callbacks are meant for
>> the drivers to know that it is this particular action going on.
> 
> So the inhibit() callback triggers the "suspend" behavior ?
> But shouldn't drivers which are capable of suspending the device
> always do so on close() ?
> 
> Since your current proposal also calls close() on inhibit() I
> really see little difference between an inhibit() and the last
> user of the device closing it and IMHO unless there is a good
> reason to actually differentiate the 2 it would be better
> to only stick with the existing close() and in cases where
> that does not put the device in a low-power mode yet, fix
> the existing close() callback to do the low-power mode
> setting instead of adding a new callback.
> 
>> For inhibit() there's one more argument: close() does not return a value,
>> so its meaning is "do some last cleanup" and as such it is not allowed
>> to fail - whatever its effect is, we must deem it successful. inhibit()
>> does return a value and so it is allowed to fail.
> 
> Well, we could make close() return an error and at least in the inhibit()
> case propagate that to userspace. I wonder if userspace is going to
> do anything useful with that error though...
> 
> In my experience errors during cleanup/shutdown are best logged
> (using dev_err) and otherwise ignored, so that we try to clean up
> as much possible. Unless the very first step of the shutdown process
> fails the device is going to be in some twilight zone state anyways
> at this point we might as well try to cleanup as much as possible.

What you say makes sense to me.
@Dmitry?

> 
>> All in all, it is up to the drivers to decide which callback they
>> provide. Based on my work so far I would say that there are tens
>> of simple cases where open() and close() are sufficient, out of total
>> ~400 users of input_allocate_device():
>>
>> $ git grep "input_allocate_device(" | grep -v ^Documentation | \
>> cut -f1 -d: | sort | uniq | wc
>>      390     390   13496
> 
> So can you explain a bit more about the cases where only having
> open/close is not sufficient?  So far I have the feeling that
> those are all we need and that we really do not need separate
> [un]inhibit callbacks.

My primary concern was not being able to propagate inhibit() error
to userspace, and then if we have inhibit(), uninhibit() should be
there for completeness. If propagating the error to userspace can
be neglected then yes, it seems open/close should be sufficient,
even more because the real meaning of "open" is "prepare the device
for generating input events".

To validate the idea of not introducing inhibit()/uninhibit() callbacks
to implement device inhibiting/uninhibiting let's look at
drivers/input/mouse/elan_i2c_core.c (PATCH 7/7):

static int elan_inhibit(struct input_dev *input)
{
[...]

	ret = mutex_lock_interruptible(&data->sysfs_mutex);
	if (ret)
		return ret;

	disable_irq(client->irq);

	ret = elan_disable_power(data);
	if (ret)
		enable_irq(client->irq);
[...]
}

First, close() does not exist in this driver. Of course this can be
fixed. Then it doesn't return a value. Then, if either taking the
mutex or disabling the power fails, the close() is still deemed
successful. Is it ok?
@Dmitry?

Regards,

Andrzej

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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-19  9:02             ` Andrzej Pietrasiewicz
@ 2020-05-19  9:36               ` Hans de Goede
  2020-05-27  6:34                 ` Dmitry Torokhov
  0 siblings, 1 reply; 80+ messages in thread
From: Hans de Goede @ 2020-05-19  9:36 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi,

On 5/19/20 11:02 AM, Andrzej Pietrasiewicz wrote:
> Hi Hans, Hi Dmitry,
> 
> W dniu 18.05.2020 o 16:23, Hans de Goede pisze:
>> Hi,
> 
> <snip>
> 
>>>>>>
>>>>>> So I wonder what this series actually adds for functionality for
>>>>>> userspace which can not already be achieved this way?
>>>>>>
>>>>>> I also noticed that you keep the device open (do not call the
>>>>>> input_device's close callback) when inhibited and just throw away
>>>>>
>>>>> I'm not sure if I understand you correctly, it is called:
>>>>>
>>>>> +static inline void input_stop(struct input_dev *dev)
>>>>> +{
>>>>> +    if (dev->poller)
>>>>> +        input_dev_poller_stop(dev->poller);
>>>>> +    if (dev->close)
>>>>> +        dev->close(dev);
>>>>>                  ^^^^^^^^^^^^^^^^
>>>>> +static int input_inhibit(struct input_dev *dev)
>>>>> +{
>>>>> +    int ret = 0;
>>>>> +
>>>>> +    mutex_lock(&dev->mutex);
>>>>> +
>>>>> +    if (dev->inhibited)
>>>>> +        goto out;
>>>>> +
>>>>> +    if (dev->users) {
>>>>> +        if (dev->inhibit) {
>>>>> +            ret = dev->inhibit(dev);
>>>>> +            if (ret)
>>>>> +                goto out;
>>>>> +        }
>>>>> +        input_stop(dev);
>>>>>                  ^^^^^^^^^^^^^^^^
>>>>>
>>>>> It will not be called when dev->users is zero, but if it is zero,
>>>>> then nobody has opened the device yet so there is nothing to close.
>>>>
>>>> Ah, I missed that.
>>>>
>>>> So if the device implements the inhibit call back then on
>>>> inhibit it will get both the inhibit and close callback called?
>>>>
>>>
>>> That's right. And conversely, upon uninhibit open() and uninhibit()
>>> callbacks will be invoked. Please note that just as with open()/close(),
>>> providing inhibit()/uninhibit() is optional.
>>
>> Ack.
>>
>>>> And what happens if the last user goes away and the device
>>>> is not inhibited?
>>>
>>> close() is called as usually.
>>
>> But not inhibit, hmm, see below.
>>
>>>> I'm trying to understand here what the difference between the 2
>>>> is / what the goal of having a separate inhibit callback ?
>>>>
>>>
>>> Drivers have very different ideas about what it means to suspend/resume
>>> and open/close. The optional inhibit/uninhibit callbacks are meant for
>>> the drivers to know that it is this particular action going on.
>>
>> So the inhibit() callback triggers the "suspend" behavior ?
>> But shouldn't drivers which are capable of suspending the device
>> always do so on close() ?
>>
>> Since your current proposal also calls close() on inhibit() I
>> really see little difference between an inhibit() and the last
>> user of the device closing it and IMHO unless there is a good
>> reason to actually differentiate the 2 it would be better
>> to only stick with the existing close() and in cases where
>> that does not put the device in a low-power mode yet, fix
>> the existing close() callback to do the low-power mode
>> setting instead of adding a new callback.
>>
>>> For inhibit() there's one more argument: close() does not return a value,
>>> so its meaning is "do some last cleanup" and as such it is not allowed
>>> to fail - whatever its effect is, we must deem it successful. inhibit()
>>> does return a value and so it is allowed to fail.
>>
>> Well, we could make close() return an error and at least in the inhibit()
>> case propagate that to userspace. I wonder if userspace is going to
>> do anything useful with that error though...
>>
>> In my experience errors during cleanup/shutdown are best logged
>> (using dev_err) and otherwise ignored, so that we try to clean up
>> as much possible. Unless the very first step of the shutdown process
>> fails the device is going to be in some twilight zone state anyways
>> at this point we might as well try to cleanup as much as possible.
> 
> What you say makes sense to me.
> @Dmitry?
> 
>>
>>> All in all, it is up to the drivers to decide which callback they
>>> provide. Based on my work so far I would say that there are tens
>>> of simple cases where open() and close() are sufficient, out of total
>>> ~400 users of input_allocate_device():
>>>
>>> $ git grep "input_allocate_device(" | grep -v ^Documentation | \
>>> cut -f1 -d: | sort | uniq | wc
>>>      390     390   13496
>>
>> So can you explain a bit more about the cases where only having
>> open/close is not sufficient?  So far I have the feeling that
>> those are all we need and that we really do not need separate
>> [un]inhibit callbacks.
> 
> My primary concern was not being able to propagate inhibit() error
> to userspace, and then if we have inhibit(), uninhibit() should be
> there for completeness. If propagating the error to userspace can
> be neglected then yes, it seems open/close should be sufficient,
> even more because the real meaning of "open" is "prepare the device
> for generating input events".
> 
> To validate the idea of not introducing inhibit()/uninhibit() callbacks
> to implement device inhibiting/uninhibiting let's look at
> drivers/input/mouse/elan_i2c_core.c (PATCH 7/7):
> 
> static int elan_inhibit(struct input_dev *input)
> {
> [...]
> 
>      ret = mutex_lock_interruptible(&data->sysfs_mutex);
>      if (ret)
>          return ret;
> 
>      disable_irq(client->irq);
> 
>      ret = elan_disable_power(data);
>      if (ret)
>          enable_irq(client->irq);
> [...]
> }
> 
> First, close() does not exist in this driver. Of course this can be
> fixed. Then it doesn't return a value. Then, if either taking the
> mutex or disabling the power fails, the close() is still deemed
> successful. Is it ok?

Note I also mentioned another solution for the error propagation,
which would require a big "flag day" commit adding "return 0"
to all existing close callbacks, but otherwise should work for your
purposes:

 > Well, we could make close() return an error and at least in the inhibit()
 > case propagate that to userspace. I wonder if userspace is going to
 > do anything useful with that error though...

And I guess we could log an error that close failed in the old close() path
where we cannot propagate the error.

Also why the mutex_lock_interruptible() ?  If you change that to
a normal mutex_lock() you loose one of the possible 2 error cases and
I doubt anyone is going to do a CTRL-C of the process doing the
inhibiting (or that that process starts a timer using a signal
to ensure the inhibit does not take to long or some such).

Regards,

Hans


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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-18  2:40       ` Dmitry Torokhov
  2020-05-18  7:36         ` Hans de Goede
@ 2020-05-22 15:35         ` Andrzej Pietrasiewicz
  2020-05-27  6:13           ` Peter Hutterer
  1 sibling, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-05-22 15:35 UTC (permalink / raw)
  To: Dmitry Torokhov, Peter Hutterer
  Cc: Hans de Goede, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi Hans, hi Dmitry,

W dniu 18.05.2020 o 04:40, Dmitry Torokhov pisze:
> Hi Hans, Peter,
> 
> On Mon, May 18, 2020 at 08:55:10AM +1000, Peter Hutterer wrote:
>> On Fri, May 15, 2020 at 08:19:10PM +0200, Hans de Goede wrote:
>>> Hi Andrezj,
>>>

<snip>

>>
>>> I also noticed that you keep the device open (do not call the
>>> input_device's close callback) when inhibited and just throw away
>>> any events generated. This seems inefficient and may lead to
>>> the internal state getting out of sync. What if a key is pressed
>>> while inhibited and then the device is uninhibited while the key
>>> is still pressed?  Now the press event is lost and userspace
>>> querying the current state will see the pressed key as being
>>> released.
> 
> This is a good point. We should look into signalling that some events
> have been dropped (via EV_SYN/SYN_DROPPED) so that clients are aware of
> it.
> 

It seems to me that the situation Hans envisions is not possible,
or will not be possible with a simple change. Let me explain.

For a start, let's recall that the input core prevents consecutive
events of the same kind (type _and_ code _and_ value) from being
delivered to handlers. The decision is made in input_get_disposition().
For EV_KEY it is:

		if (is_event_supported(code, dev->keybit, KEY_MAX)) {

			/* auto-repeat bypasses state updates */
			if (value == 2) {
				disposition = INPUT_PASS_TO_HANDLERS;
				break;
			}

			if (!!test_bit(code, dev->key) != !!value) {

				__change_bit(code, dev->key);
				disposition = INPUT_PASS_TO_HANDLERS;
			}
		}

Let's now focus on value != 2 (events other than auto-repeat).
The disposition changes from the default INPUT_IGNORE_EVENT to
INPUT_PASS_TO_HANDLERS only when the event in question changes
the current state: either by releasing a pressed key, or by
pressing a released key. Subsequent releases of a released key
or subsequent presses of a pressed key will be ignored.

What Hans points out is the possibility of uninhibiting a device
while its key is pressed and then releasing the key. First of all,
during inhibiting input_dev_release_keys() is called, so input_dev's
internal state will be cleared of all pressed keys. Then the device
- after being uninhibited - all of a sudden produces a key release
event. It will be ignored as per the "subsequent releases of a
released key" case, so the handlers will not be passed an unmatched
key release event. Assuming that passing an unmatched key release
event was Hans's concern, in this case it seems impossible.

Now, the value of 2 (auto-repeat) needs some attention. There are two
cases to consider: the device uses input core's software repeat or it
uses its own (hardware) repeat.

Let's consider the first case. The timer which generates auto-repeat
is only started on a key press event and only stopped on a key release
event. As such, if any auto-repeat was in progress when inhibiting
happened, it must have been stopped as per input_dev_release_keys().
Then the key is pressed and held after the device has been inhibited,
and the device is being uninhibited. Since it uses software auto-repeat,
no events will be reported by the device until the key is released,
and, as explained above, the release event will be ignored.

Let's consider the second case. The key is pressed and held after the
device has been inhibited and the device is being uninhibited. The worst
thing that can happen is unmatched key repeat events will start coming
from the device. We must prevent them from reaching the handlers and
ignore them instead. So I suggest something on the lines of:

if (is_event_supported(code, dev->keybit, KEY_MAX)) {

			/* auto-repeat bypasses state updates */
-			if (value == 2) {
+			if (value == 2 && test_bit(code, dev->key)) {
				disposition = INPUT_PASS_TO_HANDLERS;
				break;
			}

The intended meaning is "ignore key repeat events if the key is not
pressed".

With this small change I believe it is not possible to have neither
unmatched release nor unmatched repeat being delivered to handlers.

Regards,

Andrzej

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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-22 15:35         ` Andrzej Pietrasiewicz
@ 2020-05-27  6:13           ` Peter Hutterer
  0 siblings, 0 replies; 80+ messages in thread
From: Peter Hutterer @ 2020-05-27  6:13 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz
  Cc: Dmitry Torokhov, Hans de Goede, linux-input, linux-acpi,
	linux-iio, linux-arm-kernel, linux-samsung-soc, linux-tegra,
	patches, ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi Andrzej,

On Fri, May 22, 2020 at 05:35:56PM +0200, Andrzej Pietrasiewicz wrote:
> Hi Hans, hi Dmitry,
> 
> W dniu 18.05.2020 o 04:40, Dmitry Torokhov pisze:
> > Hi Hans, Peter,
> > 
> > On Mon, May 18, 2020 at 08:55:10AM +1000, Peter Hutterer wrote:
> > > On Fri, May 15, 2020 at 08:19:10PM +0200, Hans de Goede wrote:
> > > > Hi Andrezj,
> > > > 
> 
> <snip>
> 
> > > 
> > > > I also noticed that you keep the device open (do not call the
> > > > input_device's close callback) when inhibited and just throw away
> > > > any events generated. This seems inefficient and may lead to
> > > > the internal state getting out of sync. What if a key is pressed
> > > > while inhibited and then the device is uninhibited while the key
> > > > is still pressed?  Now the press event is lost and userspace
> > > > querying the current state will see the pressed key as being
> > > > released.
> > 
> > This is a good point. We should look into signalling that some events
> > have been dropped (via EV_SYN/SYN_DROPPED) so that clients are aware of
> > it.
> > 
> 
> It seems to me that the situation Hans envisions is not possible,
> or will not be possible with a simple change. Let me explain.
> 
> For a start, let's recall that the input core prevents consecutive
> events of the same kind (type _and_ code _and_ value) from being
> delivered to handlers. The decision is made in input_get_disposition().
> For EV_KEY it is:
> 
> 		if (is_event_supported(code, dev->keybit, KEY_MAX)) {
> 
> 			/* auto-repeat bypasses state updates */
> 			if (value == 2) {
> 				disposition = INPUT_PASS_TO_HANDLERS;
> 				break;
> 			}
> 
> 			if (!!test_bit(code, dev->key) != !!value) {
> 
> 				__change_bit(code, dev->key);
> 				disposition = INPUT_PASS_TO_HANDLERS;
> 			}
> 		}

note that this isn't per-process state, userspace can get release events
after open() for keys it never got the press event for. Simple test:
type evtest<enter> and KEY_ENTER up is the first event you'll get.

But otherwise I agree with you that press/release should always be balanced
if input_dev_release_keys() is called on inhibit and with that autorepeat
snippet below. At least I couldn't come up with any combination of multiple
clients opening/closing/inhibiting that resulted in an unwanted release
event after uninhibit.

Cheers,
   Peter

> Let's now focus on value != 2 (events other than auto-repeat).
> The disposition changes from the default INPUT_IGNORE_EVENT to
> INPUT_PASS_TO_HANDLERS only when the event in question changes
> the current state: either by releasing a pressed key, or by
> pressing a released key. Subsequent releases of a released key
> or subsequent presses of a pressed key will be ignored.
>
> What Hans points out is the possibility of uninhibiting a device
> while its key is pressed and then releasing the key. First of all,
> during inhibiting input_dev_release_keys() is called, so input_dev's
> internal state will be cleared of all pressed keys. Then the device
> - after being uninhibited - all of a sudden produces a key release
> event. It will be ignored as per the "subsequent releases of a
> released key" case, so the handlers will not be passed an unmatched
> key release event. Assuming that passing an unmatched key release
> event was Hans's concern, in this case it seems impossible.
> 
> Now, the value of 2 (auto-repeat) needs some attention. There are two
> cases to consider: the device uses input core's software repeat or it
> uses its own (hardware) repeat.
> 
> Let's consider the first case. The timer which generates auto-repeat
> is only started on a key press event and only stopped on a key release
> event. As such, if any auto-repeat was in progress when inhibiting
> happened, it must have been stopped as per input_dev_release_keys().
> Then the key is pressed and held after the device has been inhibited,
> and the device is being uninhibited. Since it uses software auto-repeat,
> no events will be reported by the device until the key is released,
> and, as explained above, the release event will be ignored.
> 
> Let's consider the second case. The key is pressed and held after the
> device has been inhibited and the device is being uninhibited. The worst
> thing that can happen is unmatched key repeat events will start coming
> from the device. We must prevent them from reaching the handlers and
> ignore them instead. So I suggest something on the lines of:
> 
> if (is_event_supported(code, dev->keybit, KEY_MAX)) {
> 
> 			/* auto-repeat bypasses state updates */
> -			if (value == 2) {
> +			if (value == 2 && test_bit(code, dev->key)) {
> 				disposition = INPUT_PASS_TO_HANDLERS;
> 				break;
> 			}
> 
> The intended meaning is "ignore key repeat events if the key is not
> pressed".
> 
> With this small change I believe it is not possible to have neither
> unmatched release nor unmatched repeat being delivered to handlers.
> 
> Regards,
> 
> Andrzej

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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-19  9:36               ` Hans de Goede
@ 2020-05-27  6:34                 ` Dmitry Torokhov
  2020-06-02 16:56                   ` Andrzej Pietrasiewicz
  0 siblings, 1 reply; 80+ messages in thread
From: Dmitry Torokhov @ 2020-05-27  6:34 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Andrzej Pietrasiewicz, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

On Tue, May 19, 2020 at 11:36:34AM +0200, Hans de Goede wrote:
> Hi,
> 
> On 5/19/20 11:02 AM, Andrzej Pietrasiewicz wrote:
> > Hi Hans, Hi Dmitry,
> > 
> > W dniu 18.05.2020 o 16:23, Hans de Goede pisze:
> > > Hi,
> > 
> > <snip>
> > 
> > > > > > > 
> > > > > > > So I wonder what this series actually adds for functionality for
> > > > > > > userspace which can not already be achieved this way?
> > > > > > > 
> > > > > > > I also noticed that you keep the device open (do not call the
> > > > > > > input_device's close callback) when inhibited and just throw away
> > > > > > 
> > > > > > I'm not sure if I understand you correctly, it is called:
> > > > > > 
> > > > > > +static inline void input_stop(struct input_dev *dev)
> > > > > > +{
> > > > > > +    if (dev->poller)
> > > > > > +        input_dev_poller_stop(dev->poller);
> > > > > > +    if (dev->close)
> > > > > > +        dev->close(dev);
> > > > > >                  ^^^^^^^^^^^^^^^^
> > > > > > +static int input_inhibit(struct input_dev *dev)
> > > > > > +{
> > > > > > +    int ret = 0;
> > > > > > +
> > > > > > +    mutex_lock(&dev->mutex);
> > > > > > +
> > > > > > +    if (dev->inhibited)
> > > > > > +        goto out;
> > > > > > +
> > > > > > +    if (dev->users) {
> > > > > > +        if (dev->inhibit) {
> > > > > > +            ret = dev->inhibit(dev);
> > > > > > +            if (ret)
> > > > > > +                goto out;
> > > > > > +        }
> > > > > > +        input_stop(dev);
> > > > > >                  ^^^^^^^^^^^^^^^^
> > > > > > 
> > > > > > It will not be called when dev->users is zero, but if it is zero,
> > > > > > then nobody has opened the device yet so there is nothing to close.
> > > > > 
> > > > > Ah, I missed that.
> > > > > 
> > > > > So if the device implements the inhibit call back then on
> > > > > inhibit it will get both the inhibit and close callback called?
> > > > > 
> > > > 
> > > > That's right. And conversely, upon uninhibit open() and uninhibit()
> > > > callbacks will be invoked. Please note that just as with open()/close(),
> > > > providing inhibit()/uninhibit() is optional.
> > > 
> > > Ack.
> > > 
> > > > > And what happens if the last user goes away and the device
> > > > > is not inhibited?
> > > > 
> > > > close() is called as usually.
> > > 
> > > But not inhibit, hmm, see below.
> > > 
> > > > > I'm trying to understand here what the difference between the 2
> > > > > is / what the goal of having a separate inhibit callback ?
> > > > > 
> > > > 
> > > > Drivers have very different ideas about what it means to suspend/resume
> > > > and open/close. The optional inhibit/uninhibit callbacks are meant for
> > > > the drivers to know that it is this particular action going on.
> > > 
> > > So the inhibit() callback triggers the "suspend" behavior ?
> > > But shouldn't drivers which are capable of suspending the device
> > > always do so on close() ?
> > > 
> > > Since your current proposal also calls close() on inhibit() I
> > > really see little difference between an inhibit() and the last
> > > user of the device closing it and IMHO unless there is a good
> > > reason to actually differentiate the 2 it would be better
> > > to only stick with the existing close() and in cases where
> > > that does not put the device in a low-power mode yet, fix
> > > the existing close() callback to do the low-power mode
> > > setting instead of adding a new callback.
> > > 
> > > > For inhibit() there's one more argument: close() does not return a value,
> > > > so its meaning is "do some last cleanup" and as such it is not allowed
> > > > to fail - whatever its effect is, we must deem it successful. inhibit()
> > > > does return a value and so it is allowed to fail.
> > > 
> > > Well, we could make close() return an error and at least in the inhibit()
> > > case propagate that to userspace. I wonder if userspace is going to
> > > do anything useful with that error though...

It really can't do anything. Have you ever seen userspace handling
errors from close()? And what can be done? A program is terminating, but
the kernel says "no, you closing input device failed, you have to
continue running indefinitely..."

> > > 
> > > In my experience errors during cleanup/shutdown are best logged
> > > (using dev_err) and otherwise ignored, so that we try to clean up
> > > as much possible. Unless the very first step of the shutdown process
> > > fails the device is going to be in some twilight zone state anyways
> > > at this point we might as well try to cleanup as much as possible.
> > 
> > What you say makes sense to me.
> > @Dmitry?

I will note here, that inhibit is closer to suspend() than to close(),
and we do report errors for suspend(). Therefore we could conceivably
try to handle errors if driver really wants to be fancy. But I think
majority of cases will be quite happy with using close() and simply
logging errors, as Hans said.

That said, I think the way we should handle inhibit/uninhibit, is that
if we have the callback defined, then we call it, and only call open and
close if uninhibit or inhibit are _not_ defined.

> > 
> > > 
> > > > All in all, it is up to the drivers to decide which callback they
> > > > provide. Based on my work so far I would say that there are tens
> > > > of simple cases where open() and close() are sufficient, out of total
> > > > ~400 users of input_allocate_device():
> > > > 
> > > > $ git grep "input_allocate_device(" | grep -v ^Documentation | \
> > > > cut -f1 -d: | sort | uniq | wc
> > > >      390     390   13496
> > > 
> > > So can you explain a bit more about the cases where only having
> > > open/close is not sufficient?  So far I have the feeling that
> > > those are all we need and that we really do not need separate
> > > [un]inhibit callbacks.
> > 
> > My primary concern was not being able to propagate inhibit() error
> > to userspace, and then if we have inhibit(), uninhibit() should be
> > there for completeness. If propagating the error to userspace can
> > be neglected then yes, it seems open/close should be sufficient,
> > even more because the real meaning of "open" is "prepare the device
> > for generating input events".
> > 
> > To validate the idea of not introducing inhibit()/uninhibit() callbacks
> > to implement device inhibiting/uninhibiting let's look at
> > drivers/input/mouse/elan_i2c_core.c (PATCH 7/7):
> > 
> > static int elan_inhibit(struct input_dev *input)
> > {
> > [...]
> > 
> >      ret = mutex_lock_interruptible(&data->sysfs_mutex);
> >      if (ret)
> >          return ret;
> > 
> >      disable_irq(client->irq);
> > 
> >      ret = elan_disable_power(data);
> >      if (ret)
> >          enable_irq(client->irq);
> > [...]
> > }
> > 
> > First, close() does not exist in this driver. Of course this can be
> > fixed. Then it doesn't return a value. Then, if either taking the
> > mutex or disabling the power fails, the close() is still deemed
> > successful. Is it ok?
> 
> Note I also mentioned another solution for the error propagation,
> which would require a big "flag day" commit adding "return 0"
> to all existing close callbacks, but otherwise should work for your
> purposes:

No, please, no flag days and no changing close() to return error, it
makes no sense for close().

> 
> > Well, we could make close() return an error and at least in the inhibit()
> > case propagate that to userspace. I wonder if userspace is going to
> > do anything useful with that error though...
> 
> And I guess we could log an error that close failed in the old close() path
> where we cannot propagate the error.
> 
> Also why the mutex_lock_interruptible() ?  If you change that to
> a normal mutex_lock() you loose one of the possible 2 error cases and
> I doubt anyone is going to do a CTRL-C of the process doing the
> inhibiting (or that that process starts a timer using a signal
> to ensure the inhibit does not take to long or some such).

Well, we have the dedicated callbacks in Chrome OS, so when I did the
patch I could even handle Ctrl-C, so why not? But it indeed can easily
be dropped in favor of straight mutex_lock().

Thanks.

-- 
Dmitry

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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-05-27  6:34                 ` Dmitry Torokhov
@ 2020-06-02 16:56                   ` Andrzej Pietrasiewicz
  2020-06-02 17:52                     ` Dmitry Torokhov
  0 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-02 16:56 UTC (permalink / raw)
  To: Dmitry Torokhov, Hans de Goede
  Cc: linux-input, linux-acpi, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-tegra, patches, ibm-acpi-devel,
	platform-driver-x86, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi Dmitry,

W dniu 27.05.2020 o 08:34, Dmitry Torokhov pisze:
> On Tue, May 19, 2020 at 11:36:34AM +0200, Hans de Goede wrote:
>> Hi,
>>
>> On 5/19/20 11:02 AM, Andrzej Pietrasiewicz wrote:
>>> Hi Hans, Hi Dmitry,
>>>
>>> W dniu 18.05.2020 o 16:23, Hans de Goede pisze:
>>>> Hi,
>>>
>>> <snip>
>>>
>>>>>>>>
>>>>>>>> So I wonder what this series actually adds for functionality for
>>>>>>>> userspace which can not already be achieved this way?
>>>>>>>>
>>>>>>>> I also noticed that you keep the device open (do not call the
>>>>>>>> input_device's close callback) when inhibited and just throw away
>>>>>>>
>>>>>>> I'm not sure if I understand you correctly, it is called:
>>>>>>>
>>>>>>> +static inline void input_stop(struct input_dev *dev)
>>>>>>> +{
>>>>>>> +    if (dev->poller)
>>>>>>> +        input_dev_poller_stop(dev->poller);
>>>>>>> +    if (dev->close)
>>>>>>> +        dev->close(dev);
>>>>>>>                   ^^^^^^^^^^^^^^^^
>>>>>>> +static int input_inhibit(struct input_dev *dev)
>>>>>>> +{
>>>>>>> +    int ret = 0;
>>>>>>> +
>>>>>>> +    mutex_lock(&dev->mutex);
>>>>>>> +
>>>>>>> +    if (dev->inhibited)
>>>>>>> +        goto out;
>>>>>>> +
>>>>>>> +    if (dev->users) {
>>>>>>> +        if (dev->inhibit) {
>>>>>>> +            ret = dev->inhibit(dev);
>>>>>>> +            if (ret)
>>>>>>> +                goto out;
>>>>>>> +        }
>>>>>>> +        input_stop(dev);
>>>>>>>                   ^^^^^^^^^^^^^^^^
>>>>>>>
>>>>>>> It will not be called when dev->users is zero, but if it is zero,
>>>>>>> then nobody has opened the device yet so there is nothing to close.
>>>>>>
>>>>>> Ah, I missed that.
>>>>>>
>>>>>> So if the device implements the inhibit call back then on
>>>>>> inhibit it will get both the inhibit and close callback called?
>>>>>>
>>>>>
>>>>> That's right. And conversely, upon uninhibit open() and uninhibit()
>>>>> callbacks will be invoked. Please note that just as with open()/close(),
>>>>> providing inhibit()/uninhibit() is optional.
>>>>
>>>> Ack.
>>>>
>>>>>> And what happens if the last user goes away and the device
>>>>>> is not inhibited?
>>>>>
>>>>> close() is called as usually.
>>>>
>>>> But not inhibit, hmm, see below.
>>>>
>>>>>> I'm trying to understand here what the difference between the 2
>>>>>> is / what the goal of having a separate inhibit callback ?
>>>>>>
>>>>>
>>>>> Drivers have very different ideas about what it means to suspend/resume
>>>>> and open/close. The optional inhibit/uninhibit callbacks are meant for
>>>>> the drivers to know that it is this particular action going on.
>>>>
>>>> So the inhibit() callback triggers the "suspend" behavior ?
>>>> But shouldn't drivers which are capable of suspending the device
>>>> always do so on close() ?
>>>>
>>>> Since your current proposal also calls close() on inhibit() I
>>>> really see little difference between an inhibit() and the last
>>>> user of the device closing it and IMHO unless there is a good
>>>> reason to actually differentiate the 2 it would be better
>>>> to only stick with the existing close() and in cases where
>>>> that does not put the device in a low-power mode yet, fix
>>>> the existing close() callback to do the low-power mode
>>>> setting instead of adding a new callback.
>>>>
>>>>> For inhibit() there's one more argument: close() does not return a value,
>>>>> so its meaning is "do some last cleanup" and as such it is not allowed
>>>>> to fail - whatever its effect is, we must deem it successful. inhibit()
>>>>> does return a value and so it is allowed to fail.
>>>>
>>>> Well, we could make close() return an error and at least in the inhibit()
>>>> case propagate that to userspace. I wonder if userspace is going to
>>>> do anything useful with that error though...
> 
> It really can't do anything. Have you ever seen userspace handling
> errors from close()? And what can be done? A program is terminating, but
> the kernel says "no, you closing input device failed, you have to
> continue running indefinitely..."
> 
>>>>
>>>> In my experience errors during cleanup/shutdown are best logged
>>>> (using dev_err) and otherwise ignored, so that we try to clean up
>>>> as much possible. Unless the very first step of the shutdown process
>>>> fails the device is going to be in some twilight zone state anyways
>>>> at this point we might as well try to cleanup as much as possible.
>>>
>>> What you say makes sense to me.
>>> @Dmitry?
> 
> I will note here, that inhibit is closer to suspend() than to close(),
> and we do report errors for suspend(). Therefore we could conceivably
> try to handle errors if driver really wants to be fancy. But I think
> majority of cases will be quite happy with using close() and simply
> logging errors, as Hans said.
> 
> That said, I think the way we should handle inhibit/uninhibit, is that
> if we have the callback defined, then we call it, and only call open and
> close if uninhibit or inhibit are _not_ defined.
> 

If I understand you correctly you suggest to call either inhibit,
if provided or close, if inhibit is not provided, but not both,
that is, if both are provided then on the inhibit path only
inhibit is called. And, consequently, you suggest to call either
uninhibit or open, but not both. The rest of my mail makes this
assumption, so kindly confirm if I understand you correctly.

In my opinion this idea will not work.

The first question is should we be able to inhibit a device
which is not opened? In my opinion we should, in order to be
able to inhibit a device in anticipation without needing to
open it first.

Then what does opening (with input_open_device()) an inhibited
device mean? Should it succeed or should it fail? If it is not
the first opening then effectively it boils down to increasing
device's and handle's counters, so we can allow it to succeed.
If, however, the device is being opened for the first time,
the ->open() method wants to be called, but that somehow
contradicts the device's inhibited state. So a logical thing
to do is to either fail input_open_device() or postpone ->open()
invocation to the moment of uninhibiting - and the latter is
what the patches in this series currently do.

Failing input_open_device() because of the inhibited state is
not the right thing to do. Let me explain. Suppose that a device
is already inhibited and then a new matching handler appears
in the system. Most handlers (apm-power.c, evbug.c, input-leds.c,
mac_hid.c, sysrq.c, vt/keyboard.c and rfkill/input.c) don't create
any character devices (only evdev.c, joydev.c and mousedev.c do),
so for them it makes no sense to delay calling input_open_device()
and it is called in handler's ->connect(). If input_open_device()
now fails, we have lost the only chance for this ->connect() to
succeed.

Summarizing, IMO the uninhibit path should be calling both
->open() and ->uninhibit() (if provided), and conversely, the inhibit
path should be calling both ->inhibit() and ->close() (if provided).

What's your opinion?

Regards,

Andrzej

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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-06-02 16:56                   ` Andrzej Pietrasiewicz
@ 2020-06-02 17:52                     ` Dmitry Torokhov
  2020-06-02 18:50                       ` Andrzej Pietrasiewicz
  0 siblings, 1 reply; 80+ messages in thread
From: Dmitry Torokhov @ 2020-06-02 17:52 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz
  Cc: Hans de Goede, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi Andrzej,

On Tue, Jun 02, 2020 at 06:56:40PM +0200, Andrzej Pietrasiewicz wrote:
> Hi Dmitry,
> 
> W dniu 27.05.2020 o 08:34, Dmitry Torokhov pisze:
> > That said, I think the way we should handle inhibit/uninhibit, is that
> > if we have the callback defined, then we call it, and only call open and
> > close if uninhibit or inhibit are _not_ defined.
> > 
> 
> If I understand you correctly you suggest to call either inhibit,
> if provided or close, if inhibit is not provided, but not both,
> that is, if both are provided then on the inhibit path only
> inhibit is called. And, consequently, you suggest to call either
> uninhibit or open, but not both. The rest of my mail makes this
> assumption, so kindly confirm if I understand you correctly.

Yes, that is correct. If a driver wants really fine-grained control, it
will provide inhibit (or both inhibit and close), otherwise it will rely
on close in place of inhibit.

> 
> In my opinion this idea will not work.
> 
> The first question is should we be able to inhibit a device
> which is not opened? In my opinion we should, in order to be
> able to inhibit a device in anticipation without needing to
> open it first.

I agree.

> 
> Then what does opening (with input_open_device()) an inhibited
> device mean? Should it succeed or should it fail?

It should succeed.

> If it is not
> the first opening then effectively it boils down to increasing
> device's and handle's counters, so we can allow it to succeed.
> If, however, the device is being opened for the first time,
> the ->open() method wants to be called, but that somehow
> contradicts the device's inhibited state. So a logical thing
> to do is to either fail input_open_device() or postpone ->open()
> invocation to the moment of uninhibiting - and the latter is
> what the patches in this series currently do.
> 
> Failing input_open_device() because of the inhibited state is
> not the right thing to do. Let me explain. Suppose that a device
> is already inhibited and then a new matching handler appears
> in the system. Most handlers (apm-power.c, evbug.c, input-leds.c,
> mac_hid.c, sysrq.c, vt/keyboard.c and rfkill/input.c) don't create
> any character devices (only evdev.c, joydev.c and mousedev.c do),
> so for them it makes no sense to delay calling input_open_device()
> and it is called in handler's ->connect(). If input_open_device()
> now fails, we have lost the only chance for this ->connect() to
> succeed.
> 
> Summarizing, IMO the uninhibit path should be calling both
> ->open() and ->uninhibit() (if provided), and conversely, the inhibit
> path should be calling both ->inhibit() and ->close() (if provided).

So what you are trying to say is that you see inhibit as something that
is done in addition to what happens in close. But what exactly do you
want to do in inhibit, in addition to what close is doing?

In my view, if we want to have a dedicated inhibit callback, then it
will do everything that close does, they both are aware of each other
and can sort out the state transitions between them. For drivers that do
not have dedicated inhibit/uninhibit, we can use open and close
handlers, and have input core sort out when each should be called. That
means that we should not call dev->open() in input_open_device() when
device is inhibited (and same for dev->close() in input_close_device).
And when uninhibiting, we should not call dev->open() when there are no
users for the device, and no dev->close() when inhibiting with no users.

Do you see any problems with this approach?

Thanks.

-- 
Dmitry

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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-06-02 17:52                     ` Dmitry Torokhov
@ 2020-06-02 18:50                       ` Andrzej Pietrasiewicz
  2020-06-02 20:19                         ` Hans de Goede
  0 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-02 18:50 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Hans de Goede, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi Dmitry,

W dniu 02.06.2020 o 19:52, Dmitry Torokhov pisze:
> Hi Andrzej,
> 
> On Tue, Jun 02, 2020 at 06:56:40PM +0200, Andrzej Pietrasiewicz wrote:
>> Hi Dmitry,
>>
>> W dniu 27.05.2020 o 08:34, Dmitry Torokhov pisze:
>>> That said, I think the way we should handle inhibit/uninhibit, is that
>>> if we have the callback defined, then we call it, and only call open and
>>> close if uninhibit or inhibit are _not_ defined.
>>>
>>
>> If I understand you correctly you suggest to call either inhibit,
>> if provided or close, if inhibit is not provided, but not both,
>> that is, if both are provided then on the inhibit path only
>> inhibit is called. And, consequently, you suggest to call either
>> uninhibit or open, but not both. The rest of my mail makes this
>> assumption, so kindly confirm if I understand you correctly.
> 
> Yes, that is correct. If a driver wants really fine-grained control, it
> will provide inhibit (or both inhibit and close), otherwise it will rely
> on close in place of inhibit.
> 
>>
>> In my opinion this idea will not work.
>>
>> The first question is should we be able to inhibit a device
>> which is not opened? In my opinion we should, in order to be
>> able to inhibit a device in anticipation without needing to
>> open it first.
> 
> I agree.
> 
>>
>> Then what does opening (with input_open_device()) an inhibited
>> device mean? Should it succeed or should it fail?
> 
> It should succeed.
> 
>> If it is not
>> the first opening then effectively it boils down to increasing
>> device's and handle's counters, so we can allow it to succeed.
>> If, however, the device is being opened for the first time,
>> the ->open() method wants to be called, but that somehow
>> contradicts the device's inhibited state. So a logical thing
>> to do is to either fail input_open_device() or postpone ->open()
>> invocation to the moment of uninhibiting - and the latter is
>> what the patches in this series currently do.
>>
>> Failing input_open_device() because of the inhibited state is
>> not the right thing to do. Let me explain. Suppose that a device
>> is already inhibited and then a new matching handler appears
>> in the system. Most handlers (apm-power.c, evbug.c, input-leds.c,
>> mac_hid.c, sysrq.c, vt/keyboard.c and rfkill/input.c) don't create
>> any character devices (only evdev.c, joydev.c and mousedev.c do),
>> so for them it makes no sense to delay calling input_open_device()
>> and it is called in handler's ->connect(). If input_open_device()
>> now fails, we have lost the only chance for this ->connect() to
>> succeed.
>>
>> Summarizing, IMO the uninhibit path should be calling both
>> ->open() and ->uninhibit() (if provided), and conversely, the inhibit
>> path should be calling both ->inhibit() and ->close() (if provided).
> 
> So what you are trying to say is that you see inhibit as something that
> is done in addition to what happens in close. But what exactly do you
> want to do in inhibit, in addition to what close is doing?

See below (*).

> 
> In my view, if we want to have a dedicated inhibit callback, then it
> will do everything that close does, they both are aware of each other
> and can sort out the state transitions between them. For drivers that do
> not have dedicated inhibit/uninhibit, we can use open and close
> handlers, and have input core sort out when each should be called. That
> means that we should not call dev->open() in input_open_device() when
> device is inhibited (and same for dev->close() in input_close_device).
> And when uninhibiting, we should not call dev->open() when there are no
> users for the device, and no dev->close() when inhibiting with no users.
> 
> Do you see any problems with this approach?

My concern is that if e.g. both ->open() and ->uninhibit() are provided,
then in certain circumstances ->open() won't be called:

1. users == 0
2. inhibit happens
3. input_open_device() happens, ->open() not called
4. uninhibit happens
5. as part of uninhibit ->uninhibit() is only called, but ->open() is not.

They way I understand your answer is that we implicitly impose requirements
on drivers which choose to implement e.g. both ->open() and ->uninhibit():
in such a case ->uninhibit() should be doing exactly the same things as
->open() does. Which leads to a conclusion that in practice no drivers
should choose to implement both, otherwise they must be aware that
->uninhibit() can be sometimes called instead of ->open(). Then ->open()
becomes synonymous with ->uninhibit(), and ->close() with ->inhibit().
Or, maybe, then ->inhibit() can be a superset of ->close() and
->uninhibit() a superset of ->open().

If such an approach is ok with you, it is ok with me, too.

(*)
Calling both ->inhibit() and ->close() (if they are provided) allows
drivers to go fancy and fail inhibiting (which is impossible using
only ->close() as it does not return a value, but ->inhibit() by design
does). Then ->uninhibit() is mostly for symmetry.

Regards,

Andrzej

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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-06-02 18:50                       ` Andrzej Pietrasiewicz
@ 2020-06-02 20:19                         ` Hans de Goede
  2020-06-03 13:07                           ` Andrzej Pietrasiewicz
  0 siblings, 1 reply; 80+ messages in thread
From: Hans de Goede @ 2020-06-02 20:19 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, Dmitry Torokhov
  Cc: linux-input, linux-acpi, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-tegra, patches, ibm-acpi-devel,
	platform-driver-x86, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi,

On 6/2/20 8:50 PM, Andrzej Pietrasiewicz wrote:
> Hi Dmitry,
> 
> W dniu 02.06.2020 o 19:52, Dmitry Torokhov pisze:
>> Hi Andrzej,
>>
>> On Tue, Jun 02, 2020 at 06:56:40PM +0200, Andrzej Pietrasiewicz wrote:
>>> Hi Dmitry,
>>>
>>> W dniu 27.05.2020 o 08:34, Dmitry Torokhov pisze:
>>>> That said, I think the way we should handle inhibit/uninhibit, is that
>>>> if we have the callback defined, then we call it, and only call open and
>>>> close if uninhibit or inhibit are _not_ defined.
>>>>
>>>
>>> If I understand you correctly you suggest to call either inhibit,
>>> if provided or close, if inhibit is not provided, but not both,
>>> that is, if both are provided then on the inhibit path only
>>> inhibit is called. And, consequently, you suggest to call either
>>> uninhibit or open, but not both. The rest of my mail makes this
>>> assumption, so kindly confirm if I understand you correctly.
>>
>> Yes, that is correct. If a driver wants really fine-grained control, it
>> will provide inhibit (or both inhibit and close), otherwise it will rely
>> on close in place of inhibit.
>>
>>>
>>> In my opinion this idea will not work.
>>>
>>> The first question is should we be able to inhibit a device
>>> which is not opened? In my opinion we should, in order to be
>>> able to inhibit a device in anticipation without needing to
>>> open it first.
>>
>> I agree.
>>
>>>
>>> Then what does opening (with input_open_device()) an inhibited
>>> device mean? Should it succeed or should it fail?
>>
>> It should succeed.
>>
>>> If it is not
>>> the first opening then effectively it boils down to increasing
>>> device's and handle's counters, so we can allow it to succeed.
>>> If, however, the device is being opened for the first time,
>>> the ->open() method wants to be called, but that somehow
>>> contradicts the device's inhibited state. So a logical thing
>>> to do is to either fail input_open_device() or postpone ->open()
>>> invocation to the moment of uninhibiting - and the latter is
>>> what the patches in this series currently do.
>>>
>>> Failing input_open_device() because of the inhibited state is
>>> not the right thing to do. Let me explain. Suppose that a device
>>> is already inhibited and then a new matching handler appears
>>> in the system. Most handlers (apm-power.c, evbug.c, input-leds.c,
>>> mac_hid.c, sysrq.c, vt/keyboard.c and rfkill/input.c) don't create
>>> any character devices (only evdev.c, joydev.c and mousedev.c do),
>>> so for them it makes no sense to delay calling input_open_device()
>>> and it is called in handler's ->connect(). If input_open_device()
>>> now fails, we have lost the only chance for this ->connect() to
>>> succeed.
>>>
>>> Summarizing, IMO the uninhibit path should be calling both
>>> ->open() and ->uninhibit() (if provided), and conversely, the inhibit
>>> path should be calling both ->inhibit() and ->close() (if provided).
>>
>> So what you are trying to say is that you see inhibit as something that
>> is done in addition to what happens in close. But what exactly do you
>> want to do in inhibit, in addition to what close is doing?
> 
> See below (*).
> 
>>
>> In my view, if we want to have a dedicated inhibit callback, then it
>> will do everything that close does, they both are aware of each other
>> and can sort out the state transitions between them. For drivers that do
>> not have dedicated inhibit/uninhibit, we can use open and close
>> handlers, and have input core sort out when each should be called. That
>> means that we should not call dev->open() in input_open_device() when
>> device is inhibited (and same for dev->close() in input_close_device).
>> And when uninhibiting, we should not call dev->open() when there are no
>> users for the device, and no dev->close() when inhibiting with no users.
>>
>> Do you see any problems with this approach?
> 
> My concern is that if e.g. both ->open() and ->uninhibit() are provided,
> then in certain circumstances ->open() won't be called:
> 
> 1. users == 0
> 2. inhibit happens
> 3. input_open_device() happens, ->open() not called
> 4. uninhibit happens
> 5. as part of uninhibit ->uninhibit() is only called, but ->open() is not.
> 
> They way I understand your answer is that we implicitly impose requirements
> on drivers which choose to implement e.g. both ->open() and ->uninhibit():
> in such a case ->uninhibit() should be doing exactly the same things as
> ->open() does. Which leads to a conclusion that in practice no drivers
> should choose to implement both, otherwise they must be aware that
> ->uninhibit() can be sometimes called instead of ->open(). Then ->open()
> becomes synonymous with ->uninhibit(), and ->close() with ->inhibit().
> Or, maybe, then ->inhibit() can be a superset of ->close() and
> ->uninhibit() a superset of ->open().
> 
> If such an approach is ok with you, it is ok with me, too.
> 
> (*)
> Calling both ->inhibit() and ->close() (if they are provided) allows
> drivers to go fancy and fail inhibiting (which is impossible using
> only ->close() as it does not return a value, but ->inhibit() by design
> does). Then ->uninhibit() is mostly for symmetry.

All the complications discussed above are exactly why I still
believe that there should be only open and close.

If error propagation on inhibit is considered as something
really important to have then we can make the input driver close
callback return an error (*), note I'm talking about the
driver close callback here, not the system call.

If the close callback is called for actually closing the fd
referring to the input node, then the new error return code
can be ignored, as we already do for errors on close atm
since the driver close callback returns void.

I still have not seen a very convincing argument for having
separate inhibit and close callbacks and as the messy discussion
above shows, having 2 such very similar yet subtly different
calls seems like a bad idea...

Regards,

Hans


*) This will require a flag day where "return 0" is added
to all current close handlers


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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-06-02 20:19                         ` Hans de Goede
@ 2020-06-03 13:07                           ` Andrzej Pietrasiewicz
  2020-06-03 17:38                             ` Hans de Goede
  0 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-03 13:07 UTC (permalink / raw)
  To: Hans de Goede, Dmitry Torokhov
  Cc: linux-input, linux-acpi, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-tegra, patches, ibm-acpi-devel,
	platform-driver-x86, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi Hans, hi Dmitry,

W dniu 02.06.2020 o 22:19, Hans de Goede pisze:
> Hi,
> 
> On 6/2/20 8:50 PM, Andrzej Pietrasiewicz wrote:
>> Hi Dmitry,
>>
>> W dniu 02.06.2020 o 19:52, Dmitry Torokhov pisze:
>>> Hi Andrzej,
>>>
>>> On Tue, Jun 02, 2020 at 06:56:40PM +0200, Andrzej Pietrasiewicz wrote:
>>>> Hi Dmitry,
>>>>
>>>> W dniu 27.05.2020 o 08:34, Dmitry Torokhov pisze:
>>>>> That said, I think the way we should handle inhibit/uninhibit, is that
>>>>> if we have the callback defined, then we call it, and only call open and
>>>>> close if uninhibit or inhibit are _not_ defined.
>>>>>
>>>>
>>>> If I understand you correctly you suggest to call either inhibit,
>>>> if provided or close, if inhibit is not provided, but not both,
>>>> that is, if both are provided then on the inhibit path only
>>>> inhibit is called. And, consequently, you suggest to call either
>>>> uninhibit or open, but not both. The rest of my mail makes this
>>>> assumption, so kindly confirm if I understand you correctly.
>>>
>>> Yes, that is correct. If a driver wants really fine-grained control, it
>>> will provide inhibit (or both inhibit and close), otherwise it will rely
>>> on close in place of inhibit.
>>>
>>>>
>>>> In my opinion this idea will not work.
>>>>
>>>> The first question is should we be able to inhibit a device
>>>> which is not opened? In my opinion we should, in order to be
>>>> able to inhibit a device in anticipation without needing to
>>>> open it first.
>>>
>>> I agree.
>>>
>>>>
>>>> Then what does opening (with input_open_device()) an inhibited
>>>> device mean? Should it succeed or should it fail?
>>>
>>> It should succeed.
>>>
>>>> If it is not
>>>> the first opening then effectively it boils down to increasing
>>>> device's and handle's counters, so we can allow it to succeed.
>>>> If, however, the device is being opened for the first time,
>>>> the ->open() method wants to be called, but that somehow
>>>> contradicts the device's inhibited state. So a logical thing
>>>> to do is to either fail input_open_device() or postpone ->open()
>>>> invocation to the moment of uninhibiting - and the latter is
>>>> what the patches in this series currently do.
>>>>
>>>> Failing input_open_device() because of the inhibited state is
>>>> not the right thing to do. Let me explain. Suppose that a device
>>>> is already inhibited and then a new matching handler appears
>>>> in the system. Most handlers (apm-power.c, evbug.c, input-leds.c,
>>>> mac_hid.c, sysrq.c, vt/keyboard.c and rfkill/input.c) don't create
>>>> any character devices (only evdev.c, joydev.c and mousedev.c do),
>>>> so for them it makes no sense to delay calling input_open_device()
>>>> and it is called in handler's ->connect(). If input_open_device()
>>>> now fails, we have lost the only chance for this ->connect() to
>>>> succeed.
>>>>
>>>> Summarizing, IMO the uninhibit path should be calling both
>>>> ->open() and ->uninhibit() (if provided), and conversely, the inhibit
>>>> path should be calling both ->inhibit() and ->close() (if provided).
>>>
>>> So what you are trying to say is that you see inhibit as something that
>>> is done in addition to what happens in close. But what exactly do you
>>> want to do in inhibit, in addition to what close is doing?
>>
>> See below (*).
>>
>>>
>>> In my view, if we want to have a dedicated inhibit callback, then it
>>> will do everything that close does, they both are aware of each other
>>> and can sort out the state transitions between them. For drivers that do
>>> not have dedicated inhibit/uninhibit, we can use open and close
>>> handlers, and have input core sort out when each should be called. That
>>> means that we should not call dev->open() in input_open_device() when
>>> device is inhibited (and same for dev->close() in input_close_device).
>>> And when uninhibiting, we should not call dev->open() when there are no
>>> users for the device, and no dev->close() when inhibiting with no users.
>>>
>>> Do you see any problems with this approach?
>>
>> My concern is that if e.g. both ->open() and ->uninhibit() are provided,
>> then in certain circumstances ->open() won't be called:
>>
>> 1. users == 0
>> 2. inhibit happens
>> 3. input_open_device() happens, ->open() not called
>> 4. uninhibit happens
>> 5. as part of uninhibit ->uninhibit() is only called, but ->open() is not.
>>
>> They way I understand your answer is that we implicitly impose requirements
>> on drivers which choose to implement e.g. both ->open() and ->uninhibit():
>> in such a case ->uninhibit() should be doing exactly the same things as
>> ->open() does. Which leads to a conclusion that in practice no drivers
>> should choose to implement both, otherwise they must be aware that
>> ->uninhibit() can be sometimes called instead of ->open(). Then ->open()
>> becomes synonymous with ->uninhibit(), and ->close() with ->inhibit().
>> Or, maybe, then ->inhibit() can be a superset of ->close() and
>> ->uninhibit() a superset of ->open().
>>
>> If such an approach is ok with you, it is ok with me, too.
>>
>> (*)
>> Calling both ->inhibit() and ->close() (if they are provided) allows
>> drivers to go fancy and fail inhibiting (which is impossible using
>> only ->close() as it does not return a value, but ->inhibit() by design
>> does). Then ->uninhibit() is mostly for symmetry.
> 
> All the complications discussed above are exactly why I still
> believe that there should be only open and close.
> 
> If error propagation on inhibit is considered as something
> really important to have then we can make the input driver close
> callback return an error (*), note I'm talking about the
> driver close callback here, not the system call.
> 
> If the close callback is called for actually closing the fd
> referring to the input node, then the new error return code
> can be ignored, as we already do for errors on close atm
> since the driver close callback returns void.
> 
> I still have not seen a very convincing argument for having
> separate inhibit and close callbacks and as the messy discussion
> above shows, having 2 such very similar yet subtly different
> calls seems like a bad idea...
> 
> Regards,
> 
> Hans
> 
> 
> *) This will require a flag day where "return 0" is added
> to all current close handlers
> 

I'm taking one step back and looking at the ->open() and ->close()
driver callbacks. They are called from input_open_device() and
input_close_device(), respectively:

input_open_device():
"This function should be called by input handlers when they
want to start receive events from given input device."

->open() callback:
"this method is called when the very first user calls
input_open_device(). The driver must prepare the device to start
generating events (start polling thread, request an IRQ, submit
URB, etc.)"

input_close_device():
"This function should be called by input handlers when they
want to stop receive events from given input device."

->close() callback:
"this method is called when the very last user calls
input_close_device()"

It seems to me that the callback names do not reflect their
purpose: their meaning is not to "open" or to "close" but to
give drivers a chance to control when they start or stop
providing events to the input core.

What would you say about changing the callbacks' names?
I'd envsion: ->provide_events() instead of ->open() and
->stop_events() instead of ->close(). Of course drivers can
exploit the fact of knowing that nobody wants any events
from them and do whatever they consider appropriate, for
example go into a low power mode - but the latter is beyond
the scope of the input subsystem and is driver-specific.

With such a naming change in mind let's consider inhibiting.
We want to be able to control when to disregard events from
a given device. It makes sense to do it at device level, otherwise
such an operation would have to be invoked in all associated
handlers (those that have an open handle associating them with
the device in question). But of course we can do better than
merely ignoring the events received: we can tell the drivers
that we don't want any events from them, and later, at uninhibit
time, tell them to start providing the events again. Conceptually,
the two operations (provide or don't provide envents) are exactly
the same thing we want to be happening at input_open_device() and
input_close_device() time. To me, changing the names of
->open() and ->close() exposes this fact very well.

Consequently, ->inhibit() and ->uninhibit() won't be needed,
and drivers which already implement ->provide_events() (formerly
->open()) and ->stop_events() (formerly ->close()) will receive
full inhibit/uninhibit support for free (subject to how well they
implement ->provide_events()/->stop_events()). Unless we can come
up with what the drivers might be doing on top of ->stop_events()
and ->provide_events() when inhibiting/uninhibiting, but it seems
to me we can't. Can we?

Optionally ->close() (only the callback, not input_close_device())
can be made return a value, just as Hans suggests. The value
can be ignored in input_close_device() but used in input_inhibit().
No strong opinion here, though. (btw it seems to me that
input_inhibit() should be renamed to input_inhibit_device()).

Regards,

Andrzej

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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-06-03 13:07                           ` Andrzej Pietrasiewicz
@ 2020-06-03 17:38                             ` Hans de Goede
  2020-06-03 17:54                               ` Andrzej Pietrasiewicz
  0 siblings, 1 reply; 80+ messages in thread
From: Hans de Goede @ 2020-06-03 17:38 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, Dmitry Torokhov
  Cc: linux-input, linux-acpi, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-tegra, patches, ibm-acpi-devel,
	platform-driver-x86, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi,

On 6/3/20 3:07 PM, Andrzej Pietrasiewicz wrote:
> Hi Hans, hi Dmitry,

<snip>

> I'm taking one step back and looking at the ->open() and ->close()
> driver callbacks. They are called from input_open_device() and
> input_close_device(), respectively:
> 
> input_open_device():
> "This function should be called by input handlers when they
> want to start receive events from given input device."
> 
> ->open() callback:
> "this method is called when the very first user calls
> input_open_device(). The driver must prepare the device to start
> generating events (start polling thread, request an IRQ, submit
> URB, etc.)"
> 
> input_close_device():
> "This function should be called by input handlers when they
> want to stop receive events from given input device."
> 
> ->close() callback:
> "this method is called when the very last user calls
> input_close_device()"
> 
> It seems to me that the callback names do not reflect their
> purpose: their meaning is not to "open" or to "close" but to
> give drivers a chance to control when they start or stop
> providing events to the input core.
> 
> What would you say about changing the callbacks' names?
> I'd envsion: ->provide_events() instead of ->open() and
> ->stop_events() instead of ->close(). Of course drivers can
> exploit the fact of knowing that nobody wants any events
> from them and do whatever they consider appropriate, for
> example go into a low power mode - but the latter is beyond
> the scope of the input subsystem and is driver-specific.

I don't have much of an opinion on changing the names,
to me open/close have always means start/stop receiving
events. This follows the everything is a file philosophy,
e.g. you can also not really "open" a serial port,
yet opening /dev/ttyS0 will activate the receive IRQ
of the UART, etc. So maybe we just need to make the
docs clearer rather then do the rename?  Doing the
rename is certainly going to cause a lot of churn.

Anyways as said, I don't have much of an opinion,
so I'll leave commenting (more) on this to Dmitry.

> With such a naming change in mind let's consider inhibiting.
> We want to be able to control when to disregard events from
> a given device. It makes sense to do it at device level, otherwise
> such an operation would have to be invoked in all associated
> handlers (those that have an open handle associating them with
> the device in question). But of course we can do better than
> merely ignoring the events received: we can tell the drivers
> that we don't want any events from them, and later, at uninhibit
> time, tell them to start providing the events again. Conceptually,
> the two operations (provide or don't provide envents) are exactly
> the same thing we want to be happening at input_open_device() and
> input_close_device() time. To me, changing the names of
> ->open() and ->close() exposes this fact very well.
> 
> Consequently, ->inhibit() and ->uninhibit() won't be needed,
> and drivers which already implement ->provide_events() (formerly
> ->open()) and ->stop_events() (formerly ->close()) will receive
> full inhibit/uninhibit support for free (subject to how well they
> implement ->provide_events()/->stop_events()). Unless we can come
> up with what the drivers might be doing on top of ->stop_events()
> and ->provide_events() when inhibiting/uninhibiting, but it seems
> to me we can't. Can we?

Right. I'm happy that you've come to see that both on open/close
and on inhibit/uninhibit we want to "start receiving events" and
"stop receiving events", so that we only need one set of callbacks.

> Optionally ->close() (only the callback, not input_close_device())
> can be made return a value, just as Hans suggests. The value
> can be ignored in input_close_device() but used in input_inhibit().
> No strong opinion here, though. (btw it seems to me that
> input_inhibit() should be renamed to input_inhibit_device()).

Ack.

Regards,

Hans


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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-06-03 17:38                             ` Hans de Goede
@ 2020-06-03 17:54                               ` Andrzej Pietrasiewicz
  2020-06-03 19:37                                 ` Hans de Goede
  0 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-03 17:54 UTC (permalink / raw)
  To: Hans de Goede, Dmitry Torokhov
  Cc: linux-input, linux-acpi, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-tegra, patches, ibm-acpi-devel,
	platform-driver-x86, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

W dniu 03.06.2020 o 19:38, Hans de Goede pisze:
> Hi,
> 
> On 6/3/20 3:07 PM, Andrzej Pietrasiewicz wrote:
>> Hi Hans, hi Dmitry,
> 
> <snip>
> 
>> I'm taking one step back and looking at the ->open() and ->close()
>> driver callbacks. They are called from input_open_device() and
>> input_close_device(), respectively:
>>
>> input_open_device():
>> "This function should be called by input handlers when they
>> want to start receive events from given input device."
>>
>> ->open() callback:
>> "this method is called when the very first user calls
>> input_open_device(). The driver must prepare the device to start
>> generating events (start polling thread, request an IRQ, submit
>> URB, etc.)"
>>
>> input_close_device():
>> "This function should be called by input handlers when they
>> want to stop receive events from given input device."
>>
>> ->close() callback:
>> "this method is called when the very last user calls
>> input_close_device()"
>>
>> It seems to me that the callback names do not reflect their
>> purpose: their meaning is not to "open" or to "close" but to
>> give drivers a chance to control when they start or stop
>> providing events to the input core.
>>
>> What would you say about changing the callbacks' names?
>> I'd envsion: ->provide_events() instead of ->open() and
>> ->stop_events() instead of ->close(). Of course drivers can
>> exploit the fact of knowing that nobody wants any events
>> from them and do whatever they consider appropriate, for
>> example go into a low power mode - but the latter is beyond
>> the scope of the input subsystem and is driver-specific.
> 
> I don't have much of an opinion on changing the names,
> to me open/close have always means start/stop receiving
> events. This follows the everything is a file philosophy,
> e.g. you can also not really "open" a serial port,
> yet opening /dev/ttyS0 will activate the receive IRQ
> of the UART, etc. So maybe we just need to make the
> docs clearer rather then do the rename?  Doing the
> rename is certainly going to cause a lot of churn.

Right, I can see now that the suggestion to change names is
too far fetched. (I feel that release() would be better
than close(), though). But it exposes the message I wanted to
pass.

> 
> Anyways as said, I don't have much of an opinion,
> so I'll leave commenting (more) on this to Dmitry.
> 
>> With such a naming change in mind let's consider inhibiting.
>> We want to be able to control when to disregard events from
>> a given device. It makes sense to do it at device level, otherwise
>> such an operation would have to be invoked in all associated
>> handlers (those that have an open handle associating them with
>> the device in question). But of course we can do better than
>> merely ignoring the events received: we can tell the drivers
>> that we don't want any events from them, and later, at uninhibit
>> time, tell them to start providing the events again. Conceptually,
>> the two operations (provide or don't provide envents) are exactly
>> the same thing we want to be happening at input_open_device() and
>> input_close_device() time. To me, changing the names of
>> ->open() and ->close() exposes this fact very well.
>>
>> Consequently, ->inhibit() and ->uninhibit() won't be needed,
>> and drivers which already implement ->provide_events() (formerly
>> ->open()) and ->stop_events() (formerly ->close()) will receive
>> full inhibit/uninhibit support for free (subject to how well they
>> implement ->provide_events()/->stop_events()). Unless we can come
>> up with what the drivers might be doing on top of ->stop_events()
>> and ->provide_events() when inhibiting/uninhibiting, but it seems
>> to me we can't. Can we?
> 
> Right. I'm happy that you've come to see that both on open/close
> and on inhibit/uninhibit we want to "start receiving events" and
> "stop receiving events", so that we only need one set of callbacks.
> 

Yeah, that's my conclusion - at least on a conceptual level.

That said, what I can imagine is an existing driver (e.g. elan_i2c)
which does not implement neither open() nor close(), but does have
suspend() and resume(). Then it is maybe a bit easier to add inhibit()
and uninhibit() /they would be similar to suspend and resume/ instead
of open() and close(): If only open() and close() are possible, then
the probe function needs to be extended to "close" the device before it
gets registered, because from the moment it is registered it might be
opened right away. And the device must be available earlier during the
course of probe to query some parameters through i2c:

+static int elan_reactivate(struct elan_tp_data *data)
+{
+	struct device *dev = &data->client->dev;
+	int ret;
+
+	ret = elan_enable_power(data);
+	if (ret)
+		dev_err(dev, "failed to restore power: %d\n", ret);
+
+	ret = elan_initialize(data);
+	if (ret)
+		dev_err(dev, "failed to re-initialize touchpad: %d\n", ret);
+
+	return ret;
+}
+
+static int elan_open(struct input_dev *input)
+{
+	struct elan_tp_data *data = input_get_drvdata(input);
+	struct i2c_client *client = data->client;
+	int ret;
+
+	dev_dbg(&client->dev, "uninhibiting\n");
+
+	ret = mutex_lock_interruptible(&data->sysfs_mutex);
+	if (ret)
+		return ret;
+
+	ret = elan_reactivate(data);
+	if (ret == 0)
+		enable_irq(client->irq);
+
+	mutex_unlock(&data->sysfs_mutex);
+
+	return ret;
+}
+
+static int elan_inhibit(struct input_dev *input)
+{
+	struct elan_tp_data *data = input_get_drvdata(input);
+	struct i2c_client *client = data->client;
+	int ret;
+
+	dev_dbg(&client->dev, "closing\n");
+
+	/*
+	 * We are taking the mutex to make sure sysfs operations are
+	 * complete before we attempt to bring the device into low[er]
+	 * power mode.
+	 */
+	ret = mutex_lock_interruptible(&data->sysfs_mutex);
+	if (ret)
+		return ret;
+
+	disable_irq(client->irq);
+
+	ret = elan_disable_power(data);
+	if (ret)
+		enable_irq(client->irq);
+
+	mutex_unlock(&data->sysfs_mutex);
+
+	return ret;
+}
+
+static void elan_close(struct input_dev *input)
+{
+	elan_inhibit(input);
+}
+
  static int elan_query_device_info(struct elan_tp_data *data)
  {
  	int error;
  	u16 ic_type;

  	error = data->ops->get_version(data->client, false, &data->fw_version);
  	if (error)
  		return error;

  	error = data->ops->get_checksum(data->client, false,
  					&data->fw_checksum);
  	if (error)
  		return error;

  	error = data->ops->get_version(data->client, true, &data->iap_version);
  	if (error)
  		return error;
@@ -1071,34 +1141,36 @@ static int elan_setup_trackpoint_input_device(struct 
elan_tp_data *data)

  static int elan_setup_input_device(struct elan_tp_data *data)
  {
  	struct device *dev = &data->client->dev;
  	struct input_dev *input;
  	unsigned int max_width = max(data->width_x, data->width_y);
  	unsigned int min_width = min(data->width_x, data->width_y);
  	int error;

  	input = devm_input_allocate_device(dev);
  	if (!input)
  		return -ENOMEM;

  	input->name = "Elan Touchpad";
  	input->id.bustype = BUS_I2C;
  	input->id.vendor = ELAN_VENDOR_ID;
  	input->id.product = data->product_id;
+	input->open = elan_open;
+	input->close = elan_close;
  	input_set_drvdata(input, data);

  	error = input_mt_init_slots(input, ETP_MAX_FINGERS,
  				    INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED);
  	if (error) {
  		dev_err(dev, "failed to initialize MT slots: %d\n", error);
  		return error;
  	}

  	__set_bit(EV_ABS, input->evbit);
  	__set_bit(INPUT_PROP_POINTER, input->propbit);
  	if (data->clickpad) {
  		__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
  	} else {
  		__set_bit(BTN_RIGHT, input->keybit);
  		if (data->middle_button)
  			__set_bit(BTN_MIDDLE, input->keybit);
@@ -1253,34 +1325,40 @@ static int elan_probe(struct i2c_client *client,
  	if (!irqflags)
  		irqflags = IRQF_TRIGGER_FALLING;

  	error = devm_request_threaded_irq(dev, client->irq, NULL, elan_isr,
  					  irqflags | IRQF_ONESHOT,
  					  client->name, data);
  	if (error) {
  		dev_err(dev, "cannot register irq=%d\n", client->irq);
  		return error;
  	}

  	error = devm_device_add_groups(dev, elan_sysfs_groups);
  	if (error) {
  		dev_err(dev, "failed to create sysfs attributes: %d\n", error);
  		return error;
  	}

+	error = elan_inhibit(data->input);
+	if (error) {
+		dev_err(dev, "failed to inhibit input device before registering: %d\n", error);
+		return error;
+	}
+
  	error = input_register_device(data->input);
  	if (error) {
  		dev_err(dev, "failed to register input device: %d\n", error);
  		return error;
  	}

  	if (data->tp_input) {
  		error = input_register_device(data->tp_input);
  		if (error) {
  			dev_err(&client->dev,
  				"failed to register TrackPoint input device: %d\n",
  				error);
  			return error;
  		}
  	}

  	/*
@@ -1294,72 +1372,71 @@ static int elan_probe(struct i2c_client *client,
  }

  static int __maybe_unused elan_suspend(struct device *dev)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct elan_tp_data *data = i2c_get_clientdata(client);
  	int ret;

  	/*
  	 * We are taking the mutex to make sure sysfs operations are
  	 * complete before we attempt to bring the device into low[er]
  	 * power mode.
  	 */
  	ret = mutex_lock_interruptible(&data->sysfs_mutex);
  	if (ret)
  		return ret;

-	disable_irq(client->irq);
+	mutex_lock(&data->input->mutex);
+	if (input_device_enabled(data->input)) {
+		disable_irq(client->irq);

-	if (device_may_wakeup(dev)) {
-		ret = elan_sleep(data);
-		/* Enable wake from IRQ */
-		data->irq_wake = (enable_irq_wake(client->irq) == 0);
-	} else {
-		ret = elan_disable_power(data);
+		if (device_may_wakeup(dev)) {
+			ret = elan_sleep(data);
+			/* Enable wake from IRQ */
+			data->irq_wake = (enable_irq_wake(client->irq) == 0);
+		} else {
+			ret = elan_disable_power(data);
+		}
  	}
+	mutex_unlock(&data->input->mutex);

  	mutex_unlock(&data->sysfs_mutex);
  	return ret;
  }

  static int __maybe_unused elan_resume(struct device *dev)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct elan_tp_data *data = i2c_get_clientdata(client);
-	int error;
+	int ret = 0;

-	if (device_may_wakeup(dev) && data->irq_wake) {
-		disable_irq_wake(client->irq);
-		data->irq_wake = false;
-	}
+	mutex_lock(&data->input->mutex);
+	if (input_device_enabled(data->input)) {
+		if (data->irq_wake) {
+			disable_irq_wake(client->irq);
+			data->irq_wake = false;
+		}

-	error = elan_enable_power(data);
-	if (error) {
-		dev_err(dev, "power up when resuming failed: %d\n", error);
-		goto err;
+		ret = elan_reactivate(data);
+		enable_irq(data->client->irq);
  	}
+	mutex_unlock(&data->input->mutex);

-	error = elan_initialize(data);
-	if (error)
-		dev_err(dev, "initialize when resuming failed: %d\n", error);
-
-err:
-	enable_irq(data->client->irq);
-	return error;
+	return ret;
  }

Regards,

Andrzej

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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-06-03 17:54                               ` Andrzej Pietrasiewicz
@ 2020-06-03 19:37                                 ` Hans de Goede
  2020-06-04  7:28                                   ` Dmitry Torokhov
  0 siblings, 1 reply; 80+ messages in thread
From: Hans de Goede @ 2020-06-03 19:37 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, Dmitry Torokhov
  Cc: linux-input, linux-acpi, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-tegra, patches, ibm-acpi-devel,
	platform-driver-x86, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi,

On 6/3/20 7:54 PM, Andrzej Pietrasiewicz wrote:
> W dniu 03.06.2020 o 19:38, Hans de Goede pisze:
>> Hi,
>>
>> On 6/3/20 3:07 PM, Andrzej Pietrasiewicz wrote:
>>> Hi Hans, hi Dmitry,
>>
>> <snip>
>>
>>> I'm taking one step back and looking at the ->open() and ->close()
>>> driver callbacks. They are called from input_open_device() and
>>> input_close_device(), respectively:
>>>
>>> input_open_device():
>>> "This function should be called by input handlers when they
>>> want to start receive events from given input device."
>>>
>>> ->open() callback:
>>> "this method is called when the very first user calls
>>> input_open_device(). The driver must prepare the device to start
>>> generating events (start polling thread, request an IRQ, submit
>>> URB, etc.)"
>>>
>>> input_close_device():
>>> "This function should be called by input handlers when they
>>> want to stop receive events from given input device."
>>>
>>> ->close() callback:
>>> "this method is called when the very last user calls
>>> input_close_device()"
>>>
>>> It seems to me that the callback names do not reflect their
>>> purpose: their meaning is not to "open" or to "close" but to
>>> give drivers a chance to control when they start or stop
>>> providing events to the input core.
>>>
>>> What would you say about changing the callbacks' names?
>>> I'd envsion: ->provide_events() instead of ->open() and
>>> ->stop_events() instead of ->close(). Of course drivers can
>>> exploit the fact of knowing that nobody wants any events
>>> from them and do whatever they consider appropriate, for
>>> example go into a low power mode - but the latter is beyond
>>> the scope of the input subsystem and is driver-specific.
>>
>> I don't have much of an opinion on changing the names,
>> to me open/close have always means start/stop receiving
>> events. This follows the everything is a file philosophy,
>> e.g. you can also not really "open" a serial port,
>> yet opening /dev/ttyS0 will activate the receive IRQ
>> of the UART, etc. So maybe we just need to make the
>> docs clearer rather then do the rename?  Doing the
>> rename is certainly going to cause a lot of churn.
> 
> Right, I can see now that the suggestion to change names is
> too far fetched. (I feel that release() would be better
> than close(), though). But it exposes the message I wanted to
> pass.
> 
>>
>> Anyways as said, I don't have much of an opinion,
>> so I'll leave commenting (more) on this to Dmitry.
>>
>>> With such a naming change in mind let's consider inhibiting.
>>> We want to be able to control when to disregard events from
>>> a given device. It makes sense to do it at device level, otherwise
>>> such an operation would have to be invoked in all associated
>>> handlers (those that have an open handle associating them with
>>> the device in question). But of course we can do better than
>>> merely ignoring the events received: we can tell the drivers
>>> that we don't want any events from them, and later, at uninhibit
>>> time, tell them to start providing the events again. Conceptually,
>>> the two operations (provide or don't provide envents) are exactly
>>> the same thing we want to be happening at input_open_device() and
>>> input_close_device() time. To me, changing the names of
>>> ->open() and ->close() exposes this fact very well.
>>>
>>> Consequently, ->inhibit() and ->uninhibit() won't be needed,
>>> and drivers which already implement ->provide_events() (formerly
>>> ->open()) and ->stop_events() (formerly ->close()) will receive
>>> full inhibit/uninhibit support for free (subject to how well they
>>> implement ->provide_events()/->stop_events()). Unless we can come
>>> up with what the drivers might be doing on top of ->stop_events()
>>> and ->provide_events() when inhibiting/uninhibiting, but it seems
>>> to me we can't. Can we?
>>
>> Right. I'm happy that you've come to see that both on open/close
>> and on inhibit/uninhibit we want to "start receiving events" and
>> "stop receiving events", so that we only need one set of callbacks.
>>
> 
> Yeah, that's my conclusion - at least on a conceptual level.
> 
> That said, what I can imagine is an existing driver (e.g. elan_i2c)
> which does not implement neither open() nor close(), but does have
> suspend() and resume(). Then it is maybe a bit easier to add inhibit()
> and uninhibit() /they would be similar to suspend and resume/ instead
> of open() and close(): If only open() and close() are possible, then
> the probe function needs to be extended to "close" the device before it
> gets registered, because from the moment it is registered it might be
> opened right away.

The probe only needs to "close" it if for some reason it
starts directly sending events in most cases the driver
must actively do something to get it to send events.

So in most cases this should be pretty straight forward,
as for having to do some init / power-on during probe
and then power-off at the end of the probe. Yes sometimes
something like that might be necessary.

Looking at your suggested elan_i2c changes I think they
look fine. I have the feeling that with some refactoring
they can be made a bit cleaner (I did not look a the
changes in too much detail) but overall I think they
look ok.

Note you may also want to look at using the runtime
suspend framework for this, doing a pm_runtime_get_sync()
in open() and then letting (runtime) suspend do the power
off if you set a reasonable timeout for autosuspend after
the last user is gone then that will also avoid an
unnecessary suspend / resume cycle between probe()
exiting and the first open() call and this avoids the
need to do a poweroff() at the end of probe(), the
runtime-pm framework will autosuspend the device after
the timeout expires.

Regards,

Hans


> And the device must be available earlier during the
> course of probe to query some parameters through i2c:
> 
> +static int elan_reactivate(struct elan_tp_data *data)
> +{
> +    struct device *dev = &data->client->dev;
> +    int ret;
> +
> +    ret = elan_enable_power(data);
> +    if (ret)
> +        dev_err(dev, "failed to restore power: %d\n", ret);
> +
> +    ret = elan_initialize(data);
> +    if (ret)
> +        dev_err(dev, "failed to re-initialize touchpad: %d\n", ret);
> +
> +    return ret;
> +}
> +
> +static int elan_open(struct input_dev *input)
> +{
> +    struct elan_tp_data *data = input_get_drvdata(input);
> +    struct i2c_client *client = data->client;
> +    int ret;
> +
> +    dev_dbg(&client->dev, "uninhibiting\n");
> +
> +    ret = mutex_lock_interruptible(&data->sysfs_mutex);
> +    if (ret)
> +        return ret;
> +
> +    ret = elan_reactivate(data);
> +    if (ret == 0)
> +        enable_irq(client->irq);
> +
> +    mutex_unlock(&data->sysfs_mutex);
> +
> +    return ret;
> +}
> +
> +static int elan_inhibit(struct input_dev *input)
> +{
> +    struct elan_tp_data *data = input_get_drvdata(input);
> +    struct i2c_client *client = data->client;
> +    int ret;
> +
> +    dev_dbg(&client->dev, "closing\n");
> +
> +    /*
> +     * We are taking the mutex to make sure sysfs operations are
> +     * complete before we attempt to bring the device into low[er]
> +     * power mode.
> +     */
> +    ret = mutex_lock_interruptible(&data->sysfs_mutex);
> +    if (ret)
> +        return ret;
> +
> +    disable_irq(client->irq);
> +
> +    ret = elan_disable_power(data);
> +    if (ret)
> +        enable_irq(client->irq);
> +
> +    mutex_unlock(&data->sysfs_mutex);
> +
> +    return ret;
> +}
> +
> +static void elan_close(struct input_dev *input)
> +{
> +    elan_inhibit(input);
> +}
> +
>   static int elan_query_device_info(struct elan_tp_data *data)
>   {
>       int error;
>       u16 ic_type;
> 
>       error = data->ops->get_version(data->client, false, &data->fw_version);
>       if (error)
>           return error;
> 
>       error = data->ops->get_checksum(data->client, false,
>                       &data->fw_checksum);
>       if (error)
>           return error;
> 
>       error = data->ops->get_version(data->client, true, &data->iap_version);
>       if (error)
>           return error;
> @@ -1071,34 +1141,36 @@ static int elan_setup_trackpoint_input_device(struct elan_tp_data *data)
> 
>   static int elan_setup_input_device(struct elan_tp_data *data)
>   {
>       struct device *dev = &data->client->dev;
>       struct input_dev *input;
>       unsigned int max_width = max(data->width_x, data->width_y);
>       unsigned int min_width = min(data->width_x, data->width_y);
>       int error;
> 
>       input = devm_input_allocate_device(dev);
>       if (!input)
>           return -ENOMEM;
> 
>       input->name = "Elan Touchpad";
>       input->id.bustype = BUS_I2C;
>       input->id.vendor = ELAN_VENDOR_ID;
>       input->id.product = data->product_id;
> +    input->open = elan_open;
> +    input->close = elan_close;
>       input_set_drvdata(input, data);
> 
>       error = input_mt_init_slots(input, ETP_MAX_FINGERS,
>                       INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED);
>       if (error) {
>           dev_err(dev, "failed to initialize MT slots: %d\n", error);
>           return error;
>       }
> 
>       __set_bit(EV_ABS, input->evbit);
>       __set_bit(INPUT_PROP_POINTER, input->propbit);
>       if (data->clickpad) {
>           __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
>       } else {
>           __set_bit(BTN_RIGHT, input->keybit);
>           if (data->middle_button)
>               __set_bit(BTN_MIDDLE, input->keybit);
> @@ -1253,34 +1325,40 @@ static int elan_probe(struct i2c_client *client,
>       if (!irqflags)
>           irqflags = IRQF_TRIGGER_FALLING;
> 
>       error = devm_request_threaded_irq(dev, client->irq, NULL, elan_isr,
>                         irqflags | IRQF_ONESHOT,
>                         client->name, data);
>       if (error) {
>           dev_err(dev, "cannot register irq=%d\n", client->irq);
>           return error;
>       }
> 
>       error = devm_device_add_groups(dev, elan_sysfs_groups);
>       if (error) {
>           dev_err(dev, "failed to create sysfs attributes: %d\n", error);
>           return error;
>       }
> 
> +    error = elan_inhibit(data->input);
> +    if (error) {
> +        dev_err(dev, "failed to inhibit input device before registering: %d\n", error);
> +        return error;
> +    }
> +
>       error = input_register_device(data->input);
>       if (error) {
>           dev_err(dev, "failed to register input device: %d\n", error);
>           return error;
>       }
> 
>       if (data->tp_input) {
>           error = input_register_device(data->tp_input);
>           if (error) {
>               dev_err(&client->dev,
>                   "failed to register TrackPoint input device: %d\n",
>                   error);
>               return error;
>           }
>       }
> 
>       /*
> @@ -1294,72 +1372,71 @@ static int elan_probe(struct i2c_client *client,
>   }
> 
>   static int __maybe_unused elan_suspend(struct device *dev)
>   {
>       struct i2c_client *client = to_i2c_client(dev);
>       struct elan_tp_data *data = i2c_get_clientdata(client);
>       int ret;
> 
>       /*
>        * We are taking the mutex to make sure sysfs operations are
>        * complete before we attempt to bring the device into low[er]
>        * power mode.
>        */
>       ret = mutex_lock_interruptible(&data->sysfs_mutex);
>       if (ret)
>           return ret;
> 
> -    disable_irq(client->irq);
> +    mutex_lock(&data->input->mutex);
> +    if (input_device_enabled(data->input)) {
> +        disable_irq(client->irq);
> 
> -    if (device_may_wakeup(dev)) {
> -        ret = elan_sleep(data);
> -        /* Enable wake from IRQ */
> -        data->irq_wake = (enable_irq_wake(client->irq) == 0);
> -    } else {
> -        ret = elan_disable_power(data);
> +        if (device_may_wakeup(dev)) {
> +            ret = elan_sleep(data);
> +            /* Enable wake from IRQ */
> +            data->irq_wake = (enable_irq_wake(client->irq) == 0);
> +        } else {
> +            ret = elan_disable_power(data);
> +        }
>       }
> +    mutex_unlock(&data->input->mutex);
> 
>       mutex_unlock(&data->sysfs_mutex);
>       return ret;
>   }
> 
>   static int __maybe_unused elan_resume(struct device *dev)
>   {
>       struct i2c_client *client = to_i2c_client(dev);
>       struct elan_tp_data *data = i2c_get_clientdata(client);
> -    int error;
> +    int ret = 0;
> 
> -    if (device_may_wakeup(dev) && data->irq_wake) {
> -        disable_irq_wake(client->irq);
> -        data->irq_wake = false;
> -    }
> +    mutex_lock(&data->input->mutex);
> +    if (input_device_enabled(data->input)) {
> +        if (data->irq_wake) {
> +            disable_irq_wake(client->irq);
> +            data->irq_wake = false;
> +        }
> 
> -    error = elan_enable_power(data);
> -    if (error) {
> -        dev_err(dev, "power up when resuming failed: %d\n", error);
> -        goto err;
> +        ret = elan_reactivate(data);
> +        enable_irq(data->client->irq);
>       }
> +    mutex_unlock(&data->input->mutex);
> 
> -    error = elan_initialize(data);
> -    if (error)
> -        dev_err(dev, "initialize when resuming failed: %d\n", error);
> -
> -err:
> -    enable_irq(data->client->irq);
> -    return error;
> +    return ret;
>   }
> 
> Regards,
> 
> Andrzej
> 


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

* Re: [PATCHv2 0/7] Support inhibiting input devices
  2020-06-03 19:37                                 ` Hans de Goede
@ 2020-06-04  7:28                                   ` Dmitry Torokhov
  2020-06-05 17:33                                     ` [PATCH v3 " Andrzej Pietrasiewicz
  0 siblings, 1 reply; 80+ messages in thread
From: Dmitry Torokhov @ 2020-06-04  7:28 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Andrzej Pietrasiewicz, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Henrique de Moraes Holschuh, kernel, Peter Hutterer,
	Benjamin Tissoires

Hi Hans, Andrzej,

On Wed, Jun 03, 2020 at 09:37:10PM +0200, Hans de Goede wrote:
> Hi,
> 
> On 6/3/20 7:54 PM, Andrzej Pietrasiewicz wrote:
> > W dniu 03.06.2020 o 19:38, Hans de Goede pisze:
> > > Hi,
> > > 
> > > On 6/3/20 3:07 PM, Andrzej Pietrasiewicz wrote:
> > > > Hi Hans, hi Dmitry,
> > > 
> > > <snip>
> > > 
> > > > I'm taking one step back and looking at the ->open() and ->close()
> > > > driver callbacks. They are called from input_open_device() and
> > > > input_close_device(), respectively:
> > > > 
> > > > input_open_device():
> > > > "This function should be called by input handlers when they
> > > > want to start receive events from given input device."
> > > > 
> > > > ->open() callback:
> > > > "this method is called when the very first user calls
> > > > input_open_device(). The driver must prepare the device to start
> > > > generating events (start polling thread, request an IRQ, submit
> > > > URB, etc.)"
> > > > 
> > > > input_close_device():
> > > > "This function should be called by input handlers when they
> > > > want to stop receive events from given input device."
> > > > 
> > > > ->close() callback:
> > > > "this method is called when the very last user calls
> > > > input_close_device()"
> > > > 
> > > > It seems to me that the callback names do not reflect their
> > > > purpose: their meaning is not to "open" or to "close" but to
> > > > give drivers a chance to control when they start or stop
> > > > providing events to the input core.
> > > > 
> > > > What would you say about changing the callbacks' names?
> > > > I'd envsion: ->provide_events() instead of ->open() and
> > > > ->stop_events() instead of ->close(). Of course drivers can
> > > > exploit the fact of knowing that nobody wants any events
> > > > from them and do whatever they consider appropriate, for
> > > > example go into a low power mode - but the latter is beyond
> > > > the scope of the input subsystem and is driver-specific.
> > > 
> > > I don't have much of an opinion on changing the names,
> > > to me open/close have always means start/stop receiving
> > > events. This follows the everything is a file philosophy,
> > > e.g. you can also not really "open" a serial port,
> > > yet opening /dev/ttyS0 will activate the receive IRQ
> > > of the UART, etc. So maybe we just need to make the
> > > docs clearer rather then do the rename?  Doing the
> > > rename is certainly going to cause a lot of churn.
> > 
> > Right, I can see now that the suggestion to change names is
> > too far fetched. (I feel that release() would be better
> > than close(), though). But it exposes the message I wanted to
> > pass.

release() usually means that the object is destroyedm, i.e this action,
unlike close() is irrevocable.

Let's leave the names as is, and adjust kerneldoc comments as needed.

> > 
> > > 
> > > Anyways as said, I don't have much of an opinion,
> > > so I'll leave commenting (more) on this to Dmitry.
> > > 
> > > > With such a naming change in mind let's consider inhibiting.
> > > > We want to be able to control when to disregard events from
> > > > a given device. It makes sense to do it at device level, otherwise
> > > > such an operation would have to be invoked in all associated
> > > > handlers (those that have an open handle associating them with
> > > > the device in question). But of course we can do better than
> > > > merely ignoring the events received: we can tell the drivers
> > > > that we don't want any events from them, and later, at uninhibit
> > > > time, tell them to start providing the events again. Conceptually,
> > > > the two operations (provide or don't provide envents) are exactly
> > > > the same thing we want to be happening at input_open_device() and
> > > > input_close_device() time. To me, changing the names of
> > > > ->open() and ->close() exposes this fact very well.
> > > > 
> > > > Consequently, ->inhibit() and ->uninhibit() won't be needed,
> > > > and drivers which already implement ->provide_events() (formerly
> > > > ->open()) and ->stop_events() (formerly ->close()) will receive
> > > > full inhibit/uninhibit support for free (subject to how well they
> > > > implement ->provide_events()/->stop_events()). Unless we can come
> > > > up with what the drivers might be doing on top of ->stop_events()
> > > > and ->provide_events() when inhibiting/uninhibiting, but it seems
> > > > to me we can't. Can we?
> > > 
> > > Right. I'm happy that you've come to see that both on open/close
> > > and on inhibit/uninhibit we want to "start receiving events" and
> > > "stop receiving events", so that we only need one set of callbacks.
> > > 
> > 
> > Yeah, that's my conclusion - at least on a conceptual level.
> > 
> > That said, what I can imagine is an existing driver (e.g. elan_i2c)
> > which does not implement neither open() nor close(), but does have
> > suspend() and resume(). Then it is maybe a bit easier to add inhibit()
> > and uninhibit() /they would be similar to suspend and resume/ instead
> > of open() and close(): If only open() and close() are possible, then
> > the probe function needs to be extended to "close" the device before it
> > gets registered, because from the moment it is registered it might be
> > opened right away.
> 
> The probe only needs to "close" it if for some reason it
> starts directly sending events in most cases the driver
> must actively do something to get it to send events.
> 
> So in most cases this should be pretty straight forward,
> as for having to do some init / power-on during probe
> and then power-off at the end of the probe. Yes sometimes
> something like that might be necessary.
> 
> Looking at your suggested elan_i2c changes I think they
> look fine. I have the feeling that with some refactoring
> they can be made a bit cleaner (I did not look a the
> changes in too much detail) but overall I think they
> look ok.
> 
> Note you may also want to look at using the runtime
> suspend framework for this, doing a pm_runtime_get_sync()
> in open() and then letting (runtime) suspend do the power
> off if you set a reasonable timeout for autosuspend after
> the last user is gone then that will also avoid an
> unnecessary suspend / resume cycle between probe()
> exiting and the first open() call and this avoids the
> need to do a poweroff() at the end of probe(), the
> runtime-pm framework will autosuspend the device after
> the timeout expires.

Yes, plugging into runtime PM would be nice, as as it currently stands
the driver will be broken with regard to trying access sysfs for
firmware update/calibration/etc if device happens to be inhibited.

The version of the driver in Chrome OS tree is similarly broken, but
because we control both kernel and the rest of the stack we know that we
do not poke at sysfs when device is inhibited. It will not be acceptable
for mainline (and that is one of reasons why elan_i2c does not have
open/close methods at the moment).

Thanks.

-- 
Dmitry

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

* [PATCH v3 0/7] Support inhibiting input devices
  2020-06-04  7:28                                   ` Dmitry Torokhov
@ 2020-06-05 17:33                                     ` Andrzej Pietrasiewicz
  2020-06-05 17:33                                       ` [PATCH v3 1/7] Input: add input_device_enabled() Andrzej Pietrasiewicz
                                                         ` (7 more replies)
  0 siblings, 8 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-05 17:33 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

Userspace might want to implement a policy to temporarily disregard input
from certain devices.

An example use case is a convertible laptop, whose keyboard can be folded
under the screen to create tablet-like experience. The user then must hold
the laptop in such a way that it is difficult to avoid pressing the keyboard
keys. It is therefore desirable to temporarily disregard input from the
keyboard, until it is folded back. This obviously is a policy which should
be kept out of the kernel, but the kernel must provide suitable means to
implement such a policy.

Due to interactions with suspend/resume, a helper has been added for drivers
to decide if the device is being used or not (PATCH 1/7) and it has been
applied to relevant drivers (PATCH 2,4,5,6/7).

PATCH 7/7 adds support for inhibiting input devices.

This work is inspired by:

https://chromium.googlesource.com/chromiumos/third_party/kernel/+/45c2d7bb398f74adfae0017e20b224152fde3822

and

https://chromium.googlesource.com/chromiumos/third_party/kernel/+/4ce0e8a3697edb8fd071110b3af65014512061c7

In this respin the elan_i2c patch is dropped and converting it will be
addressed later.

v2..v3:
- ignored autorepeat events in input_get_disposition() if a key is not
pressed (Hans)
- dropped inhibit()/uninhibit() driver callbacks (Hans)
- split ACPI button patch into taking the lock and using the helper (Rafael)
- dropped the elan_i2c conversion
- fixed typos in exynos adc

v1..v2:
- added input_device_enabled() helper and used it in drivers (Dmitry)
- the fact of open() and close() being called in inhibit/uninhibit paths has
been emphasized in the commit message of PATCH 6/7 (Dmitry)

Andrzej Pietrasiewicz (6):
  Input: add input_device_enabled()
  Input: use input_device_enabled()
  ACPI: button: Access input device's users under appropriate mutex
  ACPI: button: Use input_device_enabled() helper
  iio: adc: exynos: Use input_device_enabled()
  platform/x86: thinkpad_acpi: Use input_device_enabled()

Patrik Fimml (1):
  Input: Add "inhibited" property

 drivers/acpi/button.c                       |   7 +-
 drivers/iio/adc/exynos_adc.c                |  11 +-
 drivers/input/input.c                       | 121 +++++++++++++++++++-
 drivers/input/joystick/xpad.c               |   4 +-
 drivers/input/keyboard/ep93xx_keypad.c      |   2 +-
 drivers/input/keyboard/gpio_keys.c          |   4 +-
 drivers/input/keyboard/imx_keypad.c         |   4 +-
 drivers/input/keyboard/ipaq-micro-keys.c    |   2 +-
 drivers/input/keyboard/lpc32xx-keys.c       |   4 +-
 drivers/input/keyboard/pmic8xxx-keypad.c    |   4 +-
 drivers/input/keyboard/pxa27x_keypad.c      |   2 +-
 drivers/input/keyboard/samsung-keypad.c     |   4 +-
 drivers/input/keyboard/spear-keyboard.c     |   8 +-
 drivers/input/keyboard/st-keyscan.c         |   4 +-
 drivers/input/keyboard/tegra-kbc.c          |   4 +-
 drivers/input/misc/drv260x.c                |   4 +-
 drivers/input/misc/drv2665.c                |   4 +-
 drivers/input/misc/drv2667.c                |   4 +-
 drivers/input/misc/gp2ap002a00f.c           |   4 +-
 drivers/input/misc/kxtj9.c                  |   4 +-
 drivers/input/misc/sirfsoc-onkey.c          |   2 +-
 drivers/input/mouse/navpoint.c              |   4 +-
 drivers/input/touchscreen/ad7879.c          |   6 +-
 drivers/input/touchscreen/atmel_mxt_ts.c    |   4 +-
 drivers/input/touchscreen/auo-pixcir-ts.c   |   8 +-
 drivers/input/touchscreen/bu21029_ts.c      |   4 +-
 drivers/input/touchscreen/chipone_icn8318.c |   4 +-
 drivers/input/touchscreen/cyttsp_core.c     |   4 +-
 drivers/input/touchscreen/eeti_ts.c         |   4 +-
 drivers/input/touchscreen/ektf2127.c        |   4 +-
 drivers/input/touchscreen/imx6ul_tsc.c      |   4 +-
 drivers/input/touchscreen/ipaq-micro-ts.c   |   2 +-
 drivers/input/touchscreen/iqs5xx.c          |   4 +-
 drivers/input/touchscreen/lpc32xx_ts.c      |   4 +-
 drivers/input/touchscreen/melfas_mip4.c     |   4 +-
 drivers/input/touchscreen/mms114.c          |   6 +-
 drivers/input/touchscreen/pixcir_i2c_ts.c   |   8 +-
 drivers/input/touchscreen/ucb1400_ts.c      |   4 +-
 drivers/input/touchscreen/wm97xx-core.c     |  14 ++-
 drivers/input/touchscreen/zforce_ts.c       |   8 +-
 drivers/platform/x86/thinkpad_acpi.c        |   4 +-
 include/linux/input.h                       |  14 ++-
 42 files changed, 230 insertions(+), 95 deletions(-)


base-commit: 3d77e6a8804abcc0504c904bd6e5cdf3a5cf8162
-- 
2.17.1


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

* [PATCH v3 1/7] Input: add input_device_enabled()
  2020-06-05 17:33                                     ` [PATCH v3 " Andrzej Pietrasiewicz
@ 2020-06-05 17:33                                       ` Andrzej Pietrasiewicz
  2020-06-05 17:33                                       ` [PATCH v3 2/7] Input: use input_device_enabled() Andrzej Pietrasiewicz
                                                         ` (6 subsequent siblings)
  7 siblings, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-05 17:33 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

A helper function for drivers to decide if the device is used or not.
A lockdep check is introduced as inspecting ->users should be done under
input device's mutex.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/input/input.c | 8 ++++++++
 include/linux/input.h | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index 3cfd2c18eebd..41377bfa142d 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -2127,6 +2127,14 @@ void input_enable_softrepeat(struct input_dev *dev, int delay, int period)
 }
 EXPORT_SYMBOL(input_enable_softrepeat);
 
+bool input_device_enabled(struct input_dev *dev)
+{
+	lockdep_assert_held(&dev->mutex);
+
+	return dev->users > 0;
+}
+EXPORT_SYMBOL_GPL(input_device_enabled);
+
 /**
  * input_register_device - register device with input core
  * @dev: device to be registered
diff --git a/include/linux/input.h b/include/linux/input.h
index 56f2fd32e609..eda4587dba67 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -502,6 +502,8 @@ bool input_match_device_id(const struct input_dev *dev,
 
 void input_enable_softrepeat(struct input_dev *dev, int delay, int period);
 
+bool input_device_enabled(struct input_dev *dev);
+
 extern struct class input_class;
 
 /**
-- 
2.17.1


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

* [PATCH v3 2/7] Input: use input_device_enabled()
  2020-06-05 17:33                                     ` [PATCH v3 " Andrzej Pietrasiewicz
  2020-06-05 17:33                                       ` [PATCH v3 1/7] Input: add input_device_enabled() Andrzej Pietrasiewicz
@ 2020-06-05 17:33                                       ` Andrzej Pietrasiewicz
  2020-06-05 17:33                                       ` [PATCH v3 3/7] ACPI: button: Access input device's users under appropriate mutex Andrzej Pietrasiewicz
                                                         ` (5 subsequent siblings)
  7 siblings, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-05 17:33 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

Use the newly added helper in relevant input drivers.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/input/joystick/xpad.c               |  4 ++--
 drivers/input/keyboard/ep93xx_keypad.c      |  2 +-
 drivers/input/keyboard/gpio_keys.c          |  4 ++--
 drivers/input/keyboard/imx_keypad.c         |  4 ++--
 drivers/input/keyboard/ipaq-micro-keys.c    |  2 +-
 drivers/input/keyboard/lpc32xx-keys.c       |  4 ++--
 drivers/input/keyboard/pmic8xxx-keypad.c    |  4 ++--
 drivers/input/keyboard/pxa27x_keypad.c      |  2 +-
 drivers/input/keyboard/samsung-keypad.c     |  4 ++--
 drivers/input/keyboard/spear-keyboard.c     |  8 ++++----
 drivers/input/keyboard/st-keyscan.c         |  4 ++--
 drivers/input/keyboard/tegra-kbc.c          |  4 ++--
 drivers/input/misc/drv260x.c                |  4 ++--
 drivers/input/misc/drv2665.c                |  4 ++--
 drivers/input/misc/drv2667.c                |  4 ++--
 drivers/input/misc/gp2ap002a00f.c           |  4 ++--
 drivers/input/misc/kxtj9.c                  |  4 ++--
 drivers/input/misc/sirfsoc-onkey.c          |  2 +-
 drivers/input/mouse/navpoint.c              |  4 ++--
 drivers/input/touchscreen/ad7879.c          |  6 +++---
 drivers/input/touchscreen/atmel_mxt_ts.c    |  4 ++--
 drivers/input/touchscreen/auo-pixcir-ts.c   |  8 ++++----
 drivers/input/touchscreen/bu21029_ts.c      |  4 ++--
 drivers/input/touchscreen/chipone_icn8318.c |  4 ++--
 drivers/input/touchscreen/cyttsp_core.c     |  4 ++--
 drivers/input/touchscreen/eeti_ts.c         |  4 ++--
 drivers/input/touchscreen/ektf2127.c        |  4 ++--
 drivers/input/touchscreen/imx6ul_tsc.c      |  4 ++--
 drivers/input/touchscreen/ipaq-micro-ts.c   |  2 +-
 drivers/input/touchscreen/iqs5xx.c          |  4 ++--
 drivers/input/touchscreen/lpc32xx_ts.c      |  4 ++--
 drivers/input/touchscreen/melfas_mip4.c     |  4 ++--
 drivers/input/touchscreen/mms114.c          |  6 +++---
 drivers/input/touchscreen/pixcir_i2c_ts.c   |  8 ++++----
 drivers/input/touchscreen/ucb1400_ts.c      |  4 ++--
 drivers/input/touchscreen/wm97xx-core.c     | 14 +++++++++-----
 drivers/input/touchscreen/zforce_ts.c       |  8 ++++----
 37 files changed, 86 insertions(+), 82 deletions(-)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index c77cdb3b62b5..d8b6bc2d2171 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -1902,7 +1902,7 @@ static int xpad_suspend(struct usb_interface *intf, pm_message_t message)
 			xpad360w_poweroff_controller(xpad);
 	} else {
 		mutex_lock(&input->mutex);
-		if (input->users)
+		if (input_device_enabled(input))
 			xpad_stop_input(xpad);
 		mutex_unlock(&input->mutex);
 	}
@@ -1922,7 +1922,7 @@ static int xpad_resume(struct usb_interface *intf)
 		retval = xpad360w_start_input(xpad);
 	} else {
 		mutex_lock(&input->mutex);
-		if (input->users) {
+		if (input_device_enabled(input)) {
 			retval = xpad_start_input(xpad);
 		} else if (xpad->xtype == XTYPE_XBOXONE) {
 			/*
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
index 7c70492d9d6b..8194e843d047 100644
--- a/drivers/input/keyboard/ep93xx_keypad.c
+++ b/drivers/input/keyboard/ep93xx_keypad.c
@@ -208,7 +208,7 @@ static int ep93xx_keypad_resume(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users) {
+	if (input_device_enabled(input_dev)) {
 		if (!keypad->enabled) {
 			ep93xx_keypad_config(keypad);
 			clk_enable(keypad->clk);
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 53c9ff338dea..03ad27189553 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -966,7 +966,7 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev)
 			return error;
 	} else {
 		mutex_lock(&input->mutex);
-		if (input->users)
+		if (input_device_enabled(input))
 			gpio_keys_close(input);
 		mutex_unlock(&input->mutex);
 	}
@@ -984,7 +984,7 @@ static int __maybe_unused gpio_keys_resume(struct device *dev)
 		gpio_keys_disable_wakeup(ddata);
 	} else {
 		mutex_lock(&input->mutex);
-		if (input->users)
+		if (input_device_enabled(input))
 			error = gpio_keys_open(input);
 		mutex_unlock(&input->mutex);
 	}
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index 5a46d113e909..1f5c9ea5e9e5 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -532,7 +532,7 @@ static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev)
 	/* imx kbd can wake up system even clock is disabled */
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		clk_disable_unprepare(kbd->clk);
 
 	mutex_unlock(&input_dev->mutex);
@@ -562,7 +562,7 @@ static int __maybe_unused imx_kbd_noirq_resume(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users) {
+	if (input_device_enabled(input_dev)) {
 		ret = clk_prepare_enable(kbd->clk);
 		if (ret)
 			goto err_clk;
diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c
index e3f9e445e880..13a66a8e3411 100644
--- a/drivers/input/keyboard/ipaq-micro-keys.c
+++ b/drivers/input/keyboard/ipaq-micro-keys.c
@@ -140,7 +140,7 @@ static int __maybe_unused micro_key_resume(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users)
+	if (input_device_enabled(input))
 		micro_key_start(keys);
 
 	mutex_unlock(&input->mutex);
diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c
index 348af2aeb5de..943aeeb0de79 100644
--- a/drivers/input/keyboard/lpc32xx-keys.c
+++ b/drivers/input/keyboard/lpc32xx-keys.c
@@ -273,7 +273,7 @@ static int lpc32xx_kscan_suspend(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users) {
+	if (input_device_enabled(input)) {
 		/* Clear IRQ and disable clock */
 		writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
 		clk_disable_unprepare(kscandat->clk);
@@ -292,7 +292,7 @@ static int lpc32xx_kscan_resume(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users) {
+	if (input_device_enabled(input)) {
 		/* Enable clock and clear IRQ */
 		retval = clk_prepare_enable(kscandat->clk);
 		if (retval == 0)
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c
index 91d5811d6f0e..43b4533e7c41 100644
--- a/drivers/input/keyboard/pmic8xxx-keypad.c
+++ b/drivers/input/keyboard/pmic8xxx-keypad.c
@@ -633,7 +633,7 @@ static int pmic8xxx_kp_suspend(struct device *dev)
 	} else {
 		mutex_lock(&input_dev->mutex);
 
-		if (input_dev->users)
+		if (input_device_enabled(input_dev))
 			pmic8xxx_kp_disable(kp);
 
 		mutex_unlock(&input_dev->mutex);
@@ -653,7 +653,7 @@ static int pmic8xxx_kp_resume(struct device *dev)
 	} else {
 		mutex_lock(&input_dev->mutex);
 
-		if (input_dev->users)
+		if (input_device_enabled(input_dev))
 			pmic8xxx_kp_enable(kp);
 
 		mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 7e65708b25a4..a7f8257c8a02 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -694,7 +694,7 @@ static int pxa27x_keypad_resume(struct device *dev)
 	} else {
 		mutex_lock(&input_dev->mutex);
 
-		if (input_dev->users) {
+		if (input_device_enabled(input_dev)) {
 			/* Enable unit clock */
 			ret = clk_prepare_enable(keypad->clk);
 			if (!ret)
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c
index 70c1d086bdd2..74ec068fbf2f 100644
--- a/drivers/input/keyboard/samsung-keypad.c
+++ b/drivers/input/keyboard/samsung-keypad.c
@@ -537,7 +537,7 @@ static int samsung_keypad_suspend(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		samsung_keypad_stop(keypad);
 
 	samsung_keypad_toggle_wakeup(keypad, true);
@@ -557,7 +557,7 @@ static int samsung_keypad_resume(struct device *dev)
 
 	samsung_keypad_toggle_wakeup(keypad, false);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		samsung_keypad_start(keypad);
 
 	mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
index 9b8d78f87253..9838c79cb288 100644
--- a/drivers/input/keyboard/spear-keyboard.c
+++ b/drivers/input/keyboard/spear-keyboard.c
@@ -318,7 +318,7 @@ static int __maybe_unused spear_kbd_suspend(struct device *dev)
 		writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
 
 	} else {
-		if (input_dev->users) {
+		if (input_device_enabled(input_dev)) {
 			writel_relaxed(mode_ctl_reg & ~MODE_CTL_START_SCAN,
 					kbd->io_base + MODE_CTL_REG);
 			clk_disable(kbd->clk);
@@ -326,7 +326,7 @@ static int __maybe_unused spear_kbd_suspend(struct device *dev)
 	}
 
 	/* store current configuration */
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		kbd->mode_ctl_reg = mode_ctl_reg;
 
 	/* restore previous clk state */
@@ -351,12 +351,12 @@ static int __maybe_unused spear_kbd_resume(struct device *dev)
 			disable_irq_wake(kbd->irq);
 		}
 	} else {
-		if (input_dev->users)
+		if (input_device_enabled(input_dev))
 			clk_enable(kbd->clk);
 	}
 
 	/* restore current configuration */
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		writel_relaxed(kbd->mode_ctl_reg, kbd->io_base + MODE_CTL_REG);
 
 	mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/keyboard/st-keyscan.c b/drivers/input/keyboard/st-keyscan.c
index 27562cd67fb6..a045d61165ac 100644
--- a/drivers/input/keyboard/st-keyscan.c
+++ b/drivers/input/keyboard/st-keyscan.c
@@ -221,7 +221,7 @@ static int keyscan_suspend(struct device *dev)
 
 	if (device_may_wakeup(dev))
 		enable_irq_wake(keypad->irq);
-	else if (input->users)
+	else if (input_device_enabled(input))
 		keyscan_stop(keypad);
 
 	mutex_unlock(&input->mutex);
@@ -239,7 +239,7 @@ static int keyscan_resume(struct device *dev)
 
 	if (device_may_wakeup(dev))
 		disable_irq_wake(keypad->irq);
-	else if (input->users)
+	else if (input_device_enabled(input))
 		retval = keyscan_start(keypad);
 
 	mutex_unlock(&input->mutex);
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index d34d6947960f..9671842a082a 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -756,7 +756,7 @@ static int tegra_kbc_suspend(struct device *dev)
 		enable_irq(kbc->irq);
 		enable_irq_wake(kbc->irq);
 	} else {
-		if (kbc->idev->users)
+		if (input_device_enabled(kbc->idev))
 			tegra_kbc_stop(kbc);
 	}
 	mutex_unlock(&kbc->idev->mutex);
@@ -796,7 +796,7 @@ static int tegra_kbc_resume(struct device *dev)
 			input_sync(kbc->idev);
 		}
 	} else {
-		if (kbc->idev->users)
+		if (input_device_enabled(kbc->idev))
 			err = tegra_kbc_start(kbc);
 	}
 	mutex_unlock(&kbc->idev->mutex);
diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c
index 79d7fa710a71..11c1983e286a 100644
--- a/drivers/input/misc/drv260x.c
+++ b/drivers/input/misc/drv260x.c
@@ -580,7 +580,7 @@ static int __maybe_unused drv260x_suspend(struct device *dev)
 
 	mutex_lock(&haptics->input_dev->mutex);
 
-	if (haptics->input_dev->users) {
+	if (input_device_enabled(haptics->input_dev)) {
 		ret = regmap_update_bits(haptics->regmap,
 					 DRV260X_MODE,
 					 DRV260X_STANDBY_MASK,
@@ -612,7 +612,7 @@ static int __maybe_unused drv260x_resume(struct device *dev)
 
 	mutex_lock(&haptics->input_dev->mutex);
 
-	if (haptics->input_dev->users) {
+	if (input_device_enabled(haptics->input_dev)) {
 		ret = regulator_enable(haptics->regulator);
 		if (ret) {
 			dev_err(dev, "Failed to enable regulator\n");
diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c
index 918ad9c3fa81..e4df1a3b8655 100644
--- a/drivers/input/misc/drv2665.c
+++ b/drivers/input/misc/drv2665.c
@@ -230,7 +230,7 @@ static int __maybe_unused drv2665_suspend(struct device *dev)
 
 	mutex_lock(&haptics->input_dev->mutex);
 
-	if (haptics->input_dev->users) {
+	if (input_device_enabled(haptics->input_dev)) {
 		ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
 					 DRV2665_STANDBY, DRV2665_STANDBY);
 		if (ret) {
@@ -259,7 +259,7 @@ static int __maybe_unused drv2665_resume(struct device *dev)
 
 	mutex_lock(&haptics->input_dev->mutex);
 
-	if (haptics->input_dev->users) {
+	if (input_device_enabled(haptics->input_dev)) {
 		ret = regulator_enable(haptics->regulator);
 		if (ret) {
 			dev_err(dev, "Failed to enable regulator\n");
diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c
index bb9d5784df17..be4be2e0fd6f 100644
--- a/drivers/input/misc/drv2667.c
+++ b/drivers/input/misc/drv2667.c
@@ -405,7 +405,7 @@ static int __maybe_unused drv2667_suspend(struct device *dev)
 
 	mutex_lock(&haptics->input_dev->mutex);
 
-	if (haptics->input_dev->users) {
+	if (input_device_enabled(haptics->input_dev)) {
 		ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
 					 DRV2667_STANDBY, DRV2667_STANDBY);
 		if (ret) {
@@ -434,7 +434,7 @@ static int __maybe_unused drv2667_resume(struct device *dev)
 
 	mutex_lock(&haptics->input_dev->mutex);
 
-	if (haptics->input_dev->users) {
+	if (input_device_enabled(haptics->input_dev)) {
 		ret = regulator_enable(haptics->regulator);
 		if (ret) {
 			dev_err(dev, "Failed to enable regulator\n");
diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c
index 90abda8eea67..5f61ef90b2f2 100644
--- a/drivers/input/misc/gp2ap002a00f.c
+++ b/drivers/input/misc/gp2ap002a00f.c
@@ -230,7 +230,7 @@ static int __maybe_unused gp2a_suspend(struct device *dev)
 		enable_irq_wake(client->irq);
 	} else {
 		mutex_lock(&dt->input->mutex);
-		if (dt->input->users)
+		if (input_device_enabled(dt->input))
 			retval = gp2a_disable(dt);
 		mutex_unlock(&dt->input->mutex);
 	}
@@ -248,7 +248,7 @@ static int __maybe_unused gp2a_resume(struct device *dev)
 		disable_irq_wake(client->irq);
 	} else {
 		mutex_lock(&dt->input->mutex);
-		if (dt->input->users)
+		if (input_device_enabled(dt->input))
 			retval = gp2a_enable(dt);
 		mutex_unlock(&dt->input->mutex);
 	}
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index 52313c6e3fb3..bbb81617c2b2 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -503,7 +503,7 @@ static int __maybe_unused kxtj9_suspend(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		kxtj9_disable(tj9);
 
 	mutex_unlock(&input_dev->mutex);
@@ -518,7 +518,7 @@ static int __maybe_unused kxtj9_resume(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		kxtj9_enable(tj9);
 
 	mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c
index 60e1f31ee60a..7982bf8fb839 100644
--- a/drivers/input/misc/sirfsoc-onkey.c
+++ b/drivers/input/misc/sirfsoc-onkey.c
@@ -181,7 +181,7 @@ static int __maybe_unused sirfsoc_pwrc_resume(struct device *dev)
 	 * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c
 	 */
 	mutex_lock(&input->mutex);
-	if (input->users)
+	if (input_device_enabled(input))
 		sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
 	mutex_unlock(&input->mutex);
 
diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c
index 0b75248c8380..643d4b805b64 100644
--- a/drivers/input/mouse/navpoint.c
+++ b/drivers/input/mouse/navpoint.c
@@ -322,7 +322,7 @@ static int __maybe_unused navpoint_suspend(struct device *dev)
 	struct input_dev *input = navpoint->input;
 
 	mutex_lock(&input->mutex);
-	if (input->users)
+	if (input_device_enabled(input))
 		navpoint_down(navpoint);
 	mutex_unlock(&input->mutex);
 
@@ -336,7 +336,7 @@ static int __maybe_unused navpoint_resume(struct device *dev)
 	struct input_dev *input = navpoint->input;
 
 	mutex_lock(&input->mutex);
-	if (input->users)
+	if (input_device_enabled(input))
 		navpoint_up(navpoint);
 	mutex_unlock(&input->mutex);
 
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
index 556a2af46e18..e850853328f1 100644
--- a/drivers/input/touchscreen/ad7879.c
+++ b/drivers/input/touchscreen/ad7879.c
@@ -306,7 +306,7 @@ static int __maybe_unused ad7879_suspend(struct device *dev)
 
 	mutex_lock(&ts->input->mutex);
 
-	if (!ts->suspended && !ts->disabled && ts->input->users)
+	if (!ts->suspended && !ts->disabled && input_device_enabled(ts->input))
 		__ad7879_disable(ts);
 
 	ts->suspended = true;
@@ -322,7 +322,7 @@ static int __maybe_unused ad7879_resume(struct device *dev)
 
 	mutex_lock(&ts->input->mutex);
 
-	if (ts->suspended && !ts->disabled && ts->input->users)
+	if (ts->suspended && !ts->disabled && input_device_enabled(ts->input))
 		__ad7879_enable(ts);
 
 	ts->suspended = false;
@@ -339,7 +339,7 @@ static void ad7879_toggle(struct ad7879 *ts, bool disable)
 {
 	mutex_lock(&ts->input->mutex);
 
-	if (!ts->suspended && ts->input->users != 0) {
+	if (!ts->suspended && input_device_enabled(ts->input)) {
 
 		if (disable) {
 			if (ts->disabled)
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index ae60442efda0..47b7936bc3e3 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -3151,7 +3151,7 @@ static int __maybe_unused mxt_suspend(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		mxt_stop(data);
 
 	mutex_unlock(&input_dev->mutex);
@@ -3174,7 +3174,7 @@ static int __maybe_unused mxt_resume(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		mxt_start(data);
 
 	mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
index 8e9f3b7b8180..c33e63ca6142 100644
--- a/drivers/input/touchscreen/auo-pixcir-ts.c
+++ b/drivers/input/touchscreen/auo-pixcir-ts.c
@@ -414,7 +414,7 @@ static int __maybe_unused auo_pixcir_suspend(struct device *dev)
 	 */
 	if (device_may_wakeup(&client->dev)) {
 		/* need to start device if not open, to be wakeup source */
-		if (!input->users) {
+		if (!input_device_enabled(input)) {
 			ret = auo_pixcir_start(ts);
 			if (ret)
 				goto unlock;
@@ -422,7 +422,7 @@ static int __maybe_unused auo_pixcir_suspend(struct device *dev)
 
 		enable_irq_wake(client->irq);
 		ret = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_SLEEP);
-	} else if (input->users) {
+	} else if (input_device_enabled(input)) {
 		ret = auo_pixcir_stop(ts);
 	}
 
@@ -445,14 +445,14 @@ static int __maybe_unused auo_pixcir_resume(struct device *dev)
 		disable_irq_wake(client->irq);
 
 		/* need to stop device if it was not open on suspend */
-		if (!input->users) {
+		if (!input_device_enabled(input)) {
 			ret = auo_pixcir_stop(ts);
 			if (ret)
 				goto unlock;
 		}
 
 		/* device wakes automatically from SLEEP */
-	} else if (input->users) {
+	} else if (input_device_enabled(input)) {
 		ret = auo_pixcir_start(ts);
 	}
 
diff --git a/drivers/input/touchscreen/bu21029_ts.c b/drivers/input/touchscreen/bu21029_ts.c
index 49a8d4bbca3a..341925edb8e6 100644
--- a/drivers/input/touchscreen/bu21029_ts.c
+++ b/drivers/input/touchscreen/bu21029_ts.c
@@ -430,7 +430,7 @@ static int __maybe_unused bu21029_suspend(struct device *dev)
 
 	if (!device_may_wakeup(dev)) {
 		mutex_lock(&bu21029->in_dev->mutex);
-		if (bu21029->in_dev->users)
+		if (input_device_enabled(bu21029->in_dev))
 			bu21029_stop_chip(bu21029->in_dev);
 		mutex_unlock(&bu21029->in_dev->mutex);
 	}
@@ -445,7 +445,7 @@ static int __maybe_unused bu21029_resume(struct device *dev)
 
 	if (!device_may_wakeup(dev)) {
 		mutex_lock(&bu21029->in_dev->mutex);
-		if (bu21029->in_dev->users)
+		if (input_device_enabled(bu21029->in_dev))
 			bu21029_start_chip(bu21029->in_dev);
 		mutex_unlock(&bu21029->in_dev->mutex);
 	}
diff --git a/drivers/input/touchscreen/chipone_icn8318.c b/drivers/input/touchscreen/chipone_icn8318.c
index d91d2fd78649..f2fb41fb031e 100644
--- a/drivers/input/touchscreen/chipone_icn8318.c
+++ b/drivers/input/touchscreen/chipone_icn8318.c
@@ -154,7 +154,7 @@ static int icn8318_suspend(struct device *dev)
 	struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev));
 
 	mutex_lock(&data->input->mutex);
-	if (data->input->users)
+	if (input_device_enabled(data->input))
 		icn8318_stop(data->input);
 	mutex_unlock(&data->input->mutex);
 
@@ -166,7 +166,7 @@ static int icn8318_resume(struct device *dev)
 	struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev));
 
 	mutex_lock(&data->input->mutex);
-	if (data->input->users)
+	if (input_device_enabled(data->input))
 		icn8318_start(data->input);
 	mutex_unlock(&data->input->mutex);
 
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c
index 3f5d463dbeed..6e49cb80ec6d 100644
--- a/drivers/input/touchscreen/cyttsp_core.c
+++ b/drivers/input/touchscreen/cyttsp_core.c
@@ -479,7 +479,7 @@ static int __maybe_unused cyttsp_suspend(struct device *dev)
 
 	mutex_lock(&ts->input->mutex);
 
-	if (ts->input->users) {
+	if (input_device_enabled(ts->input)) {
 		retval = cyttsp_disable(ts);
 		if (retval == 0)
 			ts->suspended = true;
@@ -496,7 +496,7 @@ static int __maybe_unused cyttsp_resume(struct device *dev)
 
 	mutex_lock(&ts->input->mutex);
 
-	if (ts->input->users)
+	if (input_device_enabled(ts->input))
 		cyttsp_enable(ts);
 
 	ts->suspended = false;
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index 2e1404cd09ec..a639ba7e56ea 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -241,7 +241,7 @@ static int __maybe_unused eeti_ts_suspend(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		eeti_ts_stop(eeti);
 
 	mutex_unlock(&input_dev->mutex);
@@ -263,7 +263,7 @@ static int __maybe_unused eeti_ts_resume(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		eeti_ts_start(eeti);
 
 	mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/touchscreen/ektf2127.c b/drivers/input/touchscreen/ektf2127.c
index eadd389cf81f..263bbeb6cee9 100644
--- a/drivers/input/touchscreen/ektf2127.c
+++ b/drivers/input/touchscreen/ektf2127.c
@@ -154,7 +154,7 @@ static int __maybe_unused ektf2127_suspend(struct device *dev)
 	struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev));
 
 	mutex_lock(&ts->input->mutex);
-	if (ts->input->users)
+	if (input_device_enabled(ts->input))
 		ektf2127_stop(ts->input);
 	mutex_unlock(&ts->input->mutex);
 
@@ -166,7 +166,7 @@ static int __maybe_unused ektf2127_resume(struct device *dev)
 	struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev));
 
 	mutex_lock(&ts->input->mutex);
-	if (ts->input->users)
+	if (input_device_enabled(ts->input))
 		ektf2127_start(ts->input);
 	mutex_unlock(&ts->input->mutex);
 
diff --git a/drivers/input/touchscreen/imx6ul_tsc.c b/drivers/input/touchscreen/imx6ul_tsc.c
index 9ed258854349..59d4a4e9ecc2 100644
--- a/drivers/input/touchscreen/imx6ul_tsc.c
+++ b/drivers/input/touchscreen/imx6ul_tsc.c
@@ -509,7 +509,7 @@ static int __maybe_unused imx6ul_tsc_suspend(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users) {
+	if (input_device_enabled(input_dev)) {
 		imx6ul_tsc_disable(tsc);
 
 		clk_disable_unprepare(tsc->tsc_clk);
@@ -530,7 +530,7 @@ static int __maybe_unused imx6ul_tsc_resume(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users) {
+	if (input_device_enabled(input_dev)) {
 		retval = clk_prepare_enable(tsc->adc_clk);
 		if (retval)
 			goto out;
diff --git a/drivers/input/touchscreen/ipaq-micro-ts.c b/drivers/input/touchscreen/ipaq-micro-ts.c
index 5c3977e1af6f..0eb5689fe65f 100644
--- a/drivers/input/touchscreen/ipaq-micro-ts.c
+++ b/drivers/input/touchscreen/ipaq-micro-ts.c
@@ -135,7 +135,7 @@ static int __maybe_unused micro_ts_resume(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users)
+	if (input_device_enabled(input))
 		micro_ts_toggle_receive(ts, true);
 
 	mutex_unlock(&input->mutex);
diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c
index 5875bb1099a8..8b7b94ef7f39 100644
--- a/drivers/input/touchscreen/iqs5xx.c
+++ b/drivers/input/touchscreen/iqs5xx.c
@@ -1017,7 +1017,7 @@ static int __maybe_unused iqs5xx_suspend(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users)
+	if (input_device_enabled(input))
 		error = iqs5xx_set_state(iqs5xx->client, IQS5XX_SUSPEND);
 
 	mutex_unlock(&input->mutex);
@@ -1036,7 +1036,7 @@ static int __maybe_unused iqs5xx_resume(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users)
+	if (input_device_enabled(input))
 		error = iqs5xx_set_state(iqs5xx->client, IQS5XX_RESUME);
 
 	mutex_unlock(&input->mutex);
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
index b2cd9472e2d1..b51450b3d943 100644
--- a/drivers/input/touchscreen/lpc32xx_ts.c
+++ b/drivers/input/touchscreen/lpc32xx_ts.c
@@ -334,7 +334,7 @@ static int lpc32xx_ts_suspend(struct device *dev)
 	 */
 	mutex_lock(&input->mutex);
 
-	if (input->users) {
+	if (input_device_enabled(input)) {
 		if (device_may_wakeup(dev))
 			enable_irq_wake(tsc->irq);
 		else
@@ -353,7 +353,7 @@ static int lpc32xx_ts_resume(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users) {
+	if (input_device_enabled(input)) {
 		if (device_may_wakeup(dev))
 			disable_irq_wake(tsc->irq);
 		else
diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c
index 247c3aaba2d8..d33586919f58 100644
--- a/drivers/input/touchscreen/melfas_mip4.c
+++ b/drivers/input/touchscreen/melfas_mip4.c
@@ -1539,7 +1539,7 @@ static int __maybe_unused mip4_suspend(struct device *dev)
 
 	if (device_may_wakeup(dev))
 		ts->wake_irq_enabled = enable_irq_wake(client->irq) == 0;
-	else if (input->users)
+	else if (input_device_enabled(input))
 		mip4_disable(ts);
 
 	mutex_unlock(&input->mutex);
@@ -1557,7 +1557,7 @@ static int __maybe_unused mip4_resume(struct device *dev)
 
 	if (ts->wake_irq_enabled)
 		disable_irq_wake(client->irq);
-	else if (input->users)
+	else if (input_device_enabled(input))
 		mip4_enable(ts);
 
 	mutex_unlock(&input->mutex);
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 2ef1adaed9af..a87caa51204e 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -198,7 +198,7 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
 	int error;
 
 	mutex_lock(&input_dev->mutex);
-	if (!input_dev->users) {
+	if (!input_device_enabled(input_dev)) {
 		mutex_unlock(&input_dev->mutex);
 		goto out;
 	}
@@ -554,7 +554,7 @@ static int __maybe_unused mms114_suspend(struct device *dev)
 	input_sync(input_dev);
 
 	mutex_lock(&input_dev->mutex);
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		mms114_stop(data);
 	mutex_unlock(&input_dev->mutex);
 
@@ -569,7 +569,7 @@ static int __maybe_unused mms114_resume(struct device *dev)
 	int error;
 
 	mutex_lock(&input_dev->mutex);
-	if (input_dev->users) {
+	if (input_device_enabled(input_dev)) {
 		error = mms114_start(data);
 		if (error < 0) {
 			mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 9aa098577350..dc148b4bed74 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -415,14 +415,14 @@ static int __maybe_unused pixcir_i2c_ts_suspend(struct device *dev)
 	mutex_lock(&input->mutex);
 
 	if (device_may_wakeup(&client->dev)) {
-		if (!input->users) {
+		if (!input_device_enabled(input)) {
 			ret = pixcir_start(ts);
 			if (ret) {
 				dev_err(dev, "Failed to start\n");
 				goto unlock;
 			}
 		}
-	} else if (input->users) {
+	} else if (input_device_enabled(input)) {
 		ret = pixcir_stop(ts);
 	}
 
@@ -442,14 +442,14 @@ static int __maybe_unused pixcir_i2c_ts_resume(struct device *dev)
 	mutex_lock(&input->mutex);
 
 	if (device_may_wakeup(&client->dev)) {
-		if (!input->users) {
+		if (!input_device_enabled(input)) {
 			ret = pixcir_stop(ts);
 			if (ret) {
 				dev_err(dev, "Failed to stop\n");
 				goto unlock;
 			}
 		}
-	} else if (input->users) {
+	} else if (input_device_enabled(input)) {
 		ret = pixcir_start(ts);
 	}
 
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index 807d39e18091..e3f2c940ef3d 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -410,7 +410,7 @@ static int __maybe_unused ucb1400_ts_suspend(struct device *dev)
 
 	mutex_lock(&idev->mutex);
 
-	if (idev->users)
+	if (input_device_enabled(idev))
 		ucb1400_ts_stop(ucb);
 
 	mutex_unlock(&idev->mutex);
@@ -424,7 +424,7 @@ static int __maybe_unused ucb1400_ts_resume(struct device *dev)
 
 	mutex_lock(&idev->mutex);
 
-	if (idev->users)
+	if (input_device_enabled(idev))
 		ucb1400_ts_start(ucb);
 
 	mutex_unlock(&idev->mutex);
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index 0a174bd82915..2c2f1b6c5eff 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -806,23 +806,25 @@ static int __maybe_unused wm97xx_suspend(struct device *dev)
 	else
 		suspend_mode = 0;
 
-	if (wm->input_dev->users)
+	mutex_lock(&wm->input_dev->mutex);
+	if (input_device_enabled(wm->input_dev))
 		cancel_delayed_work_sync(&wm->ts_reader);
 
 	/* Power down the digitiser (bypassing the cache for resume) */
 	reg = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER2);
 	reg &= ~WM97XX_PRP_DET_DIG;
-	if (wm->input_dev->users)
+	if (input_device_enabled(wm->input_dev))
 		reg |= suspend_mode;
 	wm->ac97->bus->ops->write(wm->ac97, AC97_WM97XX_DIGITISER2, reg);
 
 	/* WM9713 has an additional power bit - turn it off if there
 	 * are no users or if suspend mode is zero. */
 	if (wm->id == WM9713_ID2 &&
-	    (!wm->input_dev->users || !suspend_mode)) {
+	    (!input_device_enabled(wm->input_dev) || !suspend_mode)) {
 		reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) | 0x8000;
 		wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
 	}
+	mutex_unlock(&wm->input_dev->mutex);
 
 	return 0;
 }
@@ -831,11 +833,12 @@ static int __maybe_unused wm97xx_resume(struct device *dev)
 {
 	struct wm97xx *wm = dev_get_drvdata(dev);
 
+	mutex_lock(&wm->input_dev->mutex);
 	/* restore digitiser and gpios */
 	if (wm->id == WM9713_ID2) {
 		wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]);
 		wm97xx_reg_write(wm, 0x5a, wm->misc);
-		if (wm->input_dev->users) {
+		if (input_device_enabled(wm->input_dev)) {
 			u16 reg;
 			reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) & 0x7fff;
 			wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
@@ -852,11 +855,12 @@ static int __maybe_unused wm97xx_resume(struct device *dev)
 	wm97xx_reg_write(wm, AC97_GPIO_STATUS, wm->gpio[4]);
 	wm97xx_reg_write(wm, AC97_MISC_AFE, wm->gpio[5]);
 
-	if (wm->input_dev->users && !wm->pen_irq) {
+	if (input_device_enabled(wm->input_dev) && !wm->pen_irq) {
 		wm->ts_reader_interval = wm->ts_reader_min_interval;
 		queue_delayed_work(wm->ts_workq, &wm->ts_reader,
 				   wm->ts_reader_interval);
 	}
+	mutex_unlock(&wm->input_dev->mutex);
 
 	return 0;
 }
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c
index 5230519b0f74..495629628af6 100644
--- a/drivers/input/touchscreen/zforce_ts.c
+++ b/drivers/input/touchscreen/zforce_ts.c
@@ -626,14 +626,14 @@ static int __maybe_unused zforce_suspend(struct device *dev)
 		dev_dbg(&client->dev, "suspend while being a wakeup source\n");
 
 		/* Need to start device, if not open, to be a wakeup source. */
-		if (!input->users) {
+		if (!input_device_enabled(input)) {
 			ret = zforce_start(ts);
 			if (ret)
 				goto unlock;
 		}
 
 		enable_irq_wake(client->irq);
-	} else if (input->users) {
+	} else if (input_device_enabled(input)) {
 		dev_dbg(&client->dev,
 			"suspend without being a wakeup source\n");
 
@@ -670,12 +670,12 @@ static int __maybe_unused zforce_resume(struct device *dev)
 		disable_irq_wake(client->irq);
 
 		/* need to stop device if it was not open on suspend */
-		if (!input->users) {
+		if (!input_device_enabled(input)) {
 			ret = zforce_stop(ts);
 			if (ret)
 				goto unlock;
 		}
-	} else if (input->users) {
+	} else if (input_device_enabled(input)) {
 		dev_dbg(&client->dev, "resume without being a wakeup source\n");
 
 		enable_irq(client->irq);
-- 
2.17.1


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

* [PATCH v3 3/7] ACPI: button: Access input device's users under appropriate mutex
  2020-06-05 17:33                                     ` [PATCH v3 " Andrzej Pietrasiewicz
  2020-06-05 17:33                                       ` [PATCH v3 1/7] Input: add input_device_enabled() Andrzej Pietrasiewicz
  2020-06-05 17:33                                       ` [PATCH v3 2/7] Input: use input_device_enabled() Andrzej Pietrasiewicz
@ 2020-06-05 17:33                                       ` Andrzej Pietrasiewicz
  2020-06-05 17:33                                       ` [PATCH v3 4/7] ACPI: button: Use input_device_enabled() helper Andrzej Pietrasiewicz
                                                         ` (4 subsequent siblings)
  7 siblings, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-05 17:33 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

Inspecting input device's 'users' member should be done under device's
mutex, so add appropriate invocations.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/acpi/button.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 78cfc70cb320..ff7ab291f678 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -456,13 +456,16 @@ static int acpi_button_resume(struct device *dev)
 {
 	struct acpi_device *device = to_acpi_device(dev);
 	struct acpi_button *button = acpi_driver_data(device);
+	struct input_dev *input = button->input;
 
 	button->suspended = false;
-	if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users) {
+	mutex_lock(&input->mutex);
+	if (button->type == ACPI_BUTTON_TYPE_LID && input->users) {
 		button->last_state = !!acpi_lid_evaluate_state(device);
 		button->last_time = ktime_get();
 		acpi_lid_initialize_state(device);
 	}
+	mutex_unlock(&input->mutex);
 	return 0;
 }
 #endif
-- 
2.17.1


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

* [PATCH v3 4/7] ACPI: button: Use input_device_enabled() helper
  2020-06-05 17:33                                     ` [PATCH v3 " Andrzej Pietrasiewicz
                                                         ` (2 preceding siblings ...)
  2020-06-05 17:33                                       ` [PATCH v3 3/7] ACPI: button: Access input device's users under appropriate mutex Andrzej Pietrasiewicz
@ 2020-06-05 17:33                                       ` Andrzej Pietrasiewicz
  2020-06-05 17:33                                       ` [PATCH v3 5/7] iio: adc: exynos: Use input_device_enabled() Andrzej Pietrasiewicz
                                                         ` (3 subsequent siblings)
  7 siblings, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-05 17:33 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

A new helper is available, so use it.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/acpi/button.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index ff7ab291f678..4deb2b48d03c 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -411,7 +411,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
 		input = button->input;
 		if (button->type == ACPI_BUTTON_TYPE_LID) {
 			mutex_lock(&button->input->mutex);
-			users = button->input->users;
+			users = input_device_enabled(button->input);
 			mutex_unlock(&button->input->mutex);
 			if (users)
 				acpi_lid_update_state(device, true);
@@ -460,7 +460,7 @@ static int acpi_button_resume(struct device *dev)
 
 	button->suspended = false;
 	mutex_lock(&input->mutex);
-	if (button->type == ACPI_BUTTON_TYPE_LID && input->users) {
+	if (button->type == ACPI_BUTTON_TYPE_LID && input_device_enabled(input)) {
 		button->last_state = !!acpi_lid_evaluate_state(device);
 		button->last_time = ktime_get();
 		acpi_lid_initialize_state(device);
-- 
2.17.1


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

* [PATCH v3 5/7] iio: adc: exynos: Use input_device_enabled()
  2020-06-05 17:33                                     ` [PATCH v3 " Andrzej Pietrasiewicz
                                                         ` (3 preceding siblings ...)
  2020-06-05 17:33                                       ` [PATCH v3 4/7] ACPI: button: Use input_device_enabled() helper Andrzej Pietrasiewicz
@ 2020-06-05 17:33                                       ` Andrzej Pietrasiewicz
  2020-06-05 19:49                                         ` Michał Mirosław
  2020-06-05 17:33                                       ` [PATCH v3 6/7] platform/x86: thinkpad_acpi: " Andrzej Pietrasiewicz
                                                         ` (2 subsequent siblings)
  7 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-05 17:33 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

A new helper is available, so use it. Inspecting 'users' member of
input_dev requires taking device's mutex.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/iio/adc/exynos_adc.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 22131a677445..294715bafe25 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -630,10 +630,13 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
 	struct exynos_adc *info = dev_id;
 	struct iio_dev *dev = dev_get_drvdata(info->dev);
 	u32 x, y;
-	bool pressed;
+	bool pressed, cont;
 	int ret;
 
-	while (info->input->users) {
+	mutex_lock(&info->input->mutex);
+	cont = input_device_enabled(info->input);
+	mutex_unlock(&info->input->mutex);
+	while (cont) {
 		ret = exynos_read_s3c64xx_ts(dev, &x, &y);
 		if (ret == -ETIMEDOUT)
 			break;
@@ -651,6 +654,10 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
 		input_sync(info->input);
 
 		usleep_range(1000, 1100);
+
+		mutex_lock(&info->input->mutex);
+		cont = input_device_enabled(info->input);
+		mutex_unlock(&info->input->mutex);
 	}
 
 	writel(0, ADC_V1_CLRINTPNDNUP(info->regs));
-- 
2.17.1


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

* [PATCH v3 6/7] platform/x86: thinkpad_acpi: Use input_device_enabled()
  2020-06-05 17:33                                     ` [PATCH v3 " Andrzej Pietrasiewicz
                                                         ` (4 preceding siblings ...)
  2020-06-05 17:33                                       ` [PATCH v3 5/7] iio: adc: exynos: Use input_device_enabled() Andrzej Pietrasiewicz
@ 2020-06-05 17:33                                       ` Andrzej Pietrasiewicz
  2020-06-05 17:33                                       ` [PATCH v3 7/7] Input: Add "inhibited" property Andrzej Pietrasiewicz
  2020-06-07 20:24                                       ` [PATCH v3 " Pavel Machek
  7 siblings, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-05 17:33 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

Use the new helper. Inspecting input device's 'users' member needs to be
done under device's mutex, so add appropriate invocations.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
Acked-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
---
 drivers/platform/x86/thinkpad_acpi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 0f704484ae1d..8ae11b8c3ebb 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -2671,9 +2671,10 @@ static void hotkey_poll_setup(const bool may_warn)
 	const u32 poll_driver_mask = hotkey_driver_mask & hotkey_source_mask;
 	const u32 poll_user_mask = hotkey_user_mask & hotkey_source_mask;
 
+	mutex_lock(&tpacpi_inputdev->mutex);
 	if (hotkey_poll_freq > 0 &&
 	    (poll_driver_mask ||
-	     (poll_user_mask && tpacpi_inputdev->users > 0))) {
+	     (poll_user_mask && input_device_enabled(tpacpi_inputdev)))) {
 		if (!tpacpi_hotkey_task) {
 			tpacpi_hotkey_task = kthread_run(hotkey_kthread,
 					NULL, TPACPI_NVRAM_KTHREAD_NAME);
@@ -2690,6 +2691,7 @@ static void hotkey_poll_setup(const bool may_warn)
 				  poll_user_mask, poll_driver_mask);
 		}
 	}
+	mutex_unlock(&tpacpi_inputdev->mutex);
 }
 
 static void hotkey_poll_setup_safe(const bool may_warn)
-- 
2.17.1


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

* [PATCH v3 7/7] Input: Add "inhibited" property
  2020-06-05 17:33                                     ` [PATCH v3 " Andrzej Pietrasiewicz
                                                         ` (5 preceding siblings ...)
  2020-06-05 17:33                                       ` [PATCH v3 6/7] platform/x86: thinkpad_acpi: " Andrzej Pietrasiewicz
@ 2020-06-05 17:33                                       ` Andrzej Pietrasiewicz
  2020-06-05 17:41                                         ` Hans de Goede
  2020-06-07 20:24                                       ` [PATCH v3 " Pavel Machek
  7 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-05 17:33 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel, Patrik Fimml

From: Patrik Fimml <patrikf@chromium.org>

Userspace might want to implement a policy to temporarily disregard input
from certain devices, including not treating them as wakeup sources.

An example use case is a laptop, whose keyboard can be folded under the
screen to create tablet-like experience. The user then must hold the laptop
in such a way that it is difficult to avoid pressing the keyboard keys. It
is therefore desirable to temporarily disregard input from the keyboard,
until it is folded back. This obviously is a policy which should be kept
out of the kernel, but the kernel must provide suitable means to implement
such a policy.

This patch adds a sysfs interface for exactly this purpose.

To implement the said interface it adds an "inhibited" property to struct
input_dev, and effectively creates four states a device can be in: closed
uninhibited, closed inhibited, open uninhibited, open inhibited. It also
defers calling driver's ->open() and ->close() to until they are actually
needed, e.g. it makes no sense to prepare the underlying device for
generating events (->open()) if the device is inhibited.

              uninhibit
closed      <------------ closed
uninhibited ------------> inhibited
      | ^     inhibit        | ^
 1st  | |               1st  | |
 open | |               open | |
      | |                    | |
      | | last               | | last
      | | close              | | close
      v |     uninhibit      v |
open        <------------ open
uninhibited ------------> inhibited

The top inhibit/uninhibit transition happens when users == 0.
The bottom inhibit/uninhibit transition happens when users > 0.
The left open/close transition happens when !inhibited.
The right open/close transition happens when inhibited.
Due to all transitions being serialized with dev->mutex, it is impossible
to have "diagonal" transitions between closed uninhibited and open
inhibited or between open uninhibited and closed inhibited.

No new callbacks are added to drivers, because their open() and close()
serve exactly the purpose to tell the driver to start/stop providing
events to the input core. Consequently, open() and close() - if provided
- are called in both inhibit and uninhibit paths.

Signed-off-by: Patrik Fimml <patrikf@chromium.org>
Co-developed-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/input/input.c | 115 +++++++++++++++++++++++++++++++++++++++---
 include/linux/input.h |  12 ++++-
 2 files changed, 118 insertions(+), 9 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index 41377bfa142d..4110b5797219 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -284,8 +284,11 @@ static int input_get_disposition(struct input_dev *dev,
 	case EV_KEY:
 		if (is_event_supported(code, dev->keybit, KEY_MAX)) {
 
-			/* auto-repeat bypasses state updates */
-			if (value == 2) {
+			/*
+			 * auto-repeat bypasses state updates but repeat
+			 * events are ignored if the key is not pressed
+			 */
+			if (value == 2 && test_bit(code, dev->key)) {
 				disposition = INPUT_PASS_TO_HANDLERS;
 				break;
 			}
@@ -367,8 +370,13 @@ static int input_get_disposition(struct input_dev *dev,
 static void input_handle_event(struct input_dev *dev,
 			       unsigned int type, unsigned int code, int value)
 {
-	int disposition = input_get_disposition(dev, type, code, &value);
+	int disposition;
+
+	/* filter-out events from inhibited devices */
+	if (dev->inhibited)
+		return;
 
+	disposition = input_get_disposition(dev, type, code, &value);
 	if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
 		add_input_randomness(type, code, value);
 
@@ -612,7 +620,7 @@ int input_open_device(struct input_handle *handle)
 
 	handle->open++;
 
-	if (dev->users++) {
+	if (dev->users++ || dev->inhibited) {
 		/*
 		 * Device is already opened, so we can exit immediately and
 		 * report success.
@@ -675,10 +683,9 @@ void input_close_device(struct input_handle *handle)
 
 	__input_release_device(handle);
 
-	if (!--dev->users) {
+	if (!dev->inhibited && !--dev->users) {
 		if (dev->poller)
 			input_dev_poller_stop(dev->poller);
-
 		if (dev->close)
 			dev->close(dev);
 	}
@@ -1416,12 +1423,49 @@ static ssize_t input_dev_show_properties(struct device *dev,
 }
 static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL);
 
+static int input_inhibit_device(struct input_dev *dev);
+static int input_uninhibit_device(struct input_dev *dev);
+
+static ssize_t inhibited_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct input_dev *input_dev = to_input_dev(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", input_dev->inhibited);
+}
+
+static ssize_t inhibited_store(struct device *dev,
+			       struct device_attribute *attr, const char *buf,
+			       size_t len)
+{
+	struct input_dev *input_dev = to_input_dev(dev);
+	ssize_t rv;
+	bool inhibited;
+
+	if (strtobool(buf, &inhibited))
+		return -EINVAL;
+
+	if (inhibited)
+		rv = input_inhibit_device(input_dev);
+	else
+		rv = input_uninhibit_device(input_dev);
+
+	if (rv != 0)
+		return rv;
+
+	return len;
+}
+
+static DEVICE_ATTR_RW(inhibited);
+
 static struct attribute *input_dev_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_phys.attr,
 	&dev_attr_uniq.attr,
 	&dev_attr_modalias.attr,
 	&dev_attr_properties.attr,
+	&dev_attr_inhibited.attr,
 	NULL
 };
 
@@ -1703,6 +1747,63 @@ void input_reset_device(struct input_dev *dev)
 }
 EXPORT_SYMBOL(input_reset_device);
 
+static int input_inhibit_device(struct input_dev *dev)
+{
+	int ret = 0;
+
+	mutex_lock(&dev->mutex);
+
+	if (dev->inhibited)
+		goto out;
+
+	if (dev->users) {
+		if (dev->close)
+			dev->close(dev);
+		if (dev->poller)
+			input_dev_poller_stop(dev->poller);
+	}
+
+	spin_lock_irq(&dev->event_lock);
+	input_dev_release_keys(dev);
+	input_dev_toggle(dev, false);
+	spin_unlock_irq(&dev->event_lock);
+
+	dev->inhibited = true;
+
+out:
+	mutex_unlock(&dev->mutex);
+	return ret;
+}
+
+static int input_uninhibit_device(struct input_dev *dev)
+{
+	int ret = 0;
+
+	mutex_lock(&dev->mutex);
+
+	if (!dev->inhibited)
+		goto out;
+
+	if (dev->users) {
+		if (dev->open) {
+			ret = dev->open(dev);
+			if (ret)
+				goto out;
+		}
+		if (dev->poller)
+			input_dev_poller_start(dev->poller);
+	}
+
+	dev->inhibited = false;
+	spin_lock_irq(&dev->event_lock);
+	input_dev_toggle(dev, true);
+	spin_unlock_irq(&dev->event_lock);
+
+out:
+	mutex_unlock(&dev->mutex);
+	return ret;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int input_dev_suspend(struct device *dev)
 {
@@ -2131,7 +2232,7 @@ bool input_device_enabled(struct input_dev *dev)
 {
 	lockdep_assert_held(&dev->mutex);
 
-	return dev->users > 0;
+	return !dev->inhibited && dev->users > 0;
 }
 EXPORT_SYMBOL_GPL(input_device_enabled);
 
diff --git a/include/linux/input.h b/include/linux/input.h
index eda4587dba67..0354b298d874 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -90,9 +90,11 @@ enum input_clock_type {
  * @open: this method is called when the very first user calls
  *	input_open_device(). The driver must prepare the device
  *	to start generating events (start polling thread,
- *	request an IRQ, submit URB, etc.)
+ *	request an IRQ, submit URB, etc.). The meaning of open() is
+ *	to start providing events to the input core.
  * @close: this method is called when the very last user calls
- *	input_close_device().
+ *	input_close_device(). The meaning of close() is to stop
+ *	providing events to the input core.
  * @flush: purges the device. Most commonly used to get rid of force
  *	feedback effects loaded into the device when disconnecting
  *	from it
@@ -127,6 +129,10 @@ enum input_clock_type {
  *	and needs not be explicitly unregistered or freed.
  * @timestamp: storage for a timestamp set by input_set_timestamp called
  *  by a driver
+ * @inhibited: indicates that the input device is inhibited. If that is
+ * the case then input core ignores any events generated by the device.
+ * Device's close() is called when it is being inhibited and its open()
+ * is called when it is being uninhibited.
  */
 struct input_dev {
 	const char *name;
@@ -201,6 +207,8 @@ struct input_dev {
 	bool devres_managed;
 
 	ktime_t timestamp[INPUT_CLK_MAX];
+
+	bool inhibited;
 };
 #define to_input_dev(d) container_of(d, struct input_dev, dev)
 
-- 
2.17.1


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

* Re: [PATCH v3 7/7] Input: Add "inhibited" property
  2020-06-05 17:33                                       ` [PATCH v3 7/7] Input: Add "inhibited" property Andrzej Pietrasiewicz
@ 2020-06-05 17:41                                         ` Hans de Goede
  2020-06-08 11:22                                           ` [PATCH v4 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
  0 siblings, 1 reply; 80+ messages in thread
From: Hans de Goede @ 2020-06-05 17:41 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, linux-pm, linux-acpi, linux-kernel,
	linux-iio, linux-arm-kernel, linux-samsung-soc, linux-input,
	linux-tegra, patches, ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, kernel, Patrik Fimml

Hi,

On 6/5/20 7:33 PM, Andrzej Pietrasiewicz wrote:
> From: Patrik Fimml <patrikf@chromium.org>
> 
> Userspace might want to implement a policy to temporarily disregard input
> from certain devices, including not treating them as wakeup sources.
> 
> An example use case is a laptop, whose keyboard can be folded under the
> screen to create tablet-like experience. The user then must hold the laptop
> in such a way that it is difficult to avoid pressing the keyboard keys. It
> is therefore desirable to temporarily disregard input from the keyboard,
> until it is folded back. This obviously is a policy which should be kept
> out of the kernel, but the kernel must provide suitable means to implement
> such a policy.
> 
> This patch adds a sysfs interface for exactly this purpose.
> 
> To implement the said interface it adds an "inhibited" property to struct
> input_dev, and effectively creates four states a device can be in: closed
> uninhibited, closed inhibited, open uninhibited, open inhibited. It also
> defers calling driver's ->open() and ->close() to until they are actually
> needed, e.g. it makes no sense to prepare the underlying device for
> generating events (->open()) if the device is inhibited.
> 
>                uninhibit
> closed      <------------ closed
> uninhibited ------------> inhibited
>        | ^     inhibit        | ^
>   1st  | |               1st  | |
>   open | |               open | |
>        | |                    | |
>        | | last               | | last
>        | | close              | | close
>        v |     uninhibit      v |
> open        <------------ open
> uninhibited ------------> inhibited
> 
> The top inhibit/uninhibit transition happens when users == 0.
> The bottom inhibit/uninhibit transition happens when users > 0.
> The left open/close transition happens when !inhibited.
> The right open/close transition happens when inhibited.
> Due to all transitions being serialized with dev->mutex, it is impossible
> to have "diagonal" transitions between closed uninhibited and open
> inhibited or between open uninhibited and closed inhibited.
> 
> No new callbacks are added to drivers, because their open() and close()
> serve exactly the purpose to tell the driver to start/stop providing
> events to the input core. Consequently, open() and close() - if provided
> - are called in both inhibit and uninhibit paths.
> 
> Signed-off-by: Patrik Fimml <patrikf@chromium.org>
> Co-developed-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> ---
>   drivers/input/input.c | 115 +++++++++++++++++++++++++++++++++++++++---
>   include/linux/input.h |  12 ++++-
>   2 files changed, 118 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/input/input.c b/drivers/input/input.c
> index 41377bfa142d..4110b5797219 100644
> --- a/drivers/input/input.c
> +++ b/drivers/input/input.c
> @@ -284,8 +284,11 @@ static int input_get_disposition(struct input_dev *dev,
>   	case EV_KEY:
>   		if (is_event_supported(code, dev->keybit, KEY_MAX)) {
>   
> -			/* auto-repeat bypasses state updates */
> -			if (value == 2) {
> +			/*
> +			 * auto-repeat bypasses state updates but repeat
> +			 * events are ignored if the key is not pressed
> +			 */
> +			if (value == 2 && test_bit(code, dev->key)) {
>   				disposition = INPUT_PASS_TO_HANDLERS;
>   				break;
>   			}
> @@ -367,8 +370,13 @@ static int input_get_disposition(struct input_dev *dev,
>   static void input_handle_event(struct input_dev *dev,
>   			       unsigned int type, unsigned int code, int value)
>   {
> -	int disposition = input_get_disposition(dev, type, code, &value);
> +	int disposition;
> +
> +	/* filter-out events from inhibited devices */
> +	if (dev->inhibited)
> +		return;
>   
> +	disposition = input_get_disposition(dev, type, code, &value);
>   	if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
>   		add_input_randomness(type, code, value);
>   
> @@ -612,7 +620,7 @@ int input_open_device(struct input_handle *handle)
>   
>   	handle->open++;
>   
> -	if (dev->users++) {
> +	if (dev->users++ || dev->inhibited) {
>   		/*
>   		 * Device is already opened, so we can exit immediately and
>   		 * report success.

It seems the comment which is part of the context here may need some
updating because of the inhibit changes ?

Otherwise this patch and the rest of the series looks good to me
now. Thank you very much for your work on this.

Regards,

Hans




> @@ -675,10 +683,9 @@ void input_close_device(struct input_handle *handle)
>   
>   	__input_release_device(handle);
>   
> -	if (!--dev->users) {
> +	if (!dev->inhibited && !--dev->users) {
>   		if (dev->poller)
>   			input_dev_poller_stop(dev->poller);
> -
>   		if (dev->close)
>   			dev->close(dev);
>   	}
> @@ -1416,12 +1423,49 @@ static ssize_t input_dev_show_properties(struct device *dev,
>   }
>   static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL);
>   
> +static int input_inhibit_device(struct input_dev *dev);
> +static int input_uninhibit_device(struct input_dev *dev);
> +
> +static ssize_t inhibited_show(struct device *dev,
> +			      struct device_attribute *attr,
> +			      char *buf)
> +{
> +	struct input_dev *input_dev = to_input_dev(dev);
> +
> +	return scnprintf(buf, PAGE_SIZE, "%d\n", input_dev->inhibited);
> +}
> +
> +static ssize_t inhibited_store(struct device *dev,
> +			       struct device_attribute *attr, const char *buf,
> +			       size_t len)
> +{
> +	struct input_dev *input_dev = to_input_dev(dev);
> +	ssize_t rv;
> +	bool inhibited;
> +
> +	if (strtobool(buf, &inhibited))
> +		return -EINVAL;
> +
> +	if (inhibited)
> +		rv = input_inhibit_device(input_dev);
> +	else
> +		rv = input_uninhibit_device(input_dev);
> +
> +	if (rv != 0)
> +		return rv;
> +
> +	return len;
> +}
> +
> +static DEVICE_ATTR_RW(inhibited);
> +
>   static struct attribute *input_dev_attrs[] = {
>   	&dev_attr_name.attr,
>   	&dev_attr_phys.attr,
>   	&dev_attr_uniq.attr,
>   	&dev_attr_modalias.attr,
>   	&dev_attr_properties.attr,
> +	&dev_attr_inhibited.attr,
>   	NULL
>   };
>   
> @@ -1703,6 +1747,63 @@ void input_reset_device(struct input_dev *dev)
>   }
>   EXPORT_SYMBOL(input_reset_device);
>   
> +static int input_inhibit_device(struct input_dev *dev)
> +{
> +	int ret = 0;
> +
> +	mutex_lock(&dev->mutex);
> +
> +	if (dev->inhibited)
> +		goto out;
> +
> +	if (dev->users) {
> +		if (dev->close)
> +			dev->close(dev);
> +		if (dev->poller)
> +			input_dev_poller_stop(dev->poller);
> +	}
> +
> +	spin_lock_irq(&dev->event_lock);
> +	input_dev_release_keys(dev);
> +	input_dev_toggle(dev, false);
> +	spin_unlock_irq(&dev->event_lock);
> +
> +	dev->inhibited = true;
> +
> +out:
> +	mutex_unlock(&dev->mutex);
> +	return ret;
> +}
> +
> +static int input_uninhibit_device(struct input_dev *dev)
> +{
> +	int ret = 0;
> +
> +	mutex_lock(&dev->mutex);
> +
> +	if (!dev->inhibited)
> +		goto out;
> +
> +	if (dev->users) {
> +		if (dev->open) {
> +			ret = dev->open(dev);
> +			if (ret)
> +				goto out;
> +		}
> +		if (dev->poller)
> +			input_dev_poller_start(dev->poller);
> +	}
> +
> +	dev->inhibited = false;
> +	spin_lock_irq(&dev->event_lock);
> +	input_dev_toggle(dev, true);
> +	spin_unlock_irq(&dev->event_lock);
> +
> +out:
> +	mutex_unlock(&dev->mutex);
> +	return ret;
> +}
> +
>   #ifdef CONFIG_PM_SLEEP
>   static int input_dev_suspend(struct device *dev)
>   {
> @@ -2131,7 +2232,7 @@ bool input_device_enabled(struct input_dev *dev)
>   {
>   	lockdep_assert_held(&dev->mutex);
>   
> -	return dev->users > 0;
> +	return !dev->inhibited && dev->users > 0;
>   }
>   EXPORT_SYMBOL_GPL(input_device_enabled);
>   
> diff --git a/include/linux/input.h b/include/linux/input.h
> index eda4587dba67..0354b298d874 100644
> --- a/include/linux/input.h
> +++ b/include/linux/input.h
> @@ -90,9 +90,11 @@ enum input_clock_type {
>    * @open: this method is called when the very first user calls
>    *	input_open_device(). The driver must prepare the device
>    *	to start generating events (start polling thread,
> - *	request an IRQ, submit URB, etc.)
> + *	request an IRQ, submit URB, etc.). The meaning of open() is
> + *	to start providing events to the input core.
>    * @close: this method is called when the very last user calls
> - *	input_close_device().
> + *	input_close_device(). The meaning of close() is to stop
> + *	providing events to the input core.
>    * @flush: purges the device. Most commonly used to get rid of force
>    *	feedback effects loaded into the device when disconnecting
>    *	from it
> @@ -127,6 +129,10 @@ enum input_clock_type {
>    *	and needs not be explicitly unregistered or freed.
>    * @timestamp: storage for a timestamp set by input_set_timestamp called
>    *  by a driver
> + * @inhibited: indicates that the input device is inhibited. If that is
> + * the case then input core ignores any events generated by the device.
> + * Device's close() is called when it is being inhibited and its open()
> + * is called when it is being uninhibited.
>    */
>   struct input_dev {
>   	const char *name;
> @@ -201,6 +207,8 @@ struct input_dev {
>   	bool devres_managed;
>   
>   	ktime_t timestamp[INPUT_CLK_MAX];
> +
> +	bool inhibited;
>   };
>   #define to_input_dev(d) container_of(d, struct input_dev, dev)
>   
> 


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

* Re: [PATCH v3 5/7] iio: adc: exynos: Use input_device_enabled()
  2020-06-05 17:33                                       ` [PATCH v3 5/7] iio: adc: exynos: Use input_device_enabled() Andrzej Pietrasiewicz
@ 2020-06-05 19:49                                         ` Michał Mirosław
  0 siblings, 0 replies; 80+ messages in thread
From: Michał Mirosław @ 2020-06-05 19:49 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz
  Cc: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh, kernel

On Fri, Jun 05, 2020 at 07:33:33PM +0200, Andrzej Pietrasiewicz wrote:
> A new helper is available, so use it. Inspecting 'users' member of
> input_dev requires taking device's mutex.
> 
> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> ---
>  drivers/iio/adc/exynos_adc.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
> index 22131a677445..294715bafe25 100644
> --- a/drivers/iio/adc/exynos_adc.c
> +++ b/drivers/iio/adc/exynos_adc.c
> @@ -630,10 +630,13 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
>  	struct exynos_adc *info = dev_id;
>  	struct iio_dev *dev = dev_get_drvdata(info->dev);
>  	u32 x, y;
> -	bool pressed;
> +	bool pressed, cont;
>  	int ret;
>  
> -	while (info->input->users) {
> +	mutex_lock(&info->input->mutex);
> +	cont = input_device_enabled(info->input);
> +	mutex_unlock(&info->input->mutex);
> +	while (cont) {
>  		ret = exynos_read_s3c64xx_ts(dev, &x, &y);
>  		if (ret == -ETIMEDOUT)
>  			break;
> @@ -651,6 +654,10 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
>  		input_sync(info->input);
>  
>  		usleep_range(1000, 1100);
> +
> +		mutex_lock(&info->input->mutex);
> +		cont = input_device_enabled(info->input);
> +		mutex_unlock(&info->input->mutex);
>  	}

The mutex doesn't really protect anything here, but I would nevertheless
suggest this sequence instead:

lock()
while (test) {
	unlock()
	...
	lock()
}
unlock()

Best Regards,
Michał Mirosław

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

* Re: [PATCH v3 0/7] Support inhibiting input devices
  2020-06-05 17:33                                     ` [PATCH v3 " Andrzej Pietrasiewicz
                                                         ` (6 preceding siblings ...)
  2020-06-05 17:33                                       ` [PATCH v3 7/7] Input: Add "inhibited" property Andrzej Pietrasiewicz
@ 2020-06-07 20:24                                       ` Pavel Machek
  2020-06-08  5:37                                         ` Dmitry Torokhov
  7 siblings, 1 reply; 80+ messages in thread
From: Pavel Machek @ 2020-06-07 20:24 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz
  Cc: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh, kernel


[-- Attachment #1: Type: text/plain, Size: 1485 bytes --]

On Fri 2020-06-05 19:33:28, Andrzej Pietrasiewicz wrote:
> Userspace might want to implement a policy to temporarily disregard input
> from certain devices.

Wow, you certainly cc a lot of lists.

> An example use case is a convertible laptop, whose keyboard can be folded
> under the screen to create tablet-like experience. The user then must hold
> the laptop in such a way that it is difficult to avoid pressing the keyboard
> keys. It is therefore desirable to temporarily disregard input from the
> keyboard, until it is folded back. This obviously is a policy which should
> be kept out of the kernel, but the kernel must provide suitable means to
> implement such a policy.
> 
> Due to interactions with suspend/resume, a helper has been added for drivers
> to decide if the device is being used or not (PATCH 1/7) and it has been
> applied to relevant drivers (PATCH 2,4,5,6/7).

But is that a right way to implement it?

We want this for cellphones, too -- touchscreen should be disabled
while the device is locked in the pocket -- but we really want the
touchscreen hardware to be powered down in that case (because it keeps
SoC busy and eats a _lot_ of electricity).

But simplistic "receive an event and then drop it if device is
inhibited" does not allow that...

Best regards,
								Pavel
								
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

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

* Re: [PATCH v3 0/7] Support inhibiting input devices
  2020-06-07 20:24                                       ` [PATCH v3 " Pavel Machek
@ 2020-06-08  5:37                                         ` Dmitry Torokhov
  2020-06-08  9:28                                           ` Andrzej Pietrasiewicz
  0 siblings, 1 reply; 80+ messages in thread
From: Dmitry Torokhov @ 2020-06-08  5:37 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Andrzej Pietrasiewicz, linux-pm, linux-acpi, linux-kernel,
	linux-iio, linux-arm-kernel, linux-samsung-soc, linux-input,
	linux-tegra, patches, ibm-acpi-devel, platform-driver-x86,
	Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh, kernel

On Sun, Jun 07, 2020 at 10:24:14PM +0200, Pavel Machek wrote:
> On Fri 2020-06-05 19:33:28, Andrzej Pietrasiewicz wrote:
> > Userspace might want to implement a policy to temporarily disregard input
> > from certain devices.
> 
> Wow, you certainly cc a lot of lists.
> 
> > An example use case is a convertible laptop, whose keyboard can be folded
> > under the screen to create tablet-like experience. The user then must hold
> > the laptop in such a way that it is difficult to avoid pressing the keyboard
> > keys. It is therefore desirable to temporarily disregard input from the
> > keyboard, until it is folded back. This obviously is a policy which should
> > be kept out of the kernel, but the kernel must provide suitable means to
> > implement such a policy.
> > 
> > Due to interactions with suspend/resume, a helper has been added for drivers
> > to decide if the device is being used or not (PATCH 1/7) and it has been
> > applied to relevant drivers (PATCH 2,4,5,6/7).
> 
> But is that a right way to implement it?
> 
> We want this for cellphones, too -- touchscreen should be disabled
> while the device is locked in the pocket -- but we really want the
> touchscreen hardware to be powered down in that case (because it keeps
> SoC busy and eats a _lot_ of electricity).
> 
> But simplistic "receive an event and then drop it if device is
> inhibited" does not allow that...

I do not think you read the entirety of this patch series...

Thanks.

-- 
Dmitry

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

* Re: [PATCH v3 0/7] Support inhibiting input devices
  2020-06-08  5:37                                         ` Dmitry Torokhov
@ 2020-06-08  9:28                                           ` Andrzej Pietrasiewicz
  0 siblings, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-08  9:28 UTC (permalink / raw)
  To: Dmitry Torokhov, Pavel Machek
  Cc: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Hans de Goede, Ferruh Yigit,
	Sangwon Jee, Peter Hutterer, Henrique de Moraes Holschuh, kernel

Hi Pavel,

W dniu 08.06.2020 o 07:37, Dmitry Torokhov pisze:
> On Sun, Jun 07, 2020 at 10:24:14PM +0200, Pavel Machek wrote:
>> On Fri 2020-06-05 19:33:28, Andrzej Pietrasiewicz wrote:
>>> Userspace might want to implement a policy to temporarily disregard input
>>> from certain devices.
>>
>> Wow, you certainly cc a lot of lists.
>>
>>> An example use case is a convertible laptop, whose keyboard can be folded
>>> under the screen to create tablet-like experience. The user then must hold
>>> the laptop in such a way that it is difficult to avoid pressing the keyboard
>>> keys. It is therefore desirable to temporarily disregard input from the
>>> keyboard, until it is folded back. This obviously is a policy which should
>>> be kept out of the kernel, but the kernel must provide suitable means to
>>> implement such a policy.
>>>
>>> Due to interactions with suspend/resume, a helper has been added for drivers
>>> to decide if the device is being used or not (PATCH 1/7) and it has been
>>> applied to relevant drivers (PATCH 2,4,5,6/7).
>>
>> But is that a right way to implement it?
>>
>> We want this for cellphones, too -- touchscreen should be disabled
>> while the device is locked in the pocket -- but we really want the
>> touchscreen hardware to be powered down in that case (because it keeps
>> SoC busy and eats a _lot_ of electricity).
>>
>> But simplistic "receive an event and then drop it if device is
>> inhibited" does not allow that...
> 
> I do not think you read the entirety of this patch series...
> 

Yeah, kindly read the whole thread. Long story short: Inhibiting _is_ about
ignoring events from inhibited devices. Obviously we can do better than
just that. Indeed, the open() and close() callbacks (which are called at
uninhibiting/inhibiting) mean "start providing events" and "stop providing
events", respectively. How that translates into driver operation is highly
driver-specific and cannot be handled at the input subsystem level, but it
is the place where power savings can be realized: whenever the driver knows
that nobody wants events from it it can do whatever it considers appropriate,
including transitioning the device into low power mode, for example using
PM runtime.

Regards,

Andrzej

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

* [PATCH v4 0/7] Support inhibiting input devices
  2020-06-05 17:41                                         ` Hans de Goede
@ 2020-06-08 11:22                                           ` Andrzej Pietrasiewicz
  2020-06-08 11:22                                             ` [PATCH v4 1/7] Input: add input_device_enabled() Andrzej Pietrasiewicz
                                                               ` (8 more replies)
  0 siblings, 9 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-08 11:22 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

This is a quick respin of v3, with just two small changes, please see
the changelog below.

Userspace might want to implement a policy to temporarily disregard input
from certain devices.

An example use case is a convertible laptop, whose keyboard can be folded
under the screen to create tablet-like experience. The user then must hold
the laptop in such a way that it is difficult to avoid pressing the keyboard
keys. It is therefore desirable to temporarily disregard input from the
keyboard, until it is folded back. This obviously is a policy which should
be kept out of the kernel, but the kernel must provide suitable means to
implement such a policy.

Due to interactions with suspend/resume, a helper has been added for drivers
to decide if the device is being used or not (PATCH 1/7) and it has been
applied to relevant drivers (PATCH 2,4,5,6/7).

PATCH 7/7 adds support for inhibiting input devices.

This work is inspired by:

https://chromium.googlesource.com/chromiumos/third_party/kernel/+/45c2d7bb398f74adfae0017e20b224152fde3822

and

https://chromium.googlesource.com/chromiumos/third_party/kernel/+/4ce0e8a3697edb8fd071110b3af65014512061c7

In this respin the elan_i2c patch is dropped and converting it will be
addressed later.

v3..v4:
- updated the comment in input_open_device() (Hans)
- used more straightforward locking pattern in adc/exynos (Michał)

v2..v3:
- ignored autorepeat events in input_get_disposition() if a key is not
pressed (Hans)
- dropped inhibit()/uninhibit() driver callbacks (Hans)
- split ACPI button patch into taking the lock and using the helper (Rafael)
- dropped the elan_i2c conversion
- fixed typos in exynos adc

v1..v2:
- added input_device_enabled() helper and used it in drivers (Dmitry)
- the fact of open() and close() being called in inhibit/uninhibit paths has
been emphasized in the commit message of PATCH 6/7 (Dmitry)

Andrzej Pietrasiewicz (6):
  Input: add input_device_enabled()
  Input: use input_device_enabled()
  ACPI: button: Access input device's users under appropriate mutex
  ACPI: button: Use input_device_enabled() helper
  iio: adc: exynos: Use input_device_enabled()
  platform/x86: thinkpad_acpi: Use input_device_enabled()

Patrik Fimml (1):
  Input: Add "inhibited" property

 drivers/acpi/button.c                       |   7 +-
 drivers/iio/adc/exynos_adc.c                |   6 +-
 drivers/input/input.c                       | 125 ++++++++++++++++++--
 drivers/input/joystick/xpad.c               |   4 +-
 drivers/input/keyboard/ep93xx_keypad.c      |   2 +-
 drivers/input/keyboard/gpio_keys.c          |   4 +-
 drivers/input/keyboard/imx_keypad.c         |   4 +-
 drivers/input/keyboard/ipaq-micro-keys.c    |   2 +-
 drivers/input/keyboard/lpc32xx-keys.c       |   4 +-
 drivers/input/keyboard/pmic8xxx-keypad.c    |   4 +-
 drivers/input/keyboard/pxa27x_keypad.c      |   2 +-
 drivers/input/keyboard/samsung-keypad.c     |   4 +-
 drivers/input/keyboard/spear-keyboard.c     |   8 +-
 drivers/input/keyboard/st-keyscan.c         |   4 +-
 drivers/input/keyboard/tegra-kbc.c          |   4 +-
 drivers/input/misc/drv260x.c                |   4 +-
 drivers/input/misc/drv2665.c                |   4 +-
 drivers/input/misc/drv2667.c                |   4 +-
 drivers/input/misc/gp2ap002a00f.c           |   4 +-
 drivers/input/misc/kxtj9.c                  |   4 +-
 drivers/input/misc/sirfsoc-onkey.c          |   2 +-
 drivers/input/mouse/navpoint.c              |   4 +-
 drivers/input/touchscreen/ad7879.c          |   6 +-
 drivers/input/touchscreen/atmel_mxt_ts.c    |   4 +-
 drivers/input/touchscreen/auo-pixcir-ts.c   |   8 +-
 drivers/input/touchscreen/bu21029_ts.c      |   4 +-
 drivers/input/touchscreen/chipone_icn8318.c |   4 +-
 drivers/input/touchscreen/cyttsp_core.c     |   4 +-
 drivers/input/touchscreen/eeti_ts.c         |   4 +-
 drivers/input/touchscreen/ektf2127.c        |   4 +-
 drivers/input/touchscreen/imx6ul_tsc.c      |   4 +-
 drivers/input/touchscreen/ipaq-micro-ts.c   |   2 +-
 drivers/input/touchscreen/iqs5xx.c          |   4 +-
 drivers/input/touchscreen/lpc32xx_ts.c      |   4 +-
 drivers/input/touchscreen/melfas_mip4.c     |   4 +-
 drivers/input/touchscreen/mms114.c          |   6 +-
 drivers/input/touchscreen/pixcir_i2c_ts.c   |   8 +-
 drivers/input/touchscreen/ucb1400_ts.c      |   4 +-
 drivers/input/touchscreen/wm97xx-core.c     |  14 ++-
 drivers/input/touchscreen/zforce_ts.c       |   8 +-
 drivers/platform/x86/thinkpad_acpi.c        |   4 +-
 include/linux/input.h                       |  14 ++-
 42 files changed, 228 insertions(+), 96 deletions(-)


base-commit: 3d77e6a8804abcc0504c904bd6e5cdf3a5cf8162
-- 
2.17.1


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

* [PATCH v4 1/7] Input: add input_device_enabled()
  2020-06-08 11:22                                           ` [PATCH v4 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
@ 2020-06-08 11:22                                             ` Andrzej Pietrasiewicz
  2020-06-08 11:22                                             ` [PATCH v4 2/7] Input: use input_device_enabled() Andrzej Pietrasiewicz
                                                               ` (7 subsequent siblings)
  8 siblings, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-08 11:22 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

A helper function for drivers to decide if the device is used or not.
A lockdep check is introduced as inspecting ->users should be done under
input device's mutex.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/input/input.c | 8 ++++++++
 include/linux/input.h | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index 3cfd2c18eebd..41377bfa142d 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -2127,6 +2127,14 @@ void input_enable_softrepeat(struct input_dev *dev, int delay, int period)
 }
 EXPORT_SYMBOL(input_enable_softrepeat);
 
+bool input_device_enabled(struct input_dev *dev)
+{
+	lockdep_assert_held(&dev->mutex);
+
+	return dev->users > 0;
+}
+EXPORT_SYMBOL_GPL(input_device_enabled);
+
 /**
  * input_register_device - register device with input core
  * @dev: device to be registered
diff --git a/include/linux/input.h b/include/linux/input.h
index 56f2fd32e609..eda4587dba67 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -502,6 +502,8 @@ bool input_match_device_id(const struct input_dev *dev,
 
 void input_enable_softrepeat(struct input_dev *dev, int delay, int period);
 
+bool input_device_enabled(struct input_dev *dev);
+
 extern struct class input_class;
 
 /**
-- 
2.17.1


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

* [PATCH v4 2/7] Input: use input_device_enabled()
  2020-06-08 11:22                                           ` [PATCH v4 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
  2020-06-08 11:22                                             ` [PATCH v4 1/7] Input: add input_device_enabled() Andrzej Pietrasiewicz
@ 2020-06-08 11:22                                             ` Andrzej Pietrasiewicz
  2020-06-08 11:22                                             ` [PATCH v4 3/7] ACPI: button: Access input device's users under appropriate mutex Andrzej Pietrasiewicz
                                                               ` (6 subsequent siblings)
  8 siblings, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-08 11:22 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

Use the newly added helper in relevant input drivers.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/input/joystick/xpad.c               |  4 ++--
 drivers/input/keyboard/ep93xx_keypad.c      |  2 +-
 drivers/input/keyboard/gpio_keys.c          |  4 ++--
 drivers/input/keyboard/imx_keypad.c         |  4 ++--
 drivers/input/keyboard/ipaq-micro-keys.c    |  2 +-
 drivers/input/keyboard/lpc32xx-keys.c       |  4 ++--
 drivers/input/keyboard/pmic8xxx-keypad.c    |  4 ++--
 drivers/input/keyboard/pxa27x_keypad.c      |  2 +-
 drivers/input/keyboard/samsung-keypad.c     |  4 ++--
 drivers/input/keyboard/spear-keyboard.c     |  8 ++++----
 drivers/input/keyboard/st-keyscan.c         |  4 ++--
 drivers/input/keyboard/tegra-kbc.c          |  4 ++--
 drivers/input/misc/drv260x.c                |  4 ++--
 drivers/input/misc/drv2665.c                |  4 ++--
 drivers/input/misc/drv2667.c                |  4 ++--
 drivers/input/misc/gp2ap002a00f.c           |  4 ++--
 drivers/input/misc/kxtj9.c                  |  4 ++--
 drivers/input/misc/sirfsoc-onkey.c          |  2 +-
 drivers/input/mouse/navpoint.c              |  4 ++--
 drivers/input/touchscreen/ad7879.c          |  6 +++---
 drivers/input/touchscreen/atmel_mxt_ts.c    |  4 ++--
 drivers/input/touchscreen/auo-pixcir-ts.c   |  8 ++++----
 drivers/input/touchscreen/bu21029_ts.c      |  4 ++--
 drivers/input/touchscreen/chipone_icn8318.c |  4 ++--
 drivers/input/touchscreen/cyttsp_core.c     |  4 ++--
 drivers/input/touchscreen/eeti_ts.c         |  4 ++--
 drivers/input/touchscreen/ektf2127.c        |  4 ++--
 drivers/input/touchscreen/imx6ul_tsc.c      |  4 ++--
 drivers/input/touchscreen/ipaq-micro-ts.c   |  2 +-
 drivers/input/touchscreen/iqs5xx.c          |  4 ++--
 drivers/input/touchscreen/lpc32xx_ts.c      |  4 ++--
 drivers/input/touchscreen/melfas_mip4.c     |  4 ++--
 drivers/input/touchscreen/mms114.c          |  6 +++---
 drivers/input/touchscreen/pixcir_i2c_ts.c   |  8 ++++----
 drivers/input/touchscreen/ucb1400_ts.c      |  4 ++--
 drivers/input/touchscreen/wm97xx-core.c     | 14 +++++++++-----
 drivers/input/touchscreen/zforce_ts.c       |  8 ++++----
 37 files changed, 86 insertions(+), 82 deletions(-)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index c77cdb3b62b5..d8b6bc2d2171 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -1902,7 +1902,7 @@ static int xpad_suspend(struct usb_interface *intf, pm_message_t message)
 			xpad360w_poweroff_controller(xpad);
 	} else {
 		mutex_lock(&input->mutex);
-		if (input->users)
+		if (input_device_enabled(input))
 			xpad_stop_input(xpad);
 		mutex_unlock(&input->mutex);
 	}
@@ -1922,7 +1922,7 @@ static int xpad_resume(struct usb_interface *intf)
 		retval = xpad360w_start_input(xpad);
 	} else {
 		mutex_lock(&input->mutex);
-		if (input->users) {
+		if (input_device_enabled(input)) {
 			retval = xpad_start_input(xpad);
 		} else if (xpad->xtype == XTYPE_XBOXONE) {
 			/*
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
index 7c70492d9d6b..8194e843d047 100644
--- a/drivers/input/keyboard/ep93xx_keypad.c
+++ b/drivers/input/keyboard/ep93xx_keypad.c
@@ -208,7 +208,7 @@ static int ep93xx_keypad_resume(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users) {
+	if (input_device_enabled(input_dev)) {
 		if (!keypad->enabled) {
 			ep93xx_keypad_config(keypad);
 			clk_enable(keypad->clk);
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 53c9ff338dea..03ad27189553 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -966,7 +966,7 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev)
 			return error;
 	} else {
 		mutex_lock(&input->mutex);
-		if (input->users)
+		if (input_device_enabled(input))
 			gpio_keys_close(input);
 		mutex_unlock(&input->mutex);
 	}
@@ -984,7 +984,7 @@ static int __maybe_unused gpio_keys_resume(struct device *dev)
 		gpio_keys_disable_wakeup(ddata);
 	} else {
 		mutex_lock(&input->mutex);
-		if (input->users)
+		if (input_device_enabled(input))
 			error = gpio_keys_open(input);
 		mutex_unlock(&input->mutex);
 	}
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index 5a46d113e909..1f5c9ea5e9e5 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -532,7 +532,7 @@ static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev)
 	/* imx kbd can wake up system even clock is disabled */
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		clk_disable_unprepare(kbd->clk);
 
 	mutex_unlock(&input_dev->mutex);
@@ -562,7 +562,7 @@ static int __maybe_unused imx_kbd_noirq_resume(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users) {
+	if (input_device_enabled(input_dev)) {
 		ret = clk_prepare_enable(kbd->clk);
 		if (ret)
 			goto err_clk;
diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c
index e3f9e445e880..13a66a8e3411 100644
--- a/drivers/input/keyboard/ipaq-micro-keys.c
+++ b/drivers/input/keyboard/ipaq-micro-keys.c
@@ -140,7 +140,7 @@ static int __maybe_unused micro_key_resume(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users)
+	if (input_device_enabled(input))
 		micro_key_start(keys);
 
 	mutex_unlock(&input->mutex);
diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c
index 348af2aeb5de..943aeeb0de79 100644
--- a/drivers/input/keyboard/lpc32xx-keys.c
+++ b/drivers/input/keyboard/lpc32xx-keys.c
@@ -273,7 +273,7 @@ static int lpc32xx_kscan_suspend(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users) {
+	if (input_device_enabled(input)) {
 		/* Clear IRQ and disable clock */
 		writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
 		clk_disable_unprepare(kscandat->clk);
@@ -292,7 +292,7 @@ static int lpc32xx_kscan_resume(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users) {
+	if (input_device_enabled(input)) {
 		/* Enable clock and clear IRQ */
 		retval = clk_prepare_enable(kscandat->clk);
 		if (retval == 0)
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c
index 91d5811d6f0e..43b4533e7c41 100644
--- a/drivers/input/keyboard/pmic8xxx-keypad.c
+++ b/drivers/input/keyboard/pmic8xxx-keypad.c
@@ -633,7 +633,7 @@ static int pmic8xxx_kp_suspend(struct device *dev)
 	} else {
 		mutex_lock(&input_dev->mutex);
 
-		if (input_dev->users)
+		if (input_device_enabled(input_dev))
 			pmic8xxx_kp_disable(kp);
 
 		mutex_unlock(&input_dev->mutex);
@@ -653,7 +653,7 @@ static int pmic8xxx_kp_resume(struct device *dev)
 	} else {
 		mutex_lock(&input_dev->mutex);
 
-		if (input_dev->users)
+		if (input_device_enabled(input_dev))
 			pmic8xxx_kp_enable(kp);
 
 		mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 7e65708b25a4..a7f8257c8a02 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -694,7 +694,7 @@ static int pxa27x_keypad_resume(struct device *dev)
 	} else {
 		mutex_lock(&input_dev->mutex);
 
-		if (input_dev->users) {
+		if (input_device_enabled(input_dev)) {
 			/* Enable unit clock */
 			ret = clk_prepare_enable(keypad->clk);
 			if (!ret)
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c
index 70c1d086bdd2..74ec068fbf2f 100644
--- a/drivers/input/keyboard/samsung-keypad.c
+++ b/drivers/input/keyboard/samsung-keypad.c
@@ -537,7 +537,7 @@ static int samsung_keypad_suspend(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		samsung_keypad_stop(keypad);
 
 	samsung_keypad_toggle_wakeup(keypad, true);
@@ -557,7 +557,7 @@ static int samsung_keypad_resume(struct device *dev)
 
 	samsung_keypad_toggle_wakeup(keypad, false);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		samsung_keypad_start(keypad);
 
 	mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
index 9b8d78f87253..9838c79cb288 100644
--- a/drivers/input/keyboard/spear-keyboard.c
+++ b/drivers/input/keyboard/spear-keyboard.c
@@ -318,7 +318,7 @@ static int __maybe_unused spear_kbd_suspend(struct device *dev)
 		writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
 
 	} else {
-		if (input_dev->users) {
+		if (input_device_enabled(input_dev)) {
 			writel_relaxed(mode_ctl_reg & ~MODE_CTL_START_SCAN,
 					kbd->io_base + MODE_CTL_REG);
 			clk_disable(kbd->clk);
@@ -326,7 +326,7 @@ static int __maybe_unused spear_kbd_suspend(struct device *dev)
 	}
 
 	/* store current configuration */
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		kbd->mode_ctl_reg = mode_ctl_reg;
 
 	/* restore previous clk state */
@@ -351,12 +351,12 @@ static int __maybe_unused spear_kbd_resume(struct device *dev)
 			disable_irq_wake(kbd->irq);
 		}
 	} else {
-		if (input_dev->users)
+		if (input_device_enabled(input_dev))
 			clk_enable(kbd->clk);
 	}
 
 	/* restore current configuration */
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		writel_relaxed(kbd->mode_ctl_reg, kbd->io_base + MODE_CTL_REG);
 
 	mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/keyboard/st-keyscan.c b/drivers/input/keyboard/st-keyscan.c
index 27562cd67fb6..a045d61165ac 100644
--- a/drivers/input/keyboard/st-keyscan.c
+++ b/drivers/input/keyboard/st-keyscan.c
@@ -221,7 +221,7 @@ static int keyscan_suspend(struct device *dev)
 
 	if (device_may_wakeup(dev))
 		enable_irq_wake(keypad->irq);
-	else if (input->users)
+	else if (input_device_enabled(input))
 		keyscan_stop(keypad);
 
 	mutex_unlock(&input->mutex);
@@ -239,7 +239,7 @@ static int keyscan_resume(struct device *dev)
 
 	if (device_may_wakeup(dev))
 		disable_irq_wake(keypad->irq);
-	else if (input->users)
+	else if (input_device_enabled(input))
 		retval = keyscan_start(keypad);
 
 	mutex_unlock(&input->mutex);
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index d34d6947960f..9671842a082a 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -756,7 +756,7 @@ static int tegra_kbc_suspend(struct device *dev)
 		enable_irq(kbc->irq);
 		enable_irq_wake(kbc->irq);
 	} else {
-		if (kbc->idev->users)
+		if (input_device_enabled(kbc->idev))
 			tegra_kbc_stop(kbc);
 	}
 	mutex_unlock(&kbc->idev->mutex);
@@ -796,7 +796,7 @@ static int tegra_kbc_resume(struct device *dev)
 			input_sync(kbc->idev);
 		}
 	} else {
-		if (kbc->idev->users)
+		if (input_device_enabled(kbc->idev))
 			err = tegra_kbc_start(kbc);
 	}
 	mutex_unlock(&kbc->idev->mutex);
diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c
index 79d7fa710a71..11c1983e286a 100644
--- a/drivers/input/misc/drv260x.c
+++ b/drivers/input/misc/drv260x.c
@@ -580,7 +580,7 @@ static int __maybe_unused drv260x_suspend(struct device *dev)
 
 	mutex_lock(&haptics->input_dev->mutex);
 
-	if (haptics->input_dev->users) {
+	if (input_device_enabled(haptics->input_dev)) {
 		ret = regmap_update_bits(haptics->regmap,
 					 DRV260X_MODE,
 					 DRV260X_STANDBY_MASK,
@@ -612,7 +612,7 @@ static int __maybe_unused drv260x_resume(struct device *dev)
 
 	mutex_lock(&haptics->input_dev->mutex);
 
-	if (haptics->input_dev->users) {
+	if (input_device_enabled(haptics->input_dev)) {
 		ret = regulator_enable(haptics->regulator);
 		if (ret) {
 			dev_err(dev, "Failed to enable regulator\n");
diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c
index 918ad9c3fa81..e4df1a3b8655 100644
--- a/drivers/input/misc/drv2665.c
+++ b/drivers/input/misc/drv2665.c
@@ -230,7 +230,7 @@ static int __maybe_unused drv2665_suspend(struct device *dev)
 
 	mutex_lock(&haptics->input_dev->mutex);
 
-	if (haptics->input_dev->users) {
+	if (input_device_enabled(haptics->input_dev)) {
 		ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
 					 DRV2665_STANDBY, DRV2665_STANDBY);
 		if (ret) {
@@ -259,7 +259,7 @@ static int __maybe_unused drv2665_resume(struct device *dev)
 
 	mutex_lock(&haptics->input_dev->mutex);
 
-	if (haptics->input_dev->users) {
+	if (input_device_enabled(haptics->input_dev)) {
 		ret = regulator_enable(haptics->regulator);
 		if (ret) {
 			dev_err(dev, "Failed to enable regulator\n");
diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c
index bb9d5784df17..be4be2e0fd6f 100644
--- a/drivers/input/misc/drv2667.c
+++ b/drivers/input/misc/drv2667.c
@@ -405,7 +405,7 @@ static int __maybe_unused drv2667_suspend(struct device *dev)
 
 	mutex_lock(&haptics->input_dev->mutex);
 
-	if (haptics->input_dev->users) {
+	if (input_device_enabled(haptics->input_dev)) {
 		ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
 					 DRV2667_STANDBY, DRV2667_STANDBY);
 		if (ret) {
@@ -434,7 +434,7 @@ static int __maybe_unused drv2667_resume(struct device *dev)
 
 	mutex_lock(&haptics->input_dev->mutex);
 
-	if (haptics->input_dev->users) {
+	if (input_device_enabled(haptics->input_dev)) {
 		ret = regulator_enable(haptics->regulator);
 		if (ret) {
 			dev_err(dev, "Failed to enable regulator\n");
diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c
index 90abda8eea67..5f61ef90b2f2 100644
--- a/drivers/input/misc/gp2ap002a00f.c
+++ b/drivers/input/misc/gp2ap002a00f.c
@@ -230,7 +230,7 @@ static int __maybe_unused gp2a_suspend(struct device *dev)
 		enable_irq_wake(client->irq);
 	} else {
 		mutex_lock(&dt->input->mutex);
-		if (dt->input->users)
+		if (input_device_enabled(dt->input))
 			retval = gp2a_disable(dt);
 		mutex_unlock(&dt->input->mutex);
 	}
@@ -248,7 +248,7 @@ static int __maybe_unused gp2a_resume(struct device *dev)
 		disable_irq_wake(client->irq);
 	} else {
 		mutex_lock(&dt->input->mutex);
-		if (dt->input->users)
+		if (input_device_enabled(dt->input))
 			retval = gp2a_enable(dt);
 		mutex_unlock(&dt->input->mutex);
 	}
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index 52313c6e3fb3..bbb81617c2b2 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -503,7 +503,7 @@ static int __maybe_unused kxtj9_suspend(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		kxtj9_disable(tj9);
 
 	mutex_unlock(&input_dev->mutex);
@@ -518,7 +518,7 @@ static int __maybe_unused kxtj9_resume(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		kxtj9_enable(tj9);
 
 	mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c
index 60e1f31ee60a..7982bf8fb839 100644
--- a/drivers/input/misc/sirfsoc-onkey.c
+++ b/drivers/input/misc/sirfsoc-onkey.c
@@ -181,7 +181,7 @@ static int __maybe_unused sirfsoc_pwrc_resume(struct device *dev)
 	 * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c
 	 */
 	mutex_lock(&input->mutex);
-	if (input->users)
+	if (input_device_enabled(input))
 		sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
 	mutex_unlock(&input->mutex);
 
diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c
index 0b75248c8380..643d4b805b64 100644
--- a/drivers/input/mouse/navpoint.c
+++ b/drivers/input/mouse/navpoint.c
@@ -322,7 +322,7 @@ static int __maybe_unused navpoint_suspend(struct device *dev)
 	struct input_dev *input = navpoint->input;
 
 	mutex_lock(&input->mutex);
-	if (input->users)
+	if (input_device_enabled(input))
 		navpoint_down(navpoint);
 	mutex_unlock(&input->mutex);
 
@@ -336,7 +336,7 @@ static int __maybe_unused navpoint_resume(struct device *dev)
 	struct input_dev *input = navpoint->input;
 
 	mutex_lock(&input->mutex);
-	if (input->users)
+	if (input_device_enabled(input))
 		navpoint_up(navpoint);
 	mutex_unlock(&input->mutex);
 
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
index 556a2af46e18..e850853328f1 100644
--- a/drivers/input/touchscreen/ad7879.c
+++ b/drivers/input/touchscreen/ad7879.c
@@ -306,7 +306,7 @@ static int __maybe_unused ad7879_suspend(struct device *dev)
 
 	mutex_lock(&ts->input->mutex);
 
-	if (!ts->suspended && !ts->disabled && ts->input->users)
+	if (!ts->suspended && !ts->disabled && input_device_enabled(ts->input))
 		__ad7879_disable(ts);
 
 	ts->suspended = true;
@@ -322,7 +322,7 @@ static int __maybe_unused ad7879_resume(struct device *dev)
 
 	mutex_lock(&ts->input->mutex);
 
-	if (ts->suspended && !ts->disabled && ts->input->users)
+	if (ts->suspended && !ts->disabled && input_device_enabled(ts->input))
 		__ad7879_enable(ts);
 
 	ts->suspended = false;
@@ -339,7 +339,7 @@ static void ad7879_toggle(struct ad7879 *ts, bool disable)
 {
 	mutex_lock(&ts->input->mutex);
 
-	if (!ts->suspended && ts->input->users != 0) {
+	if (!ts->suspended && input_device_enabled(ts->input)) {
 
 		if (disable) {
 			if (ts->disabled)
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index ae60442efda0..47b7936bc3e3 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -3151,7 +3151,7 @@ static int __maybe_unused mxt_suspend(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		mxt_stop(data);
 
 	mutex_unlock(&input_dev->mutex);
@@ -3174,7 +3174,7 @@ static int __maybe_unused mxt_resume(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		mxt_start(data);
 
 	mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
index 8e9f3b7b8180..c33e63ca6142 100644
--- a/drivers/input/touchscreen/auo-pixcir-ts.c
+++ b/drivers/input/touchscreen/auo-pixcir-ts.c
@@ -414,7 +414,7 @@ static int __maybe_unused auo_pixcir_suspend(struct device *dev)
 	 */
 	if (device_may_wakeup(&client->dev)) {
 		/* need to start device if not open, to be wakeup source */
-		if (!input->users) {
+		if (!input_device_enabled(input)) {
 			ret = auo_pixcir_start(ts);
 			if (ret)
 				goto unlock;
@@ -422,7 +422,7 @@ static int __maybe_unused auo_pixcir_suspend(struct device *dev)
 
 		enable_irq_wake(client->irq);
 		ret = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_SLEEP);
-	} else if (input->users) {
+	} else if (input_device_enabled(input)) {
 		ret = auo_pixcir_stop(ts);
 	}
 
@@ -445,14 +445,14 @@ static int __maybe_unused auo_pixcir_resume(struct device *dev)
 		disable_irq_wake(client->irq);
 
 		/* need to stop device if it was not open on suspend */
-		if (!input->users) {
+		if (!input_device_enabled(input)) {
 			ret = auo_pixcir_stop(ts);
 			if (ret)
 				goto unlock;
 		}
 
 		/* device wakes automatically from SLEEP */
-	} else if (input->users) {
+	} else if (input_device_enabled(input)) {
 		ret = auo_pixcir_start(ts);
 	}
 
diff --git a/drivers/input/touchscreen/bu21029_ts.c b/drivers/input/touchscreen/bu21029_ts.c
index 49a8d4bbca3a..341925edb8e6 100644
--- a/drivers/input/touchscreen/bu21029_ts.c
+++ b/drivers/input/touchscreen/bu21029_ts.c
@@ -430,7 +430,7 @@ static int __maybe_unused bu21029_suspend(struct device *dev)
 
 	if (!device_may_wakeup(dev)) {
 		mutex_lock(&bu21029->in_dev->mutex);
-		if (bu21029->in_dev->users)
+		if (input_device_enabled(bu21029->in_dev))
 			bu21029_stop_chip(bu21029->in_dev);
 		mutex_unlock(&bu21029->in_dev->mutex);
 	}
@@ -445,7 +445,7 @@ static int __maybe_unused bu21029_resume(struct device *dev)
 
 	if (!device_may_wakeup(dev)) {
 		mutex_lock(&bu21029->in_dev->mutex);
-		if (bu21029->in_dev->users)
+		if (input_device_enabled(bu21029->in_dev))
 			bu21029_start_chip(bu21029->in_dev);
 		mutex_unlock(&bu21029->in_dev->mutex);
 	}
diff --git a/drivers/input/touchscreen/chipone_icn8318.c b/drivers/input/touchscreen/chipone_icn8318.c
index d91d2fd78649..f2fb41fb031e 100644
--- a/drivers/input/touchscreen/chipone_icn8318.c
+++ b/drivers/input/touchscreen/chipone_icn8318.c
@@ -154,7 +154,7 @@ static int icn8318_suspend(struct device *dev)
 	struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev));
 
 	mutex_lock(&data->input->mutex);
-	if (data->input->users)
+	if (input_device_enabled(data->input))
 		icn8318_stop(data->input);
 	mutex_unlock(&data->input->mutex);
 
@@ -166,7 +166,7 @@ static int icn8318_resume(struct device *dev)
 	struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev));
 
 	mutex_lock(&data->input->mutex);
-	if (data->input->users)
+	if (input_device_enabled(data->input))
 		icn8318_start(data->input);
 	mutex_unlock(&data->input->mutex);
 
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c
index 3f5d463dbeed..6e49cb80ec6d 100644
--- a/drivers/input/touchscreen/cyttsp_core.c
+++ b/drivers/input/touchscreen/cyttsp_core.c
@@ -479,7 +479,7 @@ static int __maybe_unused cyttsp_suspend(struct device *dev)
 
 	mutex_lock(&ts->input->mutex);
 
-	if (ts->input->users) {
+	if (input_device_enabled(ts->input)) {
 		retval = cyttsp_disable(ts);
 		if (retval == 0)
 			ts->suspended = true;
@@ -496,7 +496,7 @@ static int __maybe_unused cyttsp_resume(struct device *dev)
 
 	mutex_lock(&ts->input->mutex);
 
-	if (ts->input->users)
+	if (input_device_enabled(ts->input))
 		cyttsp_enable(ts);
 
 	ts->suspended = false;
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index 2e1404cd09ec..a639ba7e56ea 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -241,7 +241,7 @@ static int __maybe_unused eeti_ts_suspend(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		eeti_ts_stop(eeti);
 
 	mutex_unlock(&input_dev->mutex);
@@ -263,7 +263,7 @@ static int __maybe_unused eeti_ts_resume(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		eeti_ts_start(eeti);
 
 	mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/touchscreen/ektf2127.c b/drivers/input/touchscreen/ektf2127.c
index eadd389cf81f..263bbeb6cee9 100644
--- a/drivers/input/touchscreen/ektf2127.c
+++ b/drivers/input/touchscreen/ektf2127.c
@@ -154,7 +154,7 @@ static int __maybe_unused ektf2127_suspend(struct device *dev)
 	struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev));
 
 	mutex_lock(&ts->input->mutex);
-	if (ts->input->users)
+	if (input_device_enabled(ts->input))
 		ektf2127_stop(ts->input);
 	mutex_unlock(&ts->input->mutex);
 
@@ -166,7 +166,7 @@ static int __maybe_unused ektf2127_resume(struct device *dev)
 	struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev));
 
 	mutex_lock(&ts->input->mutex);
-	if (ts->input->users)
+	if (input_device_enabled(ts->input))
 		ektf2127_start(ts->input);
 	mutex_unlock(&ts->input->mutex);
 
diff --git a/drivers/input/touchscreen/imx6ul_tsc.c b/drivers/input/touchscreen/imx6ul_tsc.c
index 9ed258854349..59d4a4e9ecc2 100644
--- a/drivers/input/touchscreen/imx6ul_tsc.c
+++ b/drivers/input/touchscreen/imx6ul_tsc.c
@@ -509,7 +509,7 @@ static int __maybe_unused imx6ul_tsc_suspend(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users) {
+	if (input_device_enabled(input_dev)) {
 		imx6ul_tsc_disable(tsc);
 
 		clk_disable_unprepare(tsc->tsc_clk);
@@ -530,7 +530,7 @@ static int __maybe_unused imx6ul_tsc_resume(struct device *dev)
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users) {
+	if (input_device_enabled(input_dev)) {
 		retval = clk_prepare_enable(tsc->adc_clk);
 		if (retval)
 			goto out;
diff --git a/drivers/input/touchscreen/ipaq-micro-ts.c b/drivers/input/touchscreen/ipaq-micro-ts.c
index 5c3977e1af6f..0eb5689fe65f 100644
--- a/drivers/input/touchscreen/ipaq-micro-ts.c
+++ b/drivers/input/touchscreen/ipaq-micro-ts.c
@@ -135,7 +135,7 @@ static int __maybe_unused micro_ts_resume(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users)
+	if (input_device_enabled(input))
 		micro_ts_toggle_receive(ts, true);
 
 	mutex_unlock(&input->mutex);
diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c
index 5875bb1099a8..8b7b94ef7f39 100644
--- a/drivers/input/touchscreen/iqs5xx.c
+++ b/drivers/input/touchscreen/iqs5xx.c
@@ -1017,7 +1017,7 @@ static int __maybe_unused iqs5xx_suspend(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users)
+	if (input_device_enabled(input))
 		error = iqs5xx_set_state(iqs5xx->client, IQS5XX_SUSPEND);
 
 	mutex_unlock(&input->mutex);
@@ -1036,7 +1036,7 @@ static int __maybe_unused iqs5xx_resume(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users)
+	if (input_device_enabled(input))
 		error = iqs5xx_set_state(iqs5xx->client, IQS5XX_RESUME);
 
 	mutex_unlock(&input->mutex);
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
index b2cd9472e2d1..b51450b3d943 100644
--- a/drivers/input/touchscreen/lpc32xx_ts.c
+++ b/drivers/input/touchscreen/lpc32xx_ts.c
@@ -334,7 +334,7 @@ static int lpc32xx_ts_suspend(struct device *dev)
 	 */
 	mutex_lock(&input->mutex);
 
-	if (input->users) {
+	if (input_device_enabled(input)) {
 		if (device_may_wakeup(dev))
 			enable_irq_wake(tsc->irq);
 		else
@@ -353,7 +353,7 @@ static int lpc32xx_ts_resume(struct device *dev)
 
 	mutex_lock(&input->mutex);
 
-	if (input->users) {
+	if (input_device_enabled(input)) {
 		if (device_may_wakeup(dev))
 			disable_irq_wake(tsc->irq);
 		else
diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c
index 247c3aaba2d8..d33586919f58 100644
--- a/drivers/input/touchscreen/melfas_mip4.c
+++ b/drivers/input/touchscreen/melfas_mip4.c
@@ -1539,7 +1539,7 @@ static int __maybe_unused mip4_suspend(struct device *dev)
 
 	if (device_may_wakeup(dev))
 		ts->wake_irq_enabled = enable_irq_wake(client->irq) == 0;
-	else if (input->users)
+	else if (input_device_enabled(input))
 		mip4_disable(ts);
 
 	mutex_unlock(&input->mutex);
@@ -1557,7 +1557,7 @@ static int __maybe_unused mip4_resume(struct device *dev)
 
 	if (ts->wake_irq_enabled)
 		disable_irq_wake(client->irq);
-	else if (input->users)
+	else if (input_device_enabled(input))
 		mip4_enable(ts);
 
 	mutex_unlock(&input->mutex);
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 2ef1adaed9af..a87caa51204e 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -198,7 +198,7 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
 	int error;
 
 	mutex_lock(&input_dev->mutex);
-	if (!input_dev->users) {
+	if (!input_device_enabled(input_dev)) {
 		mutex_unlock(&input_dev->mutex);
 		goto out;
 	}
@@ -554,7 +554,7 @@ static int __maybe_unused mms114_suspend(struct device *dev)
 	input_sync(input_dev);
 
 	mutex_lock(&input_dev->mutex);
-	if (input_dev->users)
+	if (input_device_enabled(input_dev))
 		mms114_stop(data);
 	mutex_unlock(&input_dev->mutex);
 
@@ -569,7 +569,7 @@ static int __maybe_unused mms114_resume(struct device *dev)
 	int error;
 
 	mutex_lock(&input_dev->mutex);
-	if (input_dev->users) {
+	if (input_device_enabled(input_dev)) {
 		error = mms114_start(data);
 		if (error < 0) {
 			mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 9aa098577350..dc148b4bed74 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -415,14 +415,14 @@ static int __maybe_unused pixcir_i2c_ts_suspend(struct device *dev)
 	mutex_lock(&input->mutex);
 
 	if (device_may_wakeup(&client->dev)) {
-		if (!input->users) {
+		if (!input_device_enabled(input)) {
 			ret = pixcir_start(ts);
 			if (ret) {
 				dev_err(dev, "Failed to start\n");
 				goto unlock;
 			}
 		}
-	} else if (input->users) {
+	} else if (input_device_enabled(input)) {
 		ret = pixcir_stop(ts);
 	}
 
@@ -442,14 +442,14 @@ static int __maybe_unused pixcir_i2c_ts_resume(struct device *dev)
 	mutex_lock(&input->mutex);
 
 	if (device_may_wakeup(&client->dev)) {
-		if (!input->users) {
+		if (!input_device_enabled(input)) {
 			ret = pixcir_stop(ts);
 			if (ret) {
 				dev_err(dev, "Failed to stop\n");
 				goto unlock;
 			}
 		}
-	} else if (input->users) {
+	} else if (input_device_enabled(input)) {
 		ret = pixcir_start(ts);
 	}
 
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index 807d39e18091..e3f2c940ef3d 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -410,7 +410,7 @@ static int __maybe_unused ucb1400_ts_suspend(struct device *dev)
 
 	mutex_lock(&idev->mutex);
 
-	if (idev->users)
+	if (input_device_enabled(idev))
 		ucb1400_ts_stop(ucb);
 
 	mutex_unlock(&idev->mutex);
@@ -424,7 +424,7 @@ static int __maybe_unused ucb1400_ts_resume(struct device *dev)
 
 	mutex_lock(&idev->mutex);
 
-	if (idev->users)
+	if (input_device_enabled(idev))
 		ucb1400_ts_start(ucb);
 
 	mutex_unlock(&idev->mutex);
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index 0a174bd82915..2c2f1b6c5eff 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -806,23 +806,25 @@ static int __maybe_unused wm97xx_suspend(struct device *dev)
 	else
 		suspend_mode = 0;
 
-	if (wm->input_dev->users)
+	mutex_lock(&wm->input_dev->mutex);
+	if (input_device_enabled(wm->input_dev))
 		cancel_delayed_work_sync(&wm->ts_reader);
 
 	/* Power down the digitiser (bypassing the cache for resume) */
 	reg = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER2);
 	reg &= ~WM97XX_PRP_DET_DIG;
-	if (wm->input_dev->users)
+	if (input_device_enabled(wm->input_dev))
 		reg |= suspend_mode;
 	wm->ac97->bus->ops->write(wm->ac97, AC97_WM97XX_DIGITISER2, reg);
 
 	/* WM9713 has an additional power bit - turn it off if there
 	 * are no users or if suspend mode is zero. */
 	if (wm->id == WM9713_ID2 &&
-	    (!wm->input_dev->users || !suspend_mode)) {
+	    (!input_device_enabled(wm->input_dev) || !suspend_mode)) {
 		reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) | 0x8000;
 		wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
 	}
+	mutex_unlock(&wm->input_dev->mutex);
 
 	return 0;
 }
@@ -831,11 +833,12 @@ static int __maybe_unused wm97xx_resume(struct device *dev)
 {
 	struct wm97xx *wm = dev_get_drvdata(dev);
 
+	mutex_lock(&wm->input_dev->mutex);
 	/* restore digitiser and gpios */
 	if (wm->id == WM9713_ID2) {
 		wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]);
 		wm97xx_reg_write(wm, 0x5a, wm->misc);
-		if (wm->input_dev->users) {
+		if (input_device_enabled(wm->input_dev)) {
 			u16 reg;
 			reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) & 0x7fff;
 			wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
@@ -852,11 +855,12 @@ static int __maybe_unused wm97xx_resume(struct device *dev)
 	wm97xx_reg_write(wm, AC97_GPIO_STATUS, wm->gpio[4]);
 	wm97xx_reg_write(wm, AC97_MISC_AFE, wm->gpio[5]);
 
-	if (wm->input_dev->users && !wm->pen_irq) {
+	if (input_device_enabled(wm->input_dev) && !wm->pen_irq) {
 		wm->ts_reader_interval = wm->ts_reader_min_interval;
 		queue_delayed_work(wm->ts_workq, &wm->ts_reader,
 				   wm->ts_reader_interval);
 	}
+	mutex_unlock(&wm->input_dev->mutex);
 
 	return 0;
 }
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c
index 5230519b0f74..495629628af6 100644
--- a/drivers/input/touchscreen/zforce_ts.c
+++ b/drivers/input/touchscreen/zforce_ts.c
@@ -626,14 +626,14 @@ static int __maybe_unused zforce_suspend(struct device *dev)
 		dev_dbg(&client->dev, "suspend while being a wakeup source\n");
 
 		/* Need to start device, if not open, to be a wakeup source. */
-		if (!input->users) {
+		if (!input_device_enabled(input)) {
 			ret = zforce_start(ts);
 			if (ret)
 				goto unlock;
 		}
 
 		enable_irq_wake(client->irq);
-	} else if (input->users) {
+	} else if (input_device_enabled(input)) {
 		dev_dbg(&client->dev,
 			"suspend without being a wakeup source\n");
 
@@ -670,12 +670,12 @@ static int __maybe_unused zforce_resume(struct device *dev)
 		disable_irq_wake(client->irq);
 
 		/* need to stop device if it was not open on suspend */
-		if (!input->users) {
+		if (!input_device_enabled(input)) {
 			ret = zforce_stop(ts);
 			if (ret)
 				goto unlock;
 		}
-	} else if (input->users) {
+	} else if (input_device_enabled(input)) {
 		dev_dbg(&client->dev, "resume without being a wakeup source\n");
 
 		enable_irq(client->irq);
-- 
2.17.1


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

* [PATCH v4 3/7] ACPI: button: Access input device's users under appropriate mutex
  2020-06-08 11:22                                           ` [PATCH v4 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
  2020-06-08 11:22                                             ` [PATCH v4 1/7] Input: add input_device_enabled() Andrzej Pietrasiewicz
  2020-06-08 11:22                                             ` [PATCH v4 2/7] Input: use input_device_enabled() Andrzej Pietrasiewicz
@ 2020-06-08 11:22                                             ` Andrzej Pietrasiewicz
  2020-06-24 15:00                                               ` Rafael J. Wysocki
  2020-06-08 11:22                                             ` [PATCH v4 4/7] ACPI: button: Use input_device_enabled() helper Andrzej Pietrasiewicz
                                                               ` (5 subsequent siblings)
  8 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-08 11:22 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

Inspecting input device's 'users' member should be done under device's
mutex, so add appropriate invocations.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/acpi/button.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 78cfc70cb320..ff7ab291f678 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -456,13 +456,16 @@ static int acpi_button_resume(struct device *dev)
 {
 	struct acpi_device *device = to_acpi_device(dev);
 	struct acpi_button *button = acpi_driver_data(device);
+	struct input_dev *input = button->input;
 
 	button->suspended = false;
-	if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users) {
+	mutex_lock(&input->mutex);
+	if (button->type == ACPI_BUTTON_TYPE_LID && input->users) {
 		button->last_state = !!acpi_lid_evaluate_state(device);
 		button->last_time = ktime_get();
 		acpi_lid_initialize_state(device);
 	}
+	mutex_unlock(&input->mutex);
 	return 0;
 }
 #endif
-- 
2.17.1


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

* [PATCH v4 4/7] ACPI: button: Use input_device_enabled() helper
  2020-06-08 11:22                                           ` [PATCH v4 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
                                                               ` (2 preceding siblings ...)
  2020-06-08 11:22                                             ` [PATCH v4 3/7] ACPI: button: Access input device's users under appropriate mutex Andrzej Pietrasiewicz
@ 2020-06-08 11:22                                             ` Andrzej Pietrasiewicz
  2020-06-25  5:24                                               ` Dmitry Torokhov
  2020-06-08 11:22                                             ` [PATCH v4 5/7] iio: adc: exynos: Use input_device_enabled() Andrzej Pietrasiewicz
                                                               ` (4 subsequent siblings)
  8 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-08 11:22 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

A new helper is available, so use it.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/acpi/button.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index ff7ab291f678..4deb2b48d03c 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -411,7 +411,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
 		input = button->input;
 		if (button->type == ACPI_BUTTON_TYPE_LID) {
 			mutex_lock(&button->input->mutex);
-			users = button->input->users;
+			users = input_device_enabled(button->input);
 			mutex_unlock(&button->input->mutex);
 			if (users)
 				acpi_lid_update_state(device, true);
@@ -460,7 +460,7 @@ static int acpi_button_resume(struct device *dev)
 
 	button->suspended = false;
 	mutex_lock(&input->mutex);
-	if (button->type == ACPI_BUTTON_TYPE_LID && input->users) {
+	if (button->type == ACPI_BUTTON_TYPE_LID && input_device_enabled(input)) {
 		button->last_state = !!acpi_lid_evaluate_state(device);
 		button->last_time = ktime_get();
 		acpi_lid_initialize_state(device);
-- 
2.17.1


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

* [PATCH v4 5/7] iio: adc: exynos: Use input_device_enabled()
  2020-06-08 11:22                                           ` [PATCH v4 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
                                                               ` (3 preceding siblings ...)
  2020-06-08 11:22                                             ` [PATCH v4 4/7] ACPI: button: Use input_device_enabled() helper Andrzej Pietrasiewicz
@ 2020-06-08 11:22                                             ` Andrzej Pietrasiewicz
  2020-06-10  1:28                                               ` Michał Mirosław
  2020-06-08 11:22                                             ` [PATCH v4 6/7] platform/x86: thinkpad_acpi: " Andrzej Pietrasiewicz
                                                               ` (3 subsequent siblings)
  8 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-08 11:22 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

A new helper is available, so use it. Inspecting 'users' member of
input_dev requires taking device's mutex.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/iio/adc/exynos_adc.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 22131a677445..9a1ddda8c5db 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -633,7 +633,9 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
 	bool pressed;
 	int ret;
 
-	while (info->input->users) {
+	mutex_lock(&info->input->mutex);
+	while (input_device_enabled(info->input)) {
+		mutex_unlock(&info->input->mutex);
 		ret = exynos_read_s3c64xx_ts(dev, &x, &y);
 		if (ret == -ETIMEDOUT)
 			break;
@@ -651,6 +653,8 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
 		input_sync(info->input);
 
 		usleep_range(1000, 1100);
+
+		mutex_lock(&info->input->mutex);
 	}
 
 	writel(0, ADC_V1_CLRINTPNDNUP(info->regs));
-- 
2.17.1


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

* [PATCH v4 6/7] platform/x86: thinkpad_acpi: Use input_device_enabled()
  2020-06-08 11:22                                           ` [PATCH v4 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
                                                               ` (4 preceding siblings ...)
  2020-06-08 11:22                                             ` [PATCH v4 5/7] iio: adc: exynos: Use input_device_enabled() Andrzej Pietrasiewicz
@ 2020-06-08 11:22                                             ` Andrzej Pietrasiewicz
  2020-06-08 11:22                                             ` [PATCH v4 7/7] Input: Add "inhibited" property Andrzej Pietrasiewicz
                                                               ` (2 subsequent siblings)
  8 siblings, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-08 11:22 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel

Use the new helper. Inspecting input device's 'users' member needs to be
done under device's mutex, so add appropriate invocations.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
Acked-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
---
 drivers/platform/x86/thinkpad_acpi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 0f704484ae1d..8ae11b8c3ebb 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -2671,9 +2671,10 @@ static void hotkey_poll_setup(const bool may_warn)
 	const u32 poll_driver_mask = hotkey_driver_mask & hotkey_source_mask;
 	const u32 poll_user_mask = hotkey_user_mask & hotkey_source_mask;
 
+	mutex_lock(&tpacpi_inputdev->mutex);
 	if (hotkey_poll_freq > 0 &&
 	    (poll_driver_mask ||
-	     (poll_user_mask && tpacpi_inputdev->users > 0))) {
+	     (poll_user_mask && input_device_enabled(tpacpi_inputdev)))) {
 		if (!tpacpi_hotkey_task) {
 			tpacpi_hotkey_task = kthread_run(hotkey_kthread,
 					NULL, TPACPI_NVRAM_KTHREAD_NAME);
@@ -2690,6 +2691,7 @@ static void hotkey_poll_setup(const bool may_warn)
 				  poll_user_mask, poll_driver_mask);
 		}
 	}
+	mutex_unlock(&tpacpi_inputdev->mutex);
 }
 
 static void hotkey_poll_setup_safe(const bool may_warn)
-- 
2.17.1


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

* [PATCH v4 7/7] Input: Add "inhibited" property
  2020-06-08 11:22                                           ` [PATCH v4 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
                                                               ` (5 preceding siblings ...)
  2020-06-08 11:22                                             ` [PATCH v4 6/7] platform/x86: thinkpad_acpi: " Andrzej Pietrasiewicz
@ 2020-06-08 11:22                                             ` Andrzej Pietrasiewicz
  2020-10-05 18:10                                               ` Dmitry Torokhov
  2020-06-10  9:49                                             ` [PATCH v4 0/7] Support inhibiting input devices Hans de Goede
  2020-06-12  8:17                                             ` Hans de Goede
  8 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-08 11:22 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh,
	Andrzej Pietrasiewicz, kernel, Patrik Fimml

From: Patrik Fimml <patrikf@chromium.org>

Userspace might want to implement a policy to temporarily disregard input
from certain devices, including not treating them as wakeup sources.

An example use case is a laptop, whose keyboard can be folded under the
screen to create tablet-like experience. The user then must hold the laptop
in such a way that it is difficult to avoid pressing the keyboard keys. It
is therefore desirable to temporarily disregard input from the keyboard,
until it is folded back. This obviously is a policy which should be kept
out of the kernel, but the kernel must provide suitable means to implement
such a policy.

This patch adds a sysfs interface for exactly this purpose.

To implement the said interface it adds an "inhibited" property to struct
input_dev, and effectively creates four states a device can be in: closed
uninhibited, closed inhibited, open uninhibited, open inhibited. It also
defers calling driver's ->open() and ->close() to until they are actually
needed, e.g. it makes no sense to prepare the underlying device for
generating events (->open()) if the device is inhibited.

              uninhibit
closed      <------------ closed
uninhibited ------------> inhibited
      | ^     inhibit        | ^
 1st  | |               1st  | |
 open | |               open | |
      | |                    | |
      | | last               | | last
      | | close              | | close
      v |     uninhibit      v |
open        <------------ open
uninhibited ------------> inhibited

The top inhibit/uninhibit transition happens when users == 0.
The bottom inhibit/uninhibit transition happens when users > 0.
The left open/close transition happens when !inhibited.
The right open/close transition happens when inhibited.
Due to all transitions being serialized with dev->mutex, it is impossible
to have "diagonal" transitions between closed uninhibited and open
inhibited or between open uninhibited and closed inhibited.

No new callbacks are added to drivers, because their open() and close()
serve exactly the purpose to tell the driver to start/stop providing
events to the input core. Consequently, open() and close() - if provided
- are called in both inhibit and uninhibit paths.

Signed-off-by: Patrik Fimml <patrikf@chromium.org>
Co-developed-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/input/input.c | 119 ++++++++++++++++++++++++++++++++++++++----
 include/linux/input.h |  12 ++++-
 2 files changed, 120 insertions(+), 11 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index 41377bfa142d..f624b09a1f00 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -284,8 +284,11 @@ static int input_get_disposition(struct input_dev *dev,
 	case EV_KEY:
 		if (is_event_supported(code, dev->keybit, KEY_MAX)) {
 
-			/* auto-repeat bypasses state updates */
-			if (value == 2) {
+			/*
+			 * auto-repeat bypasses state updates but repeat
+			 * events are ignored if the key is not pressed
+			 */
+			if (value == 2 && test_bit(code, dev->key)) {
 				disposition = INPUT_PASS_TO_HANDLERS;
 				break;
 			}
@@ -367,8 +370,13 @@ static int input_get_disposition(struct input_dev *dev,
 static void input_handle_event(struct input_dev *dev,
 			       unsigned int type, unsigned int code, int value)
 {
-	int disposition = input_get_disposition(dev, type, code, &value);
+	int disposition;
+
+	/* filter-out events from inhibited devices */
+	if (dev->inhibited)
+		return;
 
+	disposition = input_get_disposition(dev, type, code, &value);
 	if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
 		add_input_randomness(type, code, value);
 
@@ -612,10 +620,10 @@ int input_open_device(struct input_handle *handle)
 
 	handle->open++;
 
-	if (dev->users++) {
+	if (dev->users++ || dev->inhibited) {
 		/*
-		 * Device is already opened, so we can exit immediately and
-		 * report success.
+		 * Device is already opened and/or inhibited,
+		 * so we can exit immediately and report success.
 		 */
 		goto out;
 	}
@@ -675,10 +683,9 @@ void input_close_device(struct input_handle *handle)
 
 	__input_release_device(handle);
 
-	if (!--dev->users) {
+	if (!dev->inhibited && !--dev->users) {
 		if (dev->poller)
 			input_dev_poller_stop(dev->poller);
-
 		if (dev->close)
 			dev->close(dev);
 	}
@@ -1416,12 +1423,49 @@ static ssize_t input_dev_show_properties(struct device *dev,
 }
 static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL);
 
+static int input_inhibit_device(struct input_dev *dev);
+static int input_uninhibit_device(struct input_dev *dev);
+
+static ssize_t inhibited_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct input_dev *input_dev = to_input_dev(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", input_dev->inhibited);
+}
+
+static ssize_t inhibited_store(struct device *dev,
+			       struct device_attribute *attr, const char *buf,
+			       size_t len)
+{
+	struct input_dev *input_dev = to_input_dev(dev);
+	ssize_t rv;
+	bool inhibited;
+
+	if (strtobool(buf, &inhibited))
+		return -EINVAL;
+
+	if (inhibited)
+		rv = input_inhibit_device(input_dev);
+	else
+		rv = input_uninhibit_device(input_dev);
+
+	if (rv != 0)
+		return rv;
+
+	return len;
+}
+
+static DEVICE_ATTR_RW(inhibited);
+
 static struct attribute *input_dev_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_phys.attr,
 	&dev_attr_uniq.attr,
 	&dev_attr_modalias.attr,
 	&dev_attr_properties.attr,
+	&dev_attr_inhibited.attr,
 	NULL
 };
 
@@ -1703,6 +1747,63 @@ void input_reset_device(struct input_dev *dev)
 }
 EXPORT_SYMBOL(input_reset_device);
 
+static int input_inhibit_device(struct input_dev *dev)
+{
+	int ret = 0;
+
+	mutex_lock(&dev->mutex);
+
+	if (dev->inhibited)
+		goto out;
+
+	if (dev->users) {
+		if (dev->close)
+			dev->close(dev);
+		if (dev->poller)
+			input_dev_poller_stop(dev->poller);
+	}
+
+	spin_lock_irq(&dev->event_lock);
+	input_dev_release_keys(dev);
+	input_dev_toggle(dev, false);
+	spin_unlock_irq(&dev->event_lock);
+
+	dev->inhibited = true;
+
+out:
+	mutex_unlock(&dev->mutex);
+	return ret;
+}
+
+static int input_uninhibit_device(struct input_dev *dev)
+{
+	int ret = 0;
+
+	mutex_lock(&dev->mutex);
+
+	if (!dev->inhibited)
+		goto out;
+
+	if (dev->users) {
+		if (dev->open) {
+			ret = dev->open(dev);
+			if (ret)
+				goto out;
+		}
+		if (dev->poller)
+			input_dev_poller_start(dev->poller);
+	}
+
+	dev->inhibited = false;
+	spin_lock_irq(&dev->event_lock);
+	input_dev_toggle(dev, true);
+	spin_unlock_irq(&dev->event_lock);
+
+out:
+	mutex_unlock(&dev->mutex);
+	return ret;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int input_dev_suspend(struct device *dev)
 {
@@ -2131,7 +2232,7 @@ bool input_device_enabled(struct input_dev *dev)
 {
 	lockdep_assert_held(&dev->mutex);
 
-	return dev->users > 0;
+	return !dev->inhibited && dev->users > 0;
 }
 EXPORT_SYMBOL_GPL(input_device_enabled);
 
diff --git a/include/linux/input.h b/include/linux/input.h
index eda4587dba67..0354b298d874 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -90,9 +90,11 @@ enum input_clock_type {
  * @open: this method is called when the very first user calls
  *	input_open_device(). The driver must prepare the device
  *	to start generating events (start polling thread,
- *	request an IRQ, submit URB, etc.)
+ *	request an IRQ, submit URB, etc.). The meaning of open() is
+ *	to start providing events to the input core.
  * @close: this method is called when the very last user calls
- *	input_close_device().
+ *	input_close_device(). The meaning of close() is to stop
+ *	providing events to the input core.
  * @flush: purges the device. Most commonly used to get rid of force
  *	feedback effects loaded into the device when disconnecting
  *	from it
@@ -127,6 +129,10 @@ enum input_clock_type {
  *	and needs not be explicitly unregistered or freed.
  * @timestamp: storage for a timestamp set by input_set_timestamp called
  *  by a driver
+ * @inhibited: indicates that the input device is inhibited. If that is
+ * the case then input core ignores any events generated by the device.
+ * Device's close() is called when it is being inhibited and its open()
+ * is called when it is being uninhibited.
  */
 struct input_dev {
 	const char *name;
@@ -201,6 +207,8 @@ struct input_dev {
 	bool devres_managed;
 
 	ktime_t timestamp[INPUT_CLK_MAX];
+
+	bool inhibited;
 };
 #define to_input_dev(d) container_of(d, struct input_dev, dev)
 
-- 
2.17.1


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

* Re: [PATCH v4 5/7] iio: adc: exynos: Use input_device_enabled()
  2020-06-08 11:22                                             ` [PATCH v4 5/7] iio: adc: exynos: Use input_device_enabled() Andrzej Pietrasiewicz
@ 2020-06-10  1:28                                               ` Michał Mirosław
  2020-06-10  7:52                                                 ` [FIXED PATCH " Andrzej Pietrasiewicz
  0 siblings, 1 reply; 80+ messages in thread
From: Michał Mirosław @ 2020-06-10  1:28 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz
  Cc: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh, kernel

On Mon, Jun 08, 2020 at 01:22:09PM +0200, Andrzej Pietrasiewicz wrote:
> A new helper is available, so use it. Inspecting 'users' member of
> input_dev requires taking device's mutex.
[...]
> --- a/drivers/iio/adc/exynos_adc.c
> +++ b/drivers/iio/adc/exynos_adc.c
> @@ -633,7 +633,9 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
>  	bool pressed;
>  	int ret;
>  
> -	while (info->input->users) {
> +	mutex_lock(&info->input->mutex);
> +	while (input_device_enabled(info->input)) {
> +		mutex_unlock(&info->input->mutex);
>  		ret = exynos_read_s3c64xx_ts(dev, &x, &y);
>  		if (ret == -ETIMEDOUT)
>  			break;
> @@ -651,6 +653,8 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
>  		input_sync(info->input);
>  
>  		usleep_range(1000, 1100);
> +
> +		mutex_lock(&info->input->mutex);
>  	}

Missed an mutex_unlock() here.

>  
>  	writel(0, ADC_V1_CLRINTPNDNUP(info->regs));

Best Regards,
Michał Mirosław

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

* [FIXED PATCH v4 5/7] iio: adc: exynos: Use input_device_enabled()
  2020-06-10  1:28                                               ` Michał Mirosław
@ 2020-06-10  7:52                                                 ` Andrzej Pietrasiewicz
  0 siblings, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-10  7:52 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Andrzej Pietrasiewicz,
	Michał Mirosław, kernel

A new helper is available, so use it. Inspecting 'users' member of
input_dev requires taking device's mutex.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/iio/adc/exynos_adc.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 22131a677445..2761c3aea2c6 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -633,7 +633,9 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
 	bool pressed;
 	int ret;
 
-	while (info->input->users) {
+	mutex_lock(&info->input->mutex);
+	while (input_device_enabled(info->input)) {
+		mutex_unlock(&info->input->mutex);
 		ret = exynos_read_s3c64xx_ts(dev, &x, &y);
 		if (ret == -ETIMEDOUT)
 			break;
@@ -651,7 +653,10 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
 		input_sync(info->input);
 
 		usleep_range(1000, 1100);
+
+		mutex_lock(&info->input->mutex);
 	}
+	mutex_unlock(&info->input->mutex);
 
 	writel(0, ADC_V1_CLRINTPNDNUP(info->regs));
 
-- 
2.17.1


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

* Re: [PATCH v4 0/7] Support inhibiting input devices
  2020-06-08 11:22                                           ` [PATCH v4 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
                                                               ` (6 preceding siblings ...)
  2020-06-08 11:22                                             ` [PATCH v4 7/7] Input: Add "inhibited" property Andrzej Pietrasiewicz
@ 2020-06-10  9:49                                             ` Hans de Goede
  2020-06-10 10:38                                               ` Rafael J. Wysocki
  2020-06-12  8:17                                             ` Hans de Goede
  8 siblings, 1 reply; 80+ messages in thread
From: Hans de Goede @ 2020-06-10  9:49 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, linux-pm, linux-acpi, linux-kernel,
	linux-iio, linux-arm-kernel, linux-samsung-soc, linux-input,
	linux-tegra, patches, ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, kernel

Hi All,

On 6/8/20 1:22 PM, Andrzej Pietrasiewicz wrote:
> This is a quick respin of v3, with just two small changes, please see
> the changelog below.
> 
> Userspace might want to implement a policy to temporarily disregard input
> from certain devices.
> 
> An example use case is a convertible laptop, whose keyboard can be folded
> under the screen to create tablet-like experience. The user then must hold
> the laptop in such a way that it is difficult to avoid pressing the keyboard
> keys. It is therefore desirable to temporarily disregard input from the
> keyboard, until it is folded back. This obviously is a policy which should
> be kept out of the kernel, but the kernel must provide suitable means to
> implement such a policy.

First of all sorry to start a somewhat new discussion about this
while this patch set is also somewhat far along in the review process,
but I believe what I discuss below needs to be taken into account.

Yesterday I have been looking into why an Asus T101HA would not stay
suspended when the LID is closed. The cause is that the USB HID multi-touch
touchpad in the base of the device starts sending events when the screen
gets close to the touchpad (so when the LID is fully closed) and these
events are causing a wakeup from suspend. HID multi-touch devices
do have a way to tell them to fully stop sending events, also disabling
the USB remote wakeup the device is doing. The question is when to tell
it to not send events though ...

So now I've been thinking about how to fix this and I believe that there
is some interaction between this problem and this patch-set.

The problem I'm seeing on the T101HA is about wakeups, so the question
which I want to discuss is:

1. How does inhibiting interact with enabling /
disabling the device as a wakeup source ?

2. Since we have now made inhibiting equal open/close how does open/close
interact with a device being a wakeup source ?

And my own initial (to be discussed) answers to these questions:

1. It seems to me that when a device is inhibited it should not be a
wakeup source, so where possible a input-device-driver should disable
a device's wakeup capabilities on suspend if inhibited

2. This one is trickier I don't think we have really clearly specified
any behavior here. The default behavior of most drivers seems to be
using something like this in their suspend callback:

         if (device_may_wakeup(dev))
                 enable_irq_wake(data->irq);
         else if (input->users)
                 foo_stop_receiving_events(data);

Since this is what most drivers seem to do I believe we should keep
this as is and that we should just clearly document that if the
input_device has users (has been opened) or not does not matter
for its wakeup behavior.

Combining these 2 answers leads to this new pseudo code template
for an input-device's suspend method:

	/*
	 * If inhibited we have already disabled events and
	 * we do NOT want to setup the device as wake source.
	 */
	if (input->inhibited)
		return 0;

         if (device_may_wakeup(dev))
                 enable_irq_wake(data->irq);
         else if (input->users)
                 foo_stop_receiving_events(data);

###

A different, but related issue is how to make devices actually use the
new inhibit support on the builtin keyboard + touchpad when say the lid
is closed.   Arguably this is an userspace problem, but it is a tricky
one. Currently on most modern Linux distributions suspend-on-lid-close
is handled by systemd-logind and most modern desktop-environments are
happy to have logind handle this for them.

But most knowledge about input devices and e.g. heurisitics to decide
if a touchpad is internal or external are part of libinput. Now we could
have libinput use the new inhibit support (1), but then when the lid
closes we get race between whatever process is using libinput trying
to inhibit the touchpad (which must be done before to suspend to disable
it as wakeup source) and logind trying to suspend the system.

One solution here would be to move the setting of the inhibit sysfs
attr into logind, but that requires adding a whole bunch of extra
knowledge to logind which does not really belong there IMHO.

I've been thinking a bit about this and to me it seems that the kernel
is in the ideal position to automatically inhibit some devices when
some EV_SW transitions from 0->1 (and uninhibit again on 1->0). The
issue here is to chose on which devices to enable this. I believe
that the auto inhibit on some switches mechanism is best done inside
the kernel (disabled by default) and then we can have a sysfs
attr called auto_inhibit_ev_sw_mask which can be set to e.g.
(1 << SW_LID) to make the kernel auto-inhibit the input-device whenever
the lid is closed, or to ((1 << SW_LID) | (1 << SW_TABLET_MODE)) to
inhibit both when the lid is closed or when switched to tablet mode.

This could then be combined with a userspace utility run from an
udev rule which makes the actual decision what auto_inhibit_ev_sw_mask
should be set for a given input device.

This will put the mechanism for what we want inside the kernel and
leaves the policy on which switches we want this for out of the
kernel.

Note adding this new auto_inhibit_ev_sw_mask sysfs attr falls
somewhat outside the context of this patchset and could be done
as a follow up to this patch-set. But I do believe that we need to
figure out how (non ChromeOS) userspace can / will use the new inhibit
interface before merging it.

Regards,

Hans




1) There are issues here with libinput not running as root and this
being a root only sysfs interface but lets ignore those for now,
note that the auto_inhibit_ev_sw_mask also neatly solves this
problem



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

* Re: [PATCH v4 0/7] Support inhibiting input devices
  2020-06-10  9:49                                             ` [PATCH v4 0/7] Support inhibiting input devices Hans de Goede
@ 2020-06-10 10:38                                               ` Rafael J. Wysocki
  2020-06-10 13:12                                                 ` Andrzej Pietrasiewicz
                                                                   ` (2 more replies)
  0 siblings, 3 replies; 80+ messages in thread
From: Rafael J. Wysocki @ 2020-06-10 10:38 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Andrzej Pietrasiewicz, Linux PM, ACPI Devel Maling List,
	Linux Kernel Mailing List, linux-iio, Linux ARM,
	Linux Samsung SoC, linux-input, linux-tegra, patches,
	ibm-acpi-devel, Platform Driver, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Collabora Kernel ML

On Wed, Jun 10, 2020 at 11:50 AM Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi All,
>
> On 6/8/20 1:22 PM, Andrzej Pietrasiewicz wrote:
> > This is a quick respin of v3, with just two small changes, please see
> > the changelog below.
> >
> > Userspace might want to implement a policy to temporarily disregard input
> > from certain devices.
> >
> > An example use case is a convertible laptop, whose keyboard can be folded
> > under the screen to create tablet-like experience. The user then must hold
> > the laptop in such a way that it is difficult to avoid pressing the keyboard
> > keys. It is therefore desirable to temporarily disregard input from the
> > keyboard, until it is folded back. This obviously is a policy which should
> > be kept out of the kernel, but the kernel must provide suitable means to
> > implement such a policy.
>
> First of all sorry to start a somewhat new discussion about this
> while this patch set is also somewhat far along in the review process,
> but I believe what I discuss below needs to be taken into account.
>
> Yesterday I have been looking into why an Asus T101HA would not stay
> suspended when the LID is closed. The cause is that the USB HID multi-touch
> touchpad in the base of the device starts sending events when the screen
> gets close to the touchpad (so when the LID is fully closed) and these
> events are causing a wakeup from suspend. HID multi-touch devices
> do have a way to tell them to fully stop sending events, also disabling
> the USB remote wakeup the device is doing. The question is when to tell
> it to not send events though ...
>
> So now I've been thinking about how to fix this and I believe that there
> is some interaction between this problem and this patch-set.
>
> The problem I'm seeing on the T101HA is about wakeups, so the question
> which I want to discuss is:
>
> 1. How does inhibiting interact with enabling /
> disabling the device as a wakeup source ?
>
> 2. Since we have now made inhibiting equal open/close how does open/close
> interact with a device being a wakeup source ?
>
> And my own initial (to be discussed) answers to these questions:
>
> 1. It seems to me that when a device is inhibited it should not be a
> wakeup source, so where possible a input-device-driver should disable
> a device's wakeup capabilities on suspend if inhibited

If "inhibit" means "do not generate any events going forward", then
this must also cover wakeup events, so I agree.

> 2. This one is trickier I don't think we have really clearly specified
> any behavior here. The default behavior of most drivers seems to be
> using something like this in their suspend callback:
>
>          if (device_may_wakeup(dev))
>                  enable_irq_wake(data->irq);
>          else if (input->users)
>                  foo_stop_receiving_events(data);
>
> Since this is what most drivers seem to do I believe we should keep
> this as is and that we should just clearly document that if the
> input_device has users (has been opened) or not does not matter
> for its wakeup behavior.
>
> Combining these 2 answers leads to this new pseudo code template
> for an input-device's suspend method:
>
>         /*
>          * If inhibited we have already disabled events and
>          * we do NOT want to setup the device as wake source.
>          */
>         if (input->inhibited)
>                 return 0;
>
>          if (device_may_wakeup(dev))
>                  enable_irq_wake(data->irq);
>          else if (input->users)
>                  foo_stop_receiving_events(data);
>
> ###

Sounds reasonable to me.

> A different, but related issue is how to make devices actually use the
> new inhibit support on the builtin keyboard + touchpad when say the lid
> is closed.   Arguably this is an userspace problem, but it is a tricky
> one. Currently on most modern Linux distributions suspend-on-lid-close
> is handled by systemd-logind and most modern desktop-environments are
> happy to have logind handle this for them.
>
> But most knowledge about input devices and e.g. heurisitics to decide
> if a touchpad is internal or external are part of libinput. Now we could
> have libinput use the new inhibit support (1), but then when the lid
> closes we get race between whatever process is using libinput trying
> to inhibit the touchpad (which must be done before to suspend to disable
> it as wakeup source) and logind trying to suspend the system.
>
> One solution here would be to move the setting of the inhibit sysfs
> attr into logind, but that requires adding a whole bunch of extra
> knowledge to logind which does not really belong there IMHO.
>
> I've been thinking a bit about this and to me it seems that the kernel
> is in the ideal position to automatically inhibit some devices when
> some EV_SW transitions from 0->1 (and uninhibit again on 1->0). The
> issue here is to chose on which devices to enable this. I believe
> that the auto inhibit on some switches mechanism is best done inside
> the kernel (disabled by default) and then we can have a sysfs
> attr called auto_inhibit_ev_sw_mask which can be set to e.g.
> (1 << SW_LID) to make the kernel auto-inhibit the input-device whenever
> the lid is closed, or to ((1 << SW_LID) | (1 << SW_TABLET_MODE)) to
> inhibit both when the lid is closed or when switched to tablet mode.

I agree that the kernel is the right place to handle this, but it
requires some extra knowledge about dependencies between devices.

It'd be kind of like power resources in ACPI, so for each state of a
"master" device (in principle, there may be more states of it than
just two) there would be a list of "dependent" intput devices that
need to be inhibited when the "master" device goes into that state.

> This could then be combined with a userspace utility run from an
> udev rule which makes the actual decision what auto_inhibit_ev_sw_mask
> should be set for a given input device.
>
> This will put the mechanism for what we want inside the kernel and
> leaves the policy on which switches we want this for out of the
> kernel.
>
> Note adding this new auto_inhibit_ev_sw_mask sysfs attr falls
> somewhat outside the context of this patchset and could be done
> as a follow up to this patch-set. But I do believe that we need to
> figure out how (non ChromeOS) userspace can / will use the new inhibit
> interface before merging it.

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

* Re: [PATCH v4 0/7] Support inhibiting input devices
  2020-06-10 10:38                                               ` Rafael J. Wysocki
@ 2020-06-10 13:12                                                 ` Andrzej Pietrasiewicz
  2020-06-10 13:21                                                   ` Hans de Goede
  2020-06-10 13:52                                                 ` Hans de Goede
  2020-06-10 18:28                                                 ` Dmitry Torokhov
  2 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-10 13:12 UTC (permalink / raw)
  To: Rafael J. Wysocki, Hans de Goede
  Cc: Linux PM, ACPI Devel Maling List, Linux Kernel Mailing List,
	linux-iio, Linux ARM, Linux Samsung SoC, linux-input,
	linux-tegra, patches, ibm-acpi-devel, Platform Driver,
	Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Collabora Kernel ML

Hi All,

W dniu 10.06.2020 o 12:38, Rafael J. Wysocki pisze:
> On Wed, Jun 10, 2020 at 11:50 AM Hans de Goede <hdegoede@redhat.com> wrote:
>>
>> Hi All,
>>
>> On 6/8/20 1:22 PM, Andrzej Pietrasiewicz wrote:
>>> This is a quick respin of v3, with just two small changes, please see
>>> the changelog below.
>>>
>>> Userspace might want to implement a policy to temporarily disregard input
>>> from certain devices.
>>>
>>> An example use case is a convertible laptop, whose keyboard can be folded
>>> under the screen to create tablet-like experience. The user then must hold
>>> the laptop in such a way that it is difficult to avoid pressing the keyboard
>>> keys. It is therefore desirable to temporarily disregard input from the
>>> keyboard, until it is folded back. This obviously is a policy which should
>>> be kept out of the kernel, but the kernel must provide suitable means to
>>> implement such a policy.
>>
>> First of all sorry to start a somewhat new discussion about this
>> while this patch set is also somewhat far along in the review process,
>> but I believe what I discuss below needs to be taken into account.
>>
>> Yesterday I have been looking into why an Asus T101HA would not stay
>> suspended when the LID is closed. The cause is that the USB HID multi-touch
>> touchpad in the base of the device starts sending events when the screen
>> gets close to the touchpad (so when the LID is fully closed) and these
>> events are causing a wakeup from suspend. HID multi-touch devices
>> do have a way to tell them to fully stop sending events, also disabling
>> the USB remote wakeup the device is doing. The question is when to tell
>> it to not send events though ...
>>
>> So now I've been thinking about how to fix this and I believe that there
>> is some interaction between this problem and this patch-set.
>>
>> The problem I'm seeing on the T101HA is about wakeups, so the question
>> which I want to discuss is:
>>
>> 1. How does inhibiting interact with enabling /
>> disabling the device as a wakeup source ?
>>
>> 2. Since we have now made inhibiting equal open/close how does open/close
>> interact with a device being a wakeup source ?
>>
>> And my own initial (to be discussed) answers to these questions:
>>
>> 1. It seems to me that when a device is inhibited it should not be a
>> wakeup source, so where possible a input-device-driver should disable
>> a device's wakeup capabilities on suspend if inhibited
> 
> If "inhibit" means "do not generate any events going forward", then
> this must also cover wakeup events, so I agree.

I agree, too.

> 
>> 2. This one is trickier I don't think we have really clearly specified
>> any behavior here. The default behavior of most drivers seems to be
>> using something like this in their suspend callback:
>>
>>           if (device_may_wakeup(dev))
>>                   enable_irq_wake(data->irq);
>>           else if (input->users)
>>                   foo_stop_receiving_events(data);
>>
>> Since this is what most drivers seem to do I believe we should keep
>> this as is and that we should just clearly document that if the
>> input_device has users (has been opened) or not does not matter
>> for its wakeup behavior.
>>
>> Combining these 2 answers leads to this new pseudo code template
>> for an input-device's suspend method:
>>
>>          /*
>>           * If inhibited we have already disabled events and
>>           * we do NOT want to setup the device as wake source.
>>           */
>>          if (input->inhibited)
>>                  return 0;

Right, if a device is inhibited it shouldn't become a wakeup source,
because that would contradict the purpose of being inhibited.

>>
>>           if (device_may_wakeup(dev))
>>                   enable_irq_wake(data->irq);

What would it mean to become a wakeup source if there are no users,
or nobody has ever opened the device? There are no interested
input handlers (users) so what's the point of becoming a wakeup
source? Why would the system need to wake up?

>>           else if (input->users)
>>                   foo_stop_receiving_events(data);
>>
>> ###
> 
> Sounds reasonable to me.
> 
>> A different, but related issue is how to make devices actually use the
>> new inhibit support on the builtin keyboard + touchpad when say the lid
>> is closed.   Arguably this is an userspace problem, but it is a tricky
>> one. Currently on most modern Linux distributions suspend-on-lid-close
>> is handled by systemd-logind and most modern desktop-environments are
>> happy to have logind handle this for them.
>>
>> But most knowledge about input devices and e.g. heurisitics to decide
>> if a touchpad is internal or external are part of libinput. Now we could
>> have libinput use the new inhibit support (1), but then when the lid
>> closes we get race between whatever process is using libinput trying
>> to inhibit the touchpad (which must be done before to suspend to disable
>> it as wakeup source) and logind trying to suspend the system.
>>
>> One solution here would be to move the setting of the inhibit sysfs
>> attr into logind, but that requires adding a whole bunch of extra
>> knowledge to logind which does not really belong there IMHO.
>>
>> I've been thinking a bit about this and to me it seems that the kernel
>> is in the ideal position to automatically inhibit some devices when
>> some EV_SW transitions from 0->1 (and uninhibit again on 1->0). The
>> issue here is to chose on which devices to enable this. I believe
>> that the auto inhibit on some switches mechanism is best done inside
>> the kernel (disabled by default) and then we can have a sysfs
>> attr called auto_inhibit_ev_sw_mask which can be set to e.g.
>> (1 << SW_LID) to make the kernel auto-inhibit the input-device whenever
>> the lid is closed, or to ((1 << SW_LID) | (1 << SW_TABLET_MODE)) to
>> inhibit both when the lid is closed or when switched to tablet mode.
> 
> I agree that the kernel is the right place to handle this, but it
> requires some extra knowledge about dependencies between devices.
> 
> It'd be kind of like power resources in ACPI, so for each state of a
> "master" device (in principle, there may be more states of it than
> just two) there would be a list of "dependent" intput devices that
> need to be inhibited when the "master" device goes into that state.
> 
>> This could then be combined with a userspace utility run from an
>> udev rule which makes the actual decision what auto_inhibit_ev_sw_mask
>> should be set for a given input device.
>>
>> This will put the mechanism for what we want inside the kernel and
>> leaves the policy on which switches we want this for out of the
>> kernel.
>>
>> Note adding this new auto_inhibit_ev_sw_mask sysfs attr falls
>> somewhat outside the context of this patchset and could be done
>> as a follow up to this patch-set.

Yes, please ;)

But I do believe that we need to
>> figure out how (non ChromeOS) userspace can / will use the new inhibit
>> interface before merging it.

Of course.

Regards,

Andrzej

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

* Re: [PATCH v4 0/7] Support inhibiting input devices
  2020-06-10 13:12                                                 ` Andrzej Pietrasiewicz
@ 2020-06-10 13:21                                                   ` Hans de Goede
  2020-06-10 13:41                                                     ` Andrzej Pietrasiewicz
  2020-06-10 14:01                                                     ` [PATCH v4 0/7] Support inhibiting input devices Rafael J. Wysocki
  0 siblings, 2 replies; 80+ messages in thread
From: Hans de Goede @ 2020-06-10 13:21 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, Rafael J. Wysocki
  Cc: Linux PM, ACPI Devel Maling List, Linux Kernel Mailing List,
	linux-iio, Linux ARM, Linux Samsung SoC, linux-input,
	linux-tegra, patches, ibm-acpi-devel, Platform Driver,
	Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Collabora Kernel ML

Hi,

On 6/10/20 3:12 PM, Andrzej Pietrasiewicz wrote:
> Hi All,
> 
> W dniu 10.06.2020 o 12:38, Rafael J. Wysocki pisze:
>> On Wed, Jun 10, 2020 at 11:50 AM Hans de Goede <hdegoede@redhat.com> wrote:
>>>
>>> Hi All,
>>>
>>> On 6/8/20 1:22 PM, Andrzej Pietrasiewicz wrote:
>>>> This is a quick respin of v3, with just two small changes, please see
>>>> the changelog below.
>>>>
>>>> Userspace might want to implement a policy to temporarily disregard input
>>>> from certain devices.
>>>>
>>>> An example use case is a convertible laptop, whose keyboard can be folded
>>>> under the screen to create tablet-like experience. The user then must hold
>>>> the laptop in such a way that it is difficult to avoid pressing the keyboard
>>>> keys. It is therefore desirable to temporarily disregard input from the
>>>> keyboard, until it is folded back. This obviously is a policy which should
>>>> be kept out of the kernel, but the kernel must provide suitable means to
>>>> implement such a policy.
>>>
>>> First of all sorry to start a somewhat new discussion about this
>>> while this patch set is also somewhat far along in the review process,
>>> but I believe what I discuss below needs to be taken into account.
>>>
>>> Yesterday I have been looking into why an Asus T101HA would not stay
>>> suspended when the LID is closed. The cause is that the USB HID multi-touch
>>> touchpad in the base of the device starts sending events when the screen
>>> gets close to the touchpad (so when the LID is fully closed) and these
>>> events are causing a wakeup from suspend. HID multi-touch devices
>>> do have a way to tell them to fully stop sending events, also disabling
>>> the USB remote wakeup the device is doing. The question is when to tell
>>> it to not send events though ...
>>>
>>> So now I've been thinking about how to fix this and I believe that there
>>> is some interaction between this problem and this patch-set.
>>>
>>> The problem I'm seeing on the T101HA is about wakeups, so the question
>>> which I want to discuss is:
>>>
>>> 1. How does inhibiting interact with enabling /
>>> disabling the device as a wakeup source ?
>>>
>>> 2. Since we have now made inhibiting equal open/close how does open/close
>>> interact with a device being a wakeup source ?
>>>
>>> And my own initial (to be discussed) answers to these questions:
>>>
>>> 1. It seems to me that when a device is inhibited it should not be a
>>> wakeup source, so where possible a input-device-driver should disable
>>> a device's wakeup capabilities on suspend if inhibited
>>
>> If "inhibit" means "do not generate any events going forward", then
>> this must also cover wakeup events, so I agree.
> 
> I agree, too.
> 
>>
>>> 2. This one is trickier I don't think we have really clearly specified
>>> any behavior here. The default behavior of most drivers seems to be
>>> using something like this in their suspend callback:
>>>
>>>           if (device_may_wakeup(dev))
>>>                   enable_irq_wake(data->irq);
>>>           else if (input->users)
>>>                   foo_stop_receiving_events(data);
>>>
>>> Since this is what most drivers seem to do I believe we should keep
>>> this as is and that we should just clearly document that if the
>>> input_device has users (has been opened) or not does not matter
>>> for its wakeup behavior.
>>>
>>> Combining these 2 answers leads to this new pseudo code template
>>> for an input-device's suspend method:
>>>
>>>          /*
>>>           * If inhibited we have already disabled events and
>>>           * we do NOT want to setup the device as wake source.
>>>           */
>>>          if (input->inhibited)
>>>                  return 0;
> 
> Right, if a device is inhibited it shouldn't become a wakeup source,
> because that would contradict the purpose of being inhibited.

Ack. Note I do think that we need to document this (and more
in general the answer to both questions from above) clearly so
that going forward if there are any questions about how this is
supposed to work we can just point to the docs.

Can you do a follow-up patch, or include a patch in your next
version which documents this (once we agree on what "this"
exactly is) ?

>>>
>>>           if (device_may_wakeup(dev))
>>>                   enable_irq_wake(data->irq);
> 
> What would it mean to become a wakeup source if there are no users,
> or nobody has ever opened the device? There are no interested
> input handlers (users) so what's the point of becoming a wakeup
> source? Why would the system need to wake up?

Well this is what we have been doing so far, so arguably we
need to keep doing it to avoid regressions / breaking our ABI.

Lets for example take a laptop, where when suspended the
power-button is the only valid wakeup-source and this is
running good old slackware with fvwm2 or windowmaker as
"desktop environment", then likely no process will have
the power-button input evdev node open.  Still we should
wakeup the laptop on the power-button press, otherwise
it will never wakeup.

Note I agree with you that the way this works is not
ideal, I just do not think that we can change it.

>>>           else if (input->users)
>>>                   foo_stop_receiving_events(data);
>>>
>>> ###

<snip>

Regards,

Hans


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

* Re: [PATCH v4 0/7] Support inhibiting input devices
  2020-06-10 13:21                                                   ` Hans de Goede
@ 2020-06-10 13:41                                                     ` Andrzej Pietrasiewicz
  2020-06-12  8:30                                                       ` Hans de Goede
  2020-06-10 14:01                                                     ` [PATCH v4 0/7] Support inhibiting input devices Rafael J. Wysocki
  1 sibling, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-10 13:41 UTC (permalink / raw)
  To: Hans de Goede, Rafael J. Wysocki
  Cc: Linux PM, ACPI Devel Maling List, Linux Kernel Mailing List,
	linux-iio, Linux ARM, Linux Samsung SoC, linux-input,
	linux-tegra, patches, ibm-acpi-devel, Platform Driver,
	Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Collabora Kernel ML

Hi Hans,

W dniu 10.06.2020 o 15:21, Hans de Goede pisze:
> Hi,
> 
> On 6/10/20 3:12 PM, Andrzej Pietrasiewicz wrote:
>> Hi All,
>>
>> W dniu 10.06.2020 o 12:38, Rafael J. Wysocki pisze:
>>> On Wed, Jun 10, 2020 at 11:50 AM Hans de Goede <hdegoede@redhat.com> wrote:
>>>>
>>>> Hi All,
>>>>
>>>> On 6/8/20 1:22 PM, Andrzej Pietrasiewicz wrote:
>>>>> This is a quick respin of v3, with just two small changes, please see
>>>>> the changelog below.
>>>>>
>>>>> Userspace might want to implement a policy to temporarily disregard input
>>>>> from certain devices.
>>>>>
>>>>> An example use case is a convertible laptop, whose keyboard can be folded
>>>>> under the screen to create tablet-like experience. The user then must hold
>>>>> the laptop in such a way that it is difficult to avoid pressing the keyboard
>>>>> keys. It is therefore desirable to temporarily disregard input from the
>>>>> keyboard, until it is folded back. This obviously is a policy which should
>>>>> be kept out of the kernel, but the kernel must provide suitable means to
>>>>> implement such a policy.
>>>>
>>>> First of all sorry to start a somewhat new discussion about this
>>>> while this patch set is also somewhat far along in the review process,
>>>> but I believe what I discuss below needs to be taken into account.
>>>>
>>>> Yesterday I have been looking into why an Asus T101HA would not stay
>>>> suspended when the LID is closed. The cause is that the USB HID multi-touch
>>>> touchpad in the base of the device starts sending events when the screen
>>>> gets close to the touchpad (so when the LID is fully closed) and these
>>>> events are causing a wakeup from suspend. HID multi-touch devices
>>>> do have a way to tell them to fully stop sending events, also disabling
>>>> the USB remote wakeup the device is doing. The question is when to tell
>>>> it to not send events though ...
>>>>
>>>> So now I've been thinking about how to fix this and I believe that there
>>>> is some interaction between this problem and this patch-set.
>>>>
>>>> The problem I'm seeing on the T101HA is about wakeups, so the question
>>>> which I want to discuss is:
>>>>
>>>> 1. How does inhibiting interact with enabling /
>>>> disabling the device as a wakeup source ?
>>>>
>>>> 2. Since we have now made inhibiting equal open/close how does open/close
>>>> interact with a device being a wakeup source ?
>>>>
>>>> And my own initial (to be discussed) answers to these questions:
>>>>
>>>> 1. It seems to me that when a device is inhibited it should not be a
>>>> wakeup source, so where possible a input-device-driver should disable
>>>> a device's wakeup capabilities on suspend if inhibited
>>>
>>> If "inhibit" means "do not generate any events going forward", then
>>> this must also cover wakeup events, so I agree.
>>
>> I agree, too.
>>
>>>
>>>> 2. This one is trickier I don't think we have really clearly specified
>>>> any behavior here. The default behavior of most drivers seems to be
>>>> using something like this in their suspend callback:
>>>>
>>>>           if (device_may_wakeup(dev))
>>>>                   enable_irq_wake(data->irq);
>>>>           else if (input->users)
>>>>                   foo_stop_receiving_events(data);
>>>>
>>>> Since this is what most drivers seem to do I believe we should keep
>>>> this as is and that we should just clearly document that if the
>>>> input_device has users (has been opened) or not does not matter
>>>> for its wakeup behavior.
>>>>
>>>> Combining these 2 answers leads to this new pseudo code template
>>>> for an input-device's suspend method:
>>>>
>>>>          /*
>>>>           * If inhibited we have already disabled events and
>>>>           * we do NOT want to setup the device as wake source.
>>>>           */
>>>>          if (input->inhibited)
>>>>                  return 0;
>>
>> Right, if a device is inhibited it shouldn't become a wakeup source,
>> because that would contradict the purpose of being inhibited.
> 
> Ack. Note I do think that we need to document this (and more
> in general the answer to both questions from above) clearly so
> that going forward if there are any questions about how this is
> supposed to work we can just point to the docs.
> 
> Can you do a follow-up patch, or include a patch in your next
> version which documents this (once we agree on what "this"
> exactly is) ?

Sure I can. Just need to know when "this" becomes stable enough ;)
If this series otherwise looks mature enough I would opt for a
follow-up patch.

> 
>>>>
>>>>           if (device_may_wakeup(dev))
>>>>                   enable_irq_wake(data->irq);
>>
>> What would it mean to become a wakeup source if there are no users,
>> or nobody has ever opened the device? There are no interested
>> input handlers (users) so what's the point of becoming a wakeup
>> source? Why would the system need to wake up?
> 
> Well this is what we have been doing so far, so arguably we
> need to keep doing it to avoid regressions / breaking our ABI.
> 
> Lets for example take a laptop, where when suspended the
> power-button is the only valid wakeup-source and this is
> running good old slackware with fvwm2 or windowmaker as
> "desktop environment", then likely no process will have
> the power-button input evdev node open.  Still we should
> wakeup the laptop on the power-button press, otherwise
> it will never wakeup.
> 

True, thanks for explaining.

> Note I agree with you that the way this works is not
> ideal, I just do not think that we can change it.
> 

Regards,

Andrzej

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

* Re: [PATCH v4 0/7] Support inhibiting input devices
  2020-06-10 10:38                                               ` Rafael J. Wysocki
  2020-06-10 13:12                                                 ` Andrzej Pietrasiewicz
@ 2020-06-10 13:52                                                 ` Hans de Goede
  2020-06-10 18:28                                                 ` Dmitry Torokhov
  2 siblings, 0 replies; 80+ messages in thread
From: Hans de Goede @ 2020-06-10 13:52 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Andrzej Pietrasiewicz, Linux PM, ACPI Devel Maling List,
	Linux Kernel Mailing List, linux-iio, Linux ARM,
	Linux Samsung SoC, linux-input, linux-tegra, patches,
	ibm-acpi-devel, Platform Driver, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Collabora Kernel ML

Hi,

On 6/10/20 12:38 PM, Rafael J. Wysocki wrote:
> On Wed, Jun 10, 2020 at 11:50 AM Hans de Goede <hdegoede@redhat.com> wrote:

<snip>

>> A different, but related issue is how to make devices actually use the
>> new inhibit support on the builtin keyboard + touchpad when say the lid
>> is closed.   Arguably this is an userspace problem, but it is a tricky
>> one. Currently on most modern Linux distributions suspend-on-lid-close
>> is handled by systemd-logind and most modern desktop-environments are
>> happy to have logind handle this for them.
>>
>> But most knowledge about input devices and e.g. heurisitics to decide
>> if a touchpad is internal or external are part of libinput. Now we could
>> have libinput use the new inhibit support (1), but then when the lid
>> closes we get race between whatever process is using libinput trying
>> to inhibit the touchpad (which must be done before to suspend to disable
>> it as wakeup source) and logind trying to suspend the system.
>>
>> One solution here would be to move the setting of the inhibit sysfs
>> attr into logind, but that requires adding a whole bunch of extra
>> knowledge to logind which does not really belong there IMHO.
>>
>> I've been thinking a bit about this and to me it seems that the kernel
>> is in the ideal position to automatically inhibit some devices when
>> some EV_SW transitions from 0->1 (and uninhibit again on 1->0). The
>> issue here is to chose on which devices to enable this. I believe
>> that the auto inhibit on some switches mechanism is best done inside
>> the kernel (disabled by default) and then we can have a sysfs
>> attr called auto_inhibit_ev_sw_mask which can be set to e.g.
>> (1 << SW_LID) to make the kernel auto-inhibit the input-device whenever
>> the lid is closed, or to ((1 << SW_LID) | (1 << SW_TABLET_MODE)) to
>> inhibit both when the lid is closed or when switched to tablet mode.
> 
> I agree that the kernel is the right place to handle this, but it
> requires some extra knowledge about dependencies between devices.
>
> It'd be kind of like power resources in ACPI, so for each state of a
> "master" device (in principle, there may be more states of it than
> just two) there would be a list of "dependent" intput devices that
> need to be inhibited when the "master" device goes into that state.

So a big part of the reason to punt the decision on which input
devices to enable this auto-inhibit is that we don't really have
information about those relationsships / device-links you are
suggesting here.  libinput is already doing inhibiting inside
userspace for e.g. the tablet-mode switch but it relies on heuristics
+ quirk tables to decide which keyboards should be inhibited and which
not.

E.g. for a 360 degree hinges 2-in-1 we want to disable the builtin
keyboard, when folded into in tablet mode, but not any external ones.

Mostly the builtin kbd will be PS2 but I have one such 2-in-1 here
in my home office with a USB kbd ...

In general of the master devices there will be only 1, there will be
only 1 lid switch and only 1 tablet-mode switch. So my idea with the
auto_inhibit_ev_sw_mask, is for it to be a per input-device setting.

So using your terms, all input devices with the (1 << SW_LID) bit
set in their auto_inhibit_ev_sw_mask will be dependents of the
(master) device which actually is reporting the SW_LID bit.

The idea here is for this to work the same as how the rfkill code
from net/rfkill/input.c works, except instead of binding e.g.
KEY_WLAN to toggling the sw-state of rfkill devices with a type
of RFKILL_TYPE_WLAN. This will bind SW_LID to inhibiting input
devices with the SW_LID bit set in their auto_inhibit_ev_sw_mask.

Regards,

Hans


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

* Re: [PATCH v4 0/7] Support inhibiting input devices
  2020-06-10 13:21                                                   ` Hans de Goede
  2020-06-10 13:41                                                     ` Andrzej Pietrasiewicz
@ 2020-06-10 14:01                                                     ` Rafael J. Wysocki
  1 sibling, 0 replies; 80+ messages in thread
From: Rafael J. Wysocki @ 2020-06-10 14:01 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Andrzej Pietrasiewicz, Rafael J. Wysocki, Linux PM,
	ACPI Devel Maling List, Linux Kernel Mailing List, linux-iio,
	Linux ARM, Linux Samsung SoC, linux-input, linux-tegra, patches,
	ibm-acpi-devel, Platform Driver, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Collabora Kernel ML

On Wed, Jun 10, 2020 at 3:21 PM Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi,
>
> On 6/10/20 3:12 PM, Andrzej Pietrasiewicz wrote:
> > Hi All,
> >

[cut]

> > What would it mean to become a wakeup source if there are no users,
> > or nobody has ever opened the device? There are no interested
> > input handlers (users) so what's the point of becoming a wakeup
> > source? Why would the system need to wake up?
>
> Well this is what we have been doing so far, so arguably we
> need to keep doing it to avoid regressions / breaking our ABI.
>
> Lets for example take a laptop, where when suspended the
> power-button is the only valid wakeup-source and this is
> running good old slackware with fvwm2 or windowmaker as
> "desktop environment", then likely no process will have
> the power-button input evdev node open.  Still we should
> wakeup the laptop on the power-button press, otherwise
> it will never wakeup.
>
> Note I agree with you that the way this works is not
> ideal, I just do not think that we can change it.

Please note that "no users" merely means that user space is not
interested in receiving and processing the events from that device.

If it is configured for system wakeup, it doesn't matter whether or
not user space will consume the related events.

Thanks!

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

* Re: [PATCH v4 0/7] Support inhibiting input devices
  2020-06-10 10:38                                               ` Rafael J. Wysocki
  2020-06-10 13:12                                                 ` Andrzej Pietrasiewicz
  2020-06-10 13:52                                                 ` Hans de Goede
@ 2020-06-10 18:28                                                 ` Dmitry Torokhov
  2020-06-12  8:14                                                   ` Hans de Goede
  2 siblings, 1 reply; 80+ messages in thread
From: Dmitry Torokhov @ 2020-06-10 18:28 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Hans de Goede, Andrzej Pietrasiewicz, Linux PM,
	ACPI Devel Maling List, Linux Kernel Mailing List, linux-iio,
	Linux ARM, Linux Samsung SoC, linux-input, linux-tegra, patches,
	ibm-acpi-devel, Platform Driver, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh, Collabora Kernel ML

On Wed, Jun 10, 2020 at 12:38:30PM +0200, Rafael J. Wysocki wrote:
> On Wed, Jun 10, 2020 at 11:50 AM Hans de Goede <hdegoede@redhat.com> wrote:
> >
> > Hi All,
> >
> > On 6/8/20 1:22 PM, Andrzej Pietrasiewicz wrote:
> > > This is a quick respin of v3, with just two small changes, please see
> > > the changelog below.
> > >
> > > Userspace might want to implement a policy to temporarily disregard input
> > > from certain devices.
> > >
> > > An example use case is a convertible laptop, whose keyboard can be folded
> > > under the screen to create tablet-like experience. The user then must hold
> > > the laptop in such a way that it is difficult to avoid pressing the keyboard
> > > keys. It is therefore desirable to temporarily disregard input from the
> > > keyboard, until it is folded back. This obviously is a policy which should
> > > be kept out of the kernel, but the kernel must provide suitable means to
> > > implement such a policy.
> >
> > First of all sorry to start a somewhat new discussion about this
> > while this patch set is also somewhat far along in the review process,
> > but I believe what I discuss below needs to be taken into account.
> >
> > Yesterday I have been looking into why an Asus T101HA would not stay
> > suspended when the LID is closed. The cause is that the USB HID multi-touch
> > touchpad in the base of the device starts sending events when the screen
> > gets close to the touchpad (so when the LID is fully closed) and these
> > events are causing a wakeup from suspend. HID multi-touch devices
> > do have a way to tell them to fully stop sending events, also disabling
> > the USB remote wakeup the device is doing. The question is when to tell
> > it to not send events though ...
> >
> > So now I've been thinking about how to fix this and I believe that there
> > is some interaction between this problem and this patch-set.
> >
> > The problem I'm seeing on the T101HA is about wakeups, so the question
> > which I want to discuss is:
> >
> > 1. How does inhibiting interact with enabling /
> > disabling the device as a wakeup source ?

One should not affect the other.

> >
> > 2. Since we have now made inhibiting equal open/close how does open/close
> > interact with a device being a wakeup source ?

One did not affect another, and it should not.

> >
> > And my own initial (to be discussed) answers to these questions:
> >
> > 1. It seems to me that when a device is inhibited it should not be a
> > wakeup source, so where possible a input-device-driver should disable
> > a device's wakeup capabilities on suspend if inhibited
> 
> If "inhibit" means "do not generate any events going forward", then
> this must also cover wakeup events, so I agree.

Why? These are separate concepts. Do we disable wake on lan when
bringing network interface down? Do we update power/wakeup when device
is inhibited? Do we restore it afterwards? Do we un-inhibit if we
reenable wakeup after device is inhibited? Do we return error? How?

Inhibit works on logical level, i.e. if I have several input interfaces
on the same hardware device, I cam inhibit one leaving others intact.
This does not mean that the device should stop generating wakeup events.
We can't even guarantee this for composite devices.

> 
> > 2. This one is trickier I don't think we have really clearly specified
> > any behavior here. The default behavior of most drivers seems to be
> > using something like this in their suspend callback:
> >
> >          if (device_may_wakeup(dev))
> >                  enable_irq_wake(data->irq);
> >          else if (input->users)
> >                  foo_stop_receiving_events(data);
> >
> > Since this is what most drivers seem to do I believe we should keep
> > this as is and that we should just clearly document that if the
> > input_device has users (has been opened) or not does not matter
> > for its wakeup behavior.
> >
> > Combining these 2 answers leads to this new pseudo code template
> > for an input-device's suspend method:
> >
> >         /*
> >          * If inhibited we have already disabled events and
> >          * we do NOT want to setup the device as wake source.
> >          */
> >         if (input->inhibited)
> >                 return 0;
> >
> >          if (device_may_wakeup(dev))
> >                  enable_irq_wake(data->irq);
> >          else if (input->users)
> >                  foo_stop_receiving_events(data);
> >
> > ###
> 
> Sounds reasonable to me.

However it will not work. For many input devices connected to i2c we
declare interrupt as wakeup interrupt, and the driver does not need to
issue enable_irq_wake() and disable_irq_wake(). The wakeup handling is
happening in driver core, which is not aware of input-specific inhibit
(nor should it be).

I need to ping Mark about the patch adding the similar handling to SPI.

> 
> > A different, but related issue is how to make devices actually use the
> > new inhibit support on the builtin keyboard + touchpad when say the lid
> > is closed.   Arguably this is an userspace problem, but it is a tricky
> > one. Currently on most modern Linux distributions suspend-on-lid-close
> > is handled by systemd-logind and most modern desktop-environments are
> > happy to have logind handle this for them.
> >
> > But most knowledge about input devices and e.g. heurisitics to decide
> > if a touchpad is internal or external are part of libinput. Now we could
> > have libinput use the new inhibit support (1), but then when the lid
> > closes we get race between whatever process is using libinput trying
> > to inhibit the touchpad (which must be done before to suspend to disable
> > it as wakeup source) and logind trying to suspend the system.
> >
> > One solution here would be to move the setting of the inhibit sysfs
> > attr into logind, but that requires adding a whole bunch of extra
> > knowledge to logind which does not really belong there IMHO.

You do not need to push the knowledge into logind, you just need to
communicate to logind what devices can be wakeup sources and which ones
should not. Chrome OS uses udev tags/properties for that.

> >
> > I've been thinking a bit about this and to me it seems that the kernel
> > is in the ideal position to automatically inhibit some devices when
> > some EV_SW transitions from 0->1 (and uninhibit again on 1->0). The
> > issue here is to chose on which devices to enable this. I believe
> > that the auto inhibit on some switches mechanism is best done inside
> > the kernel (disabled by default) and then we can have a sysfs
> > attr called auto_inhibit_ev_sw_mask which can be set to e.g.
> > (1 << SW_LID) to make the kernel auto-inhibit the input-device whenever
> > the lid is closed, or to ((1 << SW_LID) | (1 << SW_TABLET_MODE)) to
> > inhibit both when the lid is closed or when switched to tablet mode.

This is a policy and should be kept out of the kernel. Yes, we had it
implemented with rfkill input handler, but it caused quite a few issues.
As far as I know it is not being used anymore and we should not try with
SW_LID->inhibit either.

I know it is faster to patch the kernel than to roll out proper
userspace because everyone updates kernel regularly, but it does not
mean it is the right solution.

Thanks.

-- 
Dmitry

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

* Re: [PATCH v4 0/7] Support inhibiting input devices
  2020-06-10 18:28                                                 ` Dmitry Torokhov
@ 2020-06-12  8:14                                                   ` Hans de Goede
  0 siblings, 0 replies; 80+ messages in thread
From: Hans de Goede @ 2020-06-12  8:14 UTC (permalink / raw)
  To: Dmitry Torokhov, Rafael J. Wysocki
  Cc: Andrzej Pietrasiewicz, Linux PM, ACPI Devel Maling List,
	Linux Kernel Mailing List, linux-iio, Linux ARM,
	Linux Samsung SoC, linux-input, linux-tegra, patches,
	ibm-acpi-devel, Platform Driver, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh, Collabora Kernel ML

Hi,

On 6/10/20 8:28 PM, Dmitry Torokhov wrote:
> On Wed, Jun 10, 2020 at 12:38:30PM +0200, Rafael J. Wysocki wrote:
>> On Wed, Jun 10, 2020 at 11:50 AM Hans de Goede <hdegoede@redhat.com> wrote:
>>>
>>> Hi All,
>>>
>>> On 6/8/20 1:22 PM, Andrzej Pietrasiewicz wrote:
>>>> This is a quick respin of v3, with just two small changes, please see
>>>> the changelog below.
>>>>
>>>> Userspace might want to implement a policy to temporarily disregard input
>>>> from certain devices.
>>>>
>>>> An example use case is a convertible laptop, whose keyboard can be folded
>>>> under the screen to create tablet-like experience. The user then must hold
>>>> the laptop in such a way that it is difficult to avoid pressing the keyboard
>>>> keys. It is therefore desirable to temporarily disregard input from the
>>>> keyboard, until it is folded back. This obviously is a policy which should
>>>> be kept out of the kernel, but the kernel must provide suitable means to
>>>> implement such a policy.
>>>
>>> First of all sorry to start a somewhat new discussion about this
>>> while this patch set is also somewhat far along in the review process,
>>> but I believe what I discuss below needs to be taken into account.
>>>
>>> Yesterday I have been looking into why an Asus T101HA would not stay
>>> suspended when the LID is closed. The cause is that the USB HID multi-touch
>>> touchpad in the base of the device starts sending events when the screen
>>> gets close to the touchpad (so when the LID is fully closed) and these
>>> events are causing a wakeup from suspend. HID multi-touch devices
>>> do have a way to tell them to fully stop sending events, also disabling
>>> the USB remote wakeup the device is doing. The question is when to tell
>>> it to not send events though ...
>>>
>>> So now I've been thinking about how to fix this and I believe that there
>>> is some interaction between this problem and this patch-set.
>>>
>>> The problem I'm seeing on the T101HA is about wakeups, so the question
>>> which I want to discuss is:
>>>
>>> 1. How does inhibiting interact with enabling /
>>> disabling the device as a wakeup source ?
> 
> One should not affect the other.
> 
>>>
>>> 2. Since we have now made inhibiting equal open/close how does open/close
>>> interact with a device being a wakeup source ?
> 
> One did not affect another, and it should not.
> 
>>>
>>> And my own initial (to be discussed) answers to these questions:
>>>
>>> 1. It seems to me that when a device is inhibited it should not be a
>>> wakeup source, so where possible a input-device-driver should disable
>>> a device's wakeup capabilities on suspend if inhibited
>>
>> If "inhibit" means "do not generate any events going forward", then
>> this must also cover wakeup events, so I agree.
> 
> Why? These are separate concepts. Do we disable wake on lan when
> bringing network interface down? Do we update power/wakeup when device
> is inhibited? Do we restore it afterwards? Do we un-inhibit if we
> reenable wakeup after device is inhibited? Do we return error? How?
> 
> Inhibit works on logical level, i.e. if I have several input interfaces
> on the same hardware device, I cam inhibit one leaving others intact.
> This does not mean that the device should stop generating wakeup events.
> We can't even guarantee this for composite devices.

After thinking more about this I believe you are right and we should
keep these as 2 separate, completely independent settings.

Especially since the wakeup setting typically is a setting of the
parent device, where as the inhibit is done on the actual input-dev.

###

Some quick background info on my original thoughts here, as mentioned
I started thinking about this because of spurious wakeups from suspend
when the lid of an asus t101ha is "touching" its touchpad. The HID
multi-touch protocol has a setting where we can ask the device to
stop sending events. So even though the kbd + touchpad are a
single composite USB device, we can disable wakeup (in a way)
for just the touchpad at the hid-multitouch level.

So I was thinking maybe adding a separate wakeup setting to the
input device itself for this. But thinking more about it, when
the lid is closed we can just disable wakeup on the entire USB
device, since the keyboard is covered by the lid too.

And then on suspend the hid-multitouch driver can detect that its
parent (or parents parent in the case of USB) has wakeup disabled
and also tell the device to stop scanning for fingers to save some
power.

We probably also need a close and open callbacks add the HID-driver
level, so that if there are no touchpad users we can also use
the same option to put the HID multi-touch device in a low power mode
where it does not scan for fingers.

<snip>

>>> A different, but related issue is how to make devices actually use the
>>> new inhibit support on the builtin keyboard + touchpad when say the lid
>>> is closed.   Arguably this is an userspace problem, but it is a tricky
>>> one. Currently on most modern Linux distributions suspend-on-lid-close
>>> is handled by systemd-logind and most modern desktop-environments are
>>> happy to have logind handle this for them.
>>>
>>> But most knowledge about input devices and e.g. heurisitics to decide
>>> if a touchpad is internal or external are part of libinput. Now we could
>>> have libinput use the new inhibit support (1), but then when the lid
>>> closes we get race between whatever process is using libinput trying
>>> to inhibit the touchpad (which must be done before to suspend to disable
>>> it as wakeup source) and logind trying to suspend the system.
>>>
>>> One solution here would be to move the setting of the inhibit sysfs
>>> attr into logind, but that requires adding a whole bunch of extra
>>> knowledge to logind which does not really belong there IMHO.
> 
> You do not need to push the knowledge into logind, you just need to
> communicate to logind what devices can be wakeup sources and which ones
> should not. Chrome OS uses udev tags/properties for that.

True, I did not think of doing the tag thingie + letting logind do
the inhibit on LID close based on that. logind could also disable
wakeup (to save power while suspended) on devices which are tagged
for it to do that (should probably be a separate tag from the
inhibit tag).

>>> I've been thinking a bit about this and to me it seems that the kernel
>>> is in the ideal position to automatically inhibit some devices when
>>> some EV_SW transitions from 0->1 (and uninhibit again on 1->0). The
>>> issue here is to chose on which devices to enable this. I believe
>>> that the auto inhibit on some switches mechanism is best done inside
>>> the kernel (disabled by default) and then we can have a sysfs
>>> attr called auto_inhibit_ev_sw_mask which can be set to e.g.
>>> (1 << SW_LID) to make the kernel auto-inhibit the input-device whenever
>>> the lid is closed, or to ((1 << SW_LID) | (1 << SW_TABLET_MODE)) to
>>> inhibit both when the lid is closed or when switched to tablet mode.
> 
> This is a policy and should be kept out of the kernel. Yes, we had it
> implemented with rfkill input handler, but it caused quite a few issues.
> As far as I know it is not being used anymore and we should not try with
> SW_LID->inhibit either.
> 
> I know it is faster to patch the kernel than to roll out proper
> userspace because everyone updates kernel regularly, but it does not
> mean it is the right solution.

Agreed, I just could not come up with a clean userspace solution, but
using udev+hwdb to set a tag for logind instead of having the write
to a new auto_inhibit_ev_sw_mask will work nicely.

So I think this is all resolved now (or at least we have a plan for it).

Regards,

Hans


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

* Re: [PATCH v4 0/7] Support inhibiting input devices
  2020-06-08 11:22                                           ` [PATCH v4 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
                                                               ` (7 preceding siblings ...)
  2020-06-10  9:49                                             ` [PATCH v4 0/7] Support inhibiting input devices Hans de Goede
@ 2020-06-12  8:17                                             ` Hans de Goede
  2020-08-03 14:40                                               ` Andrzej Pietrasiewicz
  8 siblings, 1 reply; 80+ messages in thread
From: Hans de Goede @ 2020-06-12  8:17 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, linux-pm, linux-acpi, linux-kernel,
	linux-iio, linux-arm-kernel, linux-samsung-soc, linux-input,
	linux-tegra, patches, ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, kernel

Hi,

On 6/8/20 1:22 PM, Andrzej Pietrasiewicz wrote:
> This is a quick respin of v3, with just two small changes, please see
> the changelog below.
> 
> Userspace might want to implement a policy to temporarily disregard input
> from certain devices.
> 
> An example use case is a convertible laptop, whose keyboard can be folded
> under the screen to create tablet-like experience. The user then must hold
> the laptop in such a way that it is difficult to avoid pressing the keyboard
> keys. It is therefore desirable to temporarily disregard input from the
> keyboard, until it is folded back. This obviously is a policy which should
> be kept out of the kernel, but the kernel must provide suitable means to
> implement such a policy.
> 
> Due to interactions with suspend/resume, a helper has been added for drivers
> to decide if the device is being used or not (PATCH 1/7) and it has been
> applied to relevant drivers (PATCH 2,4,5,6/7).
> 
> PATCH 7/7 adds support for inhibiting input devices.
> 
> This work is inspired by:
> 
> https://chromium.googlesource.com/chromiumos/third_party/kernel/+/45c2d7bb398f74adfae0017e20b224152fde3822
> 
> and
> 
> https://chromium.googlesource.com/chromiumos/third_party/kernel/+/4ce0e8a3697edb8fd071110b3af65014512061c7
> 
> In this respin the elan_i2c patch is dropped and converting it will be
> addressed later.
> 
> v3..v4:
> - updated the comment in input_open_device() (Hans)
> - used more straightforward locking pattern in adc/exynos (Michał)
> 
> v2..v3:
> - ignored autorepeat events in input_get_disposition() if a key is not
> pressed (Hans)
> - dropped inhibit()/uninhibit() driver callbacks (Hans)
> - split ACPI button patch into taking the lock and using the helper (Rafael)
> - dropped the elan_i2c conversion
> - fixed typos in exynos adc
> 
> v1..v2:
> - added input_device_enabled() helper and used it in drivers (Dmitry)
> - the fact of open() and close() being called in inhibit/uninhibit paths has
> been emphasized in the commit message of PATCH 6/7 (Dmitry)
> 
> Andrzej Pietrasiewicz (6):
>    Input: add input_device_enabled()
>    Input: use input_device_enabled()
>    ACPI: button: Access input device's users under appropriate mutex
>    ACPI: button: Use input_device_enabled() helper
>    iio: adc: exynos: Use input_device_enabled()
>    platform/x86: thinkpad_acpi: Use input_device_enabled()
> 
> Patrik Fimml (1):
>    Input: Add "inhibited" property

The entire series looks good to me:

Acked-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans



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

* Re: [PATCH v4 0/7] Support inhibiting input devices
  2020-06-10 13:41                                                     ` Andrzej Pietrasiewicz
@ 2020-06-12  8:30                                                       ` Hans de Goede
  2020-06-12  8:47                                                         ` Andrzej Pietrasiewicz
  2020-06-16 17:29                                                         ` [PATCH] Input: document inhibiting Andrzej Pietrasiewicz
  0 siblings, 2 replies; 80+ messages in thread
From: Hans de Goede @ 2020-06-12  8:30 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, Rafael J. Wysocki
  Cc: Linux PM, ACPI Devel Maling List, Linux Kernel Mailing List,
	linux-iio, Linux ARM, Linux Samsung SoC, linux-input,
	linux-tegra, patches, ibm-acpi-devel, Platform Driver,
	Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Collabora Kernel ML

Hi,

On 6/10/20 3:41 PM, Andrzej Pietrasiewicz wrote:
> Hi Hans,
> 
> W dniu 10.06.2020 o 15:21, Hans de Goede pisze:
>> Hi,
>>
>> On 6/10/20 3:12 PM, Andrzej Pietrasiewicz wrote:
>>> Hi All,
>>>
>>> W dniu 10.06.2020 o 12:38, Rafael J. Wysocki pisze:
>>>> On Wed, Jun 10, 2020 at 11:50 AM Hans de Goede <hdegoede@redhat.com> wrote:
>>>>>
>>>>> Hi All,
>>>>>
>>>>> On 6/8/20 1:22 PM, Andrzej Pietrasiewicz wrote:
>>>>>> This is a quick respin of v3, with just two small changes, please see
>>>>>> the changelog below.
>>>>>>
>>>>>> Userspace might want to implement a policy to temporarily disregard input
>>>>>> from certain devices.
>>>>>>
>>>>>> An example use case is a convertible laptop, whose keyboard can be folded
>>>>>> under the screen to create tablet-like experience. The user then must hold
>>>>>> the laptop in such a way that it is difficult to avoid pressing the keyboard
>>>>>> keys. It is therefore desirable to temporarily disregard input from the
>>>>>> keyboard, until it is folded back. This obviously is a policy which should
>>>>>> be kept out of the kernel, but the kernel must provide suitable means to
>>>>>> implement such a policy.
>>>>>
>>>>> First of all sorry to start a somewhat new discussion about this
>>>>> while this patch set is also somewhat far along in the review process,
>>>>> but I believe what I discuss below needs to be taken into account.
>>>>>
>>>>> Yesterday I have been looking into why an Asus T101HA would not stay
>>>>> suspended when the LID is closed. The cause is that the USB HID multi-touch
>>>>> touchpad in the base of the device starts sending events when the screen
>>>>> gets close to the touchpad (so when the LID is fully closed) and these
>>>>> events are causing a wakeup from suspend. HID multi-touch devices
>>>>> do have a way to tell them to fully stop sending events, also disabling
>>>>> the USB remote wakeup the device is doing. The question is when to tell
>>>>> it to not send events though ...
>>>>>
>>>>> So now I've been thinking about how to fix this and I believe that there
>>>>> is some interaction between this problem and this patch-set.
>>>>>
>>>>> The problem I'm seeing on the T101HA is about wakeups, so the question
>>>>> which I want to discuss is:
>>>>>
>>>>> 1. How does inhibiting interact with enabling /
>>>>> disabling the device as a wakeup source ?
>>>>>
>>>>> 2. Since we have now made inhibiting equal open/close how does open/close
>>>>> interact with a device being a wakeup source ?
>>>>>
>>>>> And my own initial (to be discussed) answers to these questions:
>>>>>
>>>>> 1. It seems to me that when a device is inhibited it should not be a
>>>>> wakeup source, so where possible a input-device-driver should disable
>>>>> a device's wakeup capabilities on suspend if inhibited
>>>>
>>>> If "inhibit" means "do not generate any events going forward", then
>>>> this must also cover wakeup events, so I agree.
>>>
>>> I agree, too.
>>>
>>>>
>>>>> 2. This one is trickier I don't think we have really clearly specified
>>>>> any behavior here. The default behavior of most drivers seems to be
>>>>> using something like this in their suspend callback:
>>>>>
>>>>>           if (device_may_wakeup(dev))
>>>>>                   enable_irq_wake(data->irq);
>>>>>           else if (input->users)
>>>>>                   foo_stop_receiving_events(data);
>>>>>
>>>>> Since this is what most drivers seem to do I believe we should keep
>>>>> this as is and that we should just clearly document that if the
>>>>> input_device has users (has been opened) or not does not matter
>>>>> for its wakeup behavior.
>>>>>
>>>>> Combining these 2 answers leads to this new pseudo code template
>>>>> for an input-device's suspend method:
>>>>>
>>>>>          /*
>>>>>           * If inhibited we have already disabled events and
>>>>>           * we do NOT want to setup the device as wake source.
>>>>>           */
>>>>>          if (input->inhibited)
>>>>>                  return 0;
>>>
>>> Right, if a device is inhibited it shouldn't become a wakeup source,
>>> because that would contradict the purpose of being inhibited.
>>
>> Ack. Note I do think that we need to document this (and more
>> in general the answer to both questions from above) clearly so
>> that going forward if there are any questions about how this is
>> supposed to work we can just point to the docs.
>>
>> Can you do a follow-up patch, or include a patch in your next
>> version which documents this (once we agree on what "this"
>> exactly is) ?
> 
> Sure I can. Just need to know when "this" becomes stable enough ;)
> If this series otherwise looks mature enough I would opt for a
> follow-up patch.

FWIW after my flip-flop to agreeing with Dmitry that the 2
(inhibit vs wakeup) should be completely orthogonal this new
policy is stable/mature from my pov (and consistent with how
we handle wakeup vs input_dev->users).

I still think it would be good to do a follow-up documentation
patch documenting that these (and esp. inhibit) are orthogonal.

This will mean for example that if a device is inhibit but
still wakeup enabled and the device's close method silences
the devices, that it needs to be unsilenced in suspend.
This might be worth mentioning in the docs even though
drivers which silence the device on close should already
unsilence the device on suspend when it is wakeup-enabled.

Note maybe we should give it a couple of days for others to
give their opinion before you submit the follow-up documentation
patch.

Regards,

Hans




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

* Re: [PATCH v4 0/7] Support inhibiting input devices
  2020-06-12  8:30                                                       ` Hans de Goede
@ 2020-06-12  8:47                                                         ` Andrzej Pietrasiewicz
  2020-06-16 17:29                                                         ` [PATCH] Input: document inhibiting Andrzej Pietrasiewicz
  1 sibling, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-12  8:47 UTC (permalink / raw)
  To: Hans de Goede, Rafael J. Wysocki
  Cc: Linux PM, ACPI Devel Maling List, Linux Kernel Mailing List,
	linux-iio, Linux ARM, Linux Samsung SoC, linux-input,
	linux-tegra, patches, ibm-acpi-devel, Platform Driver,
	Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Collabora Kernel ML

Hi Hans,

W dniu 12.06.2020 o 10:30, Hans de Goede pisze:
> Hi,
> 
> On 6/10/20 3:41 PM, Andrzej Pietrasiewicz wrote:
>> Hi Hans,
>>
>> W dniu 10.06.2020 o 15:21, Hans de Goede pisze:
>>> Hi,
>>>
>>> On 6/10/20 3:12 PM, Andrzej Pietrasiewicz wrote:
>>>> Hi All,
>>>>
>>>> W dniu 10.06.2020 o 12:38, Rafael J. Wysocki pisze:
>>>>> On Wed, Jun 10, 2020 at 11:50 AM Hans de Goede <hdegoede@redhat.com> wrote:
>>>>>>
>>>>>> Hi All,
>>>>>>
>>>>>> On 6/8/20 1:22 PM, Andrzej Pietrasiewicz wrote:
>>>>>>> This is a quick respin of v3, with just two small changes, please see
>>>>>>> the changelog below.
>>>>>>>
>>>>>>> Userspace might want to implement a policy to temporarily disregard input
>>>>>>> from certain devices.
>>>>>>>
>>>>>>> An example use case is a convertible laptop, whose keyboard can be folded
>>>>>>> under the screen to create tablet-like experience. The user then must hold
>>>>>>> the laptop in such a way that it is difficult to avoid pressing the keyboard
>>>>>>> keys. It is therefore desirable to temporarily disregard input from the
>>>>>>> keyboard, until it is folded back. This obviously is a policy which should
>>>>>>> be kept out of the kernel, but the kernel must provide suitable means to
>>>>>>> implement such a policy.
>>>>>>
>>>>>> First of all sorry to start a somewhat new discussion about this
>>>>>> while this patch set is also somewhat far along in the review process,
>>>>>> but I believe what I discuss below needs to be taken into account.
>>>>>>
>>>>>> Yesterday I have been looking into why an Asus T101HA would not stay
>>>>>> suspended when the LID is closed. The cause is that the USB HID multi-touch
>>>>>> touchpad in the base of the device starts sending events when the screen
>>>>>> gets close to the touchpad (so when the LID is fully closed) and these
>>>>>> events are causing a wakeup from suspend. HID multi-touch devices
>>>>>> do have a way to tell them to fully stop sending events, also disabling
>>>>>> the USB remote wakeup the device is doing. The question is when to tell
>>>>>> it to not send events though ...
>>>>>>
>>>>>> So now I've been thinking about how to fix this and I believe that there
>>>>>> is some interaction between this problem and this patch-set.
>>>>>>
>>>>>> The problem I'm seeing on the T101HA is about wakeups, so the question
>>>>>> which I want to discuss is:
>>>>>>
>>>>>> 1. How does inhibiting interact with enabling /
>>>>>> disabling the device as a wakeup source ?
>>>>>>
>>>>>> 2. Since we have now made inhibiting equal open/close how does open/close
>>>>>> interact with a device being a wakeup source ?
>>>>>>
>>>>>> And my own initial (to be discussed) answers to these questions:
>>>>>>
>>>>>> 1. It seems to me that when a device is inhibited it should not be a
>>>>>> wakeup source, so where possible a input-device-driver should disable
>>>>>> a device's wakeup capabilities on suspend if inhibited
>>>>>
>>>>> If "inhibit" means "do not generate any events going forward", then
>>>>> this must also cover wakeup events, so I agree.
>>>>
>>>> I agree, too.
>>>>
>>>>>
>>>>>> 2. This one is trickier I don't think we have really clearly specified
>>>>>> any behavior here. The default behavior of most drivers seems to be
>>>>>> using something like this in their suspend callback:
>>>>>>
>>>>>>           if (device_may_wakeup(dev))
>>>>>>                   enable_irq_wake(data->irq);
>>>>>>           else if (input->users)
>>>>>>                   foo_stop_receiving_events(data);
>>>>>>
>>>>>> Since this is what most drivers seem to do I believe we should keep
>>>>>> this as is and that we should just clearly document that if the
>>>>>> input_device has users (has been opened) or not does not matter
>>>>>> for its wakeup behavior.
>>>>>>
>>>>>> Combining these 2 answers leads to this new pseudo code template
>>>>>> for an input-device's suspend method:
>>>>>>
>>>>>>          /*
>>>>>>           * If inhibited we have already disabled events and
>>>>>>           * we do NOT want to setup the device as wake source.
>>>>>>           */
>>>>>>          if (input->inhibited)
>>>>>>                  return 0;
>>>>
>>>> Right, if a device is inhibited it shouldn't become a wakeup source,
>>>> because that would contradict the purpose of being inhibited.
>>>
>>> Ack. Note I do think that we need to document this (and more
>>> in general the answer to both questions from above) clearly so
>>> that going forward if there are any questions about how this is
>>> supposed to work we can just point to the docs.
>>>
>>> Can you do a follow-up patch, or include a patch in your next
>>> version which documents this (once we agree on what "this"
>>> exactly is) ?
>>
>> Sure I can. Just need to know when "this" becomes stable enough ;)
>> If this series otherwise looks mature enough I would opt for a
>> follow-up patch.
> 
> FWIW after my flip-flop to agreeing with Dmitry that the 2
> (inhibit vs wakeup) should be completely orthogonal this new
> policy is stable/mature from my pov (and consistent with how
> we handle wakeup vs input_dev->users).
> 
> I still think it would be good to do a follow-up documentation
> patch documenting that these (and esp. inhibit) are orthogonal.
> 
> This will mean for example that if a device is inhibit but
> still wakeup enabled and the device's close method silences
> the devices, that it needs to be unsilenced in suspend.
> This might be worth mentioning in the docs even though
> drivers which silence the device on close should already
> unsilence the device on suspend when it is wakeup-enabled.
> 
> Note maybe we should give it a couple of days for others to
> give their opinion before you submit the follow-up documentation
> patch.
> 

True. I will send something after the weekend.

Andrzej

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

* [PATCH] Input: document inhibiting
  2020-06-12  8:30                                                       ` Hans de Goede
  2020-06-12  8:47                                                         ` Andrzej Pietrasiewicz
@ 2020-06-16 17:29                                                         ` Andrzej Pietrasiewicz
  2020-06-16 17:38                                                           ` Randy Dunlap
  2020-06-17  7:44                                                           ` Hans de Goede
  1 sibling, 2 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-16 17:29 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Andrzej Pietrasiewicz,
	Michał Mirosław, kernel

Document inhibiting input devices and its relation to being
a wakeup source.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---

@Hans, @Dmitry,

My fist attempt at documenting inhibiting. Kindly look at it to see if I haven't got anything
wrong.

Andrzej

 Documentation/input/input-programming.rst | 36 +++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/Documentation/input/input-programming.rst b/Documentation/input/input-programming.rst
index 45a4c6e05e39..0cd1ad4504fb 100644
--- a/Documentation/input/input-programming.rst
+++ b/Documentation/input/input-programming.rst
@@ -164,6 +164,42 @@ disconnects. Calls to both callbacks are serialized.
 The open() callback should return a 0 in case of success or any nonzero value
 in case of failure. The close() callback (which is void) must always succeed.
 
+Inhibiting input devices
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Inhibiting a device means ignoring input events from it. As such it is about maintaining
+relationships with input handlers - either an already existing relationships, or
+relationships to be established while the device is in inhibited state.
+
+If a device is inhibited, no input handler will receive events from it.
+
+The fact that nobody wants events from the device is exploited further, by calling device's
+close() (if there are users) and open() (if there are users) on inhibit and uninhibit
+operations, respectively. Indeed, the meaning of close() is to stop providing events
+to the input core and that of open() is to start providing events to the input core.
+
+Inhibiting and uninhibiting is orthogonal to opening and closing the device by input
+handlers. Userspace might want to inhibit a device in anticipation before any handler is
+positively matched against it.
+
+Inhibiting and uninhibiting is orthogonal to device's being a wakeup source, too. Being a
+wakeup source plays a role when the system is sleeping, not when the system is operating.
+How drivers should program their interaction between inhibiting, sleeping and being a wakeup
+source is driver-specific.
+
+Taking the analogy with the network devices - bringing a network interface down doesn't mean
+that it should be impossible to be wake the system up on LAN through this interface. So, there
+may be input drivers which should be considered wakeup sources even when inhibited. Actually,
+in many i2c input devices their interrupt is declared a wakeup interrupt and its handling
+happens in driver's core, which is not aware of input-specific inhibit (nor should it be).
+Composite devices containing several interfaces can be inhibited on a per-interface basis and
+e.g. inhibiting one interface shouldn't affect the device's capability of being a wakeup source.
+
+If a device is to be considered a wakeup source while inhibited, special care must be taken when
+programming its suspend(), as it might need to call device's open(). Depending on what close()
+means for the device in question not opening() it before going to sleep might make it impossible
+to provide any wakeup events. The device is going to sleep anyway.
+
 Basic event types
 ~~~~~~~~~~~~~~~~~
 
-- 
2.17.1


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

* Re: [PATCH] Input: document inhibiting
  2020-06-16 17:29                                                         ` [PATCH] Input: document inhibiting Andrzej Pietrasiewicz
@ 2020-06-16 17:38                                                           ` Randy Dunlap
  2020-06-17  7:44                                                           ` Hans de Goede
  1 sibling, 0 replies; 80+ messages in thread
From: Randy Dunlap @ 2020-06-16 17:38 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, linux-pm, linux-acpi, linux-kernel,
	linux-iio, linux-arm-kernel, linux-samsung-soc, linux-input,
	linux-tegra, patches, ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Michał Mirosław, kernel

On 6/16/20 10:29 AM, Andrzej Pietrasiewicz wrote:
> Document inhibiting input devices and its relation to being
> a wakeup source.
> 
> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> ---

Hi,
I have some editorial comments. Please see below.


> @Hans, @Dmitry,
> 
> My fist attempt at documenting inhibiting. Kindly look at it to see if I haven't got anything
> wrong.
> 
> Andrzej
> 
>  Documentation/input/input-programming.rst | 36 +++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
> 
> diff --git a/Documentation/input/input-programming.rst b/Documentation/input/input-programming.rst
> index 45a4c6e05e39..0cd1ad4504fb 100644
> --- a/Documentation/input/input-programming.rst
> +++ b/Documentation/input/input-programming.rst
> @@ -164,6 +164,42 @@ disconnects. Calls to both callbacks are serialized.
>  The open() callback should return a 0 in case of success or any nonzero value
>  in case of failure. The close() callback (which is void) must always succeed.
>  
> +Inhibiting input devices
> +~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +Inhibiting a device means ignoring input events from it. As such it is about maintaining
> +relationships with input handlers - either an already existing relationships, or
> +relationships to be established while the device is in inhibited state.
> +
> +If a device is inhibited, no input handler will receive events from it.
> +
> +The fact that nobody wants events from the device is exploited further, by calling device's
> +close() (if there are users) and open() (if there are users) on inhibit and uninhibit
> +operations, respectively. Indeed, the meaning of close() is to stop providing events
> +to the input core and that of open() is to start providing events to the input core.
> +
> +Inhibiting and uninhibiting is orthogonal to opening and closing the device by input

                               are

> +handlers. Userspace might want to inhibit a device in anticipation before any handler is
> +positively matched against it.
> +
> +Inhibiting and uninhibiting is orthogonal to device's being a wakeup source, too. Being a

                               are

> +wakeup source plays a role when the system is sleeping, not when the system is operating.
> +How drivers should program their interaction between inhibiting, sleeping and being a wakeup
> +source is driver-specific.
> +
> +Taking the analogy with the network devices - bringing a network interface down doesn't mean
> +that it should be impossible to be wake the system up on LAN through this interface. So, there
> +may be input drivers which should be considered wakeup sources even when inhibited. Actually,
> +in many i2c input devices their interrupt is declared a wakeup interrupt and its handling

           I2C

> +happens in driver's core, which is not aware of input-specific inhibit (nor should it be).
> +Composite devices containing several interfaces can be inhibited on a per-interface basis and
> +e.g. inhibiting one interface shouldn't affect the device's capability of being a wakeup source.
> +
> +If a device is to be considered a wakeup source while inhibited, special care must be taken when
> +programming its suspend(), as it might need to call device's open(). Depending on what close()
> +means for the device in question not opening() it before going to sleep might make it impossible

                        in question, not

> +to provide any wakeup events. The device is going to sleep anyway.
> +
>  Basic event types
>  ~~~~~~~~~~~~~~~~~
>  
> 

thanks for documentation.

-- 
~Randy


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

* Re: [PATCH] Input: document inhibiting
  2020-06-16 17:29                                                         ` [PATCH] Input: document inhibiting Andrzej Pietrasiewicz
  2020-06-16 17:38                                                           ` Randy Dunlap
@ 2020-06-17  7:44                                                           ` Hans de Goede
  2020-06-17 10:18                                                             ` [PATCH v2] " Andrzej Pietrasiewicz
  1 sibling, 1 reply; 80+ messages in thread
From: Hans de Goede @ 2020-06-17  7:44 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, linux-pm, linux-acpi, linux-kernel,
	linux-iio, linux-arm-kernel, linux-samsung-soc, linux-input,
	linux-tegra, patches, ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Michał Mirosław, kernel

Hi,

On 6/16/20 7:29 PM, Andrzej Pietrasiewicz wrote:
> Document inhibiting input devices and its relation to being
> a wakeup source.
> 
> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> ---
> 
> @Hans, @Dmitry,
> 
> My fist attempt at documenting inhibiting. Kindly look at it to see if I haven't got anything
> wrong.
> 
> Andrzej
> 
>   Documentation/input/input-programming.rst | 36 +++++++++++++++++++++++
>   1 file changed, 36 insertions(+)
> 
> diff --git a/Documentation/input/input-programming.rst b/Documentation/input/input-programming.rst
> index 45a4c6e05e39..0cd1ad4504fb 100644
> --- a/Documentation/input/input-programming.rst
> +++ b/Documentation/input/input-programming.rst
> @@ -164,6 +164,42 @@ disconnects. Calls to both callbacks are serialized.
>   The open() callback should return a 0 in case of success or any nonzero value
>   in case of failure. The close() callback (which is void) must always succeed.
>   
> +Inhibiting input devices
> +~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +Inhibiting a device means ignoring input events from it. As such it is about maintaining
> +relationships with input handlers - either an already existing relationships, or
> +relationships to be established while the device is in inhibited state.
> +
> +If a device is inhibited, no input handler will receive events from it.
> +
> +The fact that nobody wants events from the device is exploited further, by calling device's
> +close() (if there are users) and open() (if there are users) on inhibit and uninhibit
> +operations, respectively. Indeed, the meaning of close() is to stop providing events
> +to the input core and that of open() is to start providing events to the input core.

Maybe add the following here? :

Calling the device's close() method on inhibit (if there are users) allows the driver
to save power. Either by directly powering down the device or by releasing the
runtime-pm reference it got in open() when the driver is using runtime-pm.

Otherwise this looks good to me. Thank you for doing this, we (including myself)
really need to get better at doucmenting all sorts of kernel things. Often we have
these long discussions about something on the mailinglist and then everyone is
expected to just know what was decided from the on, which really doesn't work all
that well.

> +
> +Inhibiting and uninhibiting is orthogonal to opening and closing the device by input
> +handlers. Userspace might want to inhibit a device in anticipation before any handler is
> +positively matched against it.
> +
> +Inhibiting and uninhibiting is orthogonal to device's being a wakeup source, too. Being a
> +wakeup source plays a role when the system is sleeping, not when the system is operating.
> +How drivers should program their interaction between inhibiting, sleeping and being a wakeup
> +source is driver-specific.
> +
> +Taking the analogy with the network devices - bringing a network interface down doesn't mean
> +that it should be impossible to be wake the system up on LAN through this interface. So, there
> +may be input drivers which should be considered wakeup sources even when inhibited. Actually,
> +in many i2c input devices their interrupt is declared a wakeup interrupt and its handling
> +happens in driver's core, which is not aware of input-specific inhibit (nor should it be).
> +Composite devices containing several interfaces can be inhibited on a per-interface basis and
> +e.g. inhibiting one interface shouldn't affect the device's capability of being a wakeup source.
> +
> +If a device is to be considered a wakeup source while inhibited, special care must be taken when
> +programming its suspend(), as it might need to call device's open(). Depending on what close()
> +means for the device in question not opening() it before going to sleep might make it impossible
> +to provide any wakeup events. The device is going to sleep anyway.
> +
>   Basic event types
>   ~~~~~~~~~~~~~~~~~
>   
> 


Regards,

Hans


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

* [PATCH v2] Input: document inhibiting
  2020-06-17  7:44                                                           ` Hans de Goede
@ 2020-06-17 10:18                                                             ` Andrzej Pietrasiewicz
  2020-06-17 10:21                                                               ` Hans de Goede
                                                                                 ` (2 more replies)
  0 siblings, 3 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-06-17 10:18 UTC (permalink / raw)
  To: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Andrzej Pietrasiewicz,
	Michał Mirosław, kernel

Document inhibiting input devices and its relation to being
a wakeup source.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
v1..v2:

- Addressed editorial comments from Randy
- Added a paragraph by Hans

 Documentation/input/input-programming.rst | 40 +++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/Documentation/input/input-programming.rst b/Documentation/input/input-programming.rst
index 45a4c6e05e39..7432315cc829 100644
--- a/Documentation/input/input-programming.rst
+++ b/Documentation/input/input-programming.rst
@@ -164,6 +164,46 @@ disconnects. Calls to both callbacks are serialized.
 The open() callback should return a 0 in case of success or any nonzero value
 in case of failure. The close() callback (which is void) must always succeed.
 
+Inhibiting input devices
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Inhibiting a device means ignoring input events from it. As such it is about maintaining
+relationships with input handlers - either already existing relationships, or relationships
+to be established while the device is in inhibited state.
+
+If a device is inhibited, no input handler will receive events from it.
+
+The fact that nobody wants events from the device is exploited further, by calling device's
+close() (if there are users) and open() (if there are users) on inhibit and uninhibit
+operations, respectively. Indeed, the meaning of close() is to stop providing events
+to the input core and that of open() is to start providing events to the input core.
+
+Calling the device's close() method on inhibit (if there are users) allows the driver
+to save power. Either by directly powering down the device or by releasing the
+runtime-pm reference it got in open() when the driver is using runtime-pm.
+
+Inhibiting and uninhibiting are orthogonal to opening and closing the device by input
+handlers. Userspace might want to inhibit a device in anticipation before any handler is
+positively matched against it.
+
+Inhibiting and uninhibiting are orthogonal to device's being a wakeup source, too. Being a
+wakeup source plays a role when the system is sleeping, not when the system is operating.
+How drivers should program their interaction between inhibiting, sleeping and being a wakeup
+source is driver-specific.
+
+Taking the analogy with the network devices - bringing a network interface down doesn't mean
+that it should be impossible be wake the system up on LAN through this interface. So, there
+may be input drivers which should be considered wakeup sources even when inhibited. Actually,
+in many I2C input devices their interrupt is declared a wakeup interrupt and its handling
+happens in driver's core, which is not aware of input-specific inhibit (nor should it be).
+Composite devices containing several interfaces can be inhibited on a per-interface basis and
+e.g. inhibiting one interface shouldn't affect the device's capability of being a wakeup source.
+
+If a device is to be considered a wakeup source while inhibited, special care must be taken when
+programming its suspend(), as it might need to call device's open(). Depending on what close()
+means for the device in question, not opening() it before going to sleep might make it
+impossible to provide any wakeup events. The device is going to sleep anyway.
+
 Basic event types
 ~~~~~~~~~~~~~~~~~
 
-- 
2.17.1


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

* Re: [PATCH v2] Input: document inhibiting
  2020-06-17 10:18                                                             ` [PATCH v2] " Andrzej Pietrasiewicz
@ 2020-06-17 10:21                                                               ` Hans de Goede
  2020-06-17 16:52                                                               ` Randy Dunlap
  2020-06-23 13:35                                                               ` Pavel Machek
  2 siblings, 0 replies; 80+ messages in thread
From: Hans de Goede @ 2020-06-17 10:21 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, linux-pm, linux-acpi, linux-kernel,
	linux-iio, linux-arm-kernel, linux-samsung-soc, linux-input,
	linux-tegra, patches, ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Michał Mirosław, kernel

Hi,

On 6/17/20 12:18 PM, Andrzej Pietrasiewicz wrote:
> Document inhibiting input devices and its relation to being
> a wakeup source.
> 
> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> ---
> v1..v2:
> 
> - Addressed editorial comments from Randy
> - Added a paragraph by Hans

Thank you.

v2 looks good to me:

Reviewed-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans



> 
>   Documentation/input/input-programming.rst | 40 +++++++++++++++++++++++
>   1 file changed, 40 insertions(+)
> 
> diff --git a/Documentation/input/input-programming.rst b/Documentation/input/input-programming.rst
> index 45a4c6e05e39..7432315cc829 100644
> --- a/Documentation/input/input-programming.rst
> +++ b/Documentation/input/input-programming.rst
> @@ -164,6 +164,46 @@ disconnects. Calls to both callbacks are serialized.
>   The open() callback should return a 0 in case of success or any nonzero value
>   in case of failure. The close() callback (which is void) must always succeed.
>   
> +Inhibiting input devices
> +~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +Inhibiting a device means ignoring input events from it. As such it is about maintaining
> +relationships with input handlers - either already existing relationships, or relationships
> +to be established while the device is in inhibited state.
> +
> +If a device is inhibited, no input handler will receive events from it.
> +
> +The fact that nobody wants events from the device is exploited further, by calling device's
> +close() (if there are users) and open() (if there are users) on inhibit and uninhibit
> +operations, respectively. Indeed, the meaning of close() is to stop providing events
> +to the input core and that of open() is to start providing events to the input core.
> +
> +Calling the device's close() method on inhibit (if there are users) allows the driver
> +to save power. Either by directly powering down the device or by releasing the
> +runtime-pm reference it got in open() when the driver is using runtime-pm.
> +
> +Inhibiting and uninhibiting are orthogonal to opening and closing the device by input
> +handlers. Userspace might want to inhibit a device in anticipation before any handler is
> +positively matched against it.
> +
> +Inhibiting and uninhibiting are orthogonal to device's being a wakeup source, too. Being a
> +wakeup source plays a role when the system is sleeping, not when the system is operating.
> +How drivers should program their interaction between inhibiting, sleeping and being a wakeup
> +source is driver-specific.
> +
> +Taking the analogy with the network devices - bringing a network interface down doesn't mean
> +that it should be impossible be wake the system up on LAN through this interface. So, there
> +may be input drivers which should be considered wakeup sources even when inhibited. Actually,
> +in many I2C input devices their interrupt is declared a wakeup interrupt and its handling
> +happens in driver's core, which is not aware of input-specific inhibit (nor should it be).
> +Composite devices containing several interfaces can be inhibited on a per-interface basis and
> +e.g. inhibiting one interface shouldn't affect the device's capability of being a wakeup source.
> +
> +If a device is to be considered a wakeup source while inhibited, special care must be taken when
> +programming its suspend(), as it might need to call device's open(). Depending on what close()
> +means for the device in question, not opening() it before going to sleep might make it
> +impossible to provide any wakeup events. The device is going to sleep anyway.
> +
>   Basic event types
>   ~~~~~~~~~~~~~~~~~
>   
> 


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

* Re: [PATCH v2] Input: document inhibiting
  2020-06-17 10:18                                                             ` [PATCH v2] " Andrzej Pietrasiewicz
  2020-06-17 10:21                                                               ` Hans de Goede
@ 2020-06-17 16:52                                                               ` Randy Dunlap
  2020-06-23 13:35                                                               ` Pavel Machek
  2 siblings, 0 replies; 80+ messages in thread
From: Randy Dunlap @ 2020-06-17 16:52 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz, linux-pm, linux-acpi, linux-kernel,
	linux-iio, linux-arm-kernel, linux-samsung-soc, linux-input,
	linux-tegra, patches, ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Michał Mirosław, kernel

On 6/17/20 3:18 AM, Andrzej Pietrasiewicz wrote:
> Document inhibiting input devices and its relation to being
> a wakeup source.
> 
> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> ---
> v1..v2:
> 
> - Addressed editorial comments from Randy
> - Added a paragraph by Hans
> 
>  Documentation/input/input-programming.rst | 40 +++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
> 
> diff --git a/Documentation/input/input-programming.rst b/Documentation/input/input-programming.rst
> index 45a4c6e05e39..7432315cc829 100644
> --- a/Documentation/input/input-programming.rst
> +++ b/Documentation/input/input-programming.rst
> @@ -164,6 +164,46 @@ disconnects. Calls to both callbacks are serialized.
>  The open() callback should return a 0 in case of success or any nonzero value
>  in case of failure. The close() callback (which is void) must always succeed.
>  
> +Inhibiting input devices
> +~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +Inhibiting a device means ignoring input events from it. As such it is about maintaining
> +relationships with input handlers - either already existing relationships, or relationships
> +to be established while the device is in inhibited state.
> +
> +If a device is inhibited, no input handler will receive events from it.
> +
> +The fact that nobody wants events from the device is exploited further, by calling device's
> +close() (if there are users) and open() (if there are users) on inhibit and uninhibit
> +operations, respectively. Indeed, the meaning of close() is to stop providing events
> +to the input core and that of open() is to start providing events to the input core.
> +
> +Calling the device's close() method on inhibit (if there are users) allows the driver
> +to save power. Either by directly powering down the device or by releasing the
> +runtime-pm reference it got in open() when the driver is using runtime-pm.
> +
> +Inhibiting and uninhibiting are orthogonal to opening and closing the device by input
> +handlers. Userspace might want to inhibit a device in anticipation before any handler is
> +positively matched against it.
> +
> +Inhibiting and uninhibiting are orthogonal to device's being a wakeup source, too. Being a
> +wakeup source plays a role when the system is sleeping, not when the system is operating.
> +How drivers should program their interaction between inhibiting, sleeping and being a wakeup
> +source is driver-specific.
> +
> +Taking the analogy with the network devices - bringing a network interface down doesn't mean
> +that it should be impossible be wake the system up on LAN through this interface. So, there
> +may be input drivers which should be considered wakeup sources even when inhibited. Actually,
> +in many I2C input devices their interrupt is declared a wakeup interrupt and its handling
> +happens in driver's core, which is not aware of input-specific inhibit (nor should it be).
> +Composite devices containing several interfaces can be inhibited on a per-interface basis and
> +e.g. inhibiting one interface shouldn't affect the device's capability of being a wakeup source.
> +
> +If a device is to be considered a wakeup source while inhibited, special care must be taken when
> +programming its suspend(), as it might need to call device's open(). Depending on what close()
> +means for the device in question, not opening() it before going to sleep might make it
> +impossible to provide any wakeup events. The device is going to sleep anyway.
> +
>  Basic event types
>  ~~~~~~~~~~~~~~~~~
>  
> 

Reviewed-by: Randy Dunlap <rdunlap@infradead.org>

Thanks.

-- 
~Randy

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

* Re: [PATCH v2] Input: document inhibiting
  2020-06-17 10:18                                                             ` [PATCH v2] " Andrzej Pietrasiewicz
  2020-06-17 10:21                                                               ` Hans de Goede
  2020-06-17 16:52                                                               ` Randy Dunlap
@ 2020-06-23 13:35                                                               ` Pavel Machek
  2 siblings, 0 replies; 80+ messages in thread
From: Pavel Machek @ 2020-06-23 13:35 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz
  Cc: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, Micha?? Miros??aw, kernel

Hi!

> +Inhibiting input devices
> +~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +Inhibiting a device means ignoring input events from it. As such it is about maintaining
> +relationships with input handlers - either already existing relationships, or relationships
> +to be established while the device is in inhibited state.
> +
> +If a device is inhibited, no input handler will receive events from it.
> +
> +The fact that nobody wants events from the device is exploited further, by calling device's
> +close() (if there are users) and open() (if there are users) on inhibit and uninhibit
> +operations, respectively. Indeed, the meaning of close() is to stop providing events
> +to the input core and that of open() is to start providing events to the input core.
> +
> +Calling the device's close() method on inhibit (if there are users) allows the driver
> +to save power. Either by directly powering down the device or by releasing the
> +runtime-pm reference it got in open() when the driver is using runtime-pm.
> +
> +Inhibiting and uninhibiting are orthogonal to opening and closing the device by input
> +handlers. Userspace might want to inhibit a device in anticipation before any handler is
> +positively matched against it.

Ok.

> +Inhibiting and uninhibiting are orthogonal to device's being a wakeup source, too. 
> Being a +wakeup source plays a role when the system is sleeping, not when the system is 
> operating. +How drivers should program their interaction between inhibiting, sleeping 
> and being a wakeup +source is driver-specific. + +Taking the analogy with the network 

I don't believe making interaction driver-specific is good idea. We should decide
what reasonable behaviour is and then make drivers implement that...

Best regards,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

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

* Re: [PATCH v4 3/7] ACPI: button: Access input device's users under appropriate mutex
  2020-06-08 11:22                                             ` [PATCH v4 3/7] ACPI: button: Access input device's users under appropriate mutex Andrzej Pietrasiewicz
@ 2020-06-24 15:00                                               ` Rafael J. Wysocki
  2020-06-25  5:23                                                 ` Dmitry Torokhov
  0 siblings, 1 reply; 80+ messages in thread
From: Rafael J. Wysocki @ 2020-06-24 15:00 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz
  Cc: Linux PM, ACPI Devel Maling List, Linux Kernel Mailing List,
	linux-iio, Linux ARM, Linux Samsung SoC, linux-input,
	linux-tegra, patches, ibm-acpi-devel, Platform Driver,
	Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Hans de Goede, Ferruh Yigit, Sangwon Jee,
	Peter Hutterer, Henrique de Moraes Holschuh, Collabora Kernel ML

On Mon, Jun 8, 2020 at 1:22 PM Andrzej Pietrasiewicz
<andrzej.p@collabora.com> wrote:
>
> Inspecting input device's 'users' member should be done under device's
> mutex, so add appropriate invocations.
>
> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>

This looks like a fix that might be applied independently of the other
patches in the series.

Do you want me to pick it up?

> ---
>  drivers/acpi/button.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> index 78cfc70cb320..ff7ab291f678 100644
> --- a/drivers/acpi/button.c
> +++ b/drivers/acpi/button.c
> @@ -456,13 +456,16 @@ static int acpi_button_resume(struct device *dev)
>  {
>         struct acpi_device *device = to_acpi_device(dev);
>         struct acpi_button *button = acpi_driver_data(device);
> +       struct input_dev *input = button->input;
>
>         button->suspended = false;
> -       if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users) {
> +       mutex_lock(&input->mutex);
> +       if (button->type == ACPI_BUTTON_TYPE_LID && input->users) {
>                 button->last_state = !!acpi_lid_evaluate_state(device);
>                 button->last_time = ktime_get();
>                 acpi_lid_initialize_state(device);
>         }
> +       mutex_unlock(&input->mutex);
>         return 0;
>  }
>  #endif
> --
> 2.17.1
>

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

* Re: [PATCH v4 3/7] ACPI: button: Access input device's users under appropriate mutex
  2020-06-24 15:00                                               ` Rafael J. Wysocki
@ 2020-06-25  5:23                                                 ` Dmitry Torokhov
  2020-06-25 10:55                                                   ` Rafael J. Wysocki
  0 siblings, 1 reply; 80+ messages in thread
From: Dmitry Torokhov @ 2020-06-25  5:23 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Andrzej Pietrasiewicz, Linux PM, ACPI Devel Maling List,
	Linux Kernel Mailing List, linux-iio, Linux ARM,
	Linux Samsung SoC, linux-input, linux-tegra, patches,
	ibm-acpi-devel, Platform Driver, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Hans de Goede, Ferruh Yigit,
	Sangwon Jee, Peter Hutterer, Henrique de Moraes Holschuh,
	Collabora Kernel ML

On Wed, Jun 24, 2020 at 05:00:09PM +0200, Rafael J. Wysocki wrote:
> On Mon, Jun 8, 2020 at 1:22 PM Andrzej Pietrasiewicz
> <andrzej.p@collabora.com> wrote:
> >
> > Inspecting input device's 'users' member should be done under device's
> > mutex, so add appropriate invocations.
> >
> > Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> 
> This looks like a fix that might be applied independently of the other
> patches in the series.
> 
> Do you want me to pick it up?

If you pick it we'll have to have a dance with this series. Can I apply
instead?

I do not think this change has any practical effect as nobody
attaches/detached input handlers or opening/closing input devices when
system goes through device resume phase.

> 
> > ---
> >  drivers/acpi/button.c | 5 ++++-
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> > index 78cfc70cb320..ff7ab291f678 100644
> > --- a/drivers/acpi/button.c
> > +++ b/drivers/acpi/button.c
> > @@ -456,13 +456,16 @@ static int acpi_button_resume(struct device *dev)
> >  {
> >         struct acpi_device *device = to_acpi_device(dev);
> >         struct acpi_button *button = acpi_driver_data(device);
> > +       struct input_dev *input = button->input;
> >
> >         button->suspended = false;
> > -       if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users) {
> > +       mutex_lock(&input->mutex);
> > +       if (button->type == ACPI_BUTTON_TYPE_LID && input->users) {
> >                 button->last_state = !!acpi_lid_evaluate_state(device);
> >                 button->last_time = ktime_get();
> >                 acpi_lid_initialize_state(device);
> >         }
> > +       mutex_unlock(&input->mutex);
> >         return 0;
> >  }
> >  #endif
> > --
> > 2.17.1
> >

Thanks.

-- 
Dmitry

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

* Re: [PATCH v4 4/7] ACPI: button: Use input_device_enabled() helper
  2020-06-08 11:22                                             ` [PATCH v4 4/7] ACPI: button: Use input_device_enabled() helper Andrzej Pietrasiewicz
@ 2020-06-25  5:24                                               ` Dmitry Torokhov
  2020-10-05  5:06                                                 ` Dmitry Torokhov
  0 siblings, 1 reply; 80+ messages in thread
From: Dmitry Torokhov @ 2020-06-25  5:24 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz
  Cc: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Hans de Goede, Ferruh Yigit,
	Sangwon Jee, Peter Hutterer, Henrique de Moraes Holschuh, kernel

On Mon, Jun 08, 2020 at 01:22:08PM +0200, Andrzej Pietrasiewicz wrote:
> A new helper is available, so use it.
> 
> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> ---
>  drivers/acpi/button.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> index ff7ab291f678..4deb2b48d03c 100644
> --- a/drivers/acpi/button.c
> +++ b/drivers/acpi/button.c
> @@ -411,7 +411,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
>  		input = button->input;
>  		if (button->type == ACPI_BUTTON_TYPE_LID) {
>  			mutex_lock(&button->input->mutex);
> -			users = button->input->users;
> +			users = input_device_enabled(button->input);
>  			mutex_unlock(&button->input->mutex);
>  			if (users)

This chunk (pre-patch) is really wrong. 'users' value is obsolete and
can not be trusted the moment we unlocked the mutex. "if" needs to be
inside critical section.

>  				acpi_lid_update_state(device, true);
> @@ -460,7 +460,7 @@ static int acpi_button_resume(struct device *dev)
>  
>  	button->suspended = false;
>  	mutex_lock(&input->mutex);
> -	if (button->type == ACPI_BUTTON_TYPE_LID && input->users) {
> +	if (button->type == ACPI_BUTTON_TYPE_LID && input_device_enabled(input)) {
>  		button->last_state = !!acpi_lid_evaluate_state(device);
>  		button->last_time = ktime_get();
>  		acpi_lid_initialize_state(device);
> -- 
> 2.17.1
> 

Thanks.

-- 
Dmitry

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

* Re: [PATCH v4 3/7] ACPI: button: Access input device's users under appropriate mutex
  2020-06-25  5:23                                                 ` Dmitry Torokhov
@ 2020-06-25 10:55                                                   ` Rafael J. Wysocki
  2020-10-05  5:08                                                     ` Dmitry Torokhov
  0 siblings, 1 reply; 80+ messages in thread
From: Rafael J. Wysocki @ 2020-06-25 10:55 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Rafael J. Wysocki, Andrzej Pietrasiewicz, Linux PM,
	ACPI Devel Maling List, Linux Kernel Mailing List, linux-iio,
	Linux ARM, Linux Samsung SoC, linux-input, linux-tegra, patches,
	ibm-acpi-devel, Platform Driver, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Hans de Goede, Ferruh Yigit,
	Sangwon Jee, Peter Hutterer, Henrique de Moraes Holschuh,
	Collabora Kernel ML

On Thu, Jun 25, 2020 at 7:23 AM Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
>
> On Wed, Jun 24, 2020 at 05:00:09PM +0200, Rafael J. Wysocki wrote:
> > On Mon, Jun 8, 2020 at 1:22 PM Andrzej Pietrasiewicz
> > <andrzej.p@collabora.com> wrote:
> > >
> > > Inspecting input device's 'users' member should be done under device's
> > > mutex, so add appropriate invocations.
> > >
> > > Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> >
> > This looks like a fix that might be applied independently of the other
> > patches in the series.
> >
> > Do you want me to pick it up?
>
> If you pick it we'll have to have a dance with this series. Can I apply
> instead?

Yes, please.

Also feel free to add

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

to it.

> I do not think this change has any practical effect as nobody
> attaches/detached input handlers or opening/closing input devices when
> system goes through device resume phase.

Indeed.

Thanks!

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

* Re: [PATCH v4 0/7] Support inhibiting input devices
  2020-06-12  8:17                                             ` Hans de Goede
@ 2020-08-03 14:40                                               ` Andrzej Pietrasiewicz
  0 siblings, 0 replies; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-08-03 14:40 UTC (permalink / raw)
  To: Hans de Goede, linux-pm, linux-acpi, linux-kernel, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-input, linux-tegra,
	patches, ibm-acpi-devel, platform-driver-x86
  Cc: Rafael J . Wysocki, Len Brown, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Kukjin Kim,
	Krzysztof Kozlowski, Dmitry Torokhov, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Vladimir Zapolskiy, Sylvain Lemieux, Laxman Dewangan,
	Thierry Reding, Jonathan Hunter, Barry Song, Michael Hennerich,
	Nick Dyer, Ferruh Yigit, Sangwon Jee, Peter Hutterer,
	Henrique de Moraes Holschuh, kernel

Hi Dmitry,

W dniu 12.06.2020 o 10:17, Hans de Goede pisze:
> Hi,
> 
> On 6/8/20 1:22 PM, Andrzej Pietrasiewicz wrote:
>> This is a quick respin of v3, with just two small changes, please see
>> the changelog below.
>>
>> Userspace might want to implement a policy to temporarily disregard input
>> from certain devices.
>>

<snip>

>> v3..v4:
>> - updated the comment in input_open_device() (Hans)
>> - used more straightforward locking pattern in adc/exynos (Michał)
>>
>> v2..v3:
>> - ignored autorepeat events in input_get_disposition() if a key is not
>> pressed (Hans)
>> - dropped inhibit()/uninhibit() driver callbacks (Hans)
>> - split ACPI button patch into taking the lock and using the helper (Rafael)
>> - dropped the elan_i2c conversion
>> - fixed typos in exynos adc
>>
>> v1..v2:
>> - added input_device_enabled() helper and used it in drivers (Dmitry)
>> - the fact of open() and close() being called in inhibit/uninhibit paths has
>> been emphasized in the commit message of PATCH 6/7 (Dmitry)

<snip>

> 
> The entire series looks good to me:
> 
> Acked-by: Hans de Goede <hdegoede@redhat.com>

What are the prospects of this series being merged?

Regards,

Andrzej

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

* Re: [PATCH v4 4/7] ACPI: button: Use input_device_enabled() helper
  2020-06-25  5:24                                               ` Dmitry Torokhov
@ 2020-10-05  5:06                                                 ` Dmitry Torokhov
  0 siblings, 0 replies; 80+ messages in thread
From: Dmitry Torokhov @ 2020-10-05  5:06 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz
  Cc: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Hans de Goede, Ferruh Yigit,
	Sangwon Jee, Peter Hutterer, Henrique de Moraes Holschuh, kernel

On Wed, Jun 24, 2020 at 10:24:46PM -0700, Dmitry Torokhov wrote:
> On Mon, Jun 08, 2020 at 01:22:08PM +0200, Andrzej Pietrasiewicz wrote:
> > A new helper is available, so use it.
> > 
> > Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> > ---
> >  drivers/acpi/button.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> > index ff7ab291f678..4deb2b48d03c 100644
> > --- a/drivers/acpi/button.c
> > +++ b/drivers/acpi/button.c
> > @@ -411,7 +411,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
> >  		input = button->input;
> >  		if (button->type == ACPI_BUTTON_TYPE_LID) {
> >  			mutex_lock(&button->input->mutex);
> > -			users = button->input->users;
> > +			users = input_device_enabled(button->input);
> >  			mutex_unlock(&button->input->mutex);
> >  			if (users)
> 
> This chunk (pre-patch) is really wrong. 'users' value is obsolete and
> can not be trusted the moment we unlocked the mutex. "if" needs to be
> inside critical section.

So looking at this patch and the previous one again, I believe this
driver is wrong to key the behavior off input->users and we should not
apply either of the patches. I'll post another patch fixing this.

Thanks.

-- 
Dmitry

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

* Re: [PATCH v4 3/7] ACPI: button: Access input device's users under appropriate mutex
  2020-06-25 10:55                                                   ` Rafael J. Wysocki
@ 2020-10-05  5:08                                                     ` Dmitry Torokhov
  0 siblings, 0 replies; 80+ messages in thread
From: Dmitry Torokhov @ 2020-10-05  5:08 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Andrzej Pietrasiewicz, Linux PM, ACPI Devel Maling List,
	Linux Kernel Mailing List, linux-iio, Linux ARM,
	Linux Samsung SoC, linux-input, linux-tegra, patches,
	ibm-acpi-devel, Platform Driver, Rafael J . Wysocki, Len Brown,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Hans de Goede, Ferruh Yigit,
	Sangwon Jee, Peter Hutterer, Henrique de Moraes Holschuh,
	Collabora Kernel ML

On Thu, Jun 25, 2020 at 12:55:29PM +0200, Rafael J. Wysocki wrote:
> On Thu, Jun 25, 2020 at 7:23 AM Dmitry Torokhov
> <dmitry.torokhov@gmail.com> wrote:
> >
> > On Wed, Jun 24, 2020 at 05:00:09PM +0200, Rafael J. Wysocki wrote:
> > > On Mon, Jun 8, 2020 at 1:22 PM Andrzej Pietrasiewicz
> > > <andrzej.p@collabora.com> wrote:
> > > >
> > > > Inspecting input device's 'users' member should be done under device's
> > > > mutex, so add appropriate invocations.
> > > >
> > > > Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> > >
> > > This looks like a fix that might be applied independently of the other
> > > patches in the series.
> > >
> > > Do you want me to pick it up?
> >
> > If you pick it we'll have to have a dance with this series. Can I apply
> > instead?
> 
> Yes, please.
> 
> Also feel free to add
> 
> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> to it.

Looking at the driver I think the patch and the original use of
input->users is not proper. I'll post another patch addressing this
shortly.

Thanks.

-- 
Dmitry

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

* Re: [PATCH v4 7/7] Input: Add "inhibited" property
  2020-06-08 11:22                                             ` [PATCH v4 7/7] Input: Add "inhibited" property Andrzej Pietrasiewicz
@ 2020-10-05 18:10                                               ` Dmitry Torokhov
  2020-10-06 13:04                                                 ` Andrzej Pietrasiewicz
  0 siblings, 1 reply; 80+ messages in thread
From: Dmitry Torokhov @ 2020-10-05 18:10 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz
  Cc: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Hans de Goede, Ferruh Yigit,
	Sangwon Jee, Peter Hutterer, Henrique de Moraes Holschuh, kernel,
	Patrik Fimml

Hi Andrzej,

On Mon, Jun 08, 2020 at 01:22:11PM +0200, Andrzej Pietrasiewicz wrote:
> @@ -284,8 +284,11 @@ static int input_get_disposition(struct input_dev *dev,
>  	case EV_KEY:
>  		if (is_event_supported(code, dev->keybit, KEY_MAX)) {
>  
> -			/* auto-repeat bypasses state updates */
> -			if (value == 2) {
> +			/*
> +			 * auto-repeat bypasses state updates but repeat
> +			 * events are ignored if the key is not pressed
> +			 */
> +			if (value == 2 && test_bit(code, dev->key)) {
>  				disposition = INPUT_PASS_TO_HANDLERS;
>  				break;
>  			}

Is this chunk really part of inhibit support? I'd think we cancel
autorepeat timer when we are releasing a key, no?

Thanks.

-- 
Dmitry

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

* Re: [PATCH v4 7/7] Input: Add "inhibited" property
  2020-10-05 18:10                                               ` Dmitry Torokhov
@ 2020-10-06 13:04                                                 ` Andrzej Pietrasiewicz
  2020-10-07  1:11                                                   ` Dmitry Torokhov
  0 siblings, 1 reply; 80+ messages in thread
From: Andrzej Pietrasiewicz @ 2020-10-06 13:04 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Hans de Goede, Ferruh Yigit,
	Sangwon Jee, Peter Hutterer, Henrique de Moraes Holschuh, kernel,
	Patrik Fimml

Hi Dmitry,

W dniu 05.10.2020 o 20:10, Dmitry Torokhov pisze:
> Hi Andrzej,
> 
> On Mon, Jun 08, 2020 at 01:22:11PM +0200, Andrzej Pietrasiewicz wrote:
>> @@ -284,8 +284,11 @@ static int input_get_disposition(struct input_dev *dev,
>>   	case EV_KEY:
>>   		if (is_event_supported(code, dev->keybit, KEY_MAX)) {
>>   
>> -			/* auto-repeat bypasses state updates */
>> -			if (value == 2) {
>> +			/*
>> +			 * auto-repeat bypasses state updates but repeat
>> +			 * events are ignored if the key is not pressed
>> +			 */
>> +			if (value == 2 && test_bit(code, dev->key)) {
>>   				disposition = INPUT_PASS_TO_HANDLERS;
>>   				break;
>>   			}
> 
> Is this chunk really part of inhibit support? I'd think we cancel
> autorepeat timer when we are releasing a key, no?
> 

When I look at it now it seems to me the chunk might be redundant.
But let me explain what I had in mind when adding it.

It is a matter of what we do with input events generated while a
device is inhibited. If ->open()/->close() are not provided by the
driver then inhibiting amounts to merely ignoring input events from
a device while it remains active. What else can you do if the driver
does not provide a method to prepare the device for generating events/
to stop generating events?

In this special case a user might trigger a repeated event while the
device is inhibited, then the user keeps holding the key down and the
device is uninhibited. Do we pass anything to handlers then?

In my opinion we should not. Such an event is "illegal" in a sense that it
was generated at a time when nobody wanted any events from the device.
Hence the test to let only those auto-repeat events through for which
a key is actually pressed.

However, what I see now is that if a device is inhibited, no key
will ever reach neither the "1" nor "2" state because of the "if"
in the very beginning of input_handle_event().

Regards,

Andrzej

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

* Re: [PATCH v4 7/7] Input: Add "inhibited" property
  2020-10-06 13:04                                                 ` Andrzej Pietrasiewicz
@ 2020-10-07  1:11                                                   ` Dmitry Torokhov
  2020-10-07  1:12                                                     ` Dmitry Torokhov
  0 siblings, 1 reply; 80+ messages in thread
From: Dmitry Torokhov @ 2020-10-07  1:11 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz
  Cc: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Hans de Goede, Ferruh Yigit,
	Sangwon Jee, Peter Hutterer, Henrique de Moraes Holschuh, kernel,
	Patrik Fimml

On Tue, Oct 06, 2020 at 03:04:28PM +0200, Andrzej Pietrasiewicz wrote:
> Hi Dmitry,
> 
> W dniu 05.10.2020 o 20:10, Dmitry Torokhov pisze:
> > Hi Andrzej,
> > 
> > On Mon, Jun 08, 2020 at 01:22:11PM +0200, Andrzej Pietrasiewicz wrote:
> > > @@ -284,8 +284,11 @@ static int input_get_disposition(struct input_dev *dev,
> > >   	case EV_KEY:
> > >   		if (is_event_supported(code, dev->keybit, KEY_MAX)) {
> > > -			/* auto-repeat bypasses state updates */
> > > -			if (value == 2) {
> > > +			/*
> > > +			 * auto-repeat bypasses state updates but repeat
> > > +			 * events are ignored if the key is not pressed
> > > +			 */
> > > +			if (value == 2 && test_bit(code, dev->key)) {
> > >   				disposition = INPUT_PASS_TO_HANDLERS;
> > >   				break;
> > >   			}
> > 
> > Is this chunk really part of inhibit support? I'd think we cancel
> > autorepeat timer when we are releasing a key, no?
> > 
> 
> When I look at it now it seems to me the chunk might be redundant.
> But let me explain what I had in mind when adding it.
> 
> It is a matter of what we do with input events generated while a
> device is inhibited. If ->open()/->close() are not provided by the
> driver then inhibiting amounts to merely ignoring input events from
> a device while it remains active. What else can you do if the driver
> does not provide a method to prepare the device for generating events/
> to stop generating events?
> 
> In this special case a user might trigger a repeated event while the
> device is inhibited, then the user keeps holding the key down and the
> device is uninhibited. Do we pass anything to handlers then?
> 
> In my opinion we should not. Such an event is "illegal" in a sense that it
> was generated at a time when nobody wanted any events from the device.
> Hence the test to let only those auto-repeat events through for which
> a key is actually pressed.
> 
> However, what I see now is that if a device is inhibited, no key
> will ever reach neither the "1" nor "2" state because of the "if"
> in the very beginning of input_handle_event().

OK, then let's drop it for now. We can revisit if we see that a problem.

Thanks.

-- 
Dmitry

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

* Re: [PATCH v4 7/7] Input: Add "inhibited" property
  2020-10-07  1:11                                                   ` Dmitry Torokhov
@ 2020-10-07  1:12                                                     ` Dmitry Torokhov
  0 siblings, 0 replies; 80+ messages in thread
From: Dmitry Torokhov @ 2020-10-07  1:12 UTC (permalink / raw)
  To: Andrzej Pietrasiewicz
  Cc: linux-pm, linux-acpi, linux-kernel, linux-iio, linux-arm-kernel,
	linux-samsung-soc, linux-input, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86, Rafael J . Wysocki,
	Len Brown, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Kukjin Kim, Krzysztof Kozlowski,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Vladimir Zapolskiy, Sylvain Lemieux,
	Laxman Dewangan, Thierry Reding, Jonathan Hunter, Barry Song,
	Michael Hennerich, Nick Dyer, Hans de Goede, Ferruh Yigit,
	Sangwon Jee, Peter Hutterer, Henrique de Moraes Holschuh, kernel,
	Patrik Fimml

On Tue, Oct 06, 2020 at 06:11:02PM -0700, Dmitry Torokhov wrote:
> On Tue, Oct 06, 2020 at 03:04:28PM +0200, Andrzej Pietrasiewicz wrote:
> > Hi Dmitry,
> > 
> > W dniu 05.10.2020 o 20:10, Dmitry Torokhov pisze:
> > > Hi Andrzej,
> > > 
> > > On Mon, Jun 08, 2020 at 01:22:11PM +0200, Andrzej Pietrasiewicz wrote:
> > > > @@ -284,8 +284,11 @@ static int input_get_disposition(struct input_dev *dev,
> > > >   	case EV_KEY:
> > > >   		if (is_event_supported(code, dev->keybit, KEY_MAX)) {
> > > > -			/* auto-repeat bypasses state updates */
> > > > -			if (value == 2) {
> > > > +			/*
> > > > +			 * auto-repeat bypasses state updates but repeat
> > > > +			 * events are ignored if the key is not pressed
> > > > +			 */
> > > > +			if (value == 2 && test_bit(code, dev->key)) {
> > > >   				disposition = INPUT_PASS_TO_HANDLERS;
> > > >   				break;
> > > >   			}
> > > 
> > > Is this chunk really part of inhibit support? I'd think we cancel
> > > autorepeat timer when we are releasing a key, no?
> > > 
> > 
> > When I look at it now it seems to me the chunk might be redundant.
> > But let me explain what I had in mind when adding it.
> > 
> > It is a matter of what we do with input events generated while a
> > device is inhibited. If ->open()/->close() are not provided by the
> > driver then inhibiting amounts to merely ignoring input events from
> > a device while it remains active. What else can you do if the driver
> > does not provide a method to prepare the device for generating events/
> > to stop generating events?
> > 
> > In this special case a user might trigger a repeated event while the
> > device is inhibited, then the user keeps holding the key down and the
> > device is uninhibited. Do we pass anything to handlers then?
> > 
> > In my opinion we should not. Such an event is "illegal" in a sense that it
> > was generated at a time when nobody wanted any events from the device.
> > Hence the test to let only those auto-repeat events through for which
> > a key is actually pressed.
> > 
> > However, what I see now is that if a device is inhibited, no key
> > will ever reach neither the "1" nor "2" state because of the "if"
> > in the very beginning of input_handle_event().
> 
> OK, then let's drop it for now. We can revisit if we see that a problem.

And by that I mean that I will drop it myself, no need to resend. I will
be applying this shortly.

Thanks.

-- 
Dmitry

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

end of thread, back to index

Thread overview: 80+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20200506002746.GB89269@dtor-ws>
2020-05-15 16:49 ` [PATCHv2 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
2020-05-15 16:51   ` [PATCHv2 1/7] Input: add input_device_enabled() Andrzej Pietrasiewicz
2020-05-15 16:52   ` [PATCHv2 6/7] Input: Add "inhibited" property Andrzej Pietrasiewicz
2020-05-15 16:53   ` [PATCHv2 3/7] ACPI: button: Use input_device_enabled() helper Andrzej Pietrasiewicz
2020-05-18 12:40     ` Rafael J. Wysocki
2020-05-15 18:19   ` [PATCHv2 0/7] Support inhibiting input devices Hans de Goede
2020-05-17 22:55     ` Peter Hutterer
2020-05-18  2:40       ` Dmitry Torokhov
2020-05-18  7:36         ` Hans de Goede
2020-05-22 15:35         ` Andrzej Pietrasiewicz
2020-05-27  6:13           ` Peter Hutterer
2020-05-18 10:48     ` Andrzej Pietrasiewicz
2020-05-18 12:24       ` Hans de Goede
2020-05-18 13:49         ` Andrzej Pietrasiewicz
2020-05-18 14:23           ` Hans de Goede
2020-05-19  9:02             ` Andrzej Pietrasiewicz
2020-05-19  9:36               ` Hans de Goede
2020-05-27  6:34                 ` Dmitry Torokhov
2020-06-02 16:56                   ` Andrzej Pietrasiewicz
2020-06-02 17:52                     ` Dmitry Torokhov
2020-06-02 18:50                       ` Andrzej Pietrasiewicz
2020-06-02 20:19                         ` Hans de Goede
2020-06-03 13:07                           ` Andrzej Pietrasiewicz
2020-06-03 17:38                             ` Hans de Goede
2020-06-03 17:54                               ` Andrzej Pietrasiewicz
2020-06-03 19:37                                 ` Hans de Goede
2020-06-04  7:28                                   ` Dmitry Torokhov
2020-06-05 17:33                                     ` [PATCH v3 " Andrzej Pietrasiewicz
2020-06-05 17:33                                       ` [PATCH v3 1/7] Input: add input_device_enabled() Andrzej Pietrasiewicz
2020-06-05 17:33                                       ` [PATCH v3 2/7] Input: use input_device_enabled() Andrzej Pietrasiewicz
2020-06-05 17:33                                       ` [PATCH v3 3/7] ACPI: button: Access input device's users under appropriate mutex Andrzej Pietrasiewicz
2020-06-05 17:33                                       ` [PATCH v3 4/7] ACPI: button: Use input_device_enabled() helper Andrzej Pietrasiewicz
2020-06-05 17:33                                       ` [PATCH v3 5/7] iio: adc: exynos: Use input_device_enabled() Andrzej Pietrasiewicz
2020-06-05 19:49                                         ` Michał Mirosław
2020-06-05 17:33                                       ` [PATCH v3 6/7] platform/x86: thinkpad_acpi: " Andrzej Pietrasiewicz
2020-06-05 17:33                                       ` [PATCH v3 7/7] Input: Add "inhibited" property Andrzej Pietrasiewicz
2020-06-05 17:41                                         ` Hans de Goede
2020-06-08 11:22                                           ` [PATCH v4 0/7] Support inhibiting input devices Andrzej Pietrasiewicz
2020-06-08 11:22                                             ` [PATCH v4 1/7] Input: add input_device_enabled() Andrzej Pietrasiewicz
2020-06-08 11:22                                             ` [PATCH v4 2/7] Input: use input_device_enabled() Andrzej Pietrasiewicz
2020-06-08 11:22                                             ` [PATCH v4 3/7] ACPI: button: Access input device's users under appropriate mutex Andrzej Pietrasiewicz
2020-06-24 15:00                                               ` Rafael J. Wysocki
2020-06-25  5:23                                                 ` Dmitry Torokhov
2020-06-25 10:55                                                   ` Rafael J. Wysocki
2020-10-05  5:08                                                     ` Dmitry Torokhov
2020-06-08 11:22                                             ` [PATCH v4 4/7] ACPI: button: Use input_device_enabled() helper Andrzej Pietrasiewicz
2020-06-25  5:24                                               ` Dmitry Torokhov
2020-10-05  5:06                                                 ` Dmitry Torokhov
2020-06-08 11:22                                             ` [PATCH v4 5/7] iio: adc: exynos: Use input_device_enabled() Andrzej Pietrasiewicz
2020-06-10  1:28                                               ` Michał Mirosław
2020-06-10  7:52                                                 ` [FIXED PATCH " Andrzej Pietrasiewicz
2020-06-08 11:22                                             ` [PATCH v4 6/7] platform/x86: thinkpad_acpi: " Andrzej Pietrasiewicz
2020-06-08 11:22                                             ` [PATCH v4 7/7] Input: Add "inhibited" property Andrzej Pietrasiewicz
2020-10-05 18:10                                               ` Dmitry Torokhov
2020-10-06 13:04                                                 ` Andrzej Pietrasiewicz
2020-10-07  1:11                                                   ` Dmitry Torokhov
2020-10-07  1:12                                                     ` Dmitry Torokhov
2020-06-10  9:49                                             ` [PATCH v4 0/7] Support inhibiting input devices Hans de Goede
2020-06-10 10:38                                               ` Rafael J. Wysocki
2020-06-10 13:12                                                 ` Andrzej Pietrasiewicz
2020-06-10 13:21                                                   ` Hans de Goede
2020-06-10 13:41                                                     ` Andrzej Pietrasiewicz
2020-06-12  8:30                                                       ` Hans de Goede
2020-06-12  8:47                                                         ` Andrzej Pietrasiewicz
2020-06-16 17:29                                                         ` [PATCH] Input: document inhibiting Andrzej Pietrasiewicz
2020-06-16 17:38                                                           ` Randy Dunlap
2020-06-17  7:44                                                           ` Hans de Goede
2020-06-17 10:18                                                             ` [PATCH v2] " Andrzej Pietrasiewicz
2020-06-17 10:21                                                               ` Hans de Goede
2020-06-17 16:52                                                               ` Randy Dunlap
2020-06-23 13:35                                                               ` Pavel Machek
2020-06-10 14:01                                                     ` [PATCH v4 0/7] Support inhibiting input devices Rafael J. Wysocki
2020-06-10 13:52                                                 ` Hans de Goede
2020-06-10 18:28                                                 ` Dmitry Torokhov
2020-06-12  8:14                                                   ` Hans de Goede
2020-06-12  8:17                                             ` Hans de Goede
2020-08-03 14:40                                               ` Andrzej Pietrasiewicz
2020-06-07 20:24                                       ` [PATCH v3 " Pavel Machek
2020-06-08  5:37                                         ` Dmitry Torokhov
2020-06-08  9:28                                           ` Andrzej Pietrasiewicz

Linux-ACPI Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-acpi/0 linux-acpi/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-acpi linux-acpi/ https://lore.kernel.org/linux-acpi \
		linux-acpi@vger.kernel.org
	public-inbox-index linux-acpi

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-acpi


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git