linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 1/2] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model
       [not found] <cbdaec17aba78c61f466efff8883d49067f2dad5.1463472125.git.lv.zheng@intel.com>
@ 2016-07-19  8:11 ` Lv Zheng
  2016-07-19  8:46   ` Benjamin Tissoires
  2016-07-21 13:35   ` Rafael J. Wysocki
  2016-07-19  8:11 ` [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng
                   ` (8 subsequent siblings)
  9 siblings, 2 replies; 34+ messages in thread
From: Lv Zheng @ 2016-07-19  8:11 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi, Dmitry Torokhov,
	Benjamin Tissoires, Bastien Nocera:, linux-input

There are many AML tables reporting wrong initial lid state, and some of
them never report lid open state. As a proxy layer acting between, ACPI
button driver is not able to handle all such cases, but need to re-define
the usage model of the ACPI lid. That is:
1. It's initial state is not reliable;
2. There may not be an open event;
3. Userspace should only take action against the close event which is
   reliable, always sent after a real lid close.

OTOH, using an input switch event for the lid device on such platforms can
cause the loss of the close event, but the platforms purposely want to use
these close events to trigger power saving actions.

So we need to introduce a new ABI, which is input key events based, not
input switch events based.

This patch adds a set of new input key events so that the new userspace
programs can use them to handle this usage model correctly. And in the
meanwhile, the old input switch event is kept so that no old programs will
be broken by the ABI change.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Cc: Bastien Nocera: <hadess@hadess.net>
Cc: linux-input@vger.kernel.org
---
 drivers/acpi/button.c                  |   34 +++++++++++++++++++++++++++++++-
 include/uapi/linux/input-event-codes.h |    7 +++++++
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 148f4e5..dd16879 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -104,6 +104,8 @@ struct acpi_button {
 	struct input_dev *input;
 	char phys[32];			/* for input device */
 	unsigned long pushed;
+	int last_state;
+	unsigned long timestamp;
 	bool suspended;
 };
 
@@ -111,6 +113,10 @@ static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
 static struct acpi_device *lid_device;
 static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
 
+static unsigned long lid_report_interval __read_mostly = 500;
+module_param(lid_report_interval, ulong, 0644);
+MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
+
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
@@ -133,12 +139,34 @@ static int acpi_lid_evaluate_state(struct acpi_device *device)
 static int acpi_lid_notify_state(struct acpi_device *device, int state)
 {
 	struct acpi_button *button = acpi_driver_data(device);
+	int keycode;
+	unsigned long timeout;
 	int ret;
 
-	/* input layer checks if event is redundant */
+	/*
+	 * Send the switch event.
+	 * The input layer checks if the event is redundant.
+	 */
 	input_report_switch(button->input, SW_LID, !state);
 	input_sync(button->input);
 
+	/*
+	 * Send the key event.
+	 * The input layer doesn't check if the event is redundant.
+	 */
+	timeout = button->timestamp +
+		  msecs_to_jiffies(lid_report_interval);
+	if (button->last_state != !!state ||
+	    time_after(jiffies, timeout)) {
+		keycode = state ? KEY_LID_OPEN : KEY_LID_CLOSE;
+		input_report_key(button->input, keycode, 1);
+		input_sync(button->input);
+		input_report_key(button->input, keycode, 0);
+		input_sync(button->input);
+		button->last_state = !!state;
+		button->timestamp = jiffies;
+	}
+
 	if (state)
 		pm_wakeup_event(&device->dev, 0);
 
@@ -407,6 +435,8 @@ static int acpi_button_add(struct acpi_device *device)
 		strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
 		sprintf(class, "%s/%s",
 			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
+		button->last_state = !!acpi_lid_evaluate_state(device);
+		button->timestamp = jiffies;
 	} else {
 		printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
 		error = -ENODEV;
@@ -436,6 +466,8 @@ static int acpi_button_add(struct acpi_device *device)
 
 	case ACPI_BUTTON_TYPE_LID:
 		input_set_capability(input, EV_SW, SW_LID);
+		input_set_capability(input, EV_KEY, KEY_LID_OPEN);
+		input_set_capability(input, EV_KEY, KEY_LID_CLOSE);
 		break;
 	}
 
diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h
index 737fa32..b062fe1 100644
--- a/include/uapi/linux/input-event-codes.h
+++ b/include/uapi/linux/input-event-codes.h
@@ -641,6 +641,13 @@
  * e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.)
  */
 #define KEY_DATA			0x275
+/*
+ * Key events sent by the lid drivers.
+ * The drivers may not be able to send paired "open"/"close" events, in
+ * which case, they send KEY_LID_OPEN/KEY_LID_CLOSE instead of SW_LID.
+ */
+#define KEY_LID_OPEN			0x278
+#define KEY_LID_CLOSE			0x279
 
 #define BTN_TRIGGER_HAPPY		0x2c0
 #define BTN_TRIGGER_HAPPY1		0x2c0
-- 
1.7.10


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

* [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
       [not found] <cbdaec17aba78c61f466efff8883d49067f2dad5.1463472125.git.lv.zheng@intel.com>
  2016-07-19  8:11 ` [PATCH v4 1/2] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model Lv Zheng
@ 2016-07-19  8:11 ` Lv Zheng
  2016-07-19  8:44   ` Benjamin Tissoires
  2016-07-21 20:32   ` Dmitry Torokhov
  2016-07-22  6:24 ` [PATCH v5 1/3] ACPI / button: Add missing event to keep SW_LID running without additional event loss Lv Zheng
                   ` (7 subsequent siblings)
  9 siblings, 2 replies; 34+ messages in thread
From: Lv Zheng @ 2016-07-19  8:11 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi, Dmitry Torokhov,
	Benjamin Tissoires, Bastien Nocera:, linux-input

This patch adds documentation for the usage model of the control method lid
device.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Cc: Bastien Nocera: <hadess@hadess.net>
Cc: linux-input@vger.kernel.org
---
 Documentation/acpi/acpi-lid.txt |   89 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 89 insertions(+)
 create mode 100644 Documentation/acpi/acpi-lid.txt

diff --git a/Documentation/acpi/acpi-lid.txt b/Documentation/acpi/acpi-lid.txt
new file mode 100644
index 0000000..2addedc
--- /dev/null
+++ b/Documentation/acpi/acpi-lid.txt
@@ -0,0 +1,89 @@
+Usage Model of the ACPI Control Method Lid Device
+
+Copyright (C) 2016, Intel Corporation
+Author: Lv Zheng <lv.zheng@intel.com>
+
+
+Abstract:
+
+Platforms containing lids convey lid state (open/close) to OSPMs using a
+control method lid device. To implement this, the AML tables issue
+Notify(lid_device, 0x80) to notify the OSPMs whenever the lid state has
+changed. The _LID control method for the lid device must be implemented to
+report the "current" state of the lid as either "opened" or "closed".
+
+This document describes the restrictions and the expections of the Linux
+ACPI lid device driver.
+
+
+1. Restrictions of the returning value of the _LID control method
+
+The _LID control method is described to return the "current" lid state.
+However the word of "current" has ambiguity, many AML tables return the lid
+state upon the last lid notification instead of returning the lid state
+upon the last _LID evaluation. There won't be difference when the _LID
+control method is evaluated during the runtime, the problem is its initial
+returning value. When the AML tables implement this control method with
+cached value, the initial returning value is likely not reliable. There are
+simply so many examples always retuning "closed" as initial lid state.
+
+2. Restrictions of the lid state change notifications
+
+There are many AML tables never notifying when the lid device state is
+changed to "opened". Thus the "opened" notification is not guaranteed.
+
+But it is guaranteed that the AML tables always notify "closed" when the
+lid state is changed to "closed". The "closed" notification is normally
+used to trigger some system power saving operations on Windows. Since it is
+fully tested, the "closed" notification is reliable for all AML tables.
+
+3. Expections for the userspace users of the ACPI lid device driver
+
+The ACPI button driver exports the lid state to the userspace via the
+following file:
+  /proc/acpi/button/lid/LID0/state
+This file actually calls the _LID control method described above. And given
+the previous explanation, it is not reliable enough on some platforms. So
+it is advised for the userspace program to not to solely rely on this file
+to determine the actual lid state.
+
+The ACPI button driver emits 2 kinds of events to the user space:
+  SW_LID
+   When the lid state/event is reliable, the userspace can behave
+   according to this input switch event.
+   This is a mode prepared for backward compatiblity.
+  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
+   When the lid state/event is not reliable, the userspace should behave
+   according to these 2 input key events.
+   New userspace programs may only be prepared for the input key events.
+
+If the userspace hasn't been prepared to handle the new input lid key
+events, Linux users can use the following kernel parameters to handle the
+possible issues triggered because of the unreliable lid state/event:
+A. button.lid_init_state=method:
+   When this option is specified, the ACPI button driver reports the
+   initial lid state using the returning value of the _LID control method.
+   This option can be used to fix some platforms where the _LID control
+   method's returning value is reliable but the initial lid state
+   notification is missing.
+   This option is the default behavior during the period the userspace
+   isn't ready to handle the new usage model.
+B. button.lid_init_state=open:
+   When this option is specified, the ACPI button driver always reports the
+   initial lid state as "opened".
+   This may fix some platforms where the returning value of the _LID
+   control method is not reliable and the initial lid state notification is
+   missing.
+
+If the userspace has been prepared to handle the new input lid key events,
+Linux users should always use the following kernel parameter:
+C. button.lid_init_state=ignore:
+   When this option is specified, the ACPI button driver never reports the
+   initial lid state. However, the platform may automatically report a
+   correct initial lid state and there is no "open" event missing. When
+   this is the case (everything is correctly implemented by the platform
+   firmware), the old input switch event based userspace can still work.
+   Otherwise, the userspace programs may only work based on the input key
+   events.
+   This option will be the default behavior after the userspace is ready to
+   handle the new usage model.
-- 
1.7.10


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

* Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-19  8:11 ` [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng
@ 2016-07-19  8:44   ` Benjamin Tissoires
  2016-07-21 20:32   ` Dmitry Torokhov
  1 sibling, 0 replies; 34+ messages in thread
From: Benjamin Tissoires @ 2016-07-19  8:44 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown, Lv Zheng,
	linux-kernel@vger.kernel.org, ACPI Devel Maling List,
	Dmitry Torokhov, Bastien Nocera:, linux-input

On Tue, Jul 19, 2016 at 10:11 AM, Lv Zheng <lv.zheng@intel.com> wrote:
> This patch adds documentation for the usage model of the control method lid
> device.
>
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> Cc: Bastien Nocera: <hadess@hadess.net>
> Cc: linux-input@vger.kernel.org
> ---

Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>

Cheers,
Benjamin

>  Documentation/acpi/acpi-lid.txt |   89 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 89 insertions(+)
>  create mode 100644 Documentation/acpi/acpi-lid.txt
>
> diff --git a/Documentation/acpi/acpi-lid.txt b/Documentation/acpi/acpi-lid.txt
> new file mode 100644
> index 0000000..2addedc
> --- /dev/null
> +++ b/Documentation/acpi/acpi-lid.txt
> @@ -0,0 +1,89 @@
> +Usage Model of the ACPI Control Method Lid Device
> +
> +Copyright (C) 2016, Intel Corporation
> +Author: Lv Zheng <lv.zheng@intel.com>
> +
> +
> +Abstract:
> +
> +Platforms containing lids convey lid state (open/close) to OSPMs using a
> +control method lid device. To implement this, the AML tables issue
> +Notify(lid_device, 0x80) to notify the OSPMs whenever the lid state has
> +changed. The _LID control method for the lid device must be implemented to
> +report the "current" state of the lid as either "opened" or "closed".
> +
> +This document describes the restrictions and the expections of the Linux
> +ACPI lid device driver.
> +
> +
> +1. Restrictions of the returning value of the _LID control method
> +
> +The _LID control method is described to return the "current" lid state.
> +However the word of "current" has ambiguity, many AML tables return the lid
> +state upon the last lid notification instead of returning the lid state
> +upon the last _LID evaluation. There won't be difference when the _LID
> +control method is evaluated during the runtime, the problem is its initial
> +returning value. When the AML tables implement this control method with
> +cached value, the initial returning value is likely not reliable. There are
> +simply so many examples always retuning "closed" as initial lid state.
> +
> +2. Restrictions of the lid state change notifications
> +
> +There are many AML tables never notifying when the lid device state is
> +changed to "opened". Thus the "opened" notification is not guaranteed.
> +
> +But it is guaranteed that the AML tables always notify "closed" when the
> +lid state is changed to "closed". The "closed" notification is normally
> +used to trigger some system power saving operations on Windows. Since it is
> +fully tested, the "closed" notification is reliable for all AML tables.
> +
> +3. Expections for the userspace users of the ACPI lid device driver
> +
> +The ACPI button driver exports the lid state to the userspace via the
> +following file:
> +  /proc/acpi/button/lid/LID0/state
> +This file actually calls the _LID control method described above. And given
> +the previous explanation, it is not reliable enough on some platforms. So
> +it is advised for the userspace program to not to solely rely on this file
> +to determine the actual lid state.
> +
> +The ACPI button driver emits 2 kinds of events to the user space:
> +  SW_LID
> +   When the lid state/event is reliable, the userspace can behave
> +   according to this input switch event.
> +   This is a mode prepared for backward compatiblity.
> +  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
> +   When the lid state/event is not reliable, the userspace should behave
> +   according to these 2 input key events.
> +   New userspace programs may only be prepared for the input key events.
> +
> +If the userspace hasn't been prepared to handle the new input lid key
> +events, Linux users can use the following kernel parameters to handle the
> +possible issues triggered because of the unreliable lid state/event:
> +A. button.lid_init_state=method:
> +   When this option is specified, the ACPI button driver reports the
> +   initial lid state using the returning value of the _LID control method.
> +   This option can be used to fix some platforms where the _LID control
> +   method's returning value is reliable but the initial lid state
> +   notification is missing.
> +   This option is the default behavior during the period the userspace
> +   isn't ready to handle the new usage model.
> +B. button.lid_init_state=open:
> +   When this option is specified, the ACPI button driver always reports the
> +   initial lid state as "opened".
> +   This may fix some platforms where the returning value of the _LID
> +   control method is not reliable and the initial lid state notification is
> +   missing.
> +
> +If the userspace has been prepared to handle the new input lid key events,
> +Linux users should always use the following kernel parameter:
> +C. button.lid_init_state=ignore:
> +   When this option is specified, the ACPI button driver never reports the
> +   initial lid state. However, the platform may automatically report a
> +   correct initial lid state and there is no "open" event missing. When
> +   this is the case (everything is correctly implemented by the platform
> +   firmware), the old input switch event based userspace can still work.
> +   Otherwise, the userspace programs may only work based on the input key
> +   events.
> +   This option will be the default behavior after the userspace is ready to
> +   handle the new usage model.
> --
> 1.7.10
>

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

* Re: [PATCH v4 1/2] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model
  2016-07-19  8:11 ` [PATCH v4 1/2] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model Lv Zheng
@ 2016-07-19  8:46   ` Benjamin Tissoires
  2016-07-21 13:35   ` Rafael J. Wysocki
  1 sibling, 0 replies; 34+ messages in thread
From: Benjamin Tissoires @ 2016-07-19  8:46 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown, Lv Zheng,
	linux-kernel@vger.kernel.org, ACPI Devel Maling List,
	Dmitry Torokhov, Bastien Nocera:, linux-input

On Tue, Jul 19, 2016 at 10:11 AM, Lv Zheng <lv.zheng@intel.com> wrote:
> There are many AML tables reporting wrong initial lid state, and some of
> them never report lid open state. As a proxy layer acting between, ACPI
> button driver is not able to handle all such cases, but need to re-define
> the usage model of the ACPI lid. That is:
> 1. It's initial state is not reliable;
> 2. There may not be an open event;
> 3. Userspace should only take action against the close event which is
>    reliable, always sent after a real lid close.
>
> OTOH, using an input switch event for the lid device on such platforms can
> cause the loss of the close event, but the platforms purposely want to use
> these close events to trigger power saving actions.
>
> So we need to introduce a new ABI, which is input key events based, not
> input switch events based.
>
> This patch adds a set of new input key events so that the new userspace
> programs can use them to handle this usage model correctly. And in the
> meanwhile, the old input switch event is kept so that no old programs will
> be broken by the ABI change.
>
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> Cc: Bastien Nocera: <hadess@hadess.net>
> Cc: linux-input@vger.kernel.org
> ---

Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>

Cheers,
Benjamin

>  drivers/acpi/button.c                  |   34 +++++++++++++++++++++++++++++++-
>  include/uapi/linux/input-event-codes.h |    7 +++++++
>  2 files changed, 40 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> index 148f4e5..dd16879 100644
> --- a/drivers/acpi/button.c
> +++ b/drivers/acpi/button.c
> @@ -104,6 +104,8 @@ struct acpi_button {
>         struct input_dev *input;
>         char phys[32];                  /* for input device */
>         unsigned long pushed;
> +       int last_state;
> +       unsigned long timestamp;
>         bool suspended;
>  };
>
> @@ -111,6 +113,10 @@ static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
>  static struct acpi_device *lid_device;
>  static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
>
> +static unsigned long lid_report_interval __read_mostly = 500;
> +module_param(lid_report_interval, ulong, 0644);
> +MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
> +
>  /* --------------------------------------------------------------------------
>                                FS Interface (/proc)
>     -------------------------------------------------------------------------- */
> @@ -133,12 +139,34 @@ static int acpi_lid_evaluate_state(struct acpi_device *device)
>  static int acpi_lid_notify_state(struct acpi_device *device, int state)
>  {
>         struct acpi_button *button = acpi_driver_data(device);
> +       int keycode;
> +       unsigned long timeout;
>         int ret;
>
> -       /* input layer checks if event is redundant */
> +       /*
> +        * Send the switch event.
> +        * The input layer checks if the event is redundant.
> +        */
>         input_report_switch(button->input, SW_LID, !state);
>         input_sync(button->input);
>
> +       /*
> +        * Send the key event.
> +        * The input layer doesn't check if the event is redundant.
> +        */
> +       timeout = button->timestamp +
> +                 msecs_to_jiffies(lid_report_interval);
> +       if (button->last_state != !!state ||
> +           time_after(jiffies, timeout)) {
> +               keycode = state ? KEY_LID_OPEN : KEY_LID_CLOSE;
> +               input_report_key(button->input, keycode, 1);
> +               input_sync(button->input);
> +               input_report_key(button->input, keycode, 0);
> +               input_sync(button->input);
> +               button->last_state = !!state;
> +               button->timestamp = jiffies;
> +       }
> +
>         if (state)
>                 pm_wakeup_event(&device->dev, 0);
>
> @@ -407,6 +435,8 @@ static int acpi_button_add(struct acpi_device *device)
>                 strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
>                 sprintf(class, "%s/%s",
>                         ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
> +               button->last_state = !!acpi_lid_evaluate_state(device);
> +               button->timestamp = jiffies;
>         } else {
>                 printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
>                 error = -ENODEV;
> @@ -436,6 +466,8 @@ static int acpi_button_add(struct acpi_device *device)
>
>         case ACPI_BUTTON_TYPE_LID:
>                 input_set_capability(input, EV_SW, SW_LID);
> +               input_set_capability(input, EV_KEY, KEY_LID_OPEN);
> +               input_set_capability(input, EV_KEY, KEY_LID_CLOSE);
>                 break;
>         }
>
> diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h
> index 737fa32..b062fe1 100644
> --- a/include/uapi/linux/input-event-codes.h
> +++ b/include/uapi/linux/input-event-codes.h
> @@ -641,6 +641,13 @@
>   * e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.)
>   */
>  #define KEY_DATA                       0x275
> +/*
> + * Key events sent by the lid drivers.
> + * The drivers may not be able to send paired "open"/"close" events, in
> + * which case, they send KEY_LID_OPEN/KEY_LID_CLOSE instead of SW_LID.
> + */
> +#define KEY_LID_OPEN                   0x278
> +#define KEY_LID_CLOSE                  0x279
>
>  #define BTN_TRIGGER_HAPPY              0x2c0
>  #define BTN_TRIGGER_HAPPY1             0x2c0
> --
> 1.7.10
>

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

* Re: [PATCH v4 1/2] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model
  2016-07-19  8:11 ` [PATCH v4 1/2] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model Lv Zheng
  2016-07-19  8:46   ` Benjamin Tissoires
@ 2016-07-21 13:35   ` Rafael J. Wysocki
  2016-07-21 20:33     ` Dmitry Torokhov
  1 sibling, 1 reply; 34+ messages in thread
From: Rafael J. Wysocki @ 2016-07-21 13:35 UTC (permalink / raw)
  To: Lv Zheng, Dmitry Torokhov
  Cc: Rafael J. Wysocki, Len Brown, Lv Zheng, linux-kernel, linux-acpi,
	Benjamin Tissoires, Bastien Nocera:, linux-input

On Tuesday, July 19, 2016 04:11:02 PM Lv Zheng wrote:
> There are many AML tables reporting wrong initial lid state, and some of
> them never report lid open state. As a proxy layer acting between, ACPI
> button driver is not able to handle all such cases, but need to re-define
> the usage model of the ACPI lid. That is:
> 1. It's initial state is not reliable;
> 2. There may not be an open event;
> 3. Userspace should only take action against the close event which is
>    reliable, always sent after a real lid close.
> 
> OTOH, using an input switch event for the lid device on such platforms can
> cause the loss of the close event, but the platforms purposely want to use
> these close events to trigger power saving actions.
> 
> So we need to introduce a new ABI, which is input key events based, not
> input switch events based.
> 
> This patch adds a set of new input key events so that the new userspace
> programs can use them to handle this usage model correctly. And in the
> meanwhile, the old input switch event is kept so that no old programs will
> be broken by the ABI change.
> 
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> Cc: Bastien Nocera: <hadess@hadess.net>
> Cc: linux-input@vger.kernel.org

Dmitry, any objections here?

> ---
>  drivers/acpi/button.c                  |   34 +++++++++++++++++++++++++++++++-
>  include/uapi/linux/input-event-codes.h |    7 +++++++
>  2 files changed, 40 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> index 148f4e5..dd16879 100644
> --- a/drivers/acpi/button.c
> +++ b/drivers/acpi/button.c
> @@ -104,6 +104,8 @@ struct acpi_button {
>  	struct input_dev *input;
>  	char phys[32];			/* for input device */
>  	unsigned long pushed;
> +	int last_state;
> +	unsigned long timestamp;
>  	bool suspended;
>  };
>  
> @@ -111,6 +113,10 @@ static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
>  static struct acpi_device *lid_device;
>  static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
>  
> +static unsigned long lid_report_interval __read_mostly = 500;
> +module_param(lid_report_interval, ulong, 0644);
> +MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
> +
>  /* --------------------------------------------------------------------------
>                                FS Interface (/proc)
>     -------------------------------------------------------------------------- */
> @@ -133,12 +139,34 @@ static int acpi_lid_evaluate_state(struct acpi_device *device)
>  static int acpi_lid_notify_state(struct acpi_device *device, int state)
>  {
>  	struct acpi_button *button = acpi_driver_data(device);
> +	int keycode;
> +	unsigned long timeout;
>  	int ret;
>  
> -	/* input layer checks if event is redundant */
> +	/*
> +	 * Send the switch event.
> +	 * The input layer checks if the event is redundant.
> +	 */
>  	input_report_switch(button->input, SW_LID, !state);
>  	input_sync(button->input);
>  
> +	/*
> +	 * Send the key event.
> +	 * The input layer doesn't check if the event is redundant.
> +	 */
> +	timeout = button->timestamp +
> +		  msecs_to_jiffies(lid_report_interval);
> +	if (button->last_state != !!state ||
> +	    time_after(jiffies, timeout)) {
> +		keycode = state ? KEY_LID_OPEN : KEY_LID_CLOSE;
> +		input_report_key(button->input, keycode, 1);
> +		input_sync(button->input);
> +		input_report_key(button->input, keycode, 0);
> +		input_sync(button->input);
> +		button->last_state = !!state;
> +		button->timestamp = jiffies;
> +	}
> +
>  	if (state)
>  		pm_wakeup_event(&device->dev, 0);
>  
> @@ -407,6 +435,8 @@ static int acpi_button_add(struct acpi_device *device)
>  		strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
>  		sprintf(class, "%s/%s",
>  			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
> +		button->last_state = !!acpi_lid_evaluate_state(device);
> +		button->timestamp = jiffies;
>  	} else {
>  		printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
>  		error = -ENODEV;
> @@ -436,6 +466,8 @@ static int acpi_button_add(struct acpi_device *device)
>  
>  	case ACPI_BUTTON_TYPE_LID:
>  		input_set_capability(input, EV_SW, SW_LID);
> +		input_set_capability(input, EV_KEY, KEY_LID_OPEN);
> +		input_set_capability(input, EV_KEY, KEY_LID_CLOSE);
>  		break;
>  	}
>  
> diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h
> index 737fa32..b062fe1 100644
> --- a/include/uapi/linux/input-event-codes.h
> +++ b/include/uapi/linux/input-event-codes.h
> @@ -641,6 +641,13 @@
>   * e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.)
>   */
>  #define KEY_DATA			0x275
> +/*
> + * Key events sent by the lid drivers.
> + * The drivers may not be able to send paired "open"/"close" events, in
> + * which case, they send KEY_LID_OPEN/KEY_LID_CLOSE instead of SW_LID.
> + */
> +#define KEY_LID_OPEN			0x278
> +#define KEY_LID_CLOSE			0x279
>  
>  #define BTN_TRIGGER_HAPPY		0x2c0
>  #define BTN_TRIGGER_HAPPY1		0x2c0

To this part in particular?

Thanks,
Rafael


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

* Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-19  8:11 ` [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng
  2016-07-19  8:44   ` Benjamin Tissoires
@ 2016-07-21 20:32   ` Dmitry Torokhov
  2016-07-22  0:24     ` Zheng, Lv
  1 sibling, 1 reply; 34+ messages in thread
From: Dmitry Torokhov @ 2016-07-21 20:32 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown, Lv Zheng,
	linux-kernel, linux-acpi, Benjamin Tissoires, Bastien Nocera:,
	linux-input

On Tue, Jul 19, 2016 at 04:11:21PM +0800, Lv Zheng wrote:
> This patch adds documentation for the usage model of the control method lid
> device.
> 
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> Cc: Bastien Nocera: <hadess@hadess.net>
> Cc: linux-input@vger.kernel.org
> ---
>  Documentation/acpi/acpi-lid.txt |   89 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 89 insertions(+)
>  create mode 100644 Documentation/acpi/acpi-lid.txt
> 
> diff --git a/Documentation/acpi/acpi-lid.txt b/Documentation/acpi/acpi-lid.txt
> new file mode 100644
> index 0000000..2addedc
> --- /dev/null
> +++ b/Documentation/acpi/acpi-lid.txt
> @@ -0,0 +1,89 @@
> +Usage Model of the ACPI Control Method Lid Device
> +
> +Copyright (C) 2016, Intel Corporation
> +Author: Lv Zheng <lv.zheng@intel.com>
> +
> +
> +Abstract:
> +
> +Platforms containing lids convey lid state (open/close) to OSPMs using a
> +control method lid device. To implement this, the AML tables issue
> +Notify(lid_device, 0x80) to notify the OSPMs whenever the lid state has
> +changed. The _LID control method for the lid device must be implemented to
> +report the "current" state of the lid as either "opened" or "closed".
> +
> +This document describes the restrictions and the expections of the Linux
> +ACPI lid device driver.
> +
> +
> +1. Restrictions of the returning value of the _LID control method
> +
> +The _LID control method is described to return the "current" lid state.
> +However the word of "current" has ambiguity, many AML tables return the lid

Can this be fixed in the next ACPI revision?

> +state upon the last lid notification instead of returning the lid state
> +upon the last _LID evaluation. There won't be difference when the _LID
> +control method is evaluated during the runtime, the problem is its initial
> +returning value. When the AML tables implement this control method with
> +cached value, the initial returning value is likely not reliable. There are
> +simply so many examples always retuning "closed" as initial lid state.
> +
> +2. Restrictions of the lid state change notifications
> +
> +There are many AML tables never notifying when the lid device state is
> +changed to "opened". Thus the "opened" notification is not guaranteed.
> +
> +But it is guaranteed that the AML tables always notify "closed" when the
> +lid state is changed to "closed". The "closed" notification is normally
> +used to trigger some system power saving operations on Windows. Since it is
> +fully tested, the "closed" notification is reliable for all AML tables.
> +
> +3. Expections for the userspace users of the ACPI lid device driver
> +
> +The ACPI button driver exports the lid state to the userspace via the
> +following file:
> +  /proc/acpi/button/lid/LID0/state
> +This file actually calls the _LID control method described above. And given
> +the previous explanation, it is not reliable enough on some platforms. So
> +it is advised for the userspace program to not to solely rely on this file
> +to determine the actual lid state.
> +
> +The ACPI button driver emits 2 kinds of events to the user space:
> +  SW_LID
> +   When the lid state/event is reliable, the userspace can behave
> +   according to this input switch event.
> +   This is a mode prepared for backward compatiblity.
> +  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
> +   When the lid state/event is not reliable, the userspace should behave
> +   according to these 2 input key events.
> +   New userspace programs may only be prepared for the input key events.

No, absolutely not. If some x86 vendors managed to mess up their
firmware implementations that does not mean that everyone now has to
abandon working perfectly well for them SW_LID events and rush to switch
to a brand new event.

Apparently were are a few issues, main is that some systems not reporting
"open" event. This can be dealt with by userspace "writing" to the
lid's evdev device EV_SW/SW_LID/0 event upon system resume (and startup)
for selected systems. This will mean that if system wakes up not because
LID is open we'll incorrectly assume that it is, but we can either add
more smarts to the process emitting SW_LID event or simply say "well,
tough, the hardware is crappy" and bug vendor to see if they can fix the
issue (if not for current firmware them for next).

As an additional workaround, we can toggle the LID switch off and on
when we get notification, much like your proposed patch does for the key
events.

Speaking of ACPI in general, does Intel have a test suite for ACPI
implementors? Could include tests for proper LID behavior?
1. The "swallowing" of input events because kernel state disagrees with
the reality

Thanks.

-- 
Dmitry

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

* Re: [PATCH v4 1/2] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model
  2016-07-21 13:35   ` Rafael J. Wysocki
@ 2016-07-21 20:33     ` Dmitry Torokhov
  0 siblings, 0 replies; 34+ messages in thread
From: Dmitry Torokhov @ 2016-07-21 20:33 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Lv Zheng, Rafael J. Wysocki, Len Brown, Lv Zheng, linux-kernel,
	linux-acpi, Benjamin Tissoires, Bastien Nocera:, linux-input

On Thu, Jul 21, 2016 at 03:35:36PM +0200, Rafael J. Wysocki wrote:
> On Tuesday, July 19, 2016 04:11:02 PM Lv Zheng wrote:
> > There are many AML tables reporting wrong initial lid state, and some of
> > them never report lid open state. As a proxy layer acting between, ACPI
> > button driver is not able to handle all such cases, but need to re-define
> > the usage model of the ACPI lid. That is:
> > 1. It's initial state is not reliable;
> > 2. There may not be an open event;
> > 3. Userspace should only take action against the close event which is
> >    reliable, always sent after a real lid close.
> > 
> > OTOH, using an input switch event for the lid device on such platforms can
> > cause the loss of the close event, but the platforms purposely want to use
> > these close events to trigger power saving actions.
> > 
> > So we need to introduce a new ABI, which is input key events based, not
> > input switch events based.
> > 
> > This patch adds a set of new input key events so that the new userspace
> > programs can use them to handle this usage model correctly. And in the
> > meanwhile, the old input switch event is kept so that no old programs will
> > be broken by the ABI change.
> > 
> > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> > Cc: Bastien Nocera: <hadess@hadess.net>
> > Cc: linux-input@vger.kernel.org
> 
> Dmitry, any objections here?

Yes I have (see the other email).

Thanks.

-- 
Dmitry

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

* RE: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-21 20:32   ` Dmitry Torokhov
@ 2016-07-22  0:24     ` Zheng, Lv
  2016-07-22  4:37       ` Dmitry Torokhov
  0 siblings, 1 reply; 34+ messages in thread
From: Zheng, Lv @ 2016-07-22  0:24 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	Benjamin Tissoires, Bastien Nocera:, linux-input@vger.kernel.org

Hi, Dmitry


Thanks for the review.

> From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control
> method lid device restrictions
> 
> On Tue, Jul 19, 2016 at 04:11:21PM +0800, Lv Zheng wrote:
> > This patch adds documentation for the usage model of the control
> method lid
> > device.
> >
> > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> > Cc: Bastien Nocera: <hadess@hadess.net>
> > Cc: linux-input@vger.kernel.org
> > ---
> >  Documentation/acpi/acpi-lid.txt |   89
> +++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 89 insertions(+)
> >  create mode 100644 Documentation/acpi/acpi-lid.txt
> >
> > diff --git a/Documentation/acpi/acpi-lid.txt b/Documentation/acpi/acpi-
> lid.txt
> > new file mode 100644
> > index 0000000..2addedc
> > --- /dev/null
> > +++ b/Documentation/acpi/acpi-lid.txt
> > @@ -0,0 +1,89 @@
> > +Usage Model of the ACPI Control Method Lid Device
> > +
> > +Copyright (C) 2016, Intel Corporation
> > +Author: Lv Zheng <lv.zheng@intel.com>
> > +
> > +
> > +Abstract:
> > +
> > +Platforms containing lids convey lid state (open/close) to OSPMs using
> a
> > +control method lid device. To implement this, the AML tables issue
> > +Notify(lid_device, 0x80) to notify the OSPMs whenever the lid state has
> > +changed. The _LID control method for the lid device must be
> implemented to
> > +report the "current" state of the lid as either "opened" or "closed".
> > +
> > +This document describes the restrictions and the expections of the
> Linux
> > +ACPI lid device driver.
> > +
> > +
> > +1. Restrictions of the returning value of the _LID control method
> > +
> > +The _LID control method is described to return the "current" lid state.
> > +However the word of "current" has ambiguity, many AML tables return
> the lid
> 
> Can this be fixed in the next ACPI revision?
[Lv Zheng] 
Even this is fixed in the ACPI specification, there are platforms already doing this.
Especially platforms from Microsoft.
So the de-facto standard OS won't care about the change.
And we can still see such platforms.

Here is an example from Surface 3:

DefinitionBlock ("dsdt.aml", "DSDT", 2, "ALASKA", "A M I ", 0x01072009)
{
    Scope (_SB)
    {
        Device (PCI0)
        {
            Name (_HID, EisaId ("PNP0A08"))  // _HID: Hardware ID
            Name (_CID, EisaId ("PNP0A03"))  // _CID: Compatible ID
            Device (SPI1)
            {
                Name (_HID, "8086228E")  // _HID: Hardware ID
                Device (NTRG)
                {
                    Name (_HID, "MSHW0037")  // _HID: Hardware ID
                }
            }
        }

        Device (LID)
        {
            Name (_HID, EisaId ("PNP0C0D"))
            Name (LIDB, Zero)
            Method (_LID, 0, NotSerialized)
            {
                Return (LIDB)
            }
        }

        Device (GPO0)
        {
            Name (_HID, "INT33FF")  // _HID: Hardware ID
            OperationRegion (GPOR, GeneralPurposeIo, Zero, One)
            Field (GPOR, ByteAcc, NoLock, Preserve)
            {
                Connection (
                    GpioIo (Shared, PullNone, 0x0000, 0x0000, IoRestrictionNone,
                        "\\_SB.GPO0", 0x00, ResourceConsumer, ,
                        )
                        {   // Pin list
                            0x004C
                        }
                ), 
                HELD,   1
            }
            Method (_E4C, 0, Serialized)
            {
                If (LEqual(HELD, One))
                {
                    Store(One, ^^LID.LIDB)

There is no "open" event generated by "Surface 3".

                }
                Else
                {
                    Store(Zero, ^^LID.LIDB)
                    Notify (LID, 0x80)

There is only "close" event generated by "Surface 3".
Thus they are not paired.

                }
                Notify (^^PCI0.SPI1.NTRG, One) // Device Check
            }
        }
    }
}

> 
> > +state upon the last lid notification instead of returning the lid state
> > +upon the last _LID evaluation. There won't be difference when the _LID
> > +control method is evaluated during the runtime, the problem is its
> initial
> > +returning value. When the AML tables implement this control method
> with
> > +cached value, the initial returning value is likely not reliable. There are
> > +simply so many examples always retuning "closed" as initial lid state.
> > +
> > +2. Restrictions of the lid state change notifications
> > +
> > +There are many AML tables never notifying when the lid device state is
> > +changed to "opened". Thus the "opened" notification is not guaranteed.
> > +
> > +But it is guaranteed that the AML tables always notify "closed" when
> the
> > +lid state is changed to "closed". The "closed" notification is normally
> > +used to trigger some system power saving operations on Windows.
> Since it is
> > +fully tested, the "closed" notification is reliable for all AML tables.
> > +
> > +3. Expections for the userspace users of the ACPI lid device driver
> > +
> > +The ACPI button driver exports the lid state to the userspace via the
> > +following file:
> > +  /proc/acpi/button/lid/LID0/state
> > +This file actually calls the _LID control method described above. And
> given
> > +the previous explanation, it is not reliable enough on some platforms.
> So
> > +it is advised for the userspace program to not to solely rely on this file
> > +to determine the actual lid state.
> > +
> > +The ACPI button driver emits 2 kinds of events to the user space:
> > +  SW_LID
> > +   When the lid state/event is reliable, the userspace can behave
> > +   according to this input switch event.
> > +   This is a mode prepared for backward compatiblity.
> > +  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
> > +   When the lid state/event is not reliable, the userspace should behave
> > +   according to these 2 input key events.
> > +   New userspace programs may only be prepared for the input key
> events.
> 
> No, absolutely not. If some x86 vendors managed to mess up their
> firmware implementations that does not mean that everyone now has to
> abandon working perfectly well for them SW_LID events and rush to
> switch
> to a brand new event.
[Lv Zheng] 
However there is no clear wording in the ACPI specification asking the vendors to achieve paired lid events.

> 
> Apparently were are a few issues, main is that some systems not reporting
> "open" event. This can be dealt with by userspace "writing" to the
> lid's evdev device EV_SW/SW_LID/0 event upon system resume (and
> startup)
> for selected systems. This will mean that if system wakes up not because
> LID is open we'll incorrectly assume that it is, but we can either add
> more smarts to the process emitting SW_LID event or simply say "well,
> tough, the hardware is crappy" and bug vendor to see if they can fix the
> issue (if not for current firmware them for next).
[Lv Zheng] 
The problem is there is no vendor actually caring about fixing this "issue".
Because Windows works well with their firmware.
Then finally becomes a big table customization business for our team.

> 
> As an additional workaround, we can toggle the LID switch off and on
> when we get notification, much like your proposed patch does for the key
> events.
[Lv Zheng] 
I think this is doable, I'll refresh my patchset to address your this comment.
By inserting open/close events when next close/open event arrives after a certain period,
this may fix some issues for the old programs.
Where user may be required to open/close lid twice to trigger 2nd suspend.

However, this still cannot fix the problems like "Surface 3".
We'll still need a new usage model for such platforms (no open event).
I'll send the next version out today, hope you can take a look to see if it's acceptable from your point of view.

> 
> Speaking of ACPI in general, does Intel have a test suite for ACPI
> implementors? Could include tests for proper LID behavior?
> 1. The "swallowing" of input events because kernel state disagrees with
> the reality
[Lv Zheng] 
I think there is test suit in UEFI forum can cover this.
However, most of the firmware vendors will just test their firmware with Windows.

Thanks
-Lv

> 
> Thanks.
> 
> --
> Dmitry

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

* Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-22  0:24     ` Zheng, Lv
@ 2016-07-22  4:37       ` Dmitry Torokhov
  2016-07-22  6:55         ` Benjamin Tissoires
  2016-07-22  8:37         ` Zheng, Lv
  0 siblings, 2 replies; 34+ messages in thread
From: Dmitry Torokhov @ 2016-07-22  4:37 UTC (permalink / raw)
  To: Zheng, Lv
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	Benjamin Tissoires, Bastien Nocera:, linux-input@vger.kernel.org

Hi Lv,

On Fri, Jul 22, 2016 at 12:24:50AM +0000, Zheng, Lv wrote:
> Hi, Dmitry
> 
> 
> Thanks for the review.
> 
> > From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> > Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control
> > method lid device restrictions
> > 
> > On Tue, Jul 19, 2016 at 04:11:21PM +0800, Lv Zheng wrote:
> > > This patch adds documentation for the usage model of the control
> > method lid
> > > device.
> > >
> > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> > > Cc: Bastien Nocera: <hadess@hadess.net>
> > > Cc: linux-input@vger.kernel.org
> > > ---
> > >  Documentation/acpi/acpi-lid.txt |   89
> > +++++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 89 insertions(+)
> > >  create mode 100644 Documentation/acpi/acpi-lid.txt
> > >
> > > diff --git a/Documentation/acpi/acpi-lid.txt b/Documentation/acpi/acpi-
> > lid.txt
> > > new file mode 100644
> > > index 0000000..2addedc
> > > --- /dev/null
> > > +++ b/Documentation/acpi/acpi-lid.txt
> > > @@ -0,0 +1,89 @@
> > > +Usage Model of the ACPI Control Method Lid Device
> > > +
> > > +Copyright (C) 2016, Intel Corporation
> > > +Author: Lv Zheng <lv.zheng@intel.com>
> > > +
> > > +
> > > +Abstract:
> > > +
> > > +Platforms containing lids convey lid state (open/close) to OSPMs using
> > a
> > > +control method lid device. To implement this, the AML tables issue
> > > +Notify(lid_device, 0x80) to notify the OSPMs whenever the lid state has
> > > +changed. The _LID control method for the lid device must be
> > implemented to
> > > +report the "current" state of the lid as either "opened" or "closed".
> > > +
> > > +This document describes the restrictions and the expections of the
> > Linux
> > > +ACPI lid device driver.
> > > +
> > > +
> > > +1. Restrictions of the returning value of the _LID control method
> > > +
> > > +The _LID control method is described to return the "current" lid state.
> > > +However the word of "current" has ambiguity, many AML tables return
> > the lid
> > 
> > Can this be fixed in the next ACPI revision?
> [Lv Zheng] 
> Even this is fixed in the ACPI specification, there are platforms already doing this.
> Especially platforms from Microsoft.
> So the de-facto standard OS won't care about the change.
> And we can still see such platforms.
> 
> Here is an example from Surface 3:
> 
> DefinitionBlock ("dsdt.aml", "DSDT", 2, "ALASKA", "A M I ", 0x01072009)
> {
>     Scope (_SB)
>     {
>         Device (PCI0)
>         {
>             Name (_HID, EisaId ("PNP0A08"))  // _HID: Hardware ID
>             Name (_CID, EisaId ("PNP0A03"))  // _CID: Compatible ID
>             Device (SPI1)
>             {
>                 Name (_HID, "8086228E")  // _HID: Hardware ID
>                 Device (NTRG)
>                 {
>                     Name (_HID, "MSHW0037")  // _HID: Hardware ID
>                 }
>             }
>         }
> 
>         Device (LID)
>         {
>             Name (_HID, EisaId ("PNP0C0D"))
>             Name (LIDB, Zero)

Start with lid closed? In any case might be wrong.

>             Method (_LID, 0, NotSerialized)
>             {
>                 Return (LIDB)

So "_LID" returns the last state read by "_EC4". "_EC4" is
edge-triggered and will be evaluated every time gpio changes state.

>             }
>         }
> 
>         Device (GPO0)
>         {
>             Name (_HID, "INT33FF")  // _HID: Hardware ID
>             OperationRegion (GPOR, GeneralPurposeIo, Zero, One)
>             Field (GPOR, ByteAcc, NoLock, Preserve)
>             {
>                 Connection (
>                     GpioIo (Shared, PullNone, 0x0000, 0x0000, IoRestrictionNone,
>                         "\\_SB.GPO0", 0x00, ResourceConsumer, ,
>                         )
>                         {   // Pin list
>                             0x004C
>                         }
>                 ), 
>                 HELD,   1

Is it possible to read state of this GPIO from userspace on startup to
correct the initial state?

>             }
>             Method (_E4C, 0, Serialized)
>             {
>                 If (LEqual(HELD, One))
>                 {
>                     Store(One, ^^LID.LIDB)
> 
> There is no "open" event generated by "Surface 3".

Right so we update the state correctly, we just forgot to send the
notification. Nothing that polling can't fix.

> 
>                 }
>                 Else
>                 {
>                     Store(Zero, ^^LID.LIDB)
>                     Notify (LID, 0x80)
> 
> There is only "close" event generated by "Surface 3".
> Thus they are not paired.
> 
>                 }
>                 Notify (^^PCI0.SPI1.NTRG, One) // Device Check
>             }
>         }
>     }
> }
> 
> > 
> > > +state upon the last lid notification instead of returning the lid state
> > > +upon the last _LID evaluation. There won't be difference when the _LID
> > > +control method is evaluated during the runtime, the problem is its
> > initial
> > > +returning value. When the AML tables implement this control method
> > with
> > > +cached value, the initial returning value is likely not reliable. There are
> > > +simply so many examples always retuning "closed" as initial lid state.
> > > +
> > > +2. Restrictions of the lid state change notifications
> > > +
> > > +There are many AML tables never notifying when the lid device state is
> > > +changed to "opened". Thus the "opened" notification is not guaranteed.
> > > +
> > > +But it is guaranteed that the AML tables always notify "closed" when
> > the
> > > +lid state is changed to "closed". The "closed" notification is normally
> > > +used to trigger some system power saving operations on Windows.
> > Since it is
> > > +fully tested, the "closed" notification is reliable for all AML tables.
> > > +
> > > +3. Expections for the userspace users of the ACPI lid device driver
> > > +
> > > +The ACPI button driver exports the lid state to the userspace via the
> > > +following file:
> > > +  /proc/acpi/button/lid/LID0/state
> > > +This file actually calls the _LID control method described above. And
> > given
> > > +the previous explanation, it is not reliable enough on some platforms.
> > So
> > > +it is advised for the userspace program to not to solely rely on this file
> > > +to determine the actual lid state.
> > > +
> > > +The ACPI button driver emits 2 kinds of events to the user space:
> > > +  SW_LID
> > > +   When the lid state/event is reliable, the userspace can behave
> > > +   according to this input switch event.
> > > +   This is a mode prepared for backward compatiblity.
> > > +  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
> > > +   When the lid state/event is not reliable, the userspace should behave
> > > +   according to these 2 input key events.
> > > +   New userspace programs may only be prepared for the input key
> > events.
> > 
> > No, absolutely not. If some x86 vendors managed to mess up their
> > firmware implementations that does not mean that everyone now has to
> > abandon working perfectly well for them SW_LID events and rush to
> > switch
> > to a brand new event.
> [Lv Zheng] 
> However there is no clear wording in the ACPI specification asking the vendors to achieve paired lid events.
> 
> > 
> > Apparently were are a few issues, main is that some systems not reporting
> > "open" event. This can be dealt with by userspace "writing" to the
> > lid's evdev device EV_SW/SW_LID/0 event upon system resume (and
> > startup)
> > for selected systems. This will mean that if system wakes up not because
> > LID is open we'll incorrectly assume that it is, but we can either add
> > more smarts to the process emitting SW_LID event or simply say "well,
> > tough, the hardware is crappy" and bug vendor to see if they can fix the
> > issue (if not for current firmware them for next).
> [Lv Zheng] 
> The problem is there is no vendor actually caring about fixing this "issue".
> Because Windows works well with their firmware.
> Then finally becomes a big table customization business for our team.

Well, OK. But you do not expect that we will redo up and down the stack
lid handling just because MS messed up DSDT on Surface 3? No, let them
know (they now care about Linux, right?) so Surface 4 works and quirk
the behavior for Surface 3.

> 
> > 
> > As an additional workaround, we can toggle the LID switch off and on
> > when we get notification, much like your proposed patch does for the key
> > events.
> [Lv Zheng] 
> I think this is doable, I'll refresh my patchset to address your this comment.
> By inserting open/close events when next close/open event arrives after a certain period,
> this may fix some issues for the old programs.
> Where user may be required to open/close lid twice to trigger 2nd suspend.
> 
> However, this still cannot fix the problems like "Surface 3".
> We'll still need a new usage model for such platforms (no open event).

No, for surface 3 you simply need to add polling of "_LID" method to the
button driver.

What are the other devices that mess up lid handling?

Thanks.

-- 
Dmitry

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

* [PATCH v5 1/3] ACPI / button: Add missing event to keep SW_LID running without additional event loss
       [not found] <cbdaec17aba78c61f466efff8883d49067f2dad5.1463472125.git.lv.zheng@intel.com>
  2016-07-19  8:11 ` [PATCH v4 1/2] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model Lv Zheng
  2016-07-19  8:11 ` [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng
@ 2016-07-22  6:24 ` Lv Zheng
  2016-07-22 10:26   ` Zheng, Lv
  2016-07-23 12:37   ` Rafael J. Wysocki
  2016-07-22  6:24 ` [PATCH v5 2/3] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model Lv Zheng
                   ` (6 subsequent siblings)
  9 siblings, 2 replies; 34+ messages in thread
From: Lv Zheng @ 2016-07-22  6:24 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi, Dmitry Torokhov,
	Benjamin Tissoires, Bastien Nocera:, linux-input

There are several possibilities that a lid event can be lost. For example,
EC event queue full, or the resume order of the underlying drivers.

When the event loss happens, new event may also be lost due to the type of
the SW_LID (switch event). The 2nd loss is what we want to avoid.

This patch adds a mechanism to insert lid events as a compensation for the
switch event nature of the lid events in order to avoid the 2nd loss.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Cc: Bastien Nocera: <hadess@hadess.net>
Cc: linux-input@vger.kernel.org
---
 drivers/acpi/button.c |   21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 148f4e5..41fd21d 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -104,6 +104,8 @@ struct acpi_button {
 	struct input_dev *input;
 	char phys[32];			/* for input device */
 	unsigned long pushed;
+	int sw_last_state;
+	unsigned long sw_last_time;
 	bool suspended;
 };
 
@@ -111,6 +113,10 @@ static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
 static struct acpi_device *lid_device;
 static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
 
+static unsigned long lid_report_interval __read_mostly = 500;
+module_param(lid_report_interval, ulong, 0644);
+MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
+
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
@@ -133,11 +139,22 @@ static int acpi_lid_evaluate_state(struct acpi_device *device)
 static int acpi_lid_notify_state(struct acpi_device *device, int state)
 {
 	struct acpi_button *button = acpi_driver_data(device);
+	unsigned long sw_tout;
 	int ret;
 
-	/* input layer checks if event is redundant */
+	/* Send the switch event */
+	sw_tout = button->sw_last_time +
+		  msecs_to_jiffies(lid_report_interval);
+	if (time_after(jiffies, sw_tout) &&
+	    (button->sw_last_state == !!state)) {
+		/* Send the complement switch event */
+		input_report_switch(button->input, SW_LID, state);
+		input_sync(button->input);
+	}
 	input_report_switch(button->input, SW_LID, !state);
 	input_sync(button->input);
+	button->sw_last_state = !!state;
+	button->sw_last_time = jiffies;
 
 	if (state)
 		pm_wakeup_event(&device->dev, 0);
@@ -407,6 +424,8 @@ static int acpi_button_add(struct acpi_device *device)
 		strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
 		sprintf(class, "%s/%s",
 			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
+		button->sw_last_state = !!acpi_lid_evaluate_state(device);
+		button->sw_last_time = jiffies;
 	} else {
 		printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
 		error = -ENODEV;
-- 
1.7.10

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

* [PATCH v5 2/3] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model
       [not found] <cbdaec17aba78c61f466efff8883d49067f2dad5.1463472125.git.lv.zheng@intel.com>
                   ` (2 preceding siblings ...)
  2016-07-22  6:24 ` [PATCH v5 1/3] ACPI / button: Add missing event to keep SW_LID running without additional event loss Lv Zheng
@ 2016-07-22  6:24 ` Lv Zheng
  2016-07-22  6:24 ` [PATCH v5 3/3] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 34+ messages in thread
From: Lv Zheng @ 2016-07-22  6:24 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi, Dmitry Torokhov,
	Bastien Nocera:, linux-input

There are many AML tables reporting wrong initial lid state (Link 1), and
some of them never report lid open state (Link 2). For example, lid
notifications on Surface 3 are as follows (no open event):
    Method (_E4C, 0, Serialized)
    {
        If (LEqual(HELD, One))
        {
            Store(One, ^^LID.LIDB)
        }
        Else
        {
            Store(Zero, ^^LID.LIDB)
            Notify (LID, 0x80)
        }
    }
For the first issue, we can work it around via reporting forced initial
"open" state (however, it is apparently still not reliable) and sending
complement switch events.
For the second issue, it is totally a different usage model than the switch
event type because the switch event type requires the driver to send paired
events while the events is naturally not paired on this platform. There is
only one case that the lid driver can help to make a paired events on such
platforms: if the "lid close" is used to trigger system pending, then the
driver can report a forced "lid open" via resume callback. But if "lid
close" is not used to trigger system suspending, then the lid driver can
never have a chance to make the events paired. And an even worse thing is
the forced value breaks some use cases (e.x., dark resume).

As a proxy layer acting between, ACPI button driver is not able to handle
all such platform designed cases via Linux input switch events, but need to
re-define the usage model of the ACPI lid. That is:
1. It's initial state is not reliable;
2. There may not be an open event;
3. Userspace should only take action against the close event which is
   reliable, always sent after a real lid close.

So we need to introduce a new ABI, which is input key events based, not
input switch events based. And this usage model could help to ensure a
reliable lid state during runtime. Adopting with this usage model, the
platform firmware has been facilitated to have the maximum possibilities to
force the hosting OS to behave as what they want.

This patch adds a set of new input key events so that the new userspace
programs can use them to handle this usage model correctly. And in the
meanwhile, the old input switch event is kept so that no old programs will
be broken by the ABI change.

Link 1: https://bugzilla.kernel.org/show_bug.cgi?id=89211
        https://bugzilla.kernel.org/show_bug.cgi?id=106151
Link 2: https://bugzilla.kernel.org/show_bug.cgi?id=106941
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Bastien Nocera: <hadess@hadess.net>
Cc: linux-input@vger.kernel.org
---
 drivers/acpi/button.c                  |   26 +++++++++++++++++++++++---
 include/uapi/linux/input-event-codes.h |    7 +++++++
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 41fd21d..c5fd793 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -106,6 +106,8 @@ struct acpi_button {
 	unsigned long pushed;
 	int sw_last_state;
 	unsigned long sw_last_time;
+	int key_last_state;
+	unsigned long key_last_time;
 	bool suspended;
 };
 
@@ -139,7 +141,8 @@ static int acpi_lid_evaluate_state(struct acpi_device *device)
 static int acpi_lid_notify_state(struct acpi_device *device, int state)
 {
 	struct acpi_button *button = acpi_driver_data(device);
-	unsigned long sw_tout;
+	int keycode;
+	unsigned long sw_tout, key_tout;
 	int ret;
 
 	/* Send the switch event */
@@ -156,6 +159,20 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
 	button->sw_last_state = !!state;
 	button->sw_last_time = jiffies;
 
+	/* Send the key event */
+	key_tout = button->key_last_time +
+		   msecs_to_jiffies(lid_report_interval);
+	if (time_after(jiffies, key_tout) ||
+	    (button->key_last_state != !!state)) {
+		keycode = state ? KEY_LID_OPEN : KEY_LID_CLOSE;
+		input_report_key(button->input, keycode, 1);
+		input_sync(button->input);
+		input_report_key(button->input, keycode, 0);
+		input_sync(button->input);
+		button->key_last_state = !!state;
+		button->key_last_time = jiffies;
+	}
+
 	if (state)
 		pm_wakeup_event(&device->dev, 0);
 
@@ -424,8 +441,9 @@ static int acpi_button_add(struct acpi_device *device)
 		strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
 		sprintf(class, "%s/%s",
 			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
-		button->sw_last_state = !!acpi_lid_evaluate_state(device);
-		button->sw_last_time = jiffies;
+		button->sw_last_state = button->key_last_state =
+			!!acpi_lid_evaluate_state(device);
+		button->sw_last_time = button->key_last_time = jiffies;
 	} else {
 		printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
 		error = -ENODEV;
@@ -455,6 +473,8 @@ static int acpi_button_add(struct acpi_device *device)
 
 	case ACPI_BUTTON_TYPE_LID:
 		input_set_capability(input, EV_SW, SW_LID);
+		input_set_capability(input, EV_KEY, KEY_LID_OPEN);
+		input_set_capability(input, EV_KEY, KEY_LID_CLOSE);
 		break;
 	}
 
diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h
index 737fa32..b062fe1 100644
--- a/include/uapi/linux/input-event-codes.h
+++ b/include/uapi/linux/input-event-codes.h
@@ -641,6 +641,13 @@
  * e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.)
  */
 #define KEY_DATA			0x275
+/*
+ * Key events sent by the lid drivers.
+ * The drivers may not be able to send paired "open"/"close" events, in
+ * which case, they send KEY_LID_OPEN/KEY_LID_CLOSE instead of SW_LID.
+ */
+#define KEY_LID_OPEN			0x278
+#define KEY_LID_CLOSE			0x279
 
 #define BTN_TRIGGER_HAPPY		0x2c0
 #define BTN_TRIGGER_HAPPY1		0x2c0
-- 
1.7.10


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

* [PATCH v5 3/3] ACPI / button: Add document for ACPI control method lid device restrictions
       [not found] <cbdaec17aba78c61f466efff8883d49067f2dad5.1463472125.git.lv.zheng@intel.com>
                   ` (3 preceding siblings ...)
  2016-07-22  6:24 ` [PATCH v5 2/3] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model Lv Zheng
@ 2016-07-22  6:24 ` Lv Zheng
  2016-07-25  1:14 ` [PATCH v6] ACPI / button: Fix an issue that the platform triggered "close" event may not be delivered to the userspace Lv Zheng
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 34+ messages in thread
From: Lv Zheng @ 2016-07-22  6:24 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi, Dmitry Torokhov,
	Bastien Nocera:, linux-input

This patch adds documentation for the usage model of the control method lid
device.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Acked-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Bastien Nocera: <hadess@hadess.net>
Cc: linux-input@vger.kernel.org
---
 Documentation/acpi/acpi-lid.txt |   89 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 89 insertions(+)
 create mode 100644 Documentation/acpi/acpi-lid.txt

diff --git a/Documentation/acpi/acpi-lid.txt b/Documentation/acpi/acpi-lid.txt
new file mode 100644
index 0000000..2addedc
--- /dev/null
+++ b/Documentation/acpi/acpi-lid.txt
@@ -0,0 +1,89 @@
+Usage Model of the ACPI Control Method Lid Device
+
+Copyright (C) 2016, Intel Corporation
+Author: Lv Zheng <lv.zheng@intel.com>
+
+
+Abstract:
+
+Platforms containing lids convey lid state (open/close) to OSPMs using a
+control method lid device. To implement this, the AML tables issue
+Notify(lid_device, 0x80) to notify the OSPMs whenever the lid state has
+changed. The _LID control method for the lid device must be implemented to
+report the "current" state of the lid as either "opened" or "closed".
+
+This document describes the restrictions and the expections of the Linux
+ACPI lid device driver.
+
+
+1. Restrictions of the returning value of the _LID control method
+
+The _LID control method is described to return the "current" lid state.
+However the word of "current" has ambiguity, many AML tables return the lid
+state upon the last lid notification instead of returning the lid state
+upon the last _LID evaluation. There won't be difference when the _LID
+control method is evaluated during the runtime, the problem is its initial
+returning value. When the AML tables implement this control method with
+cached value, the initial returning value is likely not reliable. There are
+simply so many examples always retuning "closed" as initial lid state.
+
+2. Restrictions of the lid state change notifications
+
+There are many AML tables never notifying when the lid device state is
+changed to "opened". Thus the "opened" notification is not guaranteed.
+
+But it is guaranteed that the AML tables always notify "closed" when the
+lid state is changed to "closed". The "closed" notification is normally
+used to trigger some system power saving operations on Windows. Since it is
+fully tested, the "closed" notification is reliable for all AML tables.
+
+3. Expections for the userspace users of the ACPI lid device driver
+
+The ACPI button driver exports the lid state to the userspace via the
+following file:
+  /proc/acpi/button/lid/LID0/state
+This file actually calls the _LID control method described above. And given
+the previous explanation, it is not reliable enough on some platforms. So
+it is advised for the userspace program to not to solely rely on this file
+to determine the actual lid state.
+
+The ACPI button driver emits 2 kinds of events to the user space:
+  SW_LID
+   When the lid state/event is reliable, the userspace can behave
+   according to this input switch event.
+   This is a mode prepared for backward compatiblity.
+  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
+   When the lid state/event is not reliable, the userspace should behave
+   according to these 2 input key events.
+   New userspace programs may only be prepared for the input key events.
+
+If the userspace hasn't been prepared to handle the new input lid key
+events, Linux users can use the following kernel parameters to handle the
+possible issues triggered because of the unreliable lid state/event:
+A. button.lid_init_state=method:
+   When this option is specified, the ACPI button driver reports the
+   initial lid state using the returning value of the _LID control method.
+   This option can be used to fix some platforms where the _LID control
+   method's returning value is reliable but the initial lid state
+   notification is missing.
+   This option is the default behavior during the period the userspace
+   isn't ready to handle the new usage model.
+B. button.lid_init_state=open:
+   When this option is specified, the ACPI button driver always reports the
+   initial lid state as "opened".
+   This may fix some platforms where the returning value of the _LID
+   control method is not reliable and the initial lid state notification is
+   missing.
+
+If the userspace has been prepared to handle the new input lid key events,
+Linux users should always use the following kernel parameter:
+C. button.lid_init_state=ignore:
+   When this option is specified, the ACPI button driver never reports the
+   initial lid state. However, the platform may automatically report a
+   correct initial lid state and there is no "open" event missing. When
+   this is the case (everything is correctly implemented by the platform
+   firmware), the old input switch event based userspace can still work.
+   Otherwise, the userspace programs may only work based on the input key
+   events.
+   This option will be the default behavior after the userspace is ready to
+   handle the new usage model.
-- 
1.7.10


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

* Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-22  4:37       ` Dmitry Torokhov
@ 2016-07-22  6:55         ` Benjamin Tissoires
  2016-07-22  8:47           ` Zheng, Lv
  2016-07-22 17:02           ` Dmitry Torokhov
  2016-07-22  8:37         ` Zheng, Lv
  1 sibling, 2 replies; 34+ messages in thread
From: Benjamin Tissoires @ 2016-07-22  6:55 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Zheng, Lv, Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len,
	Lv Zheng, linux-kernel@vger.kernel.org,
	linux-acpi@vger.kernel.org, Bastien Nocera:,
	linux-input@vger.kernel.org

On Fri, Jul 22, 2016 at 6:37 AM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> Hi Lv,
>
> On Fri, Jul 22, 2016 at 12:24:50AM +0000, Zheng, Lv wrote:
>> Hi, Dmitry
>>
>>
>> Thanks for the review.
>>
>> > From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
>> > Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control
>> > method lid device restrictions
>> >
>> > On Tue, Jul 19, 2016 at 04:11:21PM +0800, Lv Zheng wrote:
>> > > This patch adds documentation for the usage model of the control
>> > method lid
>> > > device.
>> > >
>> > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
>> > > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>> > > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
>> > > Cc: Bastien Nocera: <hadess@hadess.net>
>> > > Cc: linux-input@vger.kernel.org
>> > > ---
>> > >  Documentation/acpi/acpi-lid.txt |   89
>> > +++++++++++++++++++++++++++++++++++++++
>> > >  1 file changed, 89 insertions(+)
>> > >  create mode 100644 Documentation/acpi/acpi-lid.txt
>> > >
>> > > diff --git a/Documentation/acpi/acpi-lid.txt b/Documentation/acpi/acpi-
>> > lid.txt
>> > > new file mode 100644
>> > > index 0000000..2addedc
>> > > --- /dev/null
>> > > +++ b/Documentation/acpi/acpi-lid.txt
>> > > @@ -0,0 +1,89 @@
>> > > +Usage Model of the ACPI Control Method Lid Device
>> > > +
>> > > +Copyright (C) 2016, Intel Corporation
>> > > +Author: Lv Zheng <lv.zheng@intel.com>
>> > > +
>> > > +
>> > > +Abstract:
>> > > +
>> > > +Platforms containing lids convey lid state (open/close) to OSPMs using
>> > a
>> > > +control method lid device. To implement this, the AML tables issue
>> > > +Notify(lid_device, 0x80) to notify the OSPMs whenever the lid state has
>> > > +changed. The _LID control method for the lid device must be
>> > implemented to
>> > > +report the "current" state of the lid as either "opened" or "closed".
>> > > +
>> > > +This document describes the restrictions and the expections of the
>> > Linux
>> > > +ACPI lid device driver.
>> > > +
>> > > +
>> > > +1. Restrictions of the returning value of the _LID control method
>> > > +
>> > > +The _LID control method is described to return the "current" lid state.
>> > > +However the word of "current" has ambiguity, many AML tables return
>> > the lid
>> >
>> > Can this be fixed in the next ACPI revision?
>> [Lv Zheng]
>> Even this is fixed in the ACPI specification, there are platforms already doing this.
>> Especially platforms from Microsoft.
>> So the de-facto standard OS won't care about the change.
>> And we can still see such platforms.
>>
>> Here is an example from Surface 3:
>>
>> DefinitionBlock ("dsdt.aml", "DSDT", 2, "ALASKA", "A M I ", 0x01072009)
>> {
>>     Scope (_SB)
>>     {
>>         Device (PCI0)
>>         {
>>             Name (_HID, EisaId ("PNP0A08"))  // _HID: Hardware ID
>>             Name (_CID, EisaId ("PNP0A03"))  // _CID: Compatible ID
>>             Device (SPI1)
>>             {
>>                 Name (_HID, "8086228E")  // _HID: Hardware ID
>>                 Device (NTRG)
>>                 {
>>                     Name (_HID, "MSHW0037")  // _HID: Hardware ID
>>                 }
>>             }
>>         }
>>
>>         Device (LID)
>>         {
>>             Name (_HID, EisaId ("PNP0C0D"))
>>             Name (LIDB, Zero)
>
> Start with lid closed? In any case might be wrong.

Actually the initial value doesn't matter if the gpiochip triggers the
_EC4 at boot, which it should
(https://github.com/hadess/fedora-surface3-kernel/commit/13200f81662c1c0b58137947c3e6c000fe62a2ba,
still unsubmitted)

>
>>             Method (_LID, 0, NotSerialized)
>>             {
>>                 Return (LIDB)
>
> So "_LID" returns the last state read by "_EC4". "_EC4" is
> edge-triggered and will be evaluated every time gpio changes state.

That's assuming the change happens while the system is on. If you go
into suspend by closing the LID. Open it while on suspend and then hit
the power button given that the system doesn't wake up when the lid is
opened, the edge change was made while the system is asleep, and we
are screwed (from an ACPI point of view). See my next comment for a
solution.

>
>>             }
>>         }
>>
>>         Device (GPO0)
>>         {
>>             Name (_HID, "INT33FF")  // _HID: Hardware ID
>>             OperationRegion (GPOR, GeneralPurposeIo, Zero, One)
>>             Field (GPOR, ByteAcc, NoLock, Preserve)
>>             {
>>                 Connection (
>>                     GpioIo (Shared, PullNone, 0x0000, 0x0000, IoRestrictionNone,
>>                         "\\_SB.GPO0", 0x00, ResourceConsumer, ,
>>                         )
>>                         {   // Pin list
>>                             0x004C
>>                         }
>>                 ),
>>                 HELD,   1
>
> Is it possible to read state of this GPIO from userspace on startup to
> correct the initial state?
>
>>             }
>>             Method (_E4C, 0, Serialized)
>>             {
>>                 If (LEqual(HELD, One))
>>                 {
>>                     Store(One, ^^LID.LIDB)
>>
>> There is no "open" event generated by "Surface 3".
>
> Right so we update the state correctly, we just forgot to send the
> notification. Nothing that polling can't fix.

Actually, I have a better (though more hackish) way of avoiding polling:
https://github.com/hadess/fedora-surface3-kernel/blob/5e5775b9bdc308d665064387e0b144ee48e7b243/0002-WIP-add-custom-surface3-platform-device-for-controll.patch

Given that the notification is forwarded to the touchscreen anyway, we
can unregister the generic (and buggy) acpi button driver for the LID
and create our own based on this specific DSDT.
We can also make sure the LID state is also correct because of the WMI
method which allows to read the actual value of the GPIO connected to
the cover without using the cached (and most of the time wrong) acpi
LID.LIDB value.

I still yet have to submit this, but with this patch, but we can
consider the Surface 3 as working and not an issue anymore.

>
>>
>>                 }
>>                 Else
>>                 {
>>                     Store(Zero, ^^LID.LIDB)
>>                     Notify (LID, 0x80)
>>
>> There is only "close" event generated by "Surface 3".
>> Thus they are not paired.
>>
>>                 }
>>                 Notify (^^PCI0.SPI1.NTRG, One) // Device Check
>>             }
>>         }
>>     }
>> }
>>
>> >
>> > > +state upon the last lid notification instead of returning the lid state
>> > > +upon the last _LID evaluation. There won't be difference when the _LID
>> > > +control method is evaluated during the runtime, the problem is its
>> > initial
>> > > +returning value. When the AML tables implement this control method
>> > with
>> > > +cached value, the initial returning value is likely not reliable. There are
>> > > +simply so many examples always retuning "closed" as initial lid state.
>> > > +
>> > > +2. Restrictions of the lid state change notifications
>> > > +
>> > > +There are many AML tables never notifying when the lid device state is
>> > > +changed to "opened". Thus the "opened" notification is not guaranteed.
>> > > +
>> > > +But it is guaranteed that the AML tables always notify "closed" when
>> > the
>> > > +lid state is changed to "closed". The "closed" notification is normally
>> > > +used to trigger some system power saving operations on Windows.
>> > Since it is
>> > > +fully tested, the "closed" notification is reliable for all AML tables.
>> > > +
>> > > +3. Expections for the userspace users of the ACPI lid device driver
>> > > +
>> > > +The ACPI button driver exports the lid state to the userspace via the
>> > > +following file:
>> > > +  /proc/acpi/button/lid/LID0/state
>> > > +This file actually calls the _LID control method described above. And
>> > given
>> > > +the previous explanation, it is not reliable enough on some platforms.
>> > So
>> > > +it is advised for the userspace program to not to solely rely on this file
>> > > +to determine the actual lid state.
>> > > +
>> > > +The ACPI button driver emits 2 kinds of events to the user space:
>> > > +  SW_LID
>> > > +   When the lid state/event is reliable, the userspace can behave
>> > > +   according to this input switch event.
>> > > +   This is a mode prepared for backward compatiblity.
>> > > +  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
>> > > +   When the lid state/event is not reliable, the userspace should behave
>> > > +   according to these 2 input key events.
>> > > +   New userspace programs may only be prepared for the input key
>> > events.
>> >
>> > No, absolutely not. If some x86 vendors managed to mess up their
>> > firmware implementations that does not mean that everyone now has to
>> > abandon working perfectly well for them SW_LID events and rush to
>> > switch
>> > to a brand new event.
>> [Lv Zheng]
>> However there is no clear wording in the ACPI specification asking the vendors to achieve paired lid events.
>>
>> >
>> > Apparently were are a few issues, main is that some systems not reporting
>> > "open" event. This can be dealt with by userspace "writing" to the
>> > lid's evdev device EV_SW/SW_LID/0 event upon system resume (and
>> > startup)
>> > for selected systems. This will mean that if system wakes up not because
>> > LID is open we'll incorrectly assume that it is, but we can either add
>> > more smarts to the process emitting SW_LID event or simply say "well,
>> > tough, the hardware is crappy" and bug vendor to see if they can fix the
>> > issue (if not for current firmware them for next).
>> [Lv Zheng]
>> The problem is there is no vendor actually caring about fixing this "issue".
>> Because Windows works well with their firmware.
>> Then finally becomes a big table customization business for our team.
>
> Well, OK. But you do not expect that we will redo up and down the stack
> lid handling just because MS messed up DSDT on Surface 3? No, let them
> know (they now care about Linux, right?) so Surface 4 works and quirk
> the behavior for Surface 3.
>

>From what I understood, it was more than just the Surface 3. Other
laptops were having issues and Lv's team gave up on fixing those
machines.

>>
>> >
>> > As an additional workaround, we can toggle the LID switch off and on
>> > when we get notification, much like your proposed patch does for the key
>> > events.

I really don't like this approach. The problem being that we will fix
the notifications to user space, but nothing will tell userspace that
the LID state is known to be wrong.
OTOH, I already agreed for a hwdb in userspace so I guess this point is moot.

Having both events (one SW for reliable HW, always correct, and one
KEY for unreliable HW) allows userspace to make a clear distinction
between the working and non working events and they can continue to
keep using the polling of the SW node without extra addition.

Anyway, if the kernel doesn't want to (or can't) fix the actual issue
(by making sure the DSDT is reliable), userspace needs to be changed
so any solution will be acceptable.

>> [Lv Zheng]
>> I think this is doable, I'll refresh my patchset to address your this comment.
>> By inserting open/close events when next close/open event arrives after a certain period,
>> this may fix some issues for the old programs.
>> Where user may be required to open/close lid twice to trigger 2nd suspend.
>>
>> However, this still cannot fix the problems like "Surface 3".
>> We'll still need a new usage model for such platforms (no open event).
>
> No, for surface 3 you simply need to add polling of "_LID" method to the
> button driver.
>
> What are the other devices that mess up lid handling?
>

I also would be interested in knowing how much issues you are facing
compared to the average number of "good" laptops. IIRC, you talked
about 3 (counting the Surface 3), but I believe you had more in mind.

Cheers,
Benjamin

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

* RE: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-22  4:37       ` Dmitry Torokhov
  2016-07-22  6:55         ` Benjamin Tissoires
@ 2016-07-22  8:37         ` Zheng, Lv
  2016-07-22 17:22           ` Dmitry Torokhov
  1 sibling, 1 reply; 34+ messages in thread
From: Zheng, Lv @ 2016-07-22  8:37 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	Benjamin Tissoires, Bastien Nocera:, linux-input@vger.kernel.org

Hi, Dmitry

Thanks for the review.

> From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control
> method lid device restrictions
> 
> Hi Lv,
> 
> On Fri, Jul 22, 2016 at 12:24:50AM +0000, Zheng, Lv wrote:
> > Hi, Dmitry
> >
> >
> > Thanks for the review.
> >
> > > From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> > > Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI
> control
> > > method lid device restrictions
> > >
> > > On Tue, Jul 19, 2016 at 04:11:21PM +0800, Lv Zheng wrote:
> > > > This patch adds documentation for the usage model of the control
> > > method lid
> > > > device.
> > > >
> > > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > > > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > > > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> > > > Cc: Bastien Nocera: <hadess@hadess.net>
> > > > Cc: linux-input@vger.kernel.org
> > > > ---
> > > >  Documentation/acpi/acpi-lid.txt |   89
> > > +++++++++++++++++++++++++++++++++++++++
> > > >  1 file changed, 89 insertions(+)
> > > >  create mode 100644 Documentation/acpi/acpi-lid.txt
> > > >
> > > > diff --git a/Documentation/acpi/acpi-lid.txt
> b/Documentation/acpi/acpi-
> > > lid.txt
> > > > new file mode 100644
> > > > index 0000000..2addedc
> > > > --- /dev/null
> > > > +++ b/Documentation/acpi/acpi-lid.txt
> > > > @@ -0,0 +1,89 @@
> > > > +Usage Model of the ACPI Control Method Lid Device
> > > > +
> > > > +Copyright (C) 2016, Intel Corporation
> > > > +Author: Lv Zheng <lv.zheng@intel.com>
> > > > +
> > > > +
> > > > +Abstract:
> > > > +
> > > > +Platforms containing lids convey lid state (open/close) to OSPMs
> using
> > > a
> > > > +control method lid device. To implement this, the AML tables issue
> > > > +Notify(lid_device, 0x80) to notify the OSPMs whenever the lid state
> has
> > > > +changed. The _LID control method for the lid device must be
> > > implemented to
> > > > +report the "current" state of the lid as either "opened" or "closed".
> > > > +
> > > > +This document describes the restrictions and the expections of the
> > > Linux
> > > > +ACPI lid device driver.
> > > > +
> > > > +
> > > > +1. Restrictions of the returning value of the _LID control method
> > > > +
> > > > +The _LID control method is described to return the "current" lid
> state.
> > > > +However the word of "current" has ambiguity, many AML tables
> return
> > > the lid
> > >
> > > Can this be fixed in the next ACPI revision?
> > [Lv Zheng]
> > Even this is fixed in the ACPI specification, there are platforms already
> doing this.
> > Especially platforms from Microsoft.
> > So the de-facto standard OS won't care about the change.
> > And we can still see such platforms.
> >
> > Here is an example from Surface 3:
> >
> > DefinitionBlock ("dsdt.aml", "DSDT", 2, "ALASKA", "A M I ", 0x01072009)
> > {
> >     Scope (_SB)
> >     {
> >         Device (PCI0)
> >         {
> >             Name (_HID, EisaId ("PNP0A08"))  // _HID: Hardware ID
> >             Name (_CID, EisaId ("PNP0A03"))  // _CID: Compatible ID
> >             Device (SPI1)
> >             {
> >                 Name (_HID, "8086228E")  // _HID: Hardware ID
> >                 Device (NTRG)
> >                 {
> >                     Name (_HID, "MSHW0037")  // _HID: Hardware ID
> >                 }
> >             }
> >         }
> >
> >         Device (LID)
> >         {
> >             Name (_HID, EisaId ("PNP0C0D"))
> >             Name (LIDB, Zero)
> 
> Start with lid closed? In any case might be wrong.
[Lv Zheng] 
And we validated with qemu that during boot, Windows7 evaluates _LID once but doesn't get suspended because of this value.
So we think Windows only suspends against "notification" not _LID evaluation result.

> 
> >             Method (_LID, 0, NotSerialized)
> >             {
> >                 Return (LIDB)
> 
> So "_LID" returns the last state read by "_EC4". "_EC4" is
> edge-triggered and will be evaluated every time gpio changes state.
[Lv Zheng] 
Right.

> 
> >             }
> >         }
> >
> >         Device (GPO0)
> >         {
> >             Name (_HID, "INT33FF")  // _HID: Hardware ID
> >             OperationRegion (GPOR, GeneralPurposeIo, Zero, One)
> >             Field (GPOR, ByteAcc, NoLock, Preserve)
> >             {
> >                 Connection (
> >                     GpioIo (Shared, PullNone, 0x0000, 0x0000, IoRestrictionNone,
> >                         "\\_SB.GPO0", 0x00, ResourceConsumer, ,
> >                         )
> >                         {   // Pin list
> >                             0x004C
> >                         }
> >                 ),
> >                 HELD,   1
> 
> Is it possible to read state of this GPIO from userspace on startup to
> correct the initial state?
[Lv Zheng] 
I think Benjamin has a proposal of fixing this in GPIO driver.

> 
> >             }
> >             Method (_E4C, 0, Serialized)
> >             {
> >                 If (LEqual(HELD, One))
> >                 {
> >                     Store(One, ^^LID.LIDB)
> >
> > There is no "open" event generated by "Surface 3".
> 
> Right so we update the state correctly, we just forgot to send the
> notification. Nothing that polling can't fix.
> 
[Lv Zheng] 
However, polling is not efficient, and not power efficient.
OTOH, according to the validation result, Windows never poll _LID.

> >
> >                 }
> >                 Else
> >                 {
> >                     Store(Zero, ^^LID.LIDB)
> >                     Notify (LID, 0x80)
> >
> > There is only "close" event generated by "Surface 3".
> > Thus they are not paired.
> >
> >                 }
> >                 Notify (^^PCI0.SPI1.NTRG, One) // Device Check
> >             }
> >         }
> >     }
> > }
> >
> > >
> > > > +state upon the last lid notification instead of returning the lid state
> > > > +upon the last _LID evaluation. There won't be difference when the
> _LID
> > > > +control method is evaluated during the runtime, the problem is its
> > > initial
> > > > +returning value. When the AML tables implement this control
> method
> > > with
> > > > +cached value, the initial returning value is likely not reliable. There
> are
> > > > +simply so many examples always retuning "closed" as initial lid
> state.
> > > > +
> > > > +2. Restrictions of the lid state change notifications
> > > > +
> > > > +There are many AML tables never notifying when the lid device
> state is
> > > > +changed to "opened". Thus the "opened" notification is not
> guaranteed.
> > > > +
> > > > +But it is guaranteed that the AML tables always notify "closed"
> when
> > > the
> > > > +lid state is changed to "closed". The "closed" notification is normally
> > > > +used to trigger some system power saving operations on Windows.
> > > Since it is
> > > > +fully tested, the "closed" notification is reliable for all AML tables.
> > > > +
> > > > +3. Expections for the userspace users of the ACPI lid device driver
> > > > +
> > > > +The ACPI button driver exports the lid state to the userspace via the
> > > > +following file:
> > > > +  /proc/acpi/button/lid/LID0/state
> > > > +This file actually calls the _LID control method described above. And
> > > given
> > > > +the previous explanation, it is not reliable enough on some
> platforms.
> > > So
> > > > +it is advised for the userspace program to not to solely rely on this
> file
> > > > +to determine the actual lid state.
> > > > +
> > > > +The ACPI button driver emits 2 kinds of events to the user space:
> > > > +  SW_LID
> > > > +   When the lid state/event is reliable, the userspace can behave
> > > > +   according to this input switch event.
> > > > +   This is a mode prepared for backward compatiblity.
> > > > +  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
> > > > +   When the lid state/event is not reliable, the userspace should
> behave
> > > > +   according to these 2 input key events.
> > > > +   New userspace programs may only be prepared for the input key
> > > events.
> > >
> > > No, absolutely not. If some x86 vendors managed to mess up their
> > > firmware implementations that does not mean that everyone now has
> to
> > > abandon working perfectly well for them SW_LID events and rush to
> > > switch
> > > to a brand new event.
> > [Lv Zheng]
> > However there is no clear wording in the ACPI specification asking the
> vendors to achieve paired lid events.
> >
> > >
> > > Apparently were are a few issues, main is that some systems not
> reporting
> > > "open" event. This can be dealt with by userspace "writing" to the
> > > lid's evdev device EV_SW/SW_LID/0 event upon system resume (and
> > > startup)
> > > for selected systems. This will mean that if system wakes up not
> because
> > > LID is open we'll incorrectly assume that it is, but we can either add
> > > more smarts to the process emitting SW_LID event or simply say "well,
> > > tough, the hardware is crappy" and bug vendor to see if they can fix
> the
> > > issue (if not for current firmware them for next).
> > [Lv Zheng]
> > The problem is there is no vendor actually caring about fixing this "issue".
> > Because Windows works well with their firmware.
> > Then finally becomes a big table customization business for our team.
> 
> Well, OK. But you do not expect that we will redo up and down the stack
> lid handling just because MS messed up DSDT on Surface 3? No, let them
> know (they now care about Linux, right?) so Surface 4 works and quirk
> the behavior for Surface 3.
[Lv Zheng] 
I think there are other platforms broken.

> 
> >
> > >
> > > As an additional workaround, we can toggle the LID switch off and on
> > > when we get notification, much like your proposed patch does for the
> key
> > > events.
> > [Lv Zheng]
> > I think this is doable, I'll refresh my patchset to address your this
> comment.
> > By inserting open/close events when next close/open event arrives after
> a certain period,
> > this may fix some issues for the old programs.
> > Where user may be required to open/close lid twice to trigger 2nd
> suspend.
> >
> > However, this still cannot fix the problems like "Surface 3".
> > We'll still need a new usage model for such platforms (no open event).
> 
> No, for surface 3 you simply need to add polling of "_LID" method to the
> button driver.
> 
> What are the other devices that mess up lid handling?
[Lv Zheng] 
The patch lists 3 of them.
Which are known to me because they all occurred after I started to look at the lid issues.

According to my teammates.
They've been fixing such wrong "DSDT" using customization for years.
For example, by adding _LID(); Notify(lid) into _WAK() or EC._REG().

Thanks and best regards
-Lv

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

* RE: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-22  6:55         ` Benjamin Tissoires
@ 2016-07-22  8:47           ` Zheng, Lv
  2016-07-22  9:08             ` Benjamin Tissoires
  2016-07-22 17:02           ` Dmitry Torokhov
  1 sibling, 1 reply; 34+ messages in thread
From: Zheng, Lv @ 2016-07-22  8:47 UTC (permalink / raw)
  To: Benjamin Tissoires, Dmitry Torokhov, Zhang, Rui
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	Bastien Nocera:, linux-input@vger.kernel.org

Hi,

> From: Benjamin Tissoires [mailto:benjamin.tissoires@gmail.com]
> Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control
> method lid device restrictions
> 
> On Fri, Jul 22, 2016 at 6:37 AM, Dmitry Torokhov
> <dmitry.torokhov@gmail.com> wrote:
> > Hi Lv,
> >
> > On Fri, Jul 22, 2016 at 12:24:50AM +0000, Zheng, Lv wrote:
> >> Hi, Dmitry
> >>
> >>
> >> Thanks for the review.
> >>
> >> > From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> >> > Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI
> control
> >> > method lid device restrictions
> >> >
> >> > On Tue, Jul 19, 2016 at 04:11:21PM +0800, Lv Zheng wrote:
> >> > > This patch adds documentation for the usage model of the control
> >> > method lid
> >> > > device.
> >> > >
> >> > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> >> > > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> >> > > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> >> > > Cc: Bastien Nocera: <hadess@hadess.net>
> >> > > Cc: linux-input@vger.kernel.org
> >> > > ---
> >> > >  Documentation/acpi/acpi-lid.txt |   89
> >> > +++++++++++++++++++++++++++++++++++++++
> >> > >  1 file changed, 89 insertions(+)
> >> > >  create mode 100644 Documentation/acpi/acpi-lid.txt
> >> > >
> >> > > diff --git a/Documentation/acpi/acpi-lid.txt
> b/Documentation/acpi/acpi-
> >> > lid.txt
> >> > > new file mode 100644
> >> > > index 0000000..2addedc
> >> > > --- /dev/null
> >> > > +++ b/Documentation/acpi/acpi-lid.txt
> >> > > @@ -0,0 +1,89 @@
> >> > > +Usage Model of the ACPI Control Method Lid Device
> >> > > +
> >> > > +Copyright (C) 2016, Intel Corporation
> >> > > +Author: Lv Zheng <lv.zheng@intel.com>
> >> > > +
> >> > > +
> >> > > +Abstract:
> >> > > +
> >> > > +Platforms containing lids convey lid state (open/close) to OSPMs
> using
> >> > a
> >> > > +control method lid device. To implement this, the AML tables issue
> >> > > +Notify(lid_device, 0x80) to notify the OSPMs whenever the lid
> state has
> >> > > +changed. The _LID control method for the lid device must be
> >> > implemented to
> >> > > +report the "current" state of the lid as either "opened" or "closed".
> >> > > +
> >> > > +This document describes the restrictions and the expections of the
> >> > Linux
> >> > > +ACPI lid device driver.
> >> > > +
> >> > > +
> >> > > +1. Restrictions of the returning value of the _LID control method
> >> > > +
> >> > > +The _LID control method is described to return the "current" lid
> state.
> >> > > +However the word of "current" has ambiguity, many AML tables
> return
> >> > the lid
> >> >
> >> > Can this be fixed in the next ACPI revision?
> >> [Lv Zheng]
> >> Even this is fixed in the ACPI specification, there are platforms already
> doing this.
> >> Especially platforms from Microsoft.
> >> So the de-facto standard OS won't care about the change.
> >> And we can still see such platforms.
> >>
> >> Here is an example from Surface 3:
> >>
> >> DefinitionBlock ("dsdt.aml", "DSDT", 2, "ALASKA", "A M I ", 0x01072009)
> >> {
> >>     Scope (_SB)
> >>     {
> >>         Device (PCI0)
> >>         {
> >>             Name (_HID, EisaId ("PNP0A08"))  // _HID: Hardware ID
> >>             Name (_CID, EisaId ("PNP0A03"))  // _CID: Compatible ID
> >>             Device (SPI1)
> >>             {
> >>                 Name (_HID, "8086228E")  // _HID: Hardware ID
> >>                 Device (NTRG)
> >>                 {
> >>                     Name (_HID, "MSHW0037")  // _HID: Hardware ID
> >>                 }
> >>             }
> >>         }
> >>
> >>         Device (LID)
> >>         {
> >>             Name (_HID, EisaId ("PNP0C0D"))
> >>             Name (LIDB, Zero)
> >
> > Start with lid closed? In any case might be wrong.
> 
> Actually the initial value doesn't matter if the gpiochip triggers the
> _EC4 at boot, which it should
> (https://github.com/hadess/fedora-surface3-
> kernel/commit/13200f81662c1c0b58137947c3e6c000fe62a2ba,
> still unsubmitted)
> 
> >
> >>             Method (_LID, 0, NotSerialized)
> >>             {
> >>                 Return (LIDB)
> >
> > So "_LID" returns the last state read by "_EC4". "_EC4" is
> > edge-triggered and will be evaluated every time gpio changes state.
> 
> That's assuming the change happens while the system is on. If you go
> into suspend by closing the LID. Open it while on suspend and then hit
> the power button given that the system doesn't wake up when the lid is
> opened, the edge change was made while the system is asleep, and we
> are screwed (from an ACPI point of view). See my next comment for a
> solution.
> 
[Lv Zheng] 
I actually not sure if polling can fix all issues.
For example.
If a platform reporting "close" after resuming.
Then polling _LID will always return "close".
And the userspace can still get the "close" not "open".
So it seems polling is not working for such platforms (cached value, initial close).
Surface 3 is not the only platform caching an initial close value.
There are 2 traditional platforms listed in the patch description.

> >
> >>             }
> >>         }
> >>
> >>         Device (GPO0)
> >>         {
> >>             Name (_HID, "INT33FF")  // _HID: Hardware ID
> >>             OperationRegion (GPOR, GeneralPurposeIo, Zero, One)
> >>             Field (GPOR, ByteAcc, NoLock, Preserve)
> >>             {
> >>                 Connection (
> >>                     GpioIo (Shared, PullNone, 0x0000, 0x0000,
> IoRestrictionNone,
> >>                         "\\_SB.GPO0", 0x00, ResourceConsumer, ,
> >>                         )
> >>                         {   // Pin list
> >>                             0x004C
> >>                         }
> >>                 ),
> >>                 HELD,   1
> >
> > Is it possible to read state of this GPIO from userspace on startup to
> > correct the initial state?
> >
> >>             }
> >>             Method (_E4C, 0, Serialized)
> >>             {
> >>                 If (LEqual(HELD, One))
> >>                 {
> >>                     Store(One, ^^LID.LIDB)
> >>
> >> There is no "open" event generated by "Surface 3".
> >
> > Right so we update the state correctly, we just forgot to send the
> > notification. Nothing that polling can't fix.
> 
> Actually, I have a better (though more hackish) way of avoiding polling:
> https://github.com/hadess/fedora-surface3-
> kernel/blob/5e5775b9bdc308d665064387e0b144ee48e7b243/0002-WIP-
> add-custom-surface3-platform-device-for-controll.patch
> 
> Given that the notification is forwarded to the touchscreen anyway, we
> can unregister the generic (and buggy) acpi button driver for the LID
> and create our own based on this specific DSDT.
> We can also make sure the LID state is also correct because of the WMI
> method which allows to read the actual value of the GPIO connected to
> the cover without using the cached (and most of the time wrong) acpi
> LID.LIDB value.
> 
> I still yet have to submit this, but with this patch, but we can
> consider the Surface 3 as working and not an issue anymore.
> 
[Lv Zheng] 
That could make surface 3 dependent on WMI driver, not ACPI button driver.
Will this affect other buttons?
For example, power button/sleep button.

Our approach is to make ACPI button driver working.
Though this may lead to ABI changes.

> >
> >>
> >>                 }
> >>                 Else
> >>                 {
> >>                     Store(Zero, ^^LID.LIDB)
> >>                     Notify (LID, 0x80)
> >>
> >> There is only "close" event generated by "Surface 3".
> >> Thus they are not paired.
> >>
> >>                 }
> >>                 Notify (^^PCI0.SPI1.NTRG, One) // Device Check
> >>             }
> >>         }
> >>     }
> >> }
> >>
> >> >
> >> > > +state upon the last lid notification instead of returning the lid state
> >> > > +upon the last _LID evaluation. There won't be difference when the
> _LID
> >> > > +control method is evaluated during the runtime, the problem is its
> >> > initial
> >> > > +returning value. When the AML tables implement this control
> method
> >> > with
> >> > > +cached value, the initial returning value is likely not reliable. There
> are
> >> > > +simply so many examples always retuning "closed" as initial lid
> state.
> >> > > +
> >> > > +2. Restrictions of the lid state change notifications
> >> > > +
> >> > > +There are many AML tables never notifying when the lid device
> state is
> >> > > +changed to "opened". Thus the "opened" notification is not
> guaranteed.
> >> > > +
> >> > > +But it is guaranteed that the AML tables always notify "closed"
> when
> >> > the
> >> > > +lid state is changed to "closed". The "closed" notification is
> normally
> >> > > +used to trigger some system power saving operations on Windows.
> >> > Since it is
> >> > > +fully tested, the "closed" notification is reliable for all AML tables.
> >> > > +
> >> > > +3. Expections for the userspace users of the ACPI lid device driver
> >> > > +
> >> > > +The ACPI button driver exports the lid state to the userspace via
> the
> >> > > +following file:
> >> > > +  /proc/acpi/button/lid/LID0/state
> >> > > +This file actually calls the _LID control method described above.
> And
> >> > given
> >> > > +the previous explanation, it is not reliable enough on some
> platforms.
> >> > So
> >> > > +it is advised for the userspace program to not to solely rely on this
> file
> >> > > +to determine the actual lid state.
> >> > > +
> >> > > +The ACPI button driver emits 2 kinds of events to the user space:
> >> > > +  SW_LID
> >> > > +   When the lid state/event is reliable, the userspace can behave
> >> > > +   according to this input switch event.
> >> > > +   This is a mode prepared for backward compatiblity.
> >> > > +  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
> >> > > +   When the lid state/event is not reliable, the userspace should
> behave
> >> > > +   according to these 2 input key events.
> >> > > +   New userspace programs may only be prepared for the input key
> >> > events.
> >> >
> >> > No, absolutely not. If some x86 vendors managed to mess up their
> >> > firmware implementations that does not mean that everyone now
> has to
> >> > abandon working perfectly well for them SW_LID events and rush to
> >> > switch
> >> > to a brand new event.
> >> [Lv Zheng]
> >> However there is no clear wording in the ACPI specification asking the
> vendors to achieve paired lid events.
> >>
> >> >
> >> > Apparently were are a few issues, main is that some systems not
> reporting
> >> > "open" event. This can be dealt with by userspace "writing" to the
> >> > lid's evdev device EV_SW/SW_LID/0 event upon system resume (and
> >> > startup)
> >> > for selected systems. This will mean that if system wakes up not
> because
> >> > LID is open we'll incorrectly assume that it is, but we can either add
> >> > more smarts to the process emitting SW_LID event or simply say
> "well,
> >> > tough, the hardware is crappy" and bug vendor to see if they can fix
> the
> >> > issue (if not for current firmware them for next).
> >> [Lv Zheng]
> >> The problem is there is no vendor actually caring about fixing this
> "issue".
> >> Because Windows works well with their firmware.
> >> Then finally becomes a big table customization business for our team.
> >
> > Well, OK. But you do not expect that we will redo up and down the stack
> > lid handling just because MS messed up DSDT on Surface 3? No, let them
> > know (they now care about Linux, right?) so Surface 4 works and quirk
> > the behavior for Surface 3.
> >
> 
> From what I understood, it was more than just the Surface 3. Other
> laptops were having issues and Lv's team gave up on fixing those
> machines.
> 
> >>
> >> >
> >> > As an additional workaround, we can toggle the LID switch off and on
> >> > when we get notification, much like your proposed patch does for the
> key
> >> > events.
> 
> I really don't like this approach. The problem being that we will fix
> the notifications to user space, but nothing will tell userspace that
> the LID state is known to be wrong.
> OTOH, I already agreed for a hwdb in userspace so I guess this point is
> moot.
> 
> Having both events (one SW for reliable HW, always correct, and one
> KEY for unreliable HW) allows userspace to make a clear distinction
> between the working and non working events and they can continue to
> keep using the polling of the SW node without extra addition.
> 
[Lv Zheng] 
I think this solution is good and fair for all of the vendors. :-)

> Anyway, if the kernel doesn't want to (or can't) fix the actual issue
> (by making sure the DSDT is reliable), userspace needs to be changed
> so any solution will be acceptable.
[Lv Zheng] 
I think the answer is "can't".
If we introduced too many workarounds into acpi button driver,
in order to make something working while the platform firmware doesn't expect it to be working,
then we'll start to worry about breaking good laptops.

> 
> >> [Lv Zheng]
> >> I think this is doable, I'll refresh my patchset to address your this
> comment.
> >> By inserting open/close events when next close/open event arrives
> after a certain period,
> >> this may fix some issues for the old programs.
> >> Where user may be required to open/close lid twice to trigger 2nd
> suspend.
> >>
> >> However, this still cannot fix the problems like "Surface 3".
> >> We'll still need a new usage model for such platforms (no open event).
> >
> > No, for surface 3 you simply need to add polling of "_LID" method to the
> > button driver.
> >
> > What are the other devices that mess up lid handling?
> >
> 
> I also would be interested in knowing how much issues you are facing
> compared to the average number of "good" laptops. IIRC, you talked
> about 3 (counting the Surface 3), but I believe you had more in mind.

[Lv Zheng] 
Yes.
However they happened before I started to look at the lid issues.
I think Rui has several such experiences.
+Rui.

Thanks and best regards
-Lv

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

* Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-22  8:47           ` Zheng, Lv
@ 2016-07-22  9:08             ` Benjamin Tissoires
  2016-07-22  9:38               ` Zheng, Lv
  2016-07-24 11:28               ` Bastien Nocera
  0 siblings, 2 replies; 34+ messages in thread
From: Benjamin Tissoires @ 2016-07-22  9:08 UTC (permalink / raw)
  To: Zheng, Lv
  Cc: Dmitry Torokhov, Zhang, Rui, Wysocki, Rafael J, Rafael J. Wysocki,
	Brown, Len, Lv Zheng, linux-kernel@vger.kernel.org,
	linux-acpi@vger.kernel.org, Bastien Nocera:,
	linux-input@vger.kernel.org

On Fri, Jul 22, 2016 at 10:47 AM, Zheng, Lv <lv.zheng@intel.com> wrote:
> Hi,
>
>> From: Benjamin Tissoires [mailto:benjamin.tissoires@gmail.com]
>> Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control
>> method lid device restrictions
>>
>> On Fri, Jul 22, 2016 at 6:37 AM, Dmitry Torokhov
>> <dmitry.torokhov@gmail.com> wrote:
>> > Hi Lv,
>> >
>> > On Fri, Jul 22, 2016 at 12:24:50AM +0000, Zheng, Lv wrote:
>> >> Hi, Dmitry
>> >>
>> >>
>> >> Thanks for the review.
>> >>
>> >> > From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
>> >> > Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI
>> control
>> >> > method lid device restrictions
>> >> >
>> >> > On Tue, Jul 19, 2016 at 04:11:21PM +0800, Lv Zheng wrote:
>> >> > > This patch adds documentation for the usage model of the control
>> >> > method lid
>> >> > > device.
>> >> > >
>> >> > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
>> >> > > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>> >> > > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
>> >> > > Cc: Bastien Nocera: <hadess@hadess.net>
>> >> > > Cc: linux-input@vger.kernel.org
>> >> > > ---
>> >> > >  Documentation/acpi/acpi-lid.txt |   89
>> >> > +++++++++++++++++++++++++++++++++++++++
>> >> > >  1 file changed, 89 insertions(+)
>> >> > >  create mode 100644 Documentation/acpi/acpi-lid.txt
>> >> > >
>> >> > > diff --git a/Documentation/acpi/acpi-lid.txt
>> b/Documentation/acpi/acpi-
>> >> > lid.txt
>> >> > > new file mode 100644
>> >> > > index 0000000..2addedc
>> >> > > --- /dev/null
>> >> > > +++ b/Documentation/acpi/acpi-lid.txt
>> >> > > @@ -0,0 +1,89 @@
>> >> > > +Usage Model of the ACPI Control Method Lid Device
>> >> > > +
>> >> > > +Copyright (C) 2016, Intel Corporation
>> >> > > +Author: Lv Zheng <lv.zheng@intel.com>
>> >> > > +
>> >> > > +
>> >> > > +Abstract:
>> >> > > +
>> >> > > +Platforms containing lids convey lid state (open/close) to OSPMs
>> using
>> >> > a
>> >> > > +control method lid device. To implement this, the AML tables issue
>> >> > > +Notify(lid_device, 0x80) to notify the OSPMs whenever the lid
>> state has
>> >> > > +changed. The _LID control method for the lid device must be
>> >> > implemented to
>> >> > > +report the "current" state of the lid as either "opened" or "closed".
>> >> > > +
>> >> > > +This document describes the restrictions and the expections of the
>> >> > Linux
>> >> > > +ACPI lid device driver.
>> >> > > +
>> >> > > +
>> >> > > +1. Restrictions of the returning value of the _LID control method
>> >> > > +
>> >> > > +The _LID control method is described to return the "current" lid
>> state.
>> >> > > +However the word of "current" has ambiguity, many AML tables
>> return
>> >> > the lid
>> >> >
>> >> > Can this be fixed in the next ACPI revision?
>> >> [Lv Zheng]
>> >> Even this is fixed in the ACPI specification, there are platforms already
>> doing this.
>> >> Especially platforms from Microsoft.
>> >> So the de-facto standard OS won't care about the change.
>> >> And we can still see such platforms.
>> >>
>> >> Here is an example from Surface 3:
>> >>
>> >> DefinitionBlock ("dsdt.aml", "DSDT", 2, "ALASKA", "A M I ", 0x01072009)
>> >> {
>> >>     Scope (_SB)
>> >>     {
>> >>         Device (PCI0)
>> >>         {
>> >>             Name (_HID, EisaId ("PNP0A08"))  // _HID: Hardware ID
>> >>             Name (_CID, EisaId ("PNP0A03"))  // _CID: Compatible ID
>> >>             Device (SPI1)
>> >>             {
>> >>                 Name (_HID, "8086228E")  // _HID: Hardware ID
>> >>                 Device (NTRG)
>> >>                 {
>> >>                     Name (_HID, "MSHW0037")  // _HID: Hardware ID
>> >>                 }
>> >>             }
>> >>         }
>> >>
>> >>         Device (LID)
>> >>         {
>> >>             Name (_HID, EisaId ("PNP0C0D"))
>> >>             Name (LIDB, Zero)
>> >
>> > Start with lid closed? In any case might be wrong.
>>
>> Actually the initial value doesn't matter if the gpiochip triggers the
>> _EC4 at boot, which it should
>> (https://github.com/hadess/fedora-surface3-
>> kernel/commit/13200f81662c1c0b58137947c3e6c000fe62a2ba,
>> still unsubmitted)
>>
>> >
>> >>             Method (_LID, 0, NotSerialized)
>> >>             {
>> >>                 Return (LIDB)
>> >
>> > So "_LID" returns the last state read by "_EC4". "_EC4" is
>> > edge-triggered and will be evaluated every time gpio changes state.
>>
>> That's assuming the change happens while the system is on. If you go
>> into suspend by closing the LID. Open it while on suspend and then hit
>> the power button given that the system doesn't wake up when the lid is
>> opened, the edge change was made while the system is asleep, and we
>> are screwed (from an ACPI point of view). See my next comment for a
>> solution.
>>
> [Lv Zheng]
> I actually not sure if polling can fix all issues.
> For example.
> If a platform reporting "close" after resuming.
> Then polling _LID will always return "close".
> And the userspace can still get the "close" not "open".
> So it seems polling is not working for such platforms (cached value, initial close).
> Surface 3 is not the only platform caching an initial close value.
> There are 2 traditional platforms listed in the patch description.
>
>> >
>> >>             }
>> >>         }
>> >>
>> >>         Device (GPO0)
>> >>         {
>> >>             Name (_HID, "INT33FF")  // _HID: Hardware ID
>> >>             OperationRegion (GPOR, GeneralPurposeIo, Zero, One)
>> >>             Field (GPOR, ByteAcc, NoLock, Preserve)
>> >>             {
>> >>                 Connection (
>> >>                     GpioIo (Shared, PullNone, 0x0000, 0x0000,
>> IoRestrictionNone,
>> >>                         "\\_SB.GPO0", 0x00, ResourceConsumer, ,
>> >>                         )
>> >>                         {   // Pin list
>> >>                             0x004C
>> >>                         }
>> >>                 ),
>> >>                 HELD,   1
>> >
>> > Is it possible to read state of this GPIO from userspace on startup to
>> > correct the initial state?
>> >
>> >>             }
>> >>             Method (_E4C, 0, Serialized)
>> >>             {
>> >>                 If (LEqual(HELD, One))
>> >>                 {
>> >>                     Store(One, ^^LID.LIDB)
>> >>
>> >> There is no "open" event generated by "Surface 3".
>> >
>> > Right so we update the state correctly, we just forgot to send the
>> > notification. Nothing that polling can't fix.
>>
>> Actually, I have a better (though more hackish) way of avoiding polling:
>> https://github.com/hadess/fedora-surface3-
>> kernel/blob/5e5775b9bdc308d665064387e0b144ee48e7b243/0002-WIP-
>> add-custom-surface3-platform-device-for-controll.patch
>>
>> Given that the notification is forwarded to the touchscreen anyway, we
>> can unregister the generic (and buggy) acpi button driver for the LID
>> and create our own based on this specific DSDT.
>> We can also make sure the LID state is also correct because of the WMI
>> method which allows to read the actual value of the GPIO connected to
>> the cover without using the cached (and most of the time wrong) acpi
>> LID.LIDB value.
>>
>> I still yet have to submit this, but with this patch, but we can
>> consider the Surface 3 as working and not an issue anymore.
>>
> [Lv Zheng]
> That could make surface 3 dependent on WMI driver, not ACPI button driver.
> Will this affect other buttons?
> For example, power button/sleep button.

TLDR: no, there is no impact on other buttons.

There are 2 reasons why the impact is limited:
- the patch only removes the input node that contains the LID, and it
is the only one event in the input node
- power/sleep, volume +/- are not handled by ACPI as this is a reduced
platform and these buttons are not notified by ACPI. So we need an
adaptation of the GPIO button array for it to be working (patch
already submitted but I found a non-acpi platform issue, and then not
enough time to fix and send an updated version).

>
> Our approach is to make ACPI button driver working.
> Though this may lead to ABI changes.

Yes, I know you want to fix ACPI button for future non working
tablets/laptops. This is why I gave my rev-by in this series.

>
>> >
>> >>
>> >>                 }
>> >>                 Else
>> >>                 {
>> >>                     Store(Zero, ^^LID.LIDB)
>> >>                     Notify (LID, 0x80)
>> >>
>> >> There is only "close" event generated by "Surface 3".
>> >> Thus they are not paired.
>> >>
>> >>                 }
>> >>                 Notify (^^PCI0.SPI1.NTRG, One) // Device Check
>> >>             }
>> >>         }
>> >>     }
>> >> }
>> >>
>> >> >
>> >> > > +state upon the last lid notification instead of returning the lid state
>> >> > > +upon the last _LID evaluation. There won't be difference when the
>> _LID
>> >> > > +control method is evaluated during the runtime, the problem is its
>> >> > initial
>> >> > > +returning value. When the AML tables implement this control
>> method
>> >> > with
>> >> > > +cached value, the initial returning value is likely not reliable. There
>> are
>> >> > > +simply so many examples always retuning "closed" as initial lid
>> state.
>> >> > > +
>> >> > > +2. Restrictions of the lid state change notifications
>> >> > > +
>> >> > > +There are many AML tables never notifying when the lid device
>> state is
>> >> > > +changed to "opened". Thus the "opened" notification is not
>> guaranteed.
>> >> > > +
>> >> > > +But it is guaranteed that the AML tables always notify "closed"
>> when
>> >> > the
>> >> > > +lid state is changed to "closed". The "closed" notification is
>> normally
>> >> > > +used to trigger some system power saving operations on Windows.
>> >> > Since it is
>> >> > > +fully tested, the "closed" notification is reliable for all AML tables.
>> >> > > +
>> >> > > +3. Expections for the userspace users of the ACPI lid device driver
>> >> > > +
>> >> > > +The ACPI button driver exports the lid state to the userspace via
>> the
>> >> > > +following file:
>> >> > > +  /proc/acpi/button/lid/LID0/state
>> >> > > +This file actually calls the _LID control method described above.
>> And
>> >> > given
>> >> > > +the previous explanation, it is not reliable enough on some
>> platforms.
>> >> > So
>> >> > > +it is advised for the userspace program to not to solely rely on this
>> file
>> >> > > +to determine the actual lid state.
>> >> > > +
>> >> > > +The ACPI button driver emits 2 kinds of events to the user space:
>> >> > > +  SW_LID
>> >> > > +   When the lid state/event is reliable, the userspace can behave
>> >> > > +   according to this input switch event.
>> >> > > +   This is a mode prepared for backward compatiblity.
>> >> > > +  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
>> >> > > +   When the lid state/event is not reliable, the userspace should
>> behave
>> >> > > +   according to these 2 input key events.
>> >> > > +   New userspace programs may only be prepared for the input key
>> >> > events.
>> >> >
>> >> > No, absolutely not. If some x86 vendors managed to mess up their
>> >> > firmware implementations that does not mean that everyone now
>> has to
>> >> > abandon working perfectly well for them SW_LID events and rush to
>> >> > switch
>> >> > to a brand new event.
>> >> [Lv Zheng]
>> >> However there is no clear wording in the ACPI specification asking the
>> vendors to achieve paired lid events.
>> >>
>> >> >
>> >> > Apparently were are a few issues, main is that some systems not
>> reporting
>> >> > "open" event. This can be dealt with by userspace "writing" to the
>> >> > lid's evdev device EV_SW/SW_LID/0 event upon system resume (and
>> >> > startup)
>> >> > for selected systems. This will mean that if system wakes up not
>> because
>> >> > LID is open we'll incorrectly assume that it is, but we can either add
>> >> > more smarts to the process emitting SW_LID event or simply say
>> "well,
>> >> > tough, the hardware is crappy" and bug vendor to see if they can fix
>> the
>> >> > issue (if not for current firmware them for next).
>> >> [Lv Zheng]
>> >> The problem is there is no vendor actually caring about fixing this
>> "issue".
>> >> Because Windows works well with their firmware.
>> >> Then finally becomes a big table customization business for our team.
>> >
>> > Well, OK. But you do not expect that we will redo up and down the stack
>> > lid handling just because MS messed up DSDT on Surface 3? No, let them
>> > know (they now care about Linux, right?) so Surface 4 works and quirk
>> > the behavior for Surface 3.
>> >
>>
>> From what I understood, it was more than just the Surface 3. Other
>> laptops were having issues and Lv's team gave up on fixing those
>> machines.
>>
>> >>
>> >> >
>> >> > As an additional workaround, we can toggle the LID switch off and on
>> >> > when we get notification, much like your proposed patch does for the
>> key
>> >> > events.
>>
>> I really don't like this approach. The problem being that we will fix
>> the notifications to user space, but nothing will tell userspace that
>> the LID state is known to be wrong.
>> OTOH, I already agreed for a hwdb in userspace so I guess this point is
>> moot.
>>
>> Having both events (one SW for reliable HW, always correct, and one
>> KEY for unreliable HW) allows userspace to make a clear distinction
>> between the working and non working events and they can continue to
>> keep using the polling of the SW node without extra addition.
>>
> [Lv Zheng]
> I think this solution is good and fair for all of the vendors. :-)
>
>> Anyway, if the kernel doesn't want to (or can't) fix the actual issue
>> (by making sure the DSDT is reliable), userspace needs to be changed
>> so any solution will be acceptable.
> [Lv Zheng]
> I think the answer is "can't".
> If we introduced too many workarounds into acpi button driver,
> in order to make something working while the platform firmware doesn't expect it to be working,
> then we'll start to worry about breaking good laptops.

Then you just need to amend the documentation to say that the fallback
of the KEY events is not the "future" but a way to get events on some
reduced platforms and it will not be the default.
Please make sure userspace knows that the default is the good SW_LID,
and some particular cases will need to be handled through the KEY
events, not the other way around.

[few thoughts later]

How about:
- you send only one patch with the SW_LID ON/OFF or OFF/ON when we
receive the notification on buggy platform
- in the same patch, you add the documentation saying that on most
platforms, LID is reliable but some don't provide a reliable LID
state, but you guarantee to send an event when the state changes
- in userspace, we add the hwdb which says "on this particular
platform, don't rely on the actual state, but wait for events" -> this
basically removes the polling on these platforms.

Bastien, Dmitry?

I still don't like relying on userspace to actually set the SW_LID
back to open on resume, as we should not rely on some userspace
program to set the value (but if logind really wants it, it's up to
them).

Cheers,
Benjamin

>
>>
>> >> [Lv Zheng]
>> >> I think this is doable, I'll refresh my patchset to address your this
>> comment.
>> >> By inserting open/close events when next close/open event arrives
>> after a certain period,
>> >> this may fix some issues for the old programs.
>> >> Where user may be required to open/close lid twice to trigger 2nd
>> suspend.
>> >>
>> >> However, this still cannot fix the problems like "Surface 3".
>> >> We'll still need a new usage model for such platforms (no open event).
>> >
>> > No, for surface 3 you simply need to add polling of "_LID" method to the
>> > button driver.
>> >
>> > What are the other devices that mess up lid handling?
>> >
>>
>> I also would be interested in knowing how much issues you are facing
>> compared to the average number of "good" laptops. IIRC, you talked
>> about 3 (counting the Surface 3), but I believe you had more in mind.
>
> [Lv Zheng]
> Yes.
> However they happened before I started to look at the lid issues.
> I think Rui has several such experiences.
> +Rui.
>
> Thanks and best regards
> -Lv

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

* RE: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-22  9:08             ` Benjamin Tissoires
@ 2016-07-22  9:38               ` Zheng, Lv
  2016-07-24 11:28               ` Bastien Nocera
  1 sibling, 0 replies; 34+ messages in thread
From: Zheng, Lv @ 2016-07-22  9:38 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Dmitry Torokhov, Zhang, Rui, Wysocki, Rafael J, Rafael J. Wysocki,
	Brown, Len, Lv Zheng, linux-kernel@vger.kernel.org,
	linux-acpi@vger.kernel.org, Bastien Nocera:,
	linux-input@vger.kernel.org

Hi, Benjamin

> From: Benjamin Tissoires [mailto:benjamin.tissoires@gmail.com]
> Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control
> method lid device restrictions
> 
> On Fri, Jul 22, 2016 at 10:47 AM, Zheng, Lv <lv.zheng@intel.com> wrote:
> > Hi,
> >
> >> From: Benjamin Tissoires [mailto:benjamin.tissoires@gmail.com]
> >> Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI
> control
> >> method lid device restrictions
> >>
> >> On Fri, Jul 22, 2016 at 6:37 AM, Dmitry Torokhov
> >> <dmitry.torokhov@gmail.com> wrote:
> >> > Hi Lv,
> >> >
> >> > On Fri, Jul 22, 2016 at 12:24:50AM +0000, Zheng, Lv wrote:
> >> >> Hi, Dmitry
> >> >>
> >> >>
> >> >> Thanks for the review.
> >> >>
> >> >> > From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> >> >> > Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI
> >> control
> >> >> > method lid device restrictions
> >> >> >
> >> >> > On Tue, Jul 19, 2016 at 04:11:21PM +0800, Lv Zheng wrote:
> >> >> > > This patch adds documentation for the usage model of the
> control
> >> >> > method lid
> >> >> > > device.
> >> >> > >
> >> >> > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> >> >> > > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> >> >> > > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> >> >> > > Cc: Bastien Nocera: <hadess@hadess.net>
> >> >> > > Cc: linux-input@vger.kernel.org
> >> >> > > ---
> >> >> > >  Documentation/acpi/acpi-lid.txt |   89
> >> >> > +++++++++++++++++++++++++++++++++++++++
> >> >> > >  1 file changed, 89 insertions(+)
> >> >> > >  create mode 100644 Documentation/acpi/acpi-lid.txt
> >> >> > >
> >> >> > > diff --git a/Documentation/acpi/acpi-lid.txt
> >> b/Documentation/acpi/acpi-
> >> >> > lid.txt
> >> >> > > new file mode 100644
> >> >> > > index 0000000..2addedc
> >> >> > > --- /dev/null
> >> >> > > +++ b/Documentation/acpi/acpi-lid.txt
> >> >> > > @@ -0,0 +1,89 @@
> >> >> > > +Usage Model of the ACPI Control Method Lid Device
> >> >> > > +
> >> >> > > +Copyright (C) 2016, Intel Corporation
> >> >> > > +Author: Lv Zheng <lv.zheng@intel.com>
> >> >> > > +
> >> >> > > +
> >> >> > > +Abstract:
> >> >> > > +
> >> >> > > +Platforms containing lids convey lid state (open/close) to
> OSPMs
> >> using
> >> >> > a
> >> >> > > +control method lid device. To implement this, the AML tables
> issue
> >> >> > > +Notify(lid_device, 0x80) to notify the OSPMs whenever the lid
> >> state has
> >> >> > > +changed. The _LID control method for the lid device must be
> >> >> > implemented to
> >> >> > > +report the "current" state of the lid as either "opened" or
> "closed".
> >> >> > > +
> >> >> > > +This document describes the restrictions and the expections of
> the
> >> >> > Linux
> >> >> > > +ACPI lid device driver.
> >> >> > > +
> >> >> > > +
> >> >> > > +1. Restrictions of the returning value of the _LID control
> method
> >> >> > > +
> >> >> > > +The _LID control method is described to return the "current" lid
> >> state.
> >> >> > > +However the word of "current" has ambiguity, many AML
> tables
> >> return
> >> >> > the lid
> >> >> >
> >> >> > Can this be fixed in the next ACPI revision?
> >> >> [Lv Zheng]
> >> >> Even this is fixed in the ACPI specification, there are platforms
> already
> >> doing this.
> >> >> Especially platforms from Microsoft.
> >> >> So the de-facto standard OS won't care about the change.
> >> >> And we can still see such platforms.
> >> >>
> >> >> Here is an example from Surface 3:
> >> >>
> >> >> DefinitionBlock ("dsdt.aml", "DSDT", 2, "ALASKA", "A M I ",
> 0x01072009)
> >> >> {
> >> >>     Scope (_SB)
> >> >>     {
> >> >>         Device (PCI0)
> >> >>         {
> >> >>             Name (_HID, EisaId ("PNP0A08"))  // _HID: Hardware ID
> >> >>             Name (_CID, EisaId ("PNP0A03"))  // _CID: Compatible ID
> >> >>             Device (SPI1)
> >> >>             {
> >> >>                 Name (_HID, "8086228E")  // _HID: Hardware ID
> >> >>                 Device (NTRG)
> >> >>                 {
> >> >>                     Name (_HID, "MSHW0037")  // _HID: Hardware ID
> >> >>                 }
> >> >>             }
> >> >>         }
> >> >>
> >> >>         Device (LID)
> >> >>         {
> >> >>             Name (_HID, EisaId ("PNP0C0D"))
> >> >>             Name (LIDB, Zero)
> >> >
> >> > Start with lid closed? In any case might be wrong.
> >>
> >> Actually the initial value doesn't matter if the gpiochip triggers the
> >> _EC4 at boot, which it should
> >> (https://github.com/hadess/fedora-surface3-
> >> kernel/commit/13200f81662c1c0b58137947c3e6c000fe62a2ba,
> >> still unsubmitted)
> >>
> >> >
> >> >>             Method (_LID, 0, NotSerialized)
> >> >>             {
> >> >>                 Return (LIDB)
> >> >
> >> > So "_LID" returns the last state read by "_EC4". "_EC4" is
> >> > edge-triggered and will be evaluated every time gpio changes state.
> >>
> >> That's assuming the change happens while the system is on. If you go
> >> into suspend by closing the LID. Open it while on suspend and then hit
> >> the power button given that the system doesn't wake up when the lid
> is
> >> opened, the edge change was made while the system is asleep, and we
> >> are screwed (from an ACPI point of view). See my next comment for a
> >> solution.
> >>
> > [Lv Zheng]
> > I actually not sure if polling can fix all issues.
> > For example.
> > If a platform reporting "close" after resuming.
> > Then polling _LID will always return "close".
> > And the userspace can still get the "close" not "open".
> > So it seems polling is not working for such platforms (cached value,
> initial close).
> > Surface 3 is not the only platform caching an initial close value.
> > There are 2 traditional platforms listed in the patch description.
> >
> >> >
> >> >>             }
> >> >>         }
> >> >>
> >> >>         Device (GPO0)
> >> >>         {
> >> >>             Name (_HID, "INT33FF")  // _HID: Hardware ID
> >> >>             OperationRegion (GPOR, GeneralPurposeIo, Zero, One)
> >> >>             Field (GPOR, ByteAcc, NoLock, Preserve)
> >> >>             {
> >> >>                 Connection (
> >> >>                     GpioIo (Shared, PullNone, 0x0000, 0x0000,
> >> IoRestrictionNone,
> >> >>                         "\\_SB.GPO0", 0x00, ResourceConsumer, ,
> >> >>                         )
> >> >>                         {   // Pin list
> >> >>                             0x004C
> >> >>                         }
> >> >>                 ),
> >> >>                 HELD,   1
> >> >
> >> > Is it possible to read state of this GPIO from userspace on startup to
> >> > correct the initial state?
> >> >
> >> >>             }
> >> >>             Method (_E4C, 0, Serialized)
> >> >>             {
> >> >>                 If (LEqual(HELD, One))
> >> >>                 {
> >> >>                     Store(One, ^^LID.LIDB)
> >> >>
> >> >> There is no "open" event generated by "Surface 3".
> >> >
> >> > Right so we update the state correctly, we just forgot to send the
> >> > notification. Nothing that polling can't fix.
> >>
> >> Actually, I have a better (though more hackish) way of avoiding polling:
> >> https://github.com/hadess/fedora-surface3-
> >> kernel/blob/5e5775b9bdc308d665064387e0b144ee48e7b243/0002-
> WIP-
> >> add-custom-surface3-platform-device-for-controll.patch
> >>
> >> Given that the notification is forwarded to the touchscreen anyway, we
> >> can unregister the generic (and buggy) acpi button driver for the LID
> >> and create our own based on this specific DSDT.
> >> We can also make sure the LID state is also correct because of the WMI
> >> method which allows to read the actual value of the GPIO connected to
> >> the cover without using the cached (and most of the time wrong) acpi
> >> LID.LIDB value.
> >>
> >> I still yet have to submit this, but with this patch, but we can
> >> consider the Surface 3 as working and not an issue anymore.
> >>
> > [Lv Zheng]
> > That could make surface 3 dependent on WMI driver, not ACPI button
> driver.
> > Will this affect other buttons?
> > For example, power button/sleep button.
> 
> TLDR: no, there is no impact on other buttons.
> 
> There are 2 reasons why the impact is limited:
> - the patch only removes the input node that contains the LID, and it
> is the only one event in the input node
> - power/sleep, volume +/- are not handled by ACPI as this is a reduced
> platform and these buttons are not notified by ACPI. So we need an
> adaptation of the GPIO button array for it to be working (patch
> already submitted but I found a non-acpi platform issue, and then not
> enough time to fix and send an updated version).
> 
> >
> > Our approach is to make ACPI button driver working.
> > Though this may lead to ABI changes.
> 
> Yes, I know you want to fix ACPI button for future non working
> tablets/laptops. This is why I gave my rev-by in this series.
> 
> >
> >> >
> >> >>
> >> >>                 }
> >> >>                 Else
> >> >>                 {
> >> >>                     Store(Zero, ^^LID.LIDB)
> >> >>                     Notify (LID, 0x80)
> >> >>
> >> >> There is only "close" event generated by "Surface 3".
> >> >> Thus they are not paired.
> >> >>
> >> >>                 }
> >> >>                 Notify (^^PCI0.SPI1.NTRG, One) // Device Check
> >> >>             }
> >> >>         }
> >> >>     }
> >> >> }
> >> >>
> >> >> >
> >> >> > > +state upon the last lid notification instead of returning the lid
> state
> >> >> > > +upon the last _LID evaluation. There won't be difference when
> the
> >> _LID
> >> >> > > +control method is evaluated during the runtime, the problem is
> its
> >> >> > initial
> >> >> > > +returning value. When the AML tables implement this control
> >> method
> >> >> > with
> >> >> > > +cached value, the initial returning value is likely not reliable.
> There
> >> are
> >> >> > > +simply so many examples always retuning "closed" as initial lid
> >> state.
> >> >> > > +
> >> >> > > +2. Restrictions of the lid state change notifications
> >> >> > > +
> >> >> > > +There are many AML tables never notifying when the lid device
> >> state is
> >> >> > > +changed to "opened". Thus the "opened" notification is not
> >> guaranteed.
> >> >> > > +
> >> >> > > +But it is guaranteed that the AML tables always notify "closed"
> >> when
> >> >> > the
> >> >> > > +lid state is changed to "closed". The "closed" notification is
> >> normally
> >> >> > > +used to trigger some system power saving operations on
> Windows.
> >> >> > Since it is
> >> >> > > +fully tested, the "closed" notification is reliable for all AML
> tables.
> >> >> > > +
> >> >> > > +3. Expections for the userspace users of the ACPI lid device
> driver
> >> >> > > +
> >> >> > > +The ACPI button driver exports the lid state to the userspace
> via
> >> the
> >> >> > > +following file:
> >> >> > > +  /proc/acpi/button/lid/LID0/state
> >> >> > > +This file actually calls the _LID control method described above.
> >> And
> >> >> > given
> >> >> > > +the previous explanation, it is not reliable enough on some
> >> platforms.
> >> >> > So
> >> >> > > +it is advised for the userspace program to not to solely rely on
> this
> >> file
> >> >> > > +to determine the actual lid state.
> >> >> > > +
> >> >> > > +The ACPI button driver emits 2 kinds of events to the user
> space:
> >> >> > > +  SW_LID
> >> >> > > +   When the lid state/event is reliable, the userspace can behave
> >> >> > > +   according to this input switch event.
> >> >> > > +   This is a mode prepared for backward compatiblity.
> >> >> > > +  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
> >> >> > > +   When the lid state/event is not reliable, the userspace should
> >> behave
> >> >> > > +   according to these 2 input key events.
> >> >> > > +   New userspace programs may only be prepared for the input
> key
> >> >> > events.
> >> >> >
> >> >> > No, absolutely not. If some x86 vendors managed to mess up their
> >> >> > firmware implementations that does not mean that everyone now
> >> has to
> >> >> > abandon working perfectly well for them SW_LID events and rush
> to
> >> >> > switch
> >> >> > to a brand new event.
> >> >> [Lv Zheng]
> >> >> However there is no clear wording in the ACPI specification asking
> the
> >> vendors to achieve paired lid events.
> >> >>
> >> >> >
> >> >> > Apparently were are a few issues, main is that some systems not
> >> reporting
> >> >> > "open" event. This can be dealt with by userspace "writing" to the
> >> >> > lid's evdev device EV_SW/SW_LID/0 event upon system resume
> (and
> >> >> > startup)
> >> >> > for selected systems. This will mean that if system wakes up not
> >> because
> >> >> > LID is open we'll incorrectly assume that it is, but we can either
> add
> >> >> > more smarts to the process emitting SW_LID event or simply say
> >> "well,
> >> >> > tough, the hardware is crappy" and bug vendor to see if they can
> fix
> >> the
> >> >> > issue (if not for current firmware them for next).
> >> >> [Lv Zheng]
> >> >> The problem is there is no vendor actually caring about fixing this
> >> "issue".
> >> >> Because Windows works well with their firmware.
> >> >> Then finally becomes a big table customization business for our
> team.
> >> >
> >> > Well, OK. But you do not expect that we will redo up and down the
> stack
> >> > lid handling just because MS messed up DSDT on Surface 3? No, let
> them
> >> > know (they now care about Linux, right?) so Surface 4 works and
> quirk
> >> > the behavior for Surface 3.
> >> >
> >>
> >> From what I understood, it was more than just the Surface 3. Other
> >> laptops were having issues and Lv's team gave up on fixing those
> >> machines.
> >>
> >> >>
> >> >> >
> >> >> > As an additional workaround, we can toggle the LID switch off and
> on
> >> >> > when we get notification, much like your proposed patch does for
> the
> >> key
> >> >> > events.
> >>
> >> I really don't like this approach. The problem being that we will fix
> >> the notifications to user space, but nothing will tell userspace that
> >> the LID state is known to be wrong.
> >> OTOH, I already agreed for a hwdb in userspace so I guess this point is
> >> moot.
> >>
> >> Having both events (one SW for reliable HW, always correct, and one
> >> KEY for unreliable HW) allows userspace to make a clear distinction
> >> between the working and non working events and they can continue to
> >> keep using the polling of the SW node without extra addition.
> >>
> > [Lv Zheng]
> > I think this solution is good and fair for all of the vendors. :-)
> >
> >> Anyway, if the kernel doesn't want to (or can't) fix the actual issue
> >> (by making sure the DSDT is reliable), userspace needs to be changed
> >> so any solution will be acceptable.
> > [Lv Zheng]
> > I think the answer is "can't".
> > If we introduced too many workarounds into acpi button driver,
> > in order to make something working while the platform firmware
> doesn't expect it to be working,
> > then we'll start to worry about breaking good laptops.
> 
> Then you just need to amend the documentation to say that the fallback
> of the KEY events is not the "future" but a way to get events on some
> reduced platforms and it will not be the default.
[Lv Zheng] 
OK.

> Please make sure userspace knows that the default is the good SW_LID,
> and some particular cases will need to be handled through the KEY
> events, not the other way around.
[Lv Zheng] 
However, we were thinking that user space should just switch to use the key events when the lid events are from ACPI button driver.
So you mean I need to change this to say that the key events should only be used for special hardware.
Right?

> 
> [few thoughts later]
> 
> How about:
> - you send only one patch with the SW_LID ON/OFF or OFF/ON when we
> receive the notification on buggy platform
> - in the same patch, you add the documentation saying that on most
> platforms, LID is reliable but some don't provide a reliable LID
> state, but you guarantee to send an event when the state changes

[Lv Zheng] 
If I understand correctly, you mean I should improve the documentation.
Making the SW_LID the expected Linux behavior.
But allowing KEY_LID_XXX as a quirk mechanism to handle old platforms.

If so, I think I only need to refresh the document.
Right?

Cheers,
Lv

> - in userspace, we add the hwdb which says "on this particular
> platform, don't rely on the actual state, but wait for events" -> this
> basically removes the polling on these platforms.
> 
> Bastien, Dmitry?
> 
> I still don't like relying on userspace to actually set the SW_LID
> back to open on resume, as we should not rely on some userspace
> program to set the value (but if logind really wants it, it's up to
> them).
> 
> Cheers,
> Benjamin
> 
> >
> >>
> >> >> [Lv Zheng]
> >> >> I think this is doable, I'll refresh my patchset to address your this
> >> comment.
> >> >> By inserting open/close events when next close/open event arrives
> >> after a certain period,
> >> >> this may fix some issues for the old programs.
> >> >> Where user may be required to open/close lid twice to trigger 2nd
> >> suspend.
> >> >>
> >> >> However, this still cannot fix the problems like "Surface 3".
> >> >> We'll still need a new usage model for such platforms (no open
> event).
> >> >
> >> > No, for surface 3 you simply need to add polling of "_LID" method to
> the
> >> > button driver.
> >> >
> >> > What are the other devices that mess up lid handling?
> >> >
> >>
> >> I also would be interested in knowing how much issues you are facing
> >> compared to the average number of "good" laptops. IIRC, you talked
> >> about 3 (counting the Surface 3), but I believe you had more in mind.
> >
> > [Lv Zheng]
> > Yes.
> > However they happened before I started to look at the lid issues.
> > I think Rui has several such experiences.
> > +Rui.
> >
> > Thanks and best regards
> > -Lv

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

* RE: [PATCH v5 1/3] ACPI / button: Add missing event to keep SW_LID running without additional event loss
  2016-07-22  6:24 ` [PATCH v5 1/3] ACPI / button: Add missing event to keep SW_LID running without additional event loss Lv Zheng
@ 2016-07-22 10:26   ` Zheng, Lv
  2016-07-23 12:37   ` Rafael J. Wysocki
  1 sibling, 0 replies; 34+ messages in thread
From: Zheng, Lv @ 2016-07-22 10:26 UTC (permalink / raw)
  To: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len
  Cc: Lv Zheng, linux-kernel@vger.kernel.org,
	linux-acpi@vger.kernel.org, Dmitry Torokhov, Benjamin Tissoires,
	Bastien Nocera:, linux-input@vger.kernel.org

Hi, Dmitry

I'm considering what the future should be.

What if we drop PATCH 02, stop introducing KEY_LID_XXX events.
And switch ACPI button driver to lid_init_state=ignore.
So that whatever the initial state is close or open, no events will be sent to the userspace.
In the meanwhile, userspace tunes its behavior.
With PATCH 01, 2nd close can arrive to userspace, so that can be tuned to:
1. User space stops asking kernel to send open notification.
2. And only acts against "close" notification.

Thanks and best regards
-Lv

> From: Zheng, Lv
> Subject: [PATCH v5 1/3] ACPI / button: Add missing event to keep SW_LID
> running without additional event loss
> 
> There are several possibilities that a lid event can be lost. For example,
> EC event queue full, or the resume order of the underlying drivers.
> 
> When the event loss happens, new event may also be lost due to the type
> of
> the SW_LID (switch event). The 2nd loss is what we want to avoid.
> 
> This patch adds a mechanism to insert lid events as a compensation for
> the
> switch event nature of the lid events in order to avoid the 2nd loss.
> 
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> Cc: Bastien Nocera: <hadess@hadess.net>
> Cc: linux-input@vger.kernel.org
> ---
>  drivers/acpi/button.c |   21 ++++++++++++++++++++-
>  1 file changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> index 148f4e5..41fd21d 100644
> --- a/drivers/acpi/button.c
> +++ b/drivers/acpi/button.c
> @@ -104,6 +104,8 @@ struct acpi_button {
>  	struct input_dev *input;
>  	char phys[32];			/* for input device */
>  	unsigned long pushed;
> +	int sw_last_state;
> +	unsigned long sw_last_time;
>  	bool suspended;
>  };
> 
> @@ -111,6 +113,10 @@ static
> BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
>  static struct acpi_device *lid_device;
>  static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
> 
> +static unsigned long lid_report_interval __read_mostly = 500;
> +module_param(lid_report_interval, ulong, 0644);
> +MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key
> events");
> +
>  /* --------------------------------------------------------------------------
>                                FS Interface (/proc)
>     -------------------------------------------------------------------------- */
> @@ -133,11 +139,22 @@ static int acpi_lid_evaluate_state(struct
> acpi_device *device)
>  static int acpi_lid_notify_state(struct acpi_device *device, int state)
>  {
>  	struct acpi_button *button = acpi_driver_data(device);
> +	unsigned long sw_tout;
>  	int ret;
> 
> -	/* input layer checks if event is redundant */
> +	/* Send the switch event */
> +	sw_tout = button->sw_last_time +
> +		  msecs_to_jiffies(lid_report_interval);
> +	if (time_after(jiffies, sw_tout) &&
> +	    (button->sw_last_state == !!state)) {
> +		/* Send the complement switch event */
> +		input_report_switch(button->input, SW_LID, state);
> +		input_sync(button->input);
> +	}
>  	input_report_switch(button->input, SW_LID, !state);
>  	input_sync(button->input);
> +	button->sw_last_state = !!state;
> +	button->sw_last_time = jiffies;
> 
>  	if (state)
>  		pm_wakeup_event(&device->dev, 0);
> @@ -407,6 +424,8 @@ static int acpi_button_add(struct acpi_device
> *device)
>  		strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
>  		sprintf(class, "%s/%s",
>  			ACPI_BUTTON_CLASS,
> ACPI_BUTTON_SUBCLASS_LID);
> +		button->sw_last_state = !!acpi_lid_evaluate_state(device);
> +		button->sw_last_time = jiffies;
>  	} else {
>  		printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
>  		error = -ENODEV;
> --
> 1.7.10


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

* Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-22  6:55         ` Benjamin Tissoires
  2016-07-22  8:47           ` Zheng, Lv
@ 2016-07-22 17:02           ` Dmitry Torokhov
  2016-07-23 12:17             ` Zheng, Lv
  1 sibling, 1 reply; 34+ messages in thread
From: Dmitry Torokhov @ 2016-07-22 17:02 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Zheng, Lv, Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len,
	Lv Zheng, linux-kernel@vger.kernel.org,
	linux-acpi@vger.kernel.org, Bastien Nocera:,
	linux-input@vger.kernel.org

On Fri, Jul 22, 2016 at 08:55:00AM +0200, Benjamin Tissoires wrote:
> On Fri, Jul 22, 2016 at 6:37 AM, Dmitry Torokhov
> <dmitry.torokhov@gmail.com> wrote:
> > Hi Lv,
> >
> > On Fri, Jul 22, 2016 at 12:24:50AM +0000, Zheng, Lv wrote:
> >> Hi, Dmitry
> >>
> >>
> >> Thanks for the review.
> >>
> >> > From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> >> > Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control
> >> > method lid device restrictions
> >> >
> >> > On Tue, Jul 19, 2016 at 04:11:21PM +0800, Lv Zheng wrote:
> >> > > This patch adds documentation for the usage model of the control
> >> > method lid
> >> > > device.
> >> > >
> >> > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> >> > > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> >> > > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> >> > > Cc: Bastien Nocera: <hadess@hadess.net>
> >> > > Cc: linux-input@vger.kernel.org
> >> > > ---
> >> > >  Documentation/acpi/acpi-lid.txt |   89
> >> > +++++++++++++++++++++++++++++++++++++++
> >> > >  1 file changed, 89 insertions(+)
> >> > >  create mode 100644 Documentation/acpi/acpi-lid.txt
> >> > >
> >> > > diff --git a/Documentation/acpi/acpi-lid.txt b/Documentation/acpi/acpi-
> >> > lid.txt
> >> > > new file mode 100644
> >> > > index 0000000..2addedc
> >> > > --- /dev/null
> >> > > +++ b/Documentation/acpi/acpi-lid.txt
> >> > > @@ -0,0 +1,89 @@
> >> > > +Usage Model of the ACPI Control Method Lid Device
> >> > > +
> >> > > +Copyright (C) 2016, Intel Corporation
> >> > > +Author: Lv Zheng <lv.zheng@intel.com>
> >> > > +
> >> > > +
> >> > > +Abstract:
> >> > > +
> >> > > +Platforms containing lids convey lid state (open/close) to OSPMs using
> >> > a
> >> > > +control method lid device. To implement this, the AML tables issue
> >> > > +Notify(lid_device, 0x80) to notify the OSPMs whenever the lid state has
> >> > > +changed. The _LID control method for the lid device must be
> >> > implemented to
> >> > > +report the "current" state of the lid as either "opened" or "closed".
> >> > > +
> >> > > +This document describes the restrictions and the expections of the
> >> > Linux
> >> > > +ACPI lid device driver.
> >> > > +
> >> > > +
> >> > > +1. Restrictions of the returning value of the _LID control method
> >> > > +
> >> > > +The _LID control method is described to return the "current" lid state.
> >> > > +However the word of "current" has ambiguity, many AML tables return
> >> > the lid
> >> >
> >> > Can this be fixed in the next ACPI revision?
> >> [Lv Zheng]
> >> Even this is fixed in the ACPI specification, there are platforms already doing this.
> >> Especially platforms from Microsoft.
> >> So the de-facto standard OS won't care about the change.
> >> And we can still see such platforms.
> >>
> >> Here is an example from Surface 3:
> >>
> >> DefinitionBlock ("dsdt.aml", "DSDT", 2, "ALASKA", "A M I ", 0x01072009)
> >> {
> >>     Scope (_SB)
> >>     {
> >>         Device (PCI0)
> >>         {
> >>             Name (_HID, EisaId ("PNP0A08"))  // _HID: Hardware ID
> >>             Name (_CID, EisaId ("PNP0A03"))  // _CID: Compatible ID
> >>             Device (SPI1)
> >>             {
> >>                 Name (_HID, "8086228E")  // _HID: Hardware ID
> >>                 Device (NTRG)
> >>                 {
> >>                     Name (_HID, "MSHW0037")  // _HID: Hardware ID
> >>                 }
> >>             }
> >>         }
> >>
> >>         Device (LID)
> >>         {
> >>             Name (_HID, EisaId ("PNP0C0D"))
> >>             Name (LIDB, Zero)
> >
> > Start with lid closed? In any case might be wrong.
> 
> Actually the initial value doesn't matter if the gpiochip triggers the
> _EC4 at boot, which it should
> (https://github.com/hadess/fedora-surface3-kernel/commit/13200f81662c1c0b58137947c3e6c000fe62a2ba,
> still unsubmitted)
> 
> >
> >>             Method (_LID, 0, NotSerialized)
> >>             {
> >>                 Return (LIDB)
> >
> > So "_LID" returns the last state read by "_EC4". "_EC4" is
> > edge-triggered and will be evaluated every time gpio changes state.
> 
> That's assuming the change happens while the system is on. If you go
> into suspend by closing the LID. Open it while on suspend and then hit
> the power button given that the system doesn't wake up when the lid is
> opened, the edge change was made while the system is asleep, and we
> are screwed (from an ACPI point of view). See my next comment for a
> solution.

Can we extend the patch you referenced above and do similar thing on
resume? Won't help Surface but might others.

> 
> >
> >>             }
> >>         }
> >>
> >>         Device (GPO0)
> >>         {
> >>             Name (_HID, "INT33FF")  // _HID: Hardware ID
> >>             OperationRegion (GPOR, GeneralPurposeIo, Zero, One)
> >>             Field (GPOR, ByteAcc, NoLock, Preserve)
> >>             {
> >>                 Connection (
> >>                     GpioIo (Shared, PullNone, 0x0000, 0x0000, IoRestrictionNone,
> >>                         "\\_SB.GPO0", 0x00, ResourceConsumer, ,
> >>                         )
> >>                         {   // Pin list
> >>                             0x004C
> >>                         }
> >>                 ),
> >>                 HELD,   1
> >
> > Is it possible to read state of this GPIO from userspace on startup to
> > correct the initial state?
> >
> >>             }
> >>             Method (_E4C, 0, Serialized)
> >>             {
> >>                 If (LEqual(HELD, One))
> >>                 {
> >>                     Store(One, ^^LID.LIDB)
> >>
> >> There is no "open" event generated by "Surface 3".
> >
> > Right so we update the state correctly, we just forgot to send the
> > notification. Nothing that polling can't fix.
> 
> Actually, I have a better (though more hackish) way of avoiding polling:
> https://github.com/hadess/fedora-surface3-kernel/blob/5e5775b9bdc308d665064387e0b144ee48e7b243/0002-WIP-add-custom-surface3-platform-device-for-controll.patch
> 
> Given that the notification is forwarded to the touchscreen anyway, we
> can unregister the generic (and buggy) acpi button driver for the LID
> and create our own based on this specific DSDT.
> We can also make sure the LID state is also correct because of the WMI
> method which allows to read the actual value of the GPIO connected to
> the cover without using the cached (and most of the time wrong) acpi
> LID.LIDB value.
> 
> I still yet have to submit this, but with this patch, but we can
> consider the Surface 3 as working and not an issue anymore.
> 
> >
> >>
> >>                 }
> >>                 Else
> >>                 {
> >>                     Store(Zero, ^^LID.LIDB)
> >>                     Notify (LID, 0x80)
> >>
> >> There is only "close" event generated by "Surface 3".
> >> Thus they are not paired.
> >>
> >>                 }
> >>                 Notify (^^PCI0.SPI1.NTRG, One) // Device Check
> >>             }
> >>         }
> >>     }
> >> }
> >>
> >> >
> >> > > +state upon the last lid notification instead of returning the lid state
> >> > > +upon the last _LID evaluation. There won't be difference when the _LID
> >> > > +control method is evaluated during the runtime, the problem is its
> >> > initial
> >> > > +returning value. When the AML tables implement this control method
> >> > with
> >> > > +cached value, the initial returning value is likely not reliable. There are
> >> > > +simply so many examples always retuning "closed" as initial lid state.
> >> > > +
> >> > > +2. Restrictions of the lid state change notifications
> >> > > +
> >> > > +There are many AML tables never notifying when the lid device state is
> >> > > +changed to "opened". Thus the "opened" notification is not guaranteed.
> >> > > +
> >> > > +But it is guaranteed that the AML tables always notify "closed" when
> >> > the
> >> > > +lid state is changed to "closed". The "closed" notification is normally
> >> > > +used to trigger some system power saving operations on Windows.
> >> > Since it is
> >> > > +fully tested, the "closed" notification is reliable for all AML tables.
> >> > > +
> >> > > +3. Expections for the userspace users of the ACPI lid device driver
> >> > > +
> >> > > +The ACPI button driver exports the lid state to the userspace via the
> >> > > +following file:
> >> > > +  /proc/acpi/button/lid/LID0/state
> >> > > +This file actually calls the _LID control method described above. And
> >> > given
> >> > > +the previous explanation, it is not reliable enough on some platforms.
> >> > So
> >> > > +it is advised for the userspace program to not to solely rely on this file
> >> > > +to determine the actual lid state.
> >> > > +
> >> > > +The ACPI button driver emits 2 kinds of events to the user space:
> >> > > +  SW_LID
> >> > > +   When the lid state/event is reliable, the userspace can behave
> >> > > +   according to this input switch event.
> >> > > +   This is a mode prepared for backward compatiblity.
> >> > > +  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
> >> > > +   When the lid state/event is not reliable, the userspace should behave
> >> > > +   according to these 2 input key events.
> >> > > +   New userspace programs may only be prepared for the input key
> >> > events.
> >> >
> >> > No, absolutely not. If some x86 vendors managed to mess up their
> >> > firmware implementations that does not mean that everyone now has to
> >> > abandon working perfectly well for them SW_LID events and rush to
> >> > switch
> >> > to a brand new event.
> >> [Lv Zheng]
> >> However there is no clear wording in the ACPI specification asking the vendors to achieve paired lid events.
> >>
> >> >
> >> > Apparently were are a few issues, main is that some systems not reporting
> >> > "open" event. This can be dealt with by userspace "writing" to the
> >> > lid's evdev device EV_SW/SW_LID/0 event upon system resume (and
> >> > startup)
> >> > for selected systems. This will mean that if system wakes up not because
> >> > LID is open we'll incorrectly assume that it is, but we can either add
> >> > more smarts to the process emitting SW_LID event or simply say "well,
> >> > tough, the hardware is crappy" and bug vendor to see if they can fix the
> >> > issue (if not for current firmware them for next).
> >> [Lv Zheng]
> >> The problem is there is no vendor actually caring about fixing this "issue".
> >> Because Windows works well with their firmware.
> >> Then finally becomes a big table customization business for our team.
> >
> > Well, OK. But you do not expect that we will redo up and down the stack
> > lid handling just because MS messed up DSDT on Surface 3? No, let them
> > know (they now care about Linux, right?) so Surface 4 works and quirk
> > the behavior for Surface 3.
> >
> 
> From what I understood, it was more than just the Surface 3. Other
> laptops were having issues and Lv's team gave up on fixing those
> machines.
> 
> >>
> >> >
> >> > As an additional workaround, we can toggle the LID switch off and on
> >> > when we get notification, much like your proposed patch does for the key
> >> > events.
> 
> I really don't like this approach. The problem being that we will fix
> the notifications to user space, but nothing will tell userspace that
> the LID state is known to be wrong.
> OTOH, I already agreed for a hwdb in userspace so I guess this point is moot.

Yeah, I do not like this too much either, I would prefer if we could dig
out and communicate real state of LID to userspace. It sounds we have
reasonable way for the Surfaces (I assume the others will have the same
issues as 3), and we need to figure out what the other troublemakers
are.

> 
> Having both events (one SW for reliable HW, always correct, and one
> KEY for unreliable HW) allows userspace to make a clear distinction
> between the working and non working events and they can continue to
> keep using the polling of the SW node without extra addition.

At this point I would prefer not adding any "unreliable" events just yet
and concentrate on finding working solution for SW_LID.

Thanks.

-- 
Dmitry

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

* Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-22  8:37         ` Zheng, Lv
@ 2016-07-22 17:22           ` Dmitry Torokhov
  2016-07-23 11:57             ` Zheng, Lv
  0 siblings, 1 reply; 34+ messages in thread
From: Dmitry Torokhov @ 2016-07-22 17:22 UTC (permalink / raw)
  To: Zheng, Lv
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	Benjamin Tissoires, Bastien Nocera:, linux-input@vger.kernel.org

On Fri, Jul 22, 2016 at 08:37:50AM +0000, Zheng, Lv wrote:
> Hi, Dmitry
> 
> Thanks for the review.
> 
> > From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> > Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control
> > method lid device restrictions
> > 
> > Hi Lv,
> > 
> > On Fri, Jul 22, 2016 at 12:24:50AM +0000, Zheng, Lv wrote:
> > > Hi, Dmitry
> > >
> > >
> > > Thanks for the review.
> > >
> > > > From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> > > > Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI
> > control
> > > > method lid device restrictions
> > > >
> > > > On Tue, Jul 19, 2016 at 04:11:21PM +0800, Lv Zheng wrote:
> > > > > This patch adds documentation for the usage model of the control
> > > > method lid
> > > > > device.
> > > > >
> > > > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > > > > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > > > > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> > > > > Cc: Bastien Nocera: <hadess@hadess.net>
> > > > > Cc: linux-input@vger.kernel.org
> > > > > ---
> > > > >  Documentation/acpi/acpi-lid.txt |   89
> > > > +++++++++++++++++++++++++++++++++++++++
> > > > >  1 file changed, 89 insertions(+)
> > > > >  create mode 100644 Documentation/acpi/acpi-lid.txt
> > > > >
> > > > > diff --git a/Documentation/acpi/acpi-lid.txt
> > b/Documentation/acpi/acpi-
> > > > lid.txt
> > > > > new file mode 100644
> > > > > index 0000000..2addedc
> > > > > --- /dev/null
> > > > > +++ b/Documentation/acpi/acpi-lid.txt
> > > > > @@ -0,0 +1,89 @@
> > > > > +Usage Model of the ACPI Control Method Lid Device
> > > > > +
> > > > > +Copyright (C) 2016, Intel Corporation
> > > > > +Author: Lv Zheng <lv.zheng@intel.com>
> > > > > +
> > > > > +
> > > > > +Abstract:
> > > > > +
> > > > > +Platforms containing lids convey lid state (open/close) to OSPMs
> > using
> > > > a
> > > > > +control method lid device. To implement this, the AML tables issue
> > > > > +Notify(lid_device, 0x80) to notify the OSPMs whenever the lid state
> > has
> > > > > +changed. The _LID control method for the lid device must be
> > > > implemented to
> > > > > +report the "current" state of the lid as either "opened" or "closed".
> > > > > +
> > > > > +This document describes the restrictions and the expections of the
> > > > Linux
> > > > > +ACPI lid device driver.
> > > > > +
> > > > > +
> > > > > +1. Restrictions of the returning value of the _LID control method
> > > > > +
> > > > > +The _LID control method is described to return the "current" lid
> > state.
> > > > > +However the word of "current" has ambiguity, many AML tables
> > return
> > > > the lid
> > > >
> > > > Can this be fixed in the next ACPI revision?
> > > [Lv Zheng]
> > > Even this is fixed in the ACPI specification, there are platforms already
> > doing this.
> > > Especially platforms from Microsoft.
> > > So the de-facto standard OS won't care about the change.
> > > And we can still see such platforms.
> > >
> > > Here is an example from Surface 3:
> > >
> > > DefinitionBlock ("dsdt.aml", "DSDT", 2, "ALASKA", "A M I ", 0x01072009)
> > > {
> > >     Scope (_SB)
> > >     {
> > >         Device (PCI0)
> > >         {
> > >             Name (_HID, EisaId ("PNP0A08"))  // _HID: Hardware ID
> > >             Name (_CID, EisaId ("PNP0A03"))  // _CID: Compatible ID
> > >             Device (SPI1)
> > >             {
> > >                 Name (_HID, "8086228E")  // _HID: Hardware ID
> > >                 Device (NTRG)
> > >                 {
> > >                     Name (_HID, "MSHW0037")  // _HID: Hardware ID
> > >                 }
> > >             }
> > >         }
> > >
> > >         Device (LID)
> > >         {
> > >             Name (_HID, EisaId ("PNP0C0D"))
> > >             Name (LIDB, Zero)
> > 
> > Start with lid closed? In any case might be wrong.
> [Lv Zheng] 
> And we validated with qemu that during boot, Windows7 evaluates _LID once but doesn't get suspended because of this value.
> So we think Windows only suspends against "notification" not _LID evaluation result.
> 
> > 
> > >             Method (_LID, 0, NotSerialized)
> > >             {
> > >                 Return (LIDB)
> > 
> > So "_LID" returns the last state read by "_EC4". "_EC4" is
> > edge-triggered and will be evaluated every time gpio changes state.
> [Lv Zheng] 
> Right.
> 
> > 
> > >             }
> > >         }
> > >
> > >         Device (GPO0)
> > >         {
> > >             Name (_HID, "INT33FF")  // _HID: Hardware ID
> > >             OperationRegion (GPOR, GeneralPurposeIo, Zero, One)
> > >             Field (GPOR, ByteAcc, NoLock, Preserve)
> > >             {
> > >                 Connection (
> > >                     GpioIo (Shared, PullNone, 0x0000, 0x0000, IoRestrictionNone,
> > >                         "\\_SB.GPO0", 0x00, ResourceConsumer, ,
> > >                         )
> > >                         {   // Pin list
> > >                             0x004C
> > >                         }
> > >                 ),
> > >                 HELD,   1
> > 
> > Is it possible to read state of this GPIO from userspace on startup to
> > correct the initial state?
> [Lv Zheng] 
> I think Benjamin has a proposal of fixing this in GPIO driver.
> 
> > 
> > >             }
> > >             Method (_E4C, 0, Serialized)
> > >             {
> > >                 If (LEqual(HELD, One))
> > >                 {
> > >                     Store(One, ^^LID.LIDB)
> > >
> > > There is no "open" event generated by "Surface 3".
> > 
> > Right so we update the state correctly, we just forgot to send the
> > notification. Nothing that polling can't fix.
> > 
> [Lv Zheng] 
> However, polling is not efficient, and not power efficient.

We would not need to do this by default, and polling on a relaxed
schedule (so that wakeups for polling coincide with other wakeups)
should not be too bad (as in fractions of percent of power spent).

> OTOH, according to the validation result, Windows never poll _LID.
> 
> > >
> > >                 }
> > >                 Else
> > >                 {
> > >                     Store(Zero, ^^LID.LIDB)
> > >                     Notify (LID, 0x80)
> > >
> > > There is only "close" event generated by "Surface 3".
> > > Thus they are not paired.
> > >
> > >                 }
> > >                 Notify (^^PCI0.SPI1.NTRG, One) // Device Check
> > >             }
> > >         }
> > >     }
> > > }
> > >
> > > >
> > > > > +state upon the last lid notification instead of returning the lid state
> > > > > +upon the last _LID evaluation. There won't be difference when the
> > _LID
> > > > > +control method is evaluated during the runtime, the problem is its
> > > > initial
> > > > > +returning value. When the AML tables implement this control
> > method
> > > > with
> > > > > +cached value, the initial returning value is likely not reliable. There
> > are
> > > > > +simply so many examples always retuning "closed" as initial lid
> > state.
> > > > > +
> > > > > +2. Restrictions of the lid state change notifications
> > > > > +
> > > > > +There are many AML tables never notifying when the lid device
> > state is
> > > > > +changed to "opened". Thus the "opened" notification is not
> > guaranteed.
> > > > > +
> > > > > +But it is guaranteed that the AML tables always notify "closed"
> > when
> > > > the
> > > > > +lid state is changed to "closed". The "closed" notification is normally
> > > > > +used to trigger some system power saving operations on Windows.
> > > > Since it is
> > > > > +fully tested, the "closed" notification is reliable for all AML tables.
> > > > > +
> > > > > +3. Expections for the userspace users of the ACPI lid device driver
> > > > > +
> > > > > +The ACPI button driver exports the lid state to the userspace via the
> > > > > +following file:
> > > > > +  /proc/acpi/button/lid/LID0/state
> > > > > +This file actually calls the _LID control method described above. And
> > > > given
> > > > > +the previous explanation, it is not reliable enough on some
> > platforms.
> > > > So
> > > > > +it is advised for the userspace program to not to solely rely on this
> > file
> > > > > +to determine the actual lid state.
> > > > > +
> > > > > +The ACPI button driver emits 2 kinds of events to the user space:
> > > > > +  SW_LID
> > > > > +   When the lid state/event is reliable, the userspace can behave
> > > > > +   according to this input switch event.
> > > > > +   This is a mode prepared for backward compatiblity.
> > > > > +  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
> > > > > +   When the lid state/event is not reliable, the userspace should
> > behave
> > > > > +   according to these 2 input key events.
> > > > > +   New userspace programs may only be prepared for the input key
> > > > events.
> > > >
> > > > No, absolutely not. If some x86 vendors managed to mess up their
> > > > firmware implementations that does not mean that everyone now has
> > to
> > > > abandon working perfectly well for them SW_LID events and rush to
> > > > switch
> > > > to a brand new event.
> > > [Lv Zheng]
> > > However there is no clear wording in the ACPI specification asking the
> > vendors to achieve paired lid events.
> > >
> > > >
> > > > Apparently were are a few issues, main is that some systems not
> > reporting
> > > > "open" event. This can be dealt with by userspace "writing" to the
> > > > lid's evdev device EV_SW/SW_LID/0 event upon system resume (and
> > > > startup)
> > > > for selected systems. This will mean that if system wakes up not
> > because
> > > > LID is open we'll incorrectly assume that it is, but we can either add
> > > > more smarts to the process emitting SW_LID event or simply say "well,
> > > > tough, the hardware is crappy" and bug vendor to see if they can fix
> > the
> > > > issue (if not for current firmware them for next).
> > > [Lv Zheng]
> > > The problem is there is no vendor actually caring about fixing this "issue".
> > > Because Windows works well with their firmware.
> > > Then finally becomes a big table customization business for our team.
> > 
> > Well, OK. But you do not expect that we will redo up and down the stack
> > lid handling just because MS messed up DSDT on Surface 3? No, let them
> > know (they now care about Linux, right?) so Surface 4 works and quirk
> > the behavior for Surface 3.
> [Lv Zheng] 
> I think there are other platforms broken.

Probably. I think we should deal with them as they come.

> 
> > 
> > >
> > > >
> > > > As an additional workaround, we can toggle the LID switch off and on
> > > > when we get notification, much like your proposed patch does for the
> > key
> > > > events.
> > > [Lv Zheng]
> > > I think this is doable, I'll refresh my patchset to address your this
> > comment.
> > > By inserting open/close events when next close/open event arrives after
> > a certain period,
> > > this may fix some issues for the old programs.
> > > Where user may be required to open/close lid twice to trigger 2nd
> > suspend.
> > >
> > > However, this still cannot fix the problems like "Surface 3".
> > > We'll still need a new usage model for such platforms (no open event).
> > 
> > No, for surface 3 you simply need to add polling of "_LID" method to the
> > button driver.
> > 
> > What are the other devices that mess up lid handling?
> [Lv Zheng] 
> The patch lists 3 of them.
> Which are known to me because they all occurred after I started to look at the lid issues.
> 
> According to my teammates.
> They've been fixing such wrong "DSDT" using customization for years.
> For example, by adding _LID(); Notify(lid) into _WAK() or EC._REG().

What did they do with them once they did the fix? Were they submitting
fixes to manufacturers? What happened to them?

Thanks.

-- 
Dmitry

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

* RE: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-22 17:22           ` Dmitry Torokhov
@ 2016-07-23 11:57             ` Zheng, Lv
  0 siblings, 0 replies; 34+ messages in thread
From: Zheng, Lv @ 2016-07-23 11:57 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	Benjamin Tissoires, Bastien Nocera:, linux-input@vger.kernel.org

Hi, Dmitry

> From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-
> owner@vger.kernel.org] On Behalf Of Dmitry Torokhov
> Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control
> method lid device restrictions
> 
> On Fri, Jul 22, 2016 at 08:37:50AM +0000, Zheng, Lv wrote:
> > Hi, Dmitry
> >
> > Thanks for the review.
> >
> > > From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> > > Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI
> control
> > > method lid device restrictions
> > >
> > > Hi Lv,
> > >
> > > On Fri, Jul 22, 2016 at 12:24:50AM +0000, Zheng, Lv wrote:
> > > > Hi, Dmitry
> > > >
> > > >
> > > > Thanks for the review.
> > > >
> > > > > From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> > > > > Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI
> > > control
> > > > > method lid device restrictions
> > > > >
> > > > > On Tue, Jul 19, 2016 at 04:11:21PM +0800, Lv Zheng wrote:
> > > > > > This patch adds documentation for the usage model of the
> control
> > > > > method lid
> > > > > > device.
> > > > > >
> > > > > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > > > > > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > > > > > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> > > > > > Cc: Bastien Nocera: <hadess@hadess.net>
> > > > > > Cc: linux-input@vger.kernel.org
> > > > > > ---
> > > > > >  Documentation/acpi/acpi-lid.txt |   89
> > > > > +++++++++++++++++++++++++++++++++++++++
> > > > > >  1 file changed, 89 insertions(+)
> > > > > >  create mode 100644 Documentation/acpi/acpi-lid.txt
> > > > > >
> > > > > > diff --git a/Documentation/acpi/acpi-lid.txt
> > > b/Documentation/acpi/acpi-
> > > > > lid.txt
> > > > > > new file mode 100644
> > > > > > index 0000000..2addedc
> > > > > > --- /dev/null
> > > > > > +++ b/Documentation/acpi/acpi-lid.txt
> > > > > > @@ -0,0 +1,89 @@
> > > > > > +Usage Model of the ACPI Control Method Lid Device
> > > > > > +
> > > > > > +Copyright (C) 2016, Intel Corporation
> > > > > > +Author: Lv Zheng <lv.zheng@intel.com>
> > > > > > +
> > > > > > +
> > > > > > +Abstract:
> > > > > > +
> > > > > > +Platforms containing lids convey lid state (open/close) to
> OSPMs
> > > using
> > > > > a
> > > > > > +control method lid device. To implement this, the AML tables
> issue
> > > > > > +Notify(lid_device, 0x80) to notify the OSPMs whenever the lid
> state
> > > has
> > > > > > +changed. The _LID control method for the lid device must be
> > > > > implemented to
> > > > > > +report the "current" state of the lid as either "opened" or
> "closed".
> > > > > > +
> > > > > > +This document describes the restrictions and the expections of
> the
> > > > > Linux
> > > > > > +ACPI lid device driver.
> > > > > > +
> > > > > > +
> > > > > > +1. Restrictions of the returning value of the _LID control method
> > > > > > +
> > > > > > +The _LID control method is described to return the "current" lid
> > > state.
> > > > > > +However the word of "current" has ambiguity, many AML tables
> > > return
> > > > > the lid
> > > > >
> > > > > Can this be fixed in the next ACPI revision?
> > > > [Lv Zheng]
> > > > Even this is fixed in the ACPI specification, there are platforms
> already
> > > doing this.
> > > > Especially platforms from Microsoft.
> > > > So the de-facto standard OS won't care about the change.
> > > > And we can still see such platforms.
> > > >
> > > > Here is an example from Surface 3:
> > > >
> > > > DefinitionBlock ("dsdt.aml", "DSDT", 2, "ALASKA", "A M I ",
> 0x01072009)
> > > > {
> > > >     Scope (_SB)
> > > >     {
> > > >         Device (PCI0)
> > > >         {
> > > >             Name (_HID, EisaId ("PNP0A08"))  // _HID: Hardware ID
> > > >             Name (_CID, EisaId ("PNP0A03"))  // _CID: Compatible ID
> > > >             Device (SPI1)
> > > >             {
> > > >                 Name (_HID, "8086228E")  // _HID: Hardware ID
> > > >                 Device (NTRG)
> > > >                 {
> > > >                     Name (_HID, "MSHW0037")  // _HID: Hardware ID
> > > >                 }
> > > >             }
> > > >         }
> > > >
> > > >         Device (LID)
> > > >         {
> > > >             Name (_HID, EisaId ("PNP0C0D"))
> > > >             Name (LIDB, Zero)
> > >
> > > Start with lid closed? In any case might be wrong.
> > [Lv Zheng]
> > And we validated with qemu that during boot, Windows7 evaluates _LID
> once but doesn't get suspended because of this value.
> > So we think Windows only suspends against "notification" not _LID
> evaluation result.
> >
> > >
> > > >             Method (_LID, 0, NotSerialized)
> > > >             {
> > > >                 Return (LIDB)
> > >
> > > So "_LID" returns the last state read by "_EC4". "_EC4" is
> > > edge-triggered and will be evaluated every time gpio changes state.
> > [Lv Zheng]
> > Right.
> >
> > >
> > > >             }
> > > >         }
> > > >
> > > >         Device (GPO0)
> > > >         {
> > > >             Name (_HID, "INT33FF")  // _HID: Hardware ID
> > > >             OperationRegion (GPOR, GeneralPurposeIo, Zero, One)
> > > >             Field (GPOR, ByteAcc, NoLock, Preserve)
> > > >             {
> > > >                 Connection (
> > > >                     GpioIo (Shared, PullNone, 0x0000, 0x0000,
> IoRestrictionNone,
> > > >                         "\\_SB.GPO0", 0x00, ResourceConsumer, ,
> > > >                         )
> > > >                         {   // Pin list
> > > >                             0x004C
> > > >                         }
> > > >                 ),
> > > >                 HELD,   1
> > >
> > > Is it possible to read state of this GPIO from userspace on startup to
> > > correct the initial state?
> > [Lv Zheng]
> > I think Benjamin has a proposal of fixing this in GPIO driver.
> >
> > >
> > > >             }
> > > >             Method (_E4C, 0, Serialized)
> > > >             {
> > > >                 If (LEqual(HELD, One))
> > > >                 {
> > > >                     Store(One, ^^LID.LIDB)
> > > >
> > > > There is no "open" event generated by "Surface 3".
> > >
> > > Right so we update the state correctly, we just forgot to send the
> > > notification. Nothing that polling can't fix.
> > >
> > [Lv Zheng]
> > However, polling is not efficient, and not power efficient.
> 
> We would not need to do this by default, and polling on a relaxed
> schedule (so that wakeups for polling coincide with other wakeups)
> should not be too bad (as in fractions of percent of power spent).
[Lv Zheng] 
Yes, this feature is on my radar.
Because:
1. There seem to be some gaps in Linux, Linux cannot make some platforms reporting LID notifications and userspace has to poll exported lid state to work it around.
2. Since we've decided that the LID driver should be responsible for sending SW_LID, we should implement the kernel polling quirk instead of the userspace quirk.

However, this feature cannot fix the issue related to this patchset.
When the platform reports cached "close" after resuming, it seems the polling can still result in "close" to be sent.
And the userspace can still suspend the platform right after resume.

Or if we start to use lid_init_state=open, we cannot achieve "dark resume" usage model.
And after a long run, the polling code may still erroneously decide to send a "close" to the userspace.
And the userspace can still suspend the platform erroneously.

So we still need the userspace to change to be compliant to this documented new usage model (at least we need such a quirk mechanism).

> 
> > OTOH, according to the validation result, Windows never poll _LID.
> >
> > > >
> > > >                 }
> > > >                 Else
> > > >                 {
> > > >                     Store(Zero, ^^LID.LIDB)
> > > >                     Notify (LID, 0x80)
> > > >
> > > > There is only "close" event generated by "Surface 3".
> > > > Thus they are not paired.
> > > >
> > > >                 }
> > > >                 Notify (^^PCI0.SPI1.NTRG, One) // Device Check
> > > >             }
> > > >         }
> > > >     }
> > > > }
> > > >
> > > > >
> > > > > > +state upon the last lid notification instead of returning the lid
> state
> > > > > > +upon the last _LID evaluation. There won't be difference when
> the
> > > _LID
> > > > > > +control method is evaluated during the runtime, the problem is
> its
> > > > > initial
> > > > > > +returning value. When the AML tables implement this control
> > > method
> > > > > with
> > > > > > +cached value, the initial returning value is likely not reliable.
> There
> > > are
> > > > > > +simply so many examples always retuning "closed" as initial lid
> > > state.
> > > > > > +
> > > > > > +2. Restrictions of the lid state change notifications
> > > > > > +
> > > > > > +There are many AML tables never notifying when the lid device
> > > state is
> > > > > > +changed to "opened". Thus the "opened" notification is not
> > > guaranteed.
> > > > > > +
> > > > > > +But it is guaranteed that the AML tables always notify "closed"
> > > when
> > > > > the
> > > > > > +lid state is changed to "closed". The "closed" notification is
> normally
> > > > > > +used to trigger some system power saving operations on
> Windows.
> > > > > Since it is
> > > > > > +fully tested, the "closed" notification is reliable for all AML
> tables.
> > > > > > +
> > > > > > +3. Expections for the userspace users of the ACPI lid device
> driver
> > > > > > +
> > > > > > +The ACPI button driver exports the lid state to the userspace via
> the
> > > > > > +following file:
> > > > > > +  /proc/acpi/button/lid/LID0/state
> > > > > > +This file actually calls the _LID control method described above.
> And
> > > > > given
> > > > > > +the previous explanation, it is not reliable enough on some
> > > platforms.
> > > > > So
> > > > > > +it is advised for the userspace program to not to solely rely on
> this
> > > file
> > > > > > +to determine the actual lid state.
> > > > > > +
> > > > > > +The ACPI button driver emits 2 kinds of events to the user space:
> > > > > > +  SW_LID
> > > > > > +   When the lid state/event is reliable, the userspace can behave
> > > > > > +   according to this input switch event.
> > > > > > +   This is a mode prepared for backward compatiblity.
> > > > > > +  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
> > > > > > +   When the lid state/event is not reliable, the userspace should
> > > behave
> > > > > > +   according to these 2 input key events.
> > > > > > +   New userspace programs may only be prepared for the input
> key
> > > > > events.
> > > > >
> > > > > No, absolutely not. If some x86 vendors managed to mess up their
> > > > > firmware implementations that does not mean that everyone now
> has
> > > to
> > > > > abandon working perfectly well for them SW_LID events and rush
> to
> > > > > switch
> > > > > to a brand new event.
> > > > [Lv Zheng]
> > > > However there is no clear wording in the ACPI specification asking
> the
> > > vendors to achieve paired lid events.
> > > >
> > > > >
> > > > > Apparently were are a few issues, main is that some systems not
> > > reporting
> > > > > "open" event. This can be dealt with by userspace "writing" to the
> > > > > lid's evdev device EV_SW/SW_LID/0 event upon system resume
> (and
> > > > > startup)
> > > > > for selected systems. This will mean that if system wakes up not
> > > because
> > > > > LID is open we'll incorrectly assume that it is, but we can either add
> > > > > more smarts to the process emitting SW_LID event or simply say
> "well,
> > > > > tough, the hardware is crappy" and bug vendor to see if they can fix
> > > the
> > > > > issue (if not for current firmware them for next).
> > > > [Lv Zheng]
> > > > The problem is there is no vendor actually caring about fixing this
> "issue".
> > > > Because Windows works well with their firmware.
> > > > Then finally becomes a big table customization business for our team.
> > >
> > > Well, OK. But you do not expect that we will redo up and down the
> stack
> > > lid handling just because MS messed up DSDT on Surface 3? No, let
> them
> > > know (they now care about Linux, right?) so Surface 4 works and quirk
> > > the behavior for Surface 3.
> > [Lv Zheng]
> > I think there are other platforms broken.
> 
> Probably. I think we should deal with them as they come.
[Lv Zheng] 
This seems to be what the ACPI team has been doing for years.

However, if the userspace has been changed to be compliant to the new documented usage model.
I think we needn't do that for the users, users can just specify a userspace option to work it around themselves.

> 
> >
> > >
> > > >
> > > > >
> > > > > As an additional workaround, we can toggle the LID switch off and
> on
> > > > > when we get notification, much like your proposed patch does for
> the
> > > key
> > > > > events.
> > > > [Lv Zheng]
> > > > I think this is doable, I'll refresh my patchset to address your this
> > > comment.
> > > > By inserting open/close events when next close/open event arrives
> after
> > > a certain period,
> > > > this may fix some issues for the old programs.
> > > > Where user may be required to open/close lid twice to trigger 2nd
> > > suspend.
> > > >
> > > > However, this still cannot fix the problems like "Surface 3".
> > > > We'll still need a new usage model for such platforms (no open
> event).
> > >
> > > No, for surface 3 you simply need to add polling of "_LID" method to
> the
> > > button driver.
> > >
> > > What are the other devices that mess up lid handling?
> > [Lv Zheng]
> > The patch lists 3 of them.
> > Which are known to me because they all occurred after I started to look
> at the lid issues.
> >
> > According to my teammates.
> > They've been fixing such wrong "DSDT" using customization for years.
> > For example, by adding _LID(); Notify(lid) into _WAK() or EC._REG().
> 
> What did they do with them once they did the fix? Were they submitting
> fixes to manufacturers? What happened to them?
[Lv Zheng] 
I really don't know.

However, I think the ending of the story is likely:
The users who report such breakage happily get their platforms working.
And they'll never report it again.
Users using the same platforms can find the quirk via web search.

Or the best ending is:
The reporters have reported this to the Linux contribution vendors.
And the knowledge is documented in their published laptop knowledge base or included in the distribution.

I think no manufacturer really cares about such fixes.

But I'm really not the correct one to answer this question.
I'm new to ACPI bug fixing work.

IMO, if the userspace can have an option to implement a mode compliant to this documented usage model.
And always automatically enable this option when PNP0C0D is detected.
No one will need any kind of quirks.
But as Benjamin suggested, we may use the hwdb to enable this option for those buggy platforms.
So that all other platforms are compliant to the unified Linux lid model.

Cheers
-Lv

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

* RE: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-22 17:02           ` Dmitry Torokhov
@ 2016-07-23 12:17             ` Zheng, Lv
  0 siblings, 0 replies; 34+ messages in thread
From: Zheng, Lv @ 2016-07-23 12:17 UTC (permalink / raw)
  To: Dmitry Torokhov, Benjamin Tissoires
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	Bastien Nocera:, linux-input@vger.kernel.org

Hi, Dmitry

> From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-
> owner@vger.kernel.org] On Behalf Of Dmitry Torokhov
> Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control
> method lid device restrictions
> 
> On Fri, Jul 22, 2016 at 08:55:00AM +0200, Benjamin Tissoires wrote:
> > On Fri, Jul 22, 2016 at 6:37 AM, Dmitry Torokhov
> > <dmitry.torokhov@gmail.com> wrote:
> > > Hi Lv,
> > >
> > > On Fri, Jul 22, 2016 at 12:24:50AM +0000, Zheng, Lv wrote:
> > >> Hi, Dmitry
> > >>
> > >>
> > >> Thanks for the review.
> > >>
> > >> > From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> > >> > Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI
> control
> > >> > method lid device restrictions
> > >> >
> > >> > On Tue, Jul 19, 2016 at 04:11:21PM +0800, Lv Zheng wrote:
> > >> > > This patch adds documentation for the usage model of the control
> > >> > method lid
> > >> > > device.
> > >> > >
> > >> > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > >> > > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > >> > > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> > >> > > Cc: Bastien Nocera: <hadess@hadess.net>
> > >> > > Cc: linux-input@vger.kernel.org
> > >> > > ---
> > >> > >  Documentation/acpi/acpi-lid.txt |   89
> > >> > +++++++++++++++++++++++++++++++++++++++
> > >> > >  1 file changed, 89 insertions(+)
> > >> > >  create mode 100644 Documentation/acpi/acpi-lid.txt
> > >> > >
> > >> > > diff --git a/Documentation/acpi/acpi-lid.txt
> b/Documentation/acpi/acpi-
> > >> > lid.txt
> > >> > > new file mode 100644
> > >> > > index 0000000..2addedc
> > >> > > --- /dev/null
> > >> > > +++ b/Documentation/acpi/acpi-lid.txt
> > >> > > @@ -0,0 +1,89 @@
> > >> > > +Usage Model of the ACPI Control Method Lid Device
> > >> > > +
> > >> > > +Copyright (C) 2016, Intel Corporation
> > >> > > +Author: Lv Zheng <lv.zheng@intel.com>
> > >> > > +
> > >> > > +
> > >> > > +Abstract:
> > >> > > +
> > >> > > +Platforms containing lids convey lid state (open/close) to OSPMs
> using
> > >> > a
> > >> > > +control method lid device. To implement this, the AML tables
> issue
> > >> > > +Notify(lid_device, 0x80) to notify the OSPMs whenever the lid
> state has
> > >> > > +changed. The _LID control method for the lid device must be
> > >> > implemented to
> > >> > > +report the "current" state of the lid as either "opened" or
> "closed".
> > >> > > +
> > >> > > +This document describes the restrictions and the expections of
> the
> > >> > Linux
> > >> > > +ACPI lid device driver.
> > >> > > +
> > >> > > +
> > >> > > +1. Restrictions of the returning value of the _LID control method
> > >> > > +
> > >> > > +The _LID control method is described to return the "current" lid
> state.
> > >> > > +However the word of "current" has ambiguity, many AML tables
> return
> > >> > the lid
> > >> >
> > >> > Can this be fixed in the next ACPI revision?
> > >> [Lv Zheng]
> > >> Even this is fixed in the ACPI specification, there are platforms already
> doing this.
> > >> Especially platforms from Microsoft.
> > >> So the de-facto standard OS won't care about the change.
> > >> And we can still see such platforms.
> > >>
> > >> Here is an example from Surface 3:
> > >>
> > >> DefinitionBlock ("dsdt.aml", "DSDT", 2, "ALASKA", "A M I ",
> 0x01072009)
> > >> {
> > >>     Scope (_SB)
> > >>     {
> > >>         Device (PCI0)
> > >>         {
> > >>             Name (_HID, EisaId ("PNP0A08"))  // _HID: Hardware ID
> > >>             Name (_CID, EisaId ("PNP0A03"))  // _CID: Compatible ID
> > >>             Device (SPI1)
> > >>             {
> > >>                 Name (_HID, "8086228E")  // _HID: Hardware ID
> > >>                 Device (NTRG)
> > >>                 {
> > >>                     Name (_HID, "MSHW0037")  // _HID: Hardware ID
> > >>                 }
> > >>             }
> > >>         }
> > >>
> > >>         Device (LID)
> > >>         {
> > >>             Name (_HID, EisaId ("PNP0C0D"))
> > >>             Name (LIDB, Zero)
> > >
> > > Start with lid closed? In any case might be wrong.
> >
> > Actually the initial value doesn't matter if the gpiochip triggers the
> > _EC4 at boot, which it should
> > (https://github.com/hadess/fedora-surface3-
> kernel/commit/13200f81662c1c0b58137947c3e6c000fe62a2ba,
> > still unsubmitted)
> >
> > >
> > >>             Method (_LID, 0, NotSerialized)
> > >>             {
> > >>                 Return (LIDB)
> > >
> > > So "_LID" returns the last state read by "_EC4". "_EC4" is
> > > edge-triggered and will be evaluated every time gpio changes state.
> >
> > That's assuming the change happens while the system is on. If you go
> > into suspend by closing the LID. Open it while on suspend and then hit
> > the power button given that the system doesn't wake up when the lid is
> > opened, the edge change was made while the system is asleep, and we
> > are screwed (from an ACPI point of view). See my next comment for a
> > solution.
> 
> Can we extend the patch you referenced above and do similar thing on
> resume? Won't help Surface but might others.
> 
> >
> > >
> > >>             }
> > >>         }
> > >>
> > >>         Device (GPO0)
> > >>         {
> > >>             Name (_HID, "INT33FF")  // _HID: Hardware ID
> > >>             OperationRegion (GPOR, GeneralPurposeIo, Zero, One)
> > >>             Field (GPOR, ByteAcc, NoLock, Preserve)
> > >>             {
> > >>                 Connection (
> > >>                     GpioIo (Shared, PullNone, 0x0000, 0x0000,
> IoRestrictionNone,
> > >>                         "\\_SB.GPO0", 0x00, ResourceConsumer, ,
> > >>                         )
> > >>                         {   // Pin list
> > >>                             0x004C
> > >>                         }
> > >>                 ),
> > >>                 HELD,   1
> > >
> > > Is it possible to read state of this GPIO from userspace on startup to
> > > correct the initial state?
> > >
> > >>             }
> > >>             Method (_E4C, 0, Serialized)
> > >>             {
> > >>                 If (LEqual(HELD, One))
> > >>                 {
> > >>                     Store(One, ^^LID.LIDB)
> > >>
> > >> There is no "open" event generated by "Surface 3".
> > >
> > > Right so we update the state correctly, we just forgot to send the
> > > notification. Nothing that polling can't fix.
> >
> > Actually, I have a better (though more hackish) way of avoiding polling:
> > https://github.com/hadess/fedora-surface3-
> kernel/blob/5e5775b9bdc308d665064387e0b144ee48e7b243/0002-WIP-
> add-custom-surface3-platform-device-for-controll.patch
> >
> > Given that the notification is forwarded to the touchscreen anyway, we
> > can unregister the generic (and buggy) acpi button driver for the LID
> > and create our own based on this specific DSDT.
> > We can also make sure the LID state is also correct because of the WMI
> > method which allows to read the actual value of the GPIO connected to
> > the cover without using the cached (and most of the time wrong) acpi
> > LID.LIDB value.
> >
> > I still yet have to submit this, but with this patch, but we can
> > consider the Surface 3 as working and not an issue anymore.
> >
> > >
> > >>
> > >>                 }
> > >>                 Else
> > >>                 {
> > >>                     Store(Zero, ^^LID.LIDB)
> > >>                     Notify (LID, 0x80)
> > >>
> > >> There is only "close" event generated by "Surface 3".
> > >> Thus they are not paired.
> > >>
> > >>                 }
> > >>                 Notify (^^PCI0.SPI1.NTRG, One) // Device Check
> > >>             }
> > >>         }
> > >>     }
> > >> }
> > >>
> > >> >
> > >> > > +state upon the last lid notification instead of returning the lid
> state
> > >> > > +upon the last _LID evaluation. There won't be difference when
> the _LID
> > >> > > +control method is evaluated during the runtime, the problem is
> its
> > >> > initial
> > >> > > +returning value. When the AML tables implement this control
> method
> > >> > with
> > >> > > +cached value, the initial returning value is likely not reliable.
> There are
> > >> > > +simply so many examples always retuning "closed" as initial lid
> state.
> > >> > > +
> > >> > > +2. Restrictions of the lid state change notifications
> > >> > > +
> > >> > > +There are many AML tables never notifying when the lid device
> state is
> > >> > > +changed to "opened". Thus the "opened" notification is not
> guaranteed.
> > >> > > +
> > >> > > +But it is guaranteed that the AML tables always notify "closed"
> when
> > >> > the
> > >> > > +lid state is changed to "closed". The "closed" notification is
> normally
> > >> > > +used to trigger some system power saving operations on
> Windows.
> > >> > Since it is
> > >> > > +fully tested, the "closed" notification is reliable for all AML tables.
> > >> > > +
> > >> > > +3. Expections for the userspace users of the ACPI lid device driver
> > >> > > +
> > >> > > +The ACPI button driver exports the lid state to the userspace via
> the
> > >> > > +following file:
> > >> > > +  /proc/acpi/button/lid/LID0/state
> > >> > > +This file actually calls the _LID control method described above.
> And
> > >> > given
> > >> > > +the previous explanation, it is not reliable enough on some
> platforms.
> > >> > So
> > >> > > +it is advised for the userspace program to not to solely rely on
> this file
> > >> > > +to determine the actual lid state.
> > >> > > +
> > >> > > +The ACPI button driver emits 2 kinds of events to the user space:
> > >> > > +  SW_LID
> > >> > > +   When the lid state/event is reliable, the userspace can behave
> > >> > > +   according to this input switch event.
> > >> > > +   This is a mode prepared for backward compatiblity.
> > >> > > +  KEY_EVENT_OPEN/KEY_EVENT_CLOSE
> > >> > > +   When the lid state/event is not reliable, the userspace should
> behave
> > >> > > +   according to these 2 input key events.
> > >> > > +   New userspace programs may only be prepared for the input
> key
> > >> > events.
> > >> >
> > >> > No, absolutely not. If some x86 vendors managed to mess up their
> > >> > firmware implementations that does not mean that everyone now
> has to
> > >> > abandon working perfectly well for them SW_LID events and rush to
> > >> > switch
> > >> > to a brand new event.
> > >> [Lv Zheng]
> > >> However there is no clear wording in the ACPI specification asking the
> vendors to achieve paired lid events.
> > >>
> > >> >
> > >> > Apparently were are a few issues, main is that some systems not
> reporting
> > >> > "open" event. This can be dealt with by userspace "writing" to the
> > >> > lid's evdev device EV_SW/SW_LID/0 event upon system resume
> (and
> > >> > startup)
> > >> > for selected systems. This will mean that if system wakes up not
> because
> > >> > LID is open we'll incorrectly assume that it is, but we can either add
> > >> > more smarts to the process emitting SW_LID event or simply say
> "well,
> > >> > tough, the hardware is crappy" and bug vendor to see if they can fix
> the
> > >> > issue (if not for current firmware them for next).
> > >> [Lv Zheng]
> > >> The problem is there is no vendor actually caring about fixing this
> "issue".
> > >> Because Windows works well with their firmware.
> > >> Then finally becomes a big table customization business for our team.
> > >
> > > Well, OK. But you do not expect that we will redo up and down the
> stack
> > > lid handling just because MS messed up DSDT on Surface 3? No, let
> them
> > > know (they now care about Linux, right?) so Surface 4 works and quirk
> > > the behavior for Surface 3.
> > >
> >
> > From what I understood, it was more than just the Surface 3. Other
> > laptops were having issues and Lv's team gave up on fixing those
> > machines.
> >
> > >>
> > >> >
> > >> > As an additional workaround, we can toggle the LID switch off and
> on
> > >> > when we get notification, much like your proposed patch does for
> the key
> > >> > events.
> >
> > I really don't like this approach. The problem being that we will fix
> > the notifications to user space, but nothing will tell userspace that
> > the LID state is known to be wrong.
> > OTOH, I already agreed for a hwdb in userspace so I guess this point is
> moot.
> 
> Yeah, I do not like this too much either, I would prefer if we could dig
> out and communicate real state of LID to userspace. It sounds we have
> reasonable way for the Surfaces (I assume the others will have the same
> issues as 3), and we need to figure out what the other troublemakers
> are.
[Lv Zheng] 
Sorry for interruption.
Unlike other platforms, surface 3 is a hardware reduced platform.
So this might be a special case.

Then what about the others?
On traditional x86 platforms, when lid is opened, firmware is responsible to resume the platform.
And the OS is waken up via a waking vector setting through FACS table.
Then if the firmware forgot to prepare an "open" event after resuming, it would likely be that there wouldn't be an "open" event sent by the platform.

Even worse, if the platform firmware implements _LID method with a cached value, and the default value of it is "close".
Evaluating _LID after resuming could always result in "close".

However OS is lucky that, if it doesn't receive lid notification, it needn't evaluate _LID.
So OS can be immune to such "wrong close after resuming".

> 
> >
> > Having both events (one SW for reliable HW, always correct, and one
> > KEY for unreliable HW) allows userspace to make a clear distinction
> > between the working and non working events and they can continue to
> > keep using the polling of the SW node without extra addition.
> 
> At this point I would prefer not adding any "unreliable" events just yet
> and concentrate on finding working solution for SW_LID.
> 
[Lv Zheng] 
TBH, I think no user cares about the state of the lid.
It's visible. On Windows, there is even no such a tray icon indicating lid state.
When the lid is open, users can confirm that via their eyes.
If the lid is close, users cannot see the state icon through the lid cover.
So the actual "digitized" state of the lid is meaningless to the users.
It only means something to the BIOS validators.

OTOH, on traditional platforms, lid open is handled by BIOS, OS doesn't care about it.
There is a power option in Windows configuring lid close event.
But there is no similar configurable option for lid open event on Windows.

Based on these facts, I'm not sure what is the solution we are still trying to find.
If it is not the solution recommended in this document:
1. Never be strict to lid open event.
2. Never be strict to lid state.
3. But always be strict to lid close event.

Hope the information is useful for understanding the situation.

Thanks
-Lv 

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

* Re: [PATCH v5 1/3] ACPI / button: Add missing event to keep SW_LID running without additional event loss
  2016-07-22  6:24 ` [PATCH v5 1/3] ACPI / button: Add missing event to keep SW_LID running without additional event loss Lv Zheng
  2016-07-22 10:26   ` Zheng, Lv
@ 2016-07-23 12:37   ` Rafael J. Wysocki
  2016-07-25  0:24     ` Zheng, Lv
  1 sibling, 1 reply; 34+ messages in thread
From: Rafael J. Wysocki @ 2016-07-23 12:37 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Rafael J. Wysocki, Len Brown, Lv Zheng, linux-kernel, linux-acpi,
	Dmitry Torokhov, Benjamin Tissoires, Bastien Nocera:, linux-input

On Friday, July 22, 2016 02:24:42 PM Lv Zheng wrote:
> There are several possibilities that a lid event can be lost. For example,
> EC event queue full, or the resume order of the underlying drivers.
> 
> When the event loss happens, new event may also be lost due to the type of
> the SW_LID (switch event). The 2nd loss is what we want to avoid.
> 
> This patch adds a mechanism to insert lid events as a compensation for the
> switch event nature of the lid events in order to avoid the 2nd loss.

Can you please provide a high-level description of the new mechanism here?

> 
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> Cc: Bastien Nocera: <hadess@hadess.net>
> Cc: linux-input@vger.kernel.org
> ---
>  drivers/acpi/button.c |   21 ++++++++++++++++++++-
>  1 file changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> index 148f4e5..41fd21d 100644
> --- a/drivers/acpi/button.c
> +++ b/drivers/acpi/button.c
> @@ -104,6 +104,8 @@ struct acpi_button {
>  	struct input_dev *input;
>  	char phys[32];			/* for input device */
>  	unsigned long pushed;
> +	int sw_last_state;
> +	unsigned long sw_last_time;
>  	bool suspended;
>  };
>  
> @@ -111,6 +113,10 @@ static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
>  static struct acpi_device *lid_device;
>  static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
>  
> +static unsigned long lid_report_interval __read_mostly = 500;
> +module_param(lid_report_interval, ulong, 0644);
> +MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
> +
>  /* --------------------------------------------------------------------------
>                                FS Interface (/proc)
>     -------------------------------------------------------------------------- */
> @@ -133,11 +139,22 @@ static int acpi_lid_evaluate_state(struct acpi_device *device)
>  static int acpi_lid_notify_state(struct acpi_device *device, int state)
>  {
>  	struct acpi_button *button = acpi_driver_data(device);
> +	unsigned long sw_tout;
>  	int ret;
>  
> -	/* input layer checks if event is redundant */
> +	/* Send the switch event */
> +	sw_tout = button->sw_last_time +
> +		  msecs_to_jiffies(lid_report_interval);

Is it really necessary to use jiffies here?

> +	if (time_after(jiffies, sw_tout) &&
> +	    (button->sw_last_state == !!state)) {

The inner parens are not necessary.

And why not just button->sw_last_state == state?

> +		/* Send the complement switch event */
> +		input_report_switch(button->input, SW_LID, state);
> +		input_sync(button->input);
> +	}
>  	input_report_switch(button->input, SW_LID, !state);
>  	input_sync(button->input);
> +	button->sw_last_state = !!state;
> +	button->sw_last_time = jiffies;
>  
>  	if (state)
>  		pm_wakeup_event(&device->dev, 0);
> @@ -407,6 +424,8 @@ static int acpi_button_add(struct acpi_device *device)
>  		strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
>  		sprintf(class, "%s/%s",
>  			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
> +		button->sw_last_state = !!acpi_lid_evaluate_state(device);
> +		button->sw_last_time = jiffies;
>  	} else {
>  		printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
>  		error = -ENODEV;
> 

Thanks,
Rafael


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

* Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-22  9:08             ` Benjamin Tissoires
  2016-07-22  9:38               ` Zheng, Lv
@ 2016-07-24 11:28               ` Bastien Nocera
  2016-07-25  0:38                 ` Zheng, Lv
  1 sibling, 1 reply; 34+ messages in thread
From: Bastien Nocera @ 2016-07-24 11:28 UTC (permalink / raw)
  To: Benjamin Tissoires, Zheng, Lv
  Cc: Dmitry Torokhov, Zhang, Rui, Wysocki, Rafael J, Rafael J. Wysocki,
	Brown, Len, Lv Zheng, linux-kernel@vger.kernel.org,
	linux-acpi@vger.kernel.org, linux-input@vger.kernel.org

On Fri, 2016-07-22 at 11:08 +0200, Benjamin Tissoires wrote:
> 
<snip>
> Then you just need to amend the documentation to say that the
> fallback
> of the KEY events is not the "future" but a way to get events on some
> reduced platforms and it will not be the default.
> Please make sure userspace knows that the default is the good SW_LID,
> and some particular cases will need to be handled through the KEY
> events, not the other way around.
> 
> [few thoughts later]
> 
> How about:
> - you send only one patch with the SW_LID ON/OFF or OFF/ON when we
> receive the notification on buggy platform
> - in the same patch, you add the documentation saying that on most
> platforms, LID is reliable but some don't provide a reliable LID
> state, but you guarantee to send an event when the state changes
> - in userspace, we add the hwdb which says "on this particular
> platform, don't rely on the actual state, but wait for events" ->
> this
> basically removes the polling on these platforms.
> 
> Bastien, Dmitry?
> 
> I still don't like relying on userspace to actually set the SW_LID
> back to open on resume, as we should not rely on some userspace
> program to set the value (but if logind really wants it, it's up to
> them).

>From my point of view, I would only send the events that can actually
be generated by the system, not any synthetic ones, because user-space
would have no way to know that this was synthetic, and how accurate it
would be.

So we'd have a separate API, or a separate event for the "close to
Windows behaviour" devices. We'd then use hwdb in udev to tag the
machines that don't have a reliable LID status, in user-space, so we
can have a quick turn around for those machines.

That should hopefully give us a way to tag test systems, so we can test
the new behaviour, though we'll certainly need to have some changes
made in the stack.

As Benjamin mentioned, it would be nice to have a list of devices that
don't work today, because of this problem.

Cheers

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

* RE: [PATCH v5 1/3] ACPI / button: Add missing event to keep SW_LID running without additional event loss
  2016-07-23 12:37   ` Rafael J. Wysocki
@ 2016-07-25  0:24     ` Zheng, Lv
  0 siblings, 0 replies; 34+ messages in thread
From: Zheng, Lv @ 2016-07-25  0:24 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Wysocki, Rafael J, Brown, Len, Lv Zheng,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	Dmitry Torokhov, Benjamin Tissoires, Bastien Nocera:,
	linux-input@vger.kernel.org

Hi, Rafael

> From: Rafael J. Wysocki [mailto:rjw@rjwysocki.net]
> Sent: Saturday, July 23, 2016 8:37 PM
> Subject: Re: [PATCH v5 1/3] ACPI / button: Add missing event to keep
> SW_LID running without additional event loss
> 
> On Friday, July 22, 2016 02:24:42 PM Lv Zheng wrote:
> > There are several possibilities that a lid event can be lost. For example,
> > EC event queue full, or the resume order of the underlying drivers.
> >
> > When the event loss happens, new event may also be lost due to the
> type of
> > the SW_LID (switch event). The 2nd loss is what we want to avoid.
> >
> > This patch adds a mechanism to insert lid events as a compensation for
> the
> > switch event nature of the lid events in order to avoid the 2nd loss.
> 
> Can you please provide a high-level description of the new mechanism
> here?
[Lv Zheng] 
OK.

And IMO, this fix is a fix to the original ACPI button driver.
It is not dependent on the input layer.
Without the final agreement of the ABI change.
We still can get this shipped in the upstream.

If the ABI is determined to use the new KEY_LID_XX events, I'll send a series including 2 patches.
If the ABI is determined to use the old SW_LID event, I'll send a series including only the documentation.

Let me send this fix separately.

Thanks and best regards
-Lv

> 
> >
> > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> > Cc: Bastien Nocera: <hadess@hadess.net>
> > Cc: linux-input@vger.kernel.org
> > ---
> >  drivers/acpi/button.c |   21 ++++++++++++++++++++-
> >  1 file changed, 20 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> > index 148f4e5..41fd21d 100644
> > --- a/drivers/acpi/button.c
> > +++ b/drivers/acpi/button.c
> > @@ -104,6 +104,8 @@ struct acpi_button {
> >  	struct input_dev *input;
> >  	char phys[32];			/* for input device */
> >  	unsigned long pushed;
> > +	int sw_last_state;
> > +	unsigned long sw_last_time;
> >  	bool suspended;
> >  };
> >
> > @@ -111,6 +113,10 @@ static
> BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
> >  static struct acpi_device *lid_device;
> >  static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
> >
> > +static unsigned long lid_report_interval __read_mostly = 500;
> > +module_param(lid_report_interval, ulong, 0644);
> > +MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid
> key events");
> > +
> >  /* --------------------------------------------------------------------------
> >                                FS Interface (/proc)
> >     -------------------------------------------------------------------------- */
> > @@ -133,11 +139,22 @@ static int acpi_lid_evaluate_state(struct
> acpi_device *device)
> >  static int acpi_lid_notify_state(struct acpi_device *device, int state)
> >  {
> >  	struct acpi_button *button = acpi_driver_data(device);
> > +	unsigned long sw_tout;
> >  	int ret;
> >
> > -	/* input layer checks if event is redundant */
> > +	/* Send the switch event */
> > +	sw_tout = button->sw_last_time +
> > +		  msecs_to_jiffies(lid_report_interval);
> 
> Is it really necessary to use jiffies here?
> 
> > +	if (time_after(jiffies, sw_tout) &&
> > +	    (button->sw_last_state == !!state)) {
> 
> The inner parens are not necessary.
> 
> And why not just button->sw_last_state == state?
> 
> > +		/* Send the complement switch event */
> > +		input_report_switch(button->input, SW_LID, state);
> > +		input_sync(button->input);
> > +	}
> >  	input_report_switch(button->input, SW_LID, !state);
> >  	input_sync(button->input);
> > +	button->sw_last_state = !!state;
> > +	button->sw_last_time = jiffies;
> >
> >  	if (state)
> >  		pm_wakeup_event(&device->dev, 0);
> > @@ -407,6 +424,8 @@ static int acpi_button_add(struct acpi_device
> *device)
> >  		strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
> >  		sprintf(class, "%s/%s",
> >  			ACPI_BUTTON_CLASS,
> ACPI_BUTTON_SUBCLASS_LID);
> > +		button->sw_last_state = !!acpi_lid_evaluate_state(device);
> > +		button->sw_last_time = jiffies;
> >  	} else {
> >  		printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
> >  		error = -ENODEV;
> >
> 
> Thanks,
> Rafael


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

* RE: [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-07-24 11:28               ` Bastien Nocera
@ 2016-07-25  0:38                 ` Zheng, Lv
  0 siblings, 0 replies; 34+ messages in thread
From: Zheng, Lv @ 2016-07-25  0:38 UTC (permalink / raw)
  To: Bastien Nocera, Benjamin Tissoires
  Cc: Dmitry Torokhov, Zhang, Rui, Wysocki, Rafael J, Rafael J. Wysocki,
	Brown, Len, Lv Zheng, linux-kernel@vger.kernel.org,
	linux-acpi@vger.kernel.org, linux-input@vger.kernel.org

Hi, Bastien

> From: Bastien Nocera [mailto:hadess@hadess.net]
> Subject: Re: [PATCH v4 2/2] ACPI / button: Add document for ACPI control
> method lid device restrictions
> 
> On Fri, 2016-07-22 at 11:08 +0200, Benjamin Tissoires wrote:
> >
> <snip>
> > Then you just need to amend the documentation to say that the
> > fallback
> > of the KEY events is not the "future" but a way to get events on some
> > reduced platforms and it will not be the default.
> > Please make sure userspace knows that the default is the good SW_LID,
> > and some particular cases will need to be handled through the KEY
> > events, not the other way around.
> >
> > [few thoughts later]
> >
> > How about:
> > - you send only one patch with the SW_LID ON/OFF or OFF/ON when we
> > receive the notification on buggy platform
> > - in the same patch, you add the documentation saying that on most
> > platforms, LID is reliable but some don't provide a reliable LID
> > state, but you guarantee to send an event when the state changes
> > - in userspace, we add the hwdb which says "on this particular
> > platform, don't rely on the actual state, but wait for events" ->
> > this
> > basically removes the polling on these platforms.
> >
> > Bastien, Dmitry?
> >
> > I still don't like relying on userspace to actually set the SW_LID
> > back to open on resume, as we should not rely on some userspace
> > program to set the value (but if logind really wants it, it's up to
> > them).
> 
> From my point of view, I would only send the events that can actually
> be generated by the system, not any synthetic ones, because user-space
> would have no way to know that this was synthetic, and how accurate it
> would be.
> 
> So we'd have a separate API, or a separate event for the "close to
> Windows behaviour" devices. We'd then use hwdb in udev to tag the
> machines that don't have a reliable LID status, in user-space, so we
> can have a quick turn around for those machines.
> 
> That should hopefully give us a way to tag test systems, so we can test
> the new behaviour, though we'll certainly need to have some changes
> made in the stack.
 [Lv Zheng] 
That's the original motivation of PATCH 02.

However, the PATCH 01 is valid fix.
Without it, running SW_LID on such buggy platforms could cause no event.
For example, if a platform always reports close, and never reports open.
Then after the first SW_LID(close), userspace could never see the follow-up SW_LID(close).
Thus that fix is required.

Then after upstreaming PATCH 01, we can see something redundant to KEY_LID_XXX approach.
Since with PATCH 01, we managed to ensure that platform triggered event will always be delivered to the userspace.
Since:
1. Open event is not reliable
2. Close event is reliable
We finally can see that:
1. All platform triggered close event can be seen by the userspace as SW_LID(close).
2. On the buggy platforms, SW_LID(open) is meaningless.

It then looks like the KEY_LID_XXX is redundant to the improved SW_LID now.
As with the key event approach, we still cannot guarantee to send "open" when the state is changed to "opened".
__Unless we start to fix the buggy firmware tables__.
And what we want to do - delivering reliable "close" to userspace can also be achieved with the SW_LID improvement.

Thus, finally, there's no difference between the new userspace behaviors:
1. SW_LID with reliable close: userspace matches hwdb and stops acting upon open
2. KEY_LID_xxx with reliable close: userspace matches hwdb and starts acting only upon KEY_LID_CLOSE

So we just need you and Dmitry to reach an agreement here.
And this doesn't look like a big conflict.

IMO, since SW_LID(CLOSE) is reliable now, we needn't introduce the new KEY_LID_xxx events.
That means we can leave the kernel input layer unchanged.
And limits this issue to the ACPI subsystem and the userspace programs.
What do you think?

> 
> As Benjamin mentioned, it would be nice to have a list of devices that
> don't work today, because of this problem.

[Lv Zheng] 
We'll try to find that.
Before working out the full list, you can use the above mentioned 3 platforms to test.

Cheers

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

* [PATCH v6] ACPI / button: Fix an issue that the platform triggered "close" event may not be delivered to the userspace
       [not found] <cbdaec17aba78c61f466efff8883d49067f2dad5.1463472125.git.lv.zheng@intel.com>
                   ` (4 preceding siblings ...)
  2016-07-22  6:24 ` [PATCH v5 3/3] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng
@ 2016-07-25  1:14 ` Lv Zheng
  2016-07-26  9:52 ` [PATCH v7 1/2] ACPI / button: Fix an issue that the platform triggered reliable events " Lv Zheng
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 34+ messages in thread
From: Lv Zheng @ 2016-07-25  1:14 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi, Benjamin Tissoires,
	Bastien Nocera:, linux-input

There are many AML tables reporting wrong initial lid state (Link 1), and
some of them never report lid open state (Link 2). Thus, the usage model of
the ACPI control method lid device is:
1. The initial lid state returned from _LID is not reliable;
2. The lid open event is not reliable;
3. The lid close event is always reliable, used by the platform firmware to
   trigger OSPM power saving operations.

Then we can see an issue in the current ACPI button driver. When the
initial lid state is "close" and the platform never reports "open", we can
see that the userspace could only recieve "close" once. And all follow-up
"close" events can never trigger OSPM power saving operations. This is
because of the type of the lid events. The SW_LID is a switch event, only
the switched value will be delivered to the userspace. When the value never
switches, nothing can be seen by the userspace.

Currently ACPI button driver implements a lid_init_state=open quirk to send
additional "open" after resuming in order to avoid another issue that the
system may be suspended right after resuming because the userspace programs
have strict requirement of the "open" event. However, this breaks some
usage model (e.x., the dark resume scenario). So we need to stop sending
the additional "open" event and switch the driver to lid_init_state=ignore
mode. The userspace programs should also be changed to stop being strict to
the "open" event. This is the preferred mode for the Linux ACPI button
driver and the userspace programs to work together on such buggy platforms.

However, we can see that, without fixing the issue mentioned in the 2nd
paragraph, subsequent platform triggered "close" events cannot be delivered
to the userspace and the power saving operations can not be triggered. So
we need to fix the issue before the userspace changes its behavior.

This patch adds a mechanism to insert lid events as a compensation for the
platform triggered ones to form a complete event switches in order to make
the "close" switch events always reliable.

Link 1: https://bugzilla.kernel.org/show_bug.cgi?id=89211
        https://bugzilla.kernel.org/show_bug.cgi?id=106151
Link 2: https://bugzilla.kernel.org/show_bug.cgi?id=106941
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Suggested-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Cc: Bastien Nocera: <hadess@hadess.net>
Cc: linux-input@vger.kernel.org
---
 drivers/acpi/button.c |   21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 148f4e5..7e2a9eb 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -104,6 +104,8 @@ struct acpi_button {
 	struct input_dev *input;
 	char phys[32];			/* for input device */
 	unsigned long pushed;
+	int last_state;
+	unsigned long last_time;
 	bool suspended;
 };
 
@@ -111,6 +113,10 @@ static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
 static struct acpi_device *lid_device;
 static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
 
+static unsigned long lid_report_interval __read_mostly = 500;
+module_param(lid_report_interval, ulong, 0644);
+MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
+
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
@@ -133,11 +139,22 @@ static int acpi_lid_evaluate_state(struct acpi_device *device)
 static int acpi_lid_notify_state(struct acpi_device *device, int state)
 {
 	struct acpi_button *button = acpi_driver_data(device);
+	unsigned long timeout;
 	int ret;
 
-	/* input layer checks if event is redundant */
+	/* Send the switch event */
+	timeout = button->last_time +
+		  msecs_to_jiffies(lid_report_interval);
+	if (time_after(jiffies, timeout) &&
+	    (button->last_state == !!state)) {
+		/* Send the complement switch event */
+		input_report_switch(button->input, SW_LID, state);
+		input_sync(button->input);
+	}
 	input_report_switch(button->input, SW_LID, !state);
 	input_sync(button->input);
+	button->last_state = !!state;
+	button->last_time = jiffies;
 
 	if (state)
 		pm_wakeup_event(&device->dev, 0);
@@ -407,6 +424,8 @@ static int acpi_button_add(struct acpi_device *device)
 		strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
 		sprintf(class, "%s/%s",
 			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
+		button->last_state = !!acpi_lid_evaluate_state(device);
+		button->last_time = jiffies;
 	} else {
 		printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
 		error = -ENODEV;
-- 
1.7.10

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

* [PATCH v7 1/2] ACPI / button: Fix an issue that the platform triggered reliable events may not be delivered to the userspace
       [not found] <cbdaec17aba78c61f466efff8883d49067f2dad5.1463472125.git.lv.zheng@intel.com>
                   ` (5 preceding siblings ...)
  2016-07-25  1:14 ` [PATCH v6] ACPI / button: Fix an issue that the platform triggered "close" event may not be delivered to the userspace Lv Zheng
@ 2016-07-26  9:52 ` Lv Zheng
  2016-08-17  0:19   ` Rafael J. Wysocki
  2016-07-26  9:52 ` [PATCH v7 2/2] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 34+ messages in thread
From: Lv Zheng @ 2016-07-26  9:52 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi, Benjamin Tissoires,
	Bastien Nocera:, linux-input

On most platforms, _LID returning value, lid open/close events are all
reliable, but there are exceptions. Some AML tables report wrong initial
lid state (Link 1), and some of them never report lid open state (Link 2).
The usage model on such buggy platforms is:
1. The initial lid state returned from _LID is not reliable;
2. The lid open event is not reliable;
3. The lid close event is always reliable, used by the platform firmware to
   trigger OSPM power saving operations.
This usage model is not compliant to the Linux SW_LID model as the Linux
userspace is very strict to the reliability of the open events.

In order not to trigger issues on such buggy platforms, the ACPI button
driver currently implements a lid_init_state=open quirk to send additional
"open" event after resuming. However, this is still not sufficient because:
1. Some special usage models (e.x., the dark resume scenario) cannot be
   supported by this mode.
2. If a "close" event is not used to trigger "suspend", then the subsequent
   "close" events cannot be seen by the userspace.
So we need to stop sending the additional "open" event and switch the
driver to lid_init_state=ignore mode and make sure the platform triggered
events can be reliably delivered to the userspace. The userspace programs
then can be changed to not to be strict to the "open" events on such buggy
platforms.

Why will the subsequent "close" events be lost? This is because the input
layer automatically filters redundant events for switch events. Thus given
that the buggy AML tables do not guarantee paired "open"/"close" events,
the ACPI button driver currently is not able to guarantee that the platform
triggered reliable events can be always be seen by the userspace via
SW_LID.

This patch adds a mechanism to insert lid events as a compensation for the
platform triggered ones to form a complete event switches in order to make
sure that the platform triggered events can always be reliably delivered
to the userspace. This essentially guarantees that the platform triggered
reliable "close" events will always be relibly delivered to the userspace.

However this mechanism is not suitable for lid_init_state=open/method as
it should not send the complement switch event for the unreliable initial
lid state notification. 2 unreliable events can trigger unexpected
behavior. Thus this patch only implements this mechanism for
lid_init_state=ignore.

Link 1: https://bugzilla.kernel.org/show_bug.cgi?id=89211
        https://bugzilla.kernel.org/show_bug.cgi?id=106151
Link 2: https://bugzilla.kernel.org/show_bug.cgi?id=106941
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Suggested-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Cc: Bastien Nocera: <hadess@hadess.net>
Cc: linux-input@vger.kernel.org
---
 drivers/acpi/button.c |   51 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 148f4e5..dca1806 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -19,6 +19,8 @@
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
+#define pr_fmt(fmt) "ACPI : button: " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -104,6 +106,8 @@ struct acpi_button {
 	struct input_dev *input;
 	char phys[32];			/* for input device */
 	unsigned long pushed;
+	int last_state;
+	unsigned long last_time;
 	bool suspended;
 };
 
@@ -111,6 +115,10 @@ static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
 static struct acpi_device *lid_device;
 static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
 
+static unsigned long lid_report_interval __read_mostly = 500;
+module_param(lid_report_interval, ulong, 0644);
+MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
+
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
@@ -135,9 +143,48 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
 	struct acpi_button *button = acpi_driver_data(device);
 	int ret;
 
-	/* input layer checks if event is redundant */
+	if (button->last_state == !!state &&
+	    time_after(jiffies, button->last_time +
+				msecs_to_jiffies(lid_report_interval))) {
+		/* Complain the buggy firmware */
+		pr_warn_once("The lid device is not compliant to SW_LID.\n");
+
+		/*
+		 * Send the unreliable complement switch event:
+		 *
+		 * On most platforms, the lid device is reliable. However
+		 * there are exceptions:
+		 * 1. Platforms returning initial lid state as "close" by
+		 *    default after booting/resuming:
+		 *     https://bugzilla.kernel.org/show_bug.cgi?id=89211
+		 *     https://bugzilla.kernel.org/show_bug.cgi?id=106151
+		 * 2. Platforms never reporting "open" events:
+		 *     https://bugzilla.kernel.org/show_bug.cgi?id=106941
+		 * On these buggy platforms, the usage model of the ACPI
+		 * lid device actually is:
+		 * 1. The initial returning value of _LID may not be
+		 *    reliable.
+		 * 2. The open event may not be reliable.
+		 * 3. The close event is reliable.
+		 *
+		 * But SW_LID is typed as input switch event, the input
+		 * layer checks if the event is redundant. Hence if the
+		 * state is not switched, the userspace cannot see this
+		 * platform triggered reliable event. By inserting a
+		 * complement switch event, it then is guaranteed that the
+		 * platform triggered reliable one can always be seen by
+		 * the userspace.
+		 */
+		if (lid_init_state == ACPI_BUTTON_LID_INIT_IGNORE) {
+			input_report_switch(button->input, SW_LID, state);
+			input_sync(button->input);
+		}
+	}
+	/* Send the platform triggered reliable event */
 	input_report_switch(button->input, SW_LID, !state);
 	input_sync(button->input);
+	button->last_state = !!state;
+	button->last_time = jiffies;
 
 	if (state)
 		pm_wakeup_event(&device->dev, 0);
@@ -407,6 +454,8 @@ static int acpi_button_add(struct acpi_device *device)
 		strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
 		sprintf(class, "%s/%s",
 			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
+		button->last_state = !!acpi_lid_evaluate_state(device);
+		button->last_time = jiffies;
 	} else {
 		printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
 		error = -ENODEV;
-- 
1.7.10

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

* [PATCH v7 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
       [not found] <cbdaec17aba78c61f466efff8883d49067f2dad5.1463472125.git.lv.zheng@intel.com>
                   ` (6 preceding siblings ...)
  2016-07-26  9:52 ` [PATCH v7 1/2] ACPI / button: Fix an issue that the platform triggered reliable events " Lv Zheng
@ 2016-07-26  9:52 ` Lv Zheng
  2016-08-17  8:22 ` [PATCH v8 1/2] ACPI / button: Fix an issue in button.lid_init_state=ignore mode Lv Zheng
  2016-08-17  8:23 ` [PATCH v8 2/2] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng
  9 siblings, 0 replies; 34+ messages in thread
From: Lv Zheng @ 2016-07-26  9:52 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi, Dmitry Torokhov,
	Bastien Nocera:, linux-input

This patch adds documentation for the usage model of the control method lid
device on some buggy platforms.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Acked-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Bastien Nocera: <hadess@hadess.net>
Cc: linux-input@vger.kernel.org
---
 Documentation/acpi/acpi-lid.txt |   97 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 97 insertions(+)
 create mode 100644 Documentation/acpi/acpi-lid.txt

diff --git a/Documentation/acpi/acpi-lid.txt b/Documentation/acpi/acpi-lid.txt
new file mode 100644
index 0000000..4dfdc9d
--- /dev/null
+++ b/Documentation/acpi/acpi-lid.txt
@@ -0,0 +1,97 @@
+Special Usage Model of the ACPI Control Method Lid Device
+
+Copyright (C) 2016, Intel Corporation
+Author: Lv Zheng <lv.zheng@intel.com>
+
+
+Abstract:
+
+Platforms containing lids convey lid state (open/close) to OSPMs using a
+control method lid device. To implement this, the AML tables issue
+Notify(lid_device, 0x80) to notify the OSPMs whenever the lid state has
+changed. The _LID control method for the lid device must be implemented to
+report the "current" state of the lid as either "opened" or "closed".
+
+For most platforms, both the _LID method and the lid notifications are
+reliable. However, there are exceptions. In order to work with these
+exceptional buggy platforms, special restrictions and expections should be
+taken into account. This document describes the restrictions and the
+expections of the Linux ACPI lid device driver.
+
+
+1. Restrictions of the returning value of the _LID control method
+
+The _LID control method is described to return the "current" lid state.
+However the word of "current" has ambiguity, some buggy AML tables return
+the lid state upon the last lid notification instead of returning the lid
+state upon the last _LID evaluation. There won't be difference when the
+_LID control method is evaluated during the runtime, the problem is its
+initial returning value. When the AML tables implement this control method
+with cached value, the initial returning value is likely not reliable.
+There are platforms always retun "closed" as initial lid state.
+
+2. Restrictions of the lid state change notifications
+
+There are buggy AML tables never notifying when the lid device state is
+changed to "opened". Thus the "opened" notification is not guaranteed. But
+it is guaranteed that the AML tables always notify "closed" when the lid
+state is changed to "closed". The "closed" notification is normally used to
+trigger some system power saving operations on Windows. Since it is fully
+tested, it is reliable from all AML tables.
+
+3. Expections for the userspace users of the ACPI lid device driver
+
+The ACPI button driver exports the lid state to the userspace via the
+following file:
+  /proc/acpi/button/lid/LID0/state
+This file actually calls the _LID control method described above. And given
+the previous explanation, it is not reliable enough on some platforms. So
+it is advised for the userspace program to not to solely rely on this file
+to determine the actual lid state.
+
+The ACPI button driver emits the following input event to the userspace:
+  SW_LID
+The ACPI lid device driver is implemented to try to deliver the platform
+triggered events to the userspace. However, given the fact that the buggy
+firmware cannot make sure "opened"/"closed" events are paired, the ACPI
+button driver uses the following 3 modes in order not to trigger issues.
+
+If the userspace hasn't been prepared to ignore the unreliable "opened"
+events and the unreliable initial state notification, Linux users can use
+the following kernel parameters to handle the possible issues:
+A. button.lid_init_state=method:
+   When this option is specified, the ACPI button driver reports the
+   initial lid state using the returning value of the _LID control method
+   and whether the "opened"/"closed" events are paired fully relies on the
+   firmware implementation.
+   This option can be used to fix some platforms where the returning value
+   of the _LID control method is reliable but the initial lid state
+   notification is missing.
+   This option is the default behavior during the period the userspace
+   isn't ready to handle the buggy AML tables.
+B. button.lid_init_state=open:
+   When this option is specified, the ACPI button driver always reports the
+   initial lid state as "opened" and whether the "opened"/"closed" events
+   are paired fully relies on the firmware implementation.
+   This may fix some platforms where the returning value of the _LID
+   control method is not reliable and the initial lid state notification is
+   missing.
+
+If the userspace has been prepared to ignore the unreliable "opened" events
+and the unreliable initial state notification, Linux users should always
+use the following kernel parameter:
+C. button.lid_init_state=ignore:
+   When this option is specified, the ACPI button driver never reports the
+   initial lid state and there is a compensation mechanism implemented to
+   ensure that "opened"/"closed" events are always paired. By doing this,
+   the ACPI button driver guarantees that the reliable "closed"
+   notifications can always be delivered to the userspace by inserting
+   complement switch events. But there is still no guarantee that the
+   "opened" notifications can be delivered to the userspace when the lid is
+   actually opens given that some AML tables do not send "opened"
+   notifications reliably.
+   In this mode, if everything is correctly implemented by the platform
+   firmware, the old userspace programs should still work. Otherwise, the
+   new userspace programs are required to work with the ACPI button driver.
+   This option will be the default behavior after the userspace is ready to
+   handle the buggy AML tables.
-- 
1.7.10

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

* Re: [PATCH v7 1/2] ACPI / button: Fix an issue that the platform triggered reliable events may not be delivered to the userspace
  2016-07-26  9:52 ` [PATCH v7 1/2] ACPI / button: Fix an issue that the platform triggered reliable events " Lv Zheng
@ 2016-08-17  0:19   ` Rafael J. Wysocki
  2016-08-17  4:45     ` Zheng, Lv
  0 siblings, 1 reply; 34+ messages in thread
From: Rafael J. Wysocki @ 2016-08-17  0:19 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Rafael J. Wysocki, Len Brown, Lv Zheng, linux-kernel, linux-acpi,
	Benjamin Tissoires, Bastien Nocera:, linux-input

On Tuesday, July 26, 2016 05:52:24 PM Lv Zheng wrote:
> On most platforms, _LID returning value, lid open/close events are all
> reliable, but there are exceptions. Some AML tables report wrong initial
> lid state (Link 1), and some of them never report lid open state (Link 2).
> The usage model on such buggy platforms is:
> 1. The initial lid state returned from _LID is not reliable;
> 2. The lid open event is not reliable;
> 3. The lid close event is always reliable, used by the platform firmware to
>    trigger OSPM power saving operations.
> This usage model is not compliant to the Linux SW_LID model as the Linux
> userspace is very strict to the reliability of the open events.
> 
> In order not to trigger issues on such buggy platforms, the ACPI button
> driver currently implements a lid_init_state=open quirk to send additional
> "open" event after resuming. However, this is still not sufficient because:
> 1. Some special usage models (e.x., the dark resume scenario) cannot be
>    supported by this mode.
> 2. If a "close" event is not used to trigger "suspend", then the subsequent
>    "close" events cannot be seen by the userspace.
> So we need to stop sending the additional "open" event and switch the
> driver to lid_init_state=ignore mode and make sure the platform triggered
> events can be reliably delivered to the userspace. The userspace programs
> then can be changed to not to be strict to the "open" events on such buggy
> platforms.
> 
> Why will the subsequent "close" events be lost? This is because the input
> layer automatically filters redundant events for switch events. Thus given
> that the buggy AML tables do not guarantee paired "open"/"close" events,
> the ACPI button driver currently is not able to guarantee that the platform
> triggered reliable events can be always be seen by the userspace via
> SW_LID.
> 
> This patch adds a mechanism to insert lid events as a compensation for the
> platform triggered ones to form a complete event switches in order to make
> sure that the platform triggered events can always be reliably delivered
> to the userspace. This essentially guarantees that the platform triggered
> reliable "close" events will always be relibly delivered to the userspace.
> 
> However this mechanism is not suitable for lid_init_state=open/method as
> it should not send the complement switch event for the unreliable initial
> lid state notification. 2 unreliable events can trigger unexpected
> behavior. Thus this patch only implements this mechanism for
> lid_init_state=ignore.
> 
> Link 1: https://bugzilla.kernel.org/show_bug.cgi?id=89211
>         https://bugzilla.kernel.org/show_bug.cgi?id=106151
> Link 2: https://bugzilla.kernel.org/show_bug.cgi?id=106941
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Suggested-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> Cc: Bastien Nocera: <hadess@hadess.net>
> Cc: linux-input@vger.kernel.org
> ---
>  drivers/acpi/button.c |   51 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 50 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> index 148f4e5..dca1806 100644
> --- a/drivers/acpi/button.c
> +++ b/drivers/acpi/button.c
> @@ -19,6 +19,8 @@
>   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>   */
>  
> +#define pr_fmt(fmt) "ACPI : button: " fmt
> +
>  #include <linux/kernel.h>
>  #include <linux/module.h>
>  #include <linux/init.h>
> @@ -104,6 +106,8 @@ struct acpi_button {
>  	struct input_dev *input;
>  	char phys[32];			/* for input device */
>  	unsigned long pushed;
> +	int last_state;
> +	unsigned long last_time;

Why don't you use ktime_t here?

>  	bool suspended;
>  };
>  
> @@ -111,6 +115,10 @@ static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
>  static struct acpi_device *lid_device;
>  static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
>  
> +static unsigned long lid_report_interval __read_mostly = 500;
> +module_param(lid_report_interval, ulong, 0644);
> +MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
> +
>  /* --------------------------------------------------------------------------
>                                FS Interface (/proc)
>     -------------------------------------------------------------------------- */
> @@ -135,9 +143,48 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
>  	struct acpi_button *button = acpi_driver_data(device);
>  	int ret;
>  
> -	/* input layer checks if event is redundant */
> +	if (button->last_state == !!state &&
> +	    time_after(jiffies, button->last_time +
> +				msecs_to_jiffies(lid_report_interval))) {

And ktime_after() here?

> +		/* Complain the buggy firmware */
> +		pr_warn_once("The lid device is not compliant to SW_LID.\n");
> +
> +		/*
> +		 * Send the unreliable complement switch event:
> +		 *
> +		 * On most platforms, the lid device is reliable. However
> +		 * there are exceptions:
> +		 * 1. Platforms returning initial lid state as "close" by
> +		 *    default after booting/resuming:
> +		 *     https://bugzilla.kernel.org/show_bug.cgi?id=89211
> +		 *     https://bugzilla.kernel.org/show_bug.cgi?id=106151
> +		 * 2. Platforms never reporting "open" events:
> +		 *     https://bugzilla.kernel.org/show_bug.cgi?id=106941
> +		 * On these buggy platforms, the usage model of the ACPI
> +		 * lid device actually is:
> +		 * 1. The initial returning value of _LID may not be
> +		 *    reliable.
> +		 * 2. The open event may not be reliable.
> +		 * 3. The close event is reliable.
> +		 *
> +		 * But SW_LID is typed as input switch event, the input
> +		 * layer checks if the event is redundant. Hence if the
> +		 * state is not switched, the userspace cannot see this
> +		 * platform triggered reliable event. By inserting a
> +		 * complement switch event, it then is guaranteed that the
> +		 * platform triggered reliable one can always be seen by
> +		 * the userspace.
> +		 */
> +		if (lid_init_state == ACPI_BUTTON_LID_INIT_IGNORE) {
> +			input_report_switch(button->input, SW_LID, state);
> +			input_sync(button->input);
> +		}
> +	}
> +	/* Send the platform triggered reliable event */
>  	input_report_switch(button->input, SW_LID, !state);
>  	input_sync(button->input);
> +	button->last_state = !!state;
> +	button->last_time = jiffies;

And ktime_get() here?

>  
>  	if (state)
>  		pm_wakeup_event(&device->dev, 0);
> @@ -407,6 +454,8 @@ static int acpi_button_add(struct acpi_device *device)
>  		strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
>  		sprintf(class, "%s/%s",
>  			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
> +		button->last_state = !!acpi_lid_evaluate_state(device);
> +		button->last_time = jiffies;

And here?

>  	} else {
>  		printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
>  		error = -ENODEV;
> 

Thanks,
Rafael


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

* RE: [PATCH v7 1/2] ACPI / button: Fix an issue that the platform triggered reliable events may not be delivered to the userspace
  2016-08-17  0:19   ` Rafael J. Wysocki
@ 2016-08-17  4:45     ` Zheng, Lv
  0 siblings, 0 replies; 34+ messages in thread
From: Zheng, Lv @ 2016-08-17  4:45 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Wysocki, Rafael J, Brown, Len, Lv Zheng,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	Benjamin Tissoires, Bastien Nocera:, linux-input@vger.kernel.org

Hi, Rafael

> From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-owner@vger.kernel.org] On Behalf Of Rafael J.
> Wysocki
> Subject: Re: [PATCH v7 1/2] ACPI / button: Fix an issue that the platform triggered reliable events
> may not be delivered to the userspace
> 
> On Tuesday, July 26, 2016 05:52:24 PM Lv Zheng wrote:
> > On most platforms, _LID returning value, lid open/close events are all
> > reliable, but there are exceptions. Some AML tables report wrong initial
> > lid state (Link 1), and some of them never report lid open state (Link 2).
> > The usage model on such buggy platforms is:
> > 1. The initial lid state returned from _LID is not reliable;
> > 2. The lid open event is not reliable;
> > 3. The lid close event is always reliable, used by the platform firmware to
> >    trigger OSPM power saving operations.
> > This usage model is not compliant to the Linux SW_LID model as the Linux
> > userspace is very strict to the reliability of the open events.
> >
> > In order not to trigger issues on such buggy platforms, the ACPI button
> > driver currently implements a lid_init_state=open quirk to send additional
> > "open" event after resuming. However, this is still not sufficient because:
> > 1. Some special usage models (e.x., the dark resume scenario) cannot be
> >    supported by this mode.
> > 2. If a "close" event is not used to trigger "suspend", then the subsequent
> >    "close" events cannot be seen by the userspace.
> > So we need to stop sending the additional "open" event and switch the
> > driver to lid_init_state=ignore mode and make sure the platform triggered
> > events can be reliably delivered to the userspace. The userspace programs
> > then can be changed to not to be strict to the "open" events on such buggy
> > platforms.
> >
> > Why will the subsequent "close" events be lost? This is because the input
> > layer automatically filters redundant events for switch events. Thus given
> > that the buggy AML tables do not guarantee paired "open"/"close" events,
> > the ACPI button driver currently is not able to guarantee that the platform
> > triggered reliable events can be always be seen by the userspace via
> > SW_LID.
> >
> > This patch adds a mechanism to insert lid events as a compensation for the
> > platform triggered ones to form a complete event switches in order to make
> > sure that the platform triggered events can always be reliably delivered
> > to the userspace. This essentially guarantees that the platform triggered
> > reliable "close" events will always be relibly delivered to the userspace.
> >
> > However this mechanism is not suitable for lid_init_state=open/method as
> > it should not send the complement switch event for the unreliable initial
> > lid state notification. 2 unreliable events can trigger unexpected
> > behavior. Thus this patch only implements this mechanism for
> > lid_init_state=ignore.
> >
> > Link 1: https://bugzilla.kernel.org/show_bug.cgi?id=89211
> >         https://bugzilla.kernel.org/show_bug.cgi?id=106151
> > Link 2: https://bugzilla.kernel.org/show_bug.cgi?id=106941
> > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > Suggested-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> > Cc: Bastien Nocera: <hadess@hadess.net>
> > Cc: linux-input@vger.kernel.org
> > ---
> >  drivers/acpi/button.c |   51 ++++++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 50 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> > index 148f4e5..dca1806 100644
> > --- a/drivers/acpi/button.c
> > +++ b/drivers/acpi/button.c
> > @@ -19,6 +19,8 @@
> >   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >   */
> >
> > +#define pr_fmt(fmt) "ACPI : button: " fmt
> > +
> >  #include <linux/kernel.h>
> >  #include <linux/module.h>
> >  #include <linux/init.h>
> > @@ -104,6 +106,8 @@ struct acpi_button {
> >  	struct input_dev *input;
> >  	char phys[32];			/* for input device */
> >  	unsigned long pushed;
> > +	int last_state;
> > +	unsigned long last_time;
> 
> Why don't you use ktime_t here?

OK.
I'll update the patch with ktime interfaces.
And send it after tests.

Thanks,
Lv

> 
> >  	bool suspended;
> >  };
> >
> > @@ -111,6 +115,10 @@ static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
> >  static struct acpi_device *lid_device;
> >  static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
> >
> > +static unsigned long lid_report_interval __read_mostly = 500;
> > +module_param(lid_report_interval, ulong, 0644);
> > +MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
> > +
> >  /* --------------------------------------------------------------------------
> >                                FS Interface (/proc)
> >     -------------------------------------------------------------------------- */
> > @@ -135,9 +143,48 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
> >  	struct acpi_button *button = acpi_driver_data(device);
> >  	int ret;
> >
> > -	/* input layer checks if event is redundant */
> > +	if (button->last_state == !!state &&
> > +	    time_after(jiffies, button->last_time +
> > +				msecs_to_jiffies(lid_report_interval))) {
> 
> And ktime_after() here?
> 
> > +		/* Complain the buggy firmware */
> > +		pr_warn_once("The lid device is not compliant to SW_LID.\n");
> > +
> > +		/*
> > +		 * Send the unreliable complement switch event:
> > +		 *
> > +		 * On most platforms, the lid device is reliable. However
> > +		 * there are exceptions:
> > +		 * 1. Platforms returning initial lid state as "close" by
> > +		 *    default after booting/resuming:
> > +		 *     https://bugzilla.kernel.org/show_bug.cgi?id=89211
> > +		 *     https://bugzilla.kernel.org/show_bug.cgi?id=106151
> > +		 * 2. Platforms never reporting "open" events:
> > +		 *     https://bugzilla.kernel.org/show_bug.cgi?id=106941
> > +		 * On these buggy platforms, the usage model of the ACPI
> > +		 * lid device actually is:
> > +		 * 1. The initial returning value of _LID may not be
> > +		 *    reliable.
> > +		 * 2. The open event may not be reliable.
> > +		 * 3. The close event is reliable.
> > +		 *
> > +		 * But SW_LID is typed as input switch event, the input
> > +		 * layer checks if the event is redundant. Hence if the
> > +		 * state is not switched, the userspace cannot see this
> > +		 * platform triggered reliable event. By inserting a
> > +		 * complement switch event, it then is guaranteed that the
> > +		 * platform triggered reliable one can always be seen by
> > +		 * the userspace.
> > +		 */
> > +		if (lid_init_state == ACPI_BUTTON_LID_INIT_IGNORE) {
> > +			input_report_switch(button->input, SW_LID, state);
> > +			input_sync(button->input);
> > +		}
> > +	}
> > +	/* Send the platform triggered reliable event */
> >  	input_report_switch(button->input, SW_LID, !state);
> >  	input_sync(button->input);
> > +	button->last_state = !!state;
> > +	button->last_time = jiffies;
> 
> And ktime_get() here?
> 
> >
> >  	if (state)
> >  		pm_wakeup_event(&device->dev, 0);
> > @@ -407,6 +454,8 @@ static int acpi_button_add(struct acpi_device *device)
> >  		strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
> >  		sprintf(class, "%s/%s",
> >  			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
> > +		button->last_state = !!acpi_lid_evaluate_state(device);
> > +		button->last_time = jiffies;
> 
> And here?
> 
> >  	} else {
> >  		printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
> >  		error = -ENODEV;
> >
> 
> Thanks,
> Rafael
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v8 1/2] ACPI / button: Fix an issue in button.lid_init_state=ignore mode
       [not found] <cbdaec17aba78c61f466efff8883d49067f2dad5.1463472125.git.lv.zheng@intel.com>
                   ` (7 preceding siblings ...)
  2016-07-26  9:52 ` [PATCH v7 2/2] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng
@ 2016-08-17  8:22 ` Lv Zheng
  2016-09-12 22:10   ` Rafael J. Wysocki
  2016-08-17  8:23 ` [PATCH v8 2/2] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng
  9 siblings, 1 reply; 34+ messages in thread
From: Lv Zheng @ 2016-08-17  8:22 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi, Benjamin Tissoires,
	Bastien Nocera:, linux-input

On most platforms, _LID returning value, lid open/close events are all
reliable, but there are exceptions. Some AML tables report wrong initial
lid state (Link 1), and some of them never report lid open state (Link 2).
The usage model on such buggy platforms is:
1. The initial lid state returned from _LID is not reliable;
2. The lid open event is not reliable;
3. The lid close event is always reliable, used by the platform firmware to
   trigger OSPM power saving operations.
This usage model is not compliant to the Linux SW_LID model as the Linux
userspace is very strict to the reliability of the open events.

In order not to trigger issues on such buggy platforms, the ACPI button
driver currently implements a lid_init_state=open quirk to send additional
"open" event after resuming. However, this is still not sufficient because:
1. Some special usage models (e.x., the dark resume scenario) cannot be
   supported by this mode.
2. If a "close" event is not used to trigger "suspend", then the subsequent
   "close" events cannot be seen by the userspace.
So we need to stop sending the additional "open" event and switch the
driver to lid_init_state=ignore mode and make sure the platform triggered
events can be reliably delivered to the userspace. The userspace programs
then can be changed to not to be strict to the "open" events on such buggy
platforms.

Why will the subsequent "close" events be lost? This is because the input
layer automatically filters redundant events for switch events. Thus given
that the buggy AML tables do not guarantee paired "open"/"close" events,
the ACPI button driver currently is not able to guarantee that the platform
triggered reliable events can be always be seen by the userspace via
SW_LID.

This patch adds a mechanism to insert lid events as a compensation for the
platform triggered ones to form a complete event switches in order to make
sure that the platform triggered events can always be reliably delivered
to the userspace. This essentially guarantees that the platform triggered
reliable "close" events will always be relibly delivered to the userspace.

However this mechanism is not suitable for lid_init_state=open/method as
it should not send the complement switch event for the unreliable initial
lid state notification. 2 unreliable events can trigger unexpected
behavior. Thus this patch only implements this mechanism for
lid_init_state=ignore.

Known issues:
1. Possible alternative approach
   This approach is based on the fact that Linux requires a switch event
   type for LID events. Another approach is to use key event type to
   implement ACPI lid events.
   With SW event type, since ACPI button driver inserts wrong lid events,
   there could be a potential issue that an "open" event issued from some
   AML update methods could result in a wrong "close" event to be delivered
   to the userspace. While using KEY event type, there is no such problem.
   However there may not be such a kind of real case, and if there is such
   a case, it is worked around in this patch as the complement switch event
   is only generated for "close" event in order to deliver the reliable
   "close" event to the userspace.

Link 1: https://bugzilla.kernel.org/show_bug.cgi?id=89211
        https://bugzilla.kernel.org/show_bug.cgi?id=106151
Link 2: https://bugzilla.kernel.org/show_bug.cgi?id=106941
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Suggested-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Cc: Bastien Nocera: <hadess@hadess.net>
Cc: linux-input@vger.kernel.org
---
 drivers/acpi/button.c |   85 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 82 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 31abb0b..e19f530 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -19,6 +19,8 @@
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
+#define pr_fmt(fmt) "ACPI : button: " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -104,6 +106,8 @@ struct acpi_button {
 	struct input_dev *input;
 	char phys[32];			/* for input device */
 	unsigned long pushed;
+	int last_state;
+	ktime_t last_time;
 	bool suspended;
 };
 
@@ -111,6 +115,10 @@ static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
 static struct acpi_device *lid_device;
 static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
 
+static unsigned long lid_report_interval __read_mostly = 500;
+module_param(lid_report_interval, ulong, 0644);
+MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
+
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
@@ -134,10 +142,79 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
 {
 	struct acpi_button *button = acpi_driver_data(device);
 	int ret;
+	ktime_t next_report;
+	bool do_update;
+
+	/*
+	 * In lid_init_state=ignore mode, if user opens/closes lid
+	 * frequently with "open" missing, and "last_time" is also updated
+	 * frequently, "close" cannot be delivered to the userspace.
+	 * So "last_time" is only updated after a timeout or an actual
+	 * switch.
+	 */
+	if (lid_init_state != ACPI_BUTTON_LID_INIT_IGNORE ||
+	    button->last_state != !!state)
+		do_update = true;
+	else
+		do_update = false;
+
+	next_report = ktime_add(button->last_time,
+				ms_to_ktime(lid_report_interval));
+	if (button->last_state == !!state &&
+	    ktime_after(ktime_get(), next_report)) {
+		/* Complain the buggy firmware */
+		pr_warn_once("The lid device is not compliant to SW_LID.\n");
 
-	/* input layer checks if event is redundant */
-	input_report_switch(button->input, SW_LID, !state);
-	input_sync(button->input);
+		/*
+		 * Send the unreliable complement switch event:
+		 *
+		 * On most platforms, the lid device is reliable. However
+		 * there are exceptions:
+		 * 1. Platforms returning initial lid state as "close" by
+		 *    default after booting/resuming:
+		 *     https://bugzilla.kernel.org/show_bug.cgi?id=89211
+		 *     https://bugzilla.kernel.org/show_bug.cgi?id=106151
+		 * 2. Platforms never reporting "open" events:
+		 *     https://bugzilla.kernel.org/show_bug.cgi?id=106941
+		 * On these buggy platforms, the usage model of the ACPI
+		 * lid device actually is:
+		 * 1. The initial returning value of _LID may not be
+		 *    reliable.
+		 * 2. The open event may not be reliable.
+		 * 3. The close event is reliable.
+		 *
+		 * But SW_LID is typed as input switch event, the input
+		 * layer checks if the event is redundant. Hence if the
+		 * state is not switched, the userspace cannot see this
+		 * platform triggered reliable event. By inserting a
+		 * complement switch event, it then is guaranteed that the
+		 * platform triggered reliable one can always be seen by
+		 * the userspace.
+		 */
+		if (lid_init_state == ACPI_BUTTON_LID_INIT_IGNORE) {
+			do_update = true;
+			/*
+			 * Do generate complement switch event for "close"
+			 * as "close" is reliable and wrong "open" won't
+			 * trigger unexpected behaviors.
+			 * Do not generate complement switch event for
+			 * "open" as "open" is not reliable and wrong
+			 * "close" will trigger unexpected behaviors.
+			 */
+			if (!state) {
+				input_report_switch(button->input,
+						    SW_LID, state);
+				input_sync(button->input);
+			}
+		}
+	}
+	/* Send the platform triggered reliable event */
+	if (do_update) {
+		input_report_switch(button->input, SW_LID, !state);
+		input_sync(button->input);
+		button->last_state = !!state;
+		button->last_time = ktime_get();
+	}
 
 	if (state)
 		pm_wakeup_event(&device->dev, 0);
@@ -411,6 +488,8 @@ static int acpi_button_add(struct acpi_device *device)
 		strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
 		sprintf(class, "%s/%s",
 			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
+		button->last_state = !!acpi_lid_evaluate_state(device);
+		button->last_time = ktime_get();
 	} else {
 		printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
 		error = -ENODEV;
-- 
1.7.10


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

* [PATCH v8 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
       [not found] <cbdaec17aba78c61f466efff8883d49067f2dad5.1463472125.git.lv.zheng@intel.com>
                   ` (8 preceding siblings ...)
  2016-08-17  8:22 ` [PATCH v8 1/2] ACPI / button: Fix an issue in button.lid_init_state=ignore mode Lv Zheng
@ 2016-08-17  8:23 ` Lv Zheng
  9 siblings, 0 replies; 34+ messages in thread
From: Lv Zheng @ 2016-08-17  8:23 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi, Dmitry Torokhov,
	Bastien Nocera:, linux-input

This patch adds documentation for the usage model of the control method lid
device on some buggy platforms.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Acked-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Bastien Nocera: <hadess@hadess.net>
Cc: linux-input@vger.kernel.org
---
 Documentation/acpi/acpi-lid.txt |   96 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)
 create mode 100644 Documentation/acpi/acpi-lid.txt

diff --git a/Documentation/acpi/acpi-lid.txt b/Documentation/acpi/acpi-lid.txt
new file mode 100644
index 0000000..effe7af
--- /dev/null
+++ b/Documentation/acpi/acpi-lid.txt
@@ -0,0 +1,96 @@
+Special Usage Model of the ACPI Control Method Lid Device
+
+Copyright (C) 2016, Intel Corporation
+Author: Lv Zheng <lv.zheng@intel.com>
+
+
+Abstract:
+
+Platforms containing lids convey lid state (open/close) to OSPMs using a
+control method lid device. To implement this, the AML tables issue
+Notify(lid_device, 0x80) to notify the OSPMs whenever the lid state has
+changed. The _LID control method for the lid device must be implemented to
+report the "current" state of the lid as either "opened" or "closed".
+
+For most platforms, both the _LID method and the lid notifications are
+reliable. However, there are exceptions. In order to work with these
+exceptional buggy platforms, special restrictions and expections should be
+taken into account. This document describes the restrictions and the
+expections of the Linux ACPI lid device driver.
+
+
+1. Restrictions of the returning value of the _LID control method
+
+The _LID control method is described to return the "current" lid state.
+However the word of "current" has ambiguity, some buggy AML tables return
+the lid state upon the last lid notification instead of returning the lid
+state upon the last _LID evaluation. There won't be difference when the
+_LID control method is evaluated during the runtime, the problem is its
+initial returning value. When the AML tables implement this control method
+with cached value, the initial returning value is likely not reliable.
+There are platforms always retun "closed" as initial lid state.
+
+2. Restrictions of the lid state change notifications
+
+There are buggy AML tables never notifying when the lid device state is
+changed to "opened". Thus the "opened" notification is not guaranteed. But
+it is guaranteed that the AML tables always notify "closed" when the lid
+state is changed to "closed". The "closed" notification is normally used to
+trigger some system power saving operations on Windows. Since it is fully
+tested, it is reliable from all AML tables.
+
+3. Expections for the userspace users of the ACPI lid device driver
+
+The ACPI button driver exports the lid state to the userspace via the
+following file:
+  /proc/acpi/button/lid/LID0/state
+This file actually calls the _LID control method described above. And given
+the previous explanation, it is not reliable enough on some platforms. So
+it is advised for the userspace program to not to solely rely on this file
+to determine the actual lid state.
+
+The ACPI button driver emits the following input event to the userspace:
+  SW_LID
+The ACPI lid device driver is implemented to try to deliver the platform
+triggered events to the userspace. However, given the fact that the buggy
+firmware cannot make sure "opened"/"closed" events are paired, the ACPI
+button driver uses the following 3 modes in order not to trigger issues.
+
+If the userspace hasn't been prepared to ignore the unreliable "opened"
+events and the unreliable initial state notification, Linux users can use
+the following kernel parameters to handle the possible issues:
+A. button.lid_init_state=method:
+   When this option is specified, the ACPI button driver reports the
+   initial lid state using the returning value of the _LID control method
+   and whether the "opened"/"closed" events are paired fully relies on the
+   firmware implementation.
+   This option can be used to fix some platforms where the returning value
+   of the _LID control method is reliable but the initial lid state
+   notification is missing.
+   This option is the default behavior during the period the userspace
+   isn't ready to handle the buggy AML tables.
+B. button.lid_init_state=open:
+   When this option is specified, the ACPI button driver always reports the
+   initial lid state as "opened" and whether the "opened"/"closed" events
+   are paired fully relies on the firmware implementation.
+   This may fix some platforms where the returning value of the _LID
+   control method is not reliable and the initial lid state notification is
+   missing.
+
+If the userspace has been prepared to ignore the unreliable "opened" events
+and the unreliable initial state notification, Linux users should always
+use the following kernel parameter:
+C. button.lid_init_state=ignore:
+   When this option is specified, the ACPI button driver never reports the
+   initial lid state and there is a compensation mechanism implemented to
+   ensure that the reliable "closed" notifications can always be delievered
+   to the userspace by always pairing "closed" input events with complement
+   "opened" input events. But there is still no guarantee that the "opened"
+   notifications can be delivered to the userspace when the lid is actually
+   opens given that some AML tables do not send "opened" notifications
+   reliably.
+   In this mode, if everything is correctly implemented by the platform
+   firmware, the old userspace programs should still work. Otherwise, the
+   new userspace programs are required to work with the ACPI button driver.
+   This option will be the default behavior after the userspace is ready to
+   handle the buggy AML tables.
-- 
1.7.10

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

* Re: [PATCH v8 1/2] ACPI / button: Fix an issue in button.lid_init_state=ignore mode
  2016-08-17  8:22 ` [PATCH v8 1/2] ACPI / button: Fix an issue in button.lid_init_state=ignore mode Lv Zheng
@ 2016-09-12 22:10   ` Rafael J. Wysocki
  0 siblings, 0 replies; 34+ messages in thread
From: Rafael J. Wysocki @ 2016-09-12 22:10 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Rafael J. Wysocki, Len Brown, Lv Zheng, linux-kernel, linux-acpi,
	Benjamin Tissoires, Bastien Nocera:, linux-input

On Wednesday, August 17, 2016 04:22:58 PM Lv Zheng wrote:
> On most platforms, _LID returning value, lid open/close events are all
> reliable, but there are exceptions. Some AML tables report wrong initial
> lid state (Link 1), and some of them never report lid open state (Link 2).
> The usage model on such buggy platforms is:
> 1. The initial lid state returned from _LID is not reliable;
> 2. The lid open event is not reliable;
> 3. The lid close event is always reliable, used by the platform firmware to
>    trigger OSPM power saving operations.
> This usage model is not compliant to the Linux SW_LID model as the Linux
> userspace is very strict to the reliability of the open events.
> 
> In order not to trigger issues on such buggy platforms, the ACPI button
> driver currently implements a lid_init_state=open quirk to send additional
> "open" event after resuming. However, this is still not sufficient because:
> 1. Some special usage models (e.x., the dark resume scenario) cannot be
>    supported by this mode.
> 2. If a "close" event is not used to trigger "suspend", then the subsequent
>    "close" events cannot be seen by the userspace.
> So we need to stop sending the additional "open" event and switch the
> driver to lid_init_state=ignore mode and make sure the platform triggered
> events can be reliably delivered to the userspace. The userspace programs
> then can be changed to not to be strict to the "open" events on such buggy
> platforms.
> 
> Why will the subsequent "close" events be lost? This is because the input
> layer automatically filters redundant events for switch events. Thus given
> that the buggy AML tables do not guarantee paired "open"/"close" events,
> the ACPI button driver currently is not able to guarantee that the platform
> triggered reliable events can be always be seen by the userspace via
> SW_LID.
> 
> This patch adds a mechanism to insert lid events as a compensation for the
> platform triggered ones to form a complete event switches in order to make
> sure that the platform triggered events can always be reliably delivered
> to the userspace. This essentially guarantees that the platform triggered
> reliable "close" events will always be relibly delivered to the userspace.
> 
> However this mechanism is not suitable for lid_init_state=open/method as
> it should not send the complement switch event for the unreliable initial
> lid state notification. 2 unreliable events can trigger unexpected
> behavior. Thus this patch only implements this mechanism for
> lid_init_state=ignore.
> 
> Known issues:
> 1. Possible alternative approach
>    This approach is based on the fact that Linux requires a switch event
>    type for LID events. Another approach is to use key event type to
>    implement ACPI lid events.
>    With SW event type, since ACPI button driver inserts wrong lid events,
>    there could be a potential issue that an "open" event issued from some
>    AML update methods could result in a wrong "close" event to be delivered
>    to the userspace. While using KEY event type, there is no such problem.
>    However there may not be such a kind of real case, and if there is such
>    a case, it is worked around in this patch as the complement switch event
>    is only generated for "close" event in order to deliver the reliable
>    "close" event to the userspace.
> 
> Link 1: https://bugzilla.kernel.org/show_bug.cgi?id=89211
>         https://bugzilla.kernel.org/show_bug.cgi?id=106151
> Link 2: https://bugzilla.kernel.org/show_bug.cgi?id=106941
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Suggested-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> Cc: Bastien Nocera: <hadess@hadess.net>
> Cc: linux-input@vger.kernel.org

Both the [1/2] and the [2/2] applied.

Thanks,
Rafael


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

end of thread, other threads:[~2016-09-12 22:10 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <cbdaec17aba78c61f466efff8883d49067f2dad5.1463472125.git.lv.zheng@intel.com>
2016-07-19  8:11 ` [PATCH v4 1/2] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model Lv Zheng
2016-07-19  8:46   ` Benjamin Tissoires
2016-07-21 13:35   ` Rafael J. Wysocki
2016-07-21 20:33     ` Dmitry Torokhov
2016-07-19  8:11 ` [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng
2016-07-19  8:44   ` Benjamin Tissoires
2016-07-21 20:32   ` Dmitry Torokhov
2016-07-22  0:24     ` Zheng, Lv
2016-07-22  4:37       ` Dmitry Torokhov
2016-07-22  6:55         ` Benjamin Tissoires
2016-07-22  8:47           ` Zheng, Lv
2016-07-22  9:08             ` Benjamin Tissoires
2016-07-22  9:38               ` Zheng, Lv
2016-07-24 11:28               ` Bastien Nocera
2016-07-25  0:38                 ` Zheng, Lv
2016-07-22 17:02           ` Dmitry Torokhov
2016-07-23 12:17             ` Zheng, Lv
2016-07-22  8:37         ` Zheng, Lv
2016-07-22 17:22           ` Dmitry Torokhov
2016-07-23 11:57             ` Zheng, Lv
2016-07-22  6:24 ` [PATCH v5 1/3] ACPI / button: Add missing event to keep SW_LID running without additional event loss Lv Zheng
2016-07-22 10:26   ` Zheng, Lv
2016-07-23 12:37   ` Rafael J. Wysocki
2016-07-25  0:24     ` Zheng, Lv
2016-07-22  6:24 ` [PATCH v5 2/3] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model Lv Zheng
2016-07-22  6:24 ` [PATCH v5 3/3] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng
2016-07-25  1:14 ` [PATCH v6] ACPI / button: Fix an issue that the platform triggered "close" event may not be delivered to the userspace Lv Zheng
2016-07-26  9:52 ` [PATCH v7 1/2] ACPI / button: Fix an issue that the platform triggered reliable events " Lv Zheng
2016-08-17  0:19   ` Rafael J. Wysocki
2016-08-17  4:45     ` Zheng, Lv
2016-07-26  9:52 ` [PATCH v7 2/2] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng
2016-08-17  8:22 ` [PATCH v8 1/2] ACPI / button: Fix an issue in button.lid_init_state=ignore mode Lv Zheng
2016-09-12 22:10   ` Rafael J. Wysocki
2016-08-17  8:23 ` [PATCH v8 2/2] ACPI / button: Add document for ACPI control method lid device restrictions Lv Zheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).