linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume
@ 2016-05-17  8:27 Lv Zheng
  2016-05-17 23:36 ` Rafael J. Wysocki
                   ` (15 more replies)
  0 siblings, 16 replies; 66+ messages in thread
From: Lv Zheng @ 2016-05-17  8:27 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi, Bastien Nocera:

(This patch hasn't been tested, it's sent for comments)

Linux userspace (systemd-logind) keeps on rechecking lid state when the
lid state is closed. If it failed to update the lid state to open after
boot/resume, it could suspend the system. But as:
1. Traditional ACPI platform may not generate the lid open event after
   resuming as the open event is actually handled by the BIOS and the system
   is then resumed from a FACS vector.
2. The _LID control method's initial returning value is not reliable. The
   _LID control method is described to return the "current" lid state,
   however the word of "current" has ambiguity, many BIOSen return lid
   state upon last lid notification while the developers may think the
   BIOSen should always return the lid state upon last _LID evaluation.
   There won't be difference when we evaluate _LID during the runtime, the
   problem is the initial returning value of this function. When the BIOSen
   implement this control method with cached value, the initial returning
   value is likely not reliable.
Thus there is no mean for the ACPI lid driver to provide such an event
conveying correct current lid state. When there is no such an event or the
event conveys wrong result, false suspending can be examined.

The root cause of the issue is systemd itself, it could handle the ACPI
control method lid device by implementing a special option like
LidSwitchLevelTriggered=False when it detected the ACPI lid device. However
there is no explicit documentation clarified the ambiguity, we need to
work it around in the kernel before systemd changing its mind.

Link 1: https://lkml.org/2016/3/7/460
Link 2: https://github.com/systemd/systemd/issues/2087
Link 3: https://bugzilla.kernel.org/show_bug.cgi?id=89211
        https://bugzilla.kernel.org/show_bug.cgi?id=106151
        https://bugzilla.kernel.org/show_bug.cgi?id=106941
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Cc: Bastien Nocera: <hadess@hadess.net>
---
 drivers/acpi/button.c |   63 +++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 59 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 5c3b091..bb14ca5 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -53,6 +53,10 @@
 #define ACPI_BUTTON_DEVICE_NAME_LID	"Lid Switch"
 #define ACPI_BUTTON_TYPE_LID		0x05
 
+#define ACPI_BUTTON_LID_INIT_IGNORE	0x00
+#define ACPI_BUTTON_LID_INIT_OPEN	0x01
+#define ACPI_BUTTON_LID_INIT_METHOD	0x02
+
 #define _COMPONENT		ACPI_BUTTON_COMPONENT
 ACPI_MODULE_NAME("button");
 
@@ -105,6 +109,7 @@ struct acpi_button {
 
 static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
 static struct acpi_device *lid_device;
+static u8 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
 
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
@@ -246,7 +251,8 @@ int acpi_lid_open(void)
 }
 EXPORT_SYMBOL(acpi_lid_open);
 
-static int acpi_lid_send_state(struct acpi_device *device)
+static int acpi_lid_send_state(struct acpi_device *device,
+			       bool notify_init_state)
 {
 	struct acpi_button *button = acpi_driver_data(device);
 	unsigned long long state;
@@ -257,6 +263,10 @@ static int acpi_lid_send_state(struct acpi_device *device)
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
 
+	if (notify_init_state &&
+	    lid_init_state == ACPI_BUTTON_LID_INIT_OPEN)
+		state = 1;
+
 	/* input layer checks if event is redundant */
 	input_report_switch(button->input, SW_LID, !state);
 	input_sync(button->input);
@@ -278,6 +288,13 @@ static int acpi_lid_send_state(struct acpi_device *device)
 	return ret;
 }
 
+static int acpi_lid_send_init_state(struct acpi_device *device)
+{
+	if (lid_init_state != ACPI_BUTTON_LID_INIT_IGNORE)
+		return acpi_lid_send_state(device, true);
+	return 0;
+}
+
 static void acpi_button_notify(struct acpi_device *device, u32 event)
 {
 	struct acpi_button *button = acpi_driver_data(device);
@@ -290,7 +307,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
 	case ACPI_BUTTON_NOTIFY_STATUS:
 		input = button->input;
 		if (button->type == ACPI_BUTTON_TYPE_LID) {
-			acpi_lid_send_state(device);
+			acpi_lid_send_state(device, false);
 		} else {
 			int keycode;
 
@@ -335,7 +352,7 @@ static int acpi_button_resume(struct device *dev)
 
 	button->suspended = false;
 	if (button->type == ACPI_BUTTON_TYPE_LID)
-		return acpi_lid_send_state(device);
+		return acpi_lid_send_init_state(device);
 	return 0;
 }
 #endif
@@ -416,7 +433,7 @@ static int acpi_button_add(struct acpi_device *device)
 	if (error)
 		goto err_remove_fs;
 	if (button->type == ACPI_BUTTON_TYPE_LID) {
-		acpi_lid_send_state(device);
+		acpi_lid_send_init_state(device);
 		/*
 		 * This assumes there's only one lid device, or if there are
 		 * more we only care about the last one...
@@ -446,4 +463,42 @@ static int acpi_button_remove(struct acpi_device *device)
 	return 0;
 }
 
+static int param_set_lid_init_state(const char *val, struct kernel_param *kp)
+{
+	int result = 0;
+
+	if (!strncmp(val, "open", sizeof("open") - 1)) {
+		lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
+		pr_info("Notify initial lid state as open\n");
+	} else if (!strncmp(val, "method", sizeof("method") - 1)) {
+		lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
+		pr_info("Notify initial lid state with _LID return value\n");
+	} else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) {
+		lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE;
+		pr_info("Do not notify initial lid state\n");
+	} else
+		result = -EINVAL;
+	return result;
+}
+
+static int param_get_lid_init_state(char *buffer, struct kernel_param *kp)
+{
+	switch (lid_init_state) {
+	case ACPI_BUTTON_LID_INIT_OPEN:
+		return sprintf(buffer, "open");
+	case ACPI_BUTTON_LID_INIT_METHOD:
+		return sprintf(buffer, "method");
+	case ACPI_BUTTON_LID_INIT_IGNORE:
+		return sprintf(buffer, "ignore");
+	default:
+		return sprintf(buffer, "invalid");
+	}
+	return 0;
+}
+
+module_param_call(lid_init_state,
+		  param_set_lid_init_state, param_get_lid_init_state,
+		  NULL, 0644);
+MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial state");
+
 module_acpi_driver(acpi_button_driver);
-- 
1.7.10

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

* Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
@ 2016-05-17 23:36 ` Rafael J. Wysocki
  2016-05-18  1:25   ` Zheng, Lv
  2016-05-18 12:57 ` Bastien Nocera
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 66+ messages in thread
From: Rafael J. Wysocki @ 2016-05-17 23:36 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown, Lv Zheng,
	Linux Kernel Mailing List, ACPI Devel Maling List,
	Bastien Nocera:

On Tue, May 17, 2016 at 10:27 AM, Lv Zheng <lv.zheng@intel.com> wrote:
> (This patch hasn't been tested, it's sent for comments)

I have a couple of concerns (see below).

> Linux userspace (systemd-logind) keeps on rechecking lid state when the
> lid state is closed. If it failed to update the lid state to open after
> boot/resume, it could suspend the system. But as:
> 1. Traditional ACPI platform may not generate the lid open event after
>    resuming as the open event is actually handled by the BIOS and the system
>    is then resumed from a FACS vector.
> 2. The _LID control method's initial returning value is not reliable. The
>    _LID control method is described to return the "current" lid state,
>    however the word of "current" has ambiguity, many BIOSen return lid
>    state upon last lid notification while the developers may think the
>    BIOSen should always return the lid state upon last _LID evaluation.
>    There won't be difference when we evaluate _LID during the runtime, the
>    problem is the initial returning value of this function. When the BIOSen
>    implement this control method with cached value, the initial returning
>    value is likely not reliable.
> Thus there is no mean for the ACPI lid driver to provide such an event
> conveying correct current lid state. When there is no such an event or the
> event conveys wrong result, false suspending can be examined.
>
> The root cause of the issue is systemd itself, it could handle the ACPI
> control method lid device by implementing a special option like
> LidSwitchLevelTriggered=False when it detected the ACPI lid device. However
> there is no explicit documentation clarified the ambiguity, we need to
> work it around in the kernel before systemd changing its mind.

The above doesn't explain how the issue is addressed here.

> Link 1: https://lkml.org/2016/3/7/460
> Link 2: https://github.com/systemd/systemd/issues/2087
> Link 3: https://bugzilla.kernel.org/show_bug.cgi?id=89211
>         https://bugzilla.kernel.org/show_bug.cgi?id=106151
>         https://bugzilla.kernel.org/show_bug.cgi?id=106941
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Cc: Bastien Nocera: <hadess@hadess.net>
> ---
>  drivers/acpi/button.c |   63 +++++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 59 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> index 5c3b091..bb14ca5 100644
> --- a/drivers/acpi/button.c
> +++ b/drivers/acpi/button.c
> @@ -53,6 +53,10 @@
>  #define ACPI_BUTTON_DEVICE_NAME_LID    "Lid Switch"
>  #define ACPI_BUTTON_TYPE_LID           0x05
>
> +#define ACPI_BUTTON_LID_INIT_IGNORE    0x00
> +#define ACPI_BUTTON_LID_INIT_OPEN      0x01
> +#define ACPI_BUTTON_LID_INIT_METHOD    0x02
> +
>  #define _COMPONENT             ACPI_BUTTON_COMPONENT
>  ACPI_MODULE_NAME("button");
>
> @@ -105,6 +109,7 @@ struct acpi_button {
>
>  static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
>  static struct acpi_device *lid_device;
> +static u8 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
>
>  /* --------------------------------------------------------------------------
>                                FS Interface (/proc)
> @@ -246,7 +251,8 @@ int acpi_lid_open(void)
>  }
>  EXPORT_SYMBOL(acpi_lid_open);
>
> -static int acpi_lid_send_state(struct acpi_device *device)
> +static int acpi_lid_send_state(struct acpi_device *device,
> +                              bool notify_init_state)
>  {
>         struct acpi_button *button = acpi_driver_data(device);
>         unsigned long long state;
> @@ -257,6 +263,10 @@ static int acpi_lid_send_state(struct acpi_device *device)
>         if (ACPI_FAILURE(status))
>                 return -ENODEV;
>
> +       if (notify_init_state &&
> +           lid_init_state == ACPI_BUTTON_LID_INIT_OPEN)
> +               state = 1;
> +

Why do we need to complicate this function?

Can't we have a separate function for sending the fake "lid open" event?

>         /* input layer checks if event is redundant */
>         input_report_switch(button->input, SW_LID, !state);
>         input_sync(button->input);
> @@ -278,6 +288,13 @@ static int acpi_lid_send_state(struct acpi_device *device)
>         return ret;
>  }
>
> +static int acpi_lid_send_init_state(struct acpi_device *device)
> +{
> +       if (lid_init_state != ACPI_BUTTON_LID_INIT_IGNORE)
> +               return acpi_lid_send_state(device, true);
> +       return 0;
> +}
> +
>  static void acpi_button_notify(struct acpi_device *device, u32 event)
>  {
>         struct acpi_button *button = acpi_driver_data(device);
> @@ -290,7 +307,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
>         case ACPI_BUTTON_NOTIFY_STATUS:
>                 input = button->input;
>                 if (button->type == ACPI_BUTTON_TYPE_LID) {
> -                       acpi_lid_send_state(device);
> +                       acpi_lid_send_state(device, false);

I wouldn't change this code at all.

>                 } else {
>                         int keycode;
>
> @@ -335,7 +352,7 @@ static int acpi_button_resume(struct device *dev)
>
>         button->suspended = false;
>         if (button->type == ACPI_BUTTON_TYPE_LID)
> -               return acpi_lid_send_state(device);
> +               return acpi_lid_send_init_state(device);
>         return 0;
>  }
>  #endif
> @@ -416,7 +433,7 @@ static int acpi_button_add(struct acpi_device *device)
>         if (error)
>                 goto err_remove_fs;
>         if (button->type == ACPI_BUTTON_TYPE_LID) {
> -               acpi_lid_send_state(device);
> +               acpi_lid_send_init_state(device);
>                 /*
>                  * This assumes there's only one lid device, or if there are
>                  * more we only care about the last one...
> @@ -446,4 +463,42 @@ static int acpi_button_remove(struct acpi_device *device)
>         return 0;
>  }
>
> +static int param_set_lid_init_state(const char *val, struct kernel_param *kp)
> +{
> +       int result = 0;
> +
> +       if (!strncmp(val, "open", sizeof("open") - 1)) {
> +               lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
> +               pr_info("Notify initial lid state as open\n");
> +       } else if (!strncmp(val, "method", sizeof("method") - 1)) {
> +               lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
> +               pr_info("Notify initial lid state with _LID return value\n");
> +       } else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) {
> +               lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE;
> +               pr_info("Do not notify initial lid state\n");
> +       } else
> +               result = -EINVAL;
> +       return result;
> +}
> +
> +static int param_get_lid_init_state(char *buffer, struct kernel_param *kp)
> +{
> +       switch (lid_init_state) {
> +       case ACPI_BUTTON_LID_INIT_OPEN:
> +               return sprintf(buffer, "open");
> +       case ACPI_BUTTON_LID_INIT_METHOD:
> +               return sprintf(buffer, "method");
> +       case ACPI_BUTTON_LID_INIT_IGNORE:
> +               return sprintf(buffer, "ignore");
> +       default:
> +               return sprintf(buffer, "invalid");
> +       }
> +       return 0;
> +}
> +
> +module_param_call(lid_init_state,
> +                 param_set_lid_init_state, param_get_lid_init_state,
> +                 NULL, 0644);
> +MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial state");
> +

I'm not seeing a particular value in having this command line switch
to be honest.  Apparently, the issue can be worked around from user
space in any case, so why do we need one more way to work around it?

>  module_acpi_driver(acpi_button_driver);
> --

The main concern is general, though.  Evidently, we send fake lid
input events to user space on init and resume.  I don't think this is
a good idea, because it may confuse systems like Chrome that want to
implement "dark resume" scenarios and may rely on input events to
decide whether to start a UI or suspend again.

Thus it might be better to simply drop the sending of those fake input
events from the code.

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

* RE: [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume
  2016-05-17 23:36 ` Rafael J. Wysocki
@ 2016-05-18  1:25   ` Zheng, Lv
  2016-05-18 22:56     ` Rafael J. Wysocki
  0 siblings, 1 reply; 66+ messages in thread
From: Zheng, Lv @ 2016-05-18  1:25 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	Linux Kernel Mailing List, ACPI Devel Maling List,
	Bastien Nocera:

Hi, Rafael

Thanks for the review.

> From: rjwysocki@gmail.com [mailto:rjwysocki@gmail.com] On Behalf Of
> Rafael J. Wysocki
> Sent: Wednesday, May 18, 2016 7:37 AM
> To: Zheng, Lv <lv.zheng@intel.com>
> Cc: Wysocki, Rafael J <rafael.j.wysocki@intel.com>; Rafael J. Wysocki
> <rjw@rjwysocki.net>; Brown, Len <len.brown@intel.com>; Lv Zheng
> <zetalog@gmail.com>; Linux Kernel Mailing List <linux-
> kernel@vger.kernel.org>; ACPI Devel Maling List <linux-acpi@vger.kernel.org>;
> Bastien Nocera: <hadess@hadess.net>
> Subject: Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after
> boot/resume
> 
> On Tue, May 17, 2016 at 10:27 AM, Lv Zheng <lv.zheng@intel.com> wrote:
> > (This patch hasn't been tested, it's sent for comments)
> 
> I have a couple of concerns (see below).
> 
> > Linux userspace (systemd-logind) keeps on rechecking lid state when the
> > lid state is closed. If it failed to update the lid state to open after
> > boot/resume, it could suspend the system. But as:
> > 1. Traditional ACPI platform may not generate the lid open event after
> >    resuming as the open event is actually handled by the BIOS and the system
> >    is then resumed from a FACS vector.
> > 2. The _LID control method's initial returning value is not reliable. The
> >    _LID control method is described to return the "current" lid state,
> >    however the word of "current" has ambiguity, many BIOSen return lid
> >    state upon last lid notification while the developers may think the
> >    BIOSen should always return the lid state upon last _LID evaluation.
> >    There won't be difference when we evaluate _LID during the runtime, the
> >    problem is the initial returning value of this function. When the BIOSen
> >    implement this control method with cached value, the initial returning
> >    value is likely not reliable.
> > Thus there is no mean for the ACPI lid driver to provide such an event
> > conveying correct current lid state. When there is no such an event or the
> > event conveys wrong result, false suspending can be examined.
> >
> > The root cause of the issue is systemd itself, it could handle the ACPI
> > control method lid device by implementing a special option like
> > LidSwitchLevelTriggered=False when it detected the ACPI lid device. However
> > there is no explicit documentation clarified the ambiguity, we need to
> > work it around in the kernel before systemd changing its mind.
> 
> The above doesn't explain how the issue is addressed here.
[Lv Zheng] 
The story is a bit long.
We can see several issues that some platform suspends right after boot/resume.
We noticed that on that platforms, _LID is always implemented with cached lid state returned.
And it's initial returning value may be "closed" after boot/resume.

It appears the acpi_lid_send_state() sent after boot/resume is the culprit to report the wrong lid state to the userspace.
But to our surprise, after delete the 2 lines, reporters still can see suspends after boot/resume.
That's because of systemd implementation.
It contains code logic that:
When the lid state is closed, a re-checking mechanism is installed.
So if we do not send any notification after boot/resume and the old lid state is "closed".
systemd determines to suspend in the re-checking mechanism.


> 
> > Link 1: https://lkml.org/2016/3/7/460
> > Link 2: https://github.com/systemd/systemd/issues/2087
> > Link 3: https://bugzilla.kernel.org/show_bug.cgi?id=89211
> >         https://bugzilla.kernel.org/show_bug.cgi?id=106151
> >         https://bugzilla.kernel.org/show_bug.cgi?id=106941
> > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > Cc: Bastien Nocera: <hadess@hadess.net>
> > ---
> >  drivers/acpi/button.c |   63
> +++++++++++++++++++++++++++++++++++++++++++++----
> >  1 file changed, 59 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> > index 5c3b091..bb14ca5 100644
> > --- a/drivers/acpi/button.c
> > +++ b/drivers/acpi/button.c
> > @@ -53,6 +53,10 @@
> >  #define ACPI_BUTTON_DEVICE_NAME_LID    "Lid Switch"
> >  #define ACPI_BUTTON_TYPE_LID           0x05
> >
> > +#define ACPI_BUTTON_LID_INIT_IGNORE    0x00
> > +#define ACPI_BUTTON_LID_INIT_OPEN      0x01
> > +#define ACPI_BUTTON_LID_INIT_METHOD    0x02
> > +
> >  #define _COMPONENT             ACPI_BUTTON_COMPONENT
> >  ACPI_MODULE_NAME("button");
> >
> > @@ -105,6 +109,7 @@ struct acpi_button {
> >
> >  static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
> >  static struct acpi_device *lid_device;
> > +static u8 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
> >
> >  /* --------------------------------------------------------------------------
> >                                FS Interface (/proc)
> > @@ -246,7 +251,8 @@ int acpi_lid_open(void)
> >  }
> >  EXPORT_SYMBOL(acpi_lid_open);
> >
> > -static int acpi_lid_send_state(struct acpi_device *device)
> > +static int acpi_lid_send_state(struct acpi_device *device,
> > +                              bool notify_init_state)
> >  {
> >         struct acpi_button *button = acpi_driver_data(device);
> >         unsigned long long state;
> > @@ -257,6 +263,10 @@ static int acpi_lid_send_state(struct acpi_device
> *device)
> >         if (ACPI_FAILURE(status))
> >                 return -ENODEV;
> >
> > +       if (notify_init_state &&
> > +           lid_init_state == ACPI_BUTTON_LID_INIT_OPEN)
> > +               state = 1;
> > +
> 
> Why do we need to complicate this function?
> 
> Can't we have a separate function for sending the fake "lid open" event?
[Lv Zheng] 

Yes, we can.
But I put the code here for reasons.

I intentionally kept the _LID evaluation right after boot/resume.
Because I validated Windows behavior.
It seems Windows evaluates _LID right after boot.
So I kept _LID evaluated right after boot to prevent compliance issues.

> 
> >         /* input layer checks if event is redundant */
> >         input_report_switch(button->input, SW_LID, !state);
> >         input_sync(button->input);
> > @@ -278,6 +288,13 @@ static int acpi_lid_send_state(struct acpi_device
> *device)
> >         return ret;
> >  }
> >
> > +static int acpi_lid_send_init_state(struct acpi_device *device)
> > +{
> > +       if (lid_init_state != ACPI_BUTTON_LID_INIT_IGNORE)
> > +               return acpi_lid_send_state(device, true);
> > +       return 0;
> > +}
> > +
> >  static void acpi_button_notify(struct acpi_device *device, u32 event)
> >  {
> >         struct acpi_button *button = acpi_driver_data(device);
> > @@ -290,7 +307,7 @@ static void acpi_button_notify(struct acpi_device
> *device, u32 event)
> >         case ACPI_BUTTON_NOTIFY_STATUS:
> >                 input = button->input;
> >                 if (button->type == ACPI_BUTTON_TYPE_LID) {
> > -                       acpi_lid_send_state(device);
> > +                       acpi_lid_send_state(device, false);
> 
> I wouldn't change this code at all.
> 
> >                 } else {
> >                         int keycode;
> >
> > @@ -335,7 +352,7 @@ static int acpi_button_resume(struct device *dev)
> >
> >         button->suspended = false;
> >         if (button->type == ACPI_BUTTON_TYPE_LID)
> > -               return acpi_lid_send_state(device);
> > +               return acpi_lid_send_init_state(device);
> >         return 0;
> >  }
> >  #endif
> > @@ -416,7 +433,7 @@ static int acpi_button_add(struct acpi_device *device)
> >         if (error)
> >                 goto err_remove_fs;
> >         if (button->type == ACPI_BUTTON_TYPE_LID) {
> > -               acpi_lid_send_state(device);
> > +               acpi_lid_send_init_state(device);
> >                 /*
> >                  * This assumes there's only one lid device, or if there are
> >                  * more we only care about the last one...
> > @@ -446,4 +463,42 @@ static int acpi_button_remove(struct acpi_device
> *device)
> >         return 0;
> >  }
> >
> > +static int param_set_lid_init_state(const char *val, struct kernel_param *kp)
> > +{
> > +       int result = 0;
> > +
> > +       if (!strncmp(val, "open", sizeof("open") - 1)) {
> > +               lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
> > +               pr_info("Notify initial lid state as open\n");
> > +       } else if (!strncmp(val, "method", sizeof("method") - 1)) {
> > +               lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
> > +               pr_info("Notify initial lid state with _LID return value\n");
> > +       } else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) {
> > +               lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE;
> > +               pr_info("Do not notify initial lid state\n");
> > +       } else
> > +               result = -EINVAL;
> > +       return result;
> > +}
> > +
> > +static int param_get_lid_init_state(char *buffer, struct kernel_param *kp)
> > +{
> > +       switch (lid_init_state) {
> > +       case ACPI_BUTTON_LID_INIT_OPEN:
> > +               return sprintf(buffer, "open");
> > +       case ACPI_BUTTON_LID_INIT_METHOD:
> > +               return sprintf(buffer, "method");
> > +       case ACPI_BUTTON_LID_INIT_IGNORE:
> > +               return sprintf(buffer, "ignore");
> > +       default:
> > +               return sprintf(buffer, "invalid");
> > +       }
> > +       return 0;
> > +}
> > +
> > +module_param_call(lid_init_state,
> > +                 param_set_lid_init_state, param_get_lid_init_state,
> > +                 NULL, 0644);
> > +MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial
> state");
> > +
> 
> I'm not seeing a particular value in having this command line switch
> to be honest.  Apparently, the issue can be worked around from user
> space in any case, so why do we need one more way to work around it?
> 
> >  module_acpi_driver(acpi_button_driver);
> > --
> 
> The main concern is general, though.  Evidently, we send fake lid
> input events to user space on init and resume.  I don't think this is
> a good idea, because it may confuse systems like Chrome that want to
> implement "dark resume" scenarios and may rely on input events to
> decide whether to start a UI or suspend again.
> 
> Thus it might be better to simply drop the sending of those fake input
> events from the code.
[Lv Zheng] 
If we did this right now, many other userspace could be broken.
So we prepared the options to allow users to choose.

Thanks and best regards
-Lv

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

* Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
  2016-05-17 23:36 ` Rafael J. Wysocki
@ 2016-05-18 12:57 ` Bastien Nocera
  2016-05-18 21:41   ` Rafael J. Wysocki
  2016-05-19  1:59   ` Zheng, Lv
  2016-05-27  7:15 ` [PATCH v2 0/3] ACPI / button: Clarify initial lid state Lv Zheng
                   ` (13 subsequent siblings)
  15 siblings, 2 replies; 66+ messages in thread
From: Bastien Nocera @ 2016-05-18 12:57 UTC (permalink / raw)
  To: Lv Zheng, Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, linux-kernel, linux-acpi

On Tue, 2016-05-17 at 16:27 +0800, Lv Zheng wrote:
> (This patch hasn't been tested, it's sent for comments)
> 
> Linux userspace (systemd-logind) keeps on rechecking lid state when the
> lid state is closed. If it failed to update the lid state to open after
> boot/resume, it could suspend the system. But as:
> 1. Traditional ACPI platform may not generate the lid open event after
>    resuming as the open event is actually handled by the BIOS and the system
>    is then resumed from a FACS vector.
> 2. The _LID control method's initial returning value is not reliable. The
>    _LID control method is described to return the "current" lid state,
>    however the word of "current" has ambiguity, many BIOSen return lid
>    state upon last lid notification while the developers may think the
>    BIOSen should always return the lid state upon last _LID evaluation.
>    There won't be difference when we evaluate _LID during the runtime, the
>    problem is the initial returning value of this function. When the BIOSen
>    implement this control method with cached value, the initial returning
>    value is likely not reliable.
> Thus there is no mean for the ACPI lid driver to provide such an event
> conveying correct current lid state. When there is no such an event or the
> event conveys wrong result, false suspending can be examined.
> 
> The root cause of the issue is systemd itself, it could handle the ACPI
> control method lid device by implementing a special option like
> LidSwitchLevelTriggered=False when it detected the ACPI lid device. However
> there is no explicit documentation clarified the ambiguity, we need to
> work it around in the kernel before systemd changing its mind.
> 
> Link 1: https://lkml.org/2016/3/7/460
> Link 2: https://github.com/systemd/systemd/issues/2087
> Link 3: https://bugzilla.kernel.org/show_bug.cgi?id=89211
>         https://bugzilla.kernel.org/show_bug.cgi?id=106151
>         https://bugzilla.kernel.org/show_bug.cgi?id=106941
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Cc: Bastien Nocera: <hadess@hadess.net>

As mentioned previously, I'd be much happier if either:
- a new system was put in place that matched the ACPI specs and the way
they are used by Windows
- an additional tag/property was added to show that the API offered by
the LID switch is different from the one that existing since ACPI
support was added to Linux.

And I'd really appreciate it if you stopped saying that it's systemd's
fault.

The kernel has offered an API to user-space that included the state of
the LID switch. And the state of the LID switch has been correct for
the majority of systems and devices for the past decade or so. The fact
that this device means that the LID state isn't reliable anymore means
that the kernel needs to communicate that to user-space.

I'm volunteering to modify systemd and UPower to respect the fact that
the LID switch state isn't available on those devices. If you want to
find something to blame, blame the kernel for implementing an API that
doesn't reflect what the hardware makes available. Though you can only
say that with the benefit of hindsight.

So, NAK from me.

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

* Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume
  2016-05-18 12:57 ` Bastien Nocera
@ 2016-05-18 21:41   ` Rafael J. Wysocki
  2016-05-19  1:59   ` Zheng, Lv
  1 sibling, 0 replies; 66+ messages in thread
From: Rafael J. Wysocki @ 2016-05-18 21:41 UTC (permalink / raw)
  To: Bastien Nocera
  Cc: Lv Zheng, Rafael J. Wysocki, Rafael J. Wysocki, Len Brown,
	Lv Zheng, Linux Kernel Mailing List, ACPI Devel Maling List

On Wed, May 18, 2016 at 2:57 PM, Bastien Nocera <hadess@hadess.net> wrote:
> On Tue, 2016-05-17 at 16:27 +0800, Lv Zheng wrote:
>> (This patch hasn't been tested, it's sent for comments)
>>

[cut]

>
> As mentioned previously, I'd be much happier if either:
> - a new system was put in place that matched the ACPI specs and the way
> they are used by Windows
> - an additional tag/property was added to show that the API offered by
> the LID switch is different from the one that existing since ACPI
> support was added to Linux.

I'm sorry, but I'm not following either of the above.

> And I'd really appreciate it if you stopped saying that it's systemd's
> fault.
>
> The kernel has offered an API to user-space that included the state of
> the LID switch.

To be precise, this is not what the kernel has been providing.

It really is the state of the lid switch as reported by the platform
firmware.  The "as reported by the platform firmware" part appears to
be missing from your argumentation and it is quite relevant, because
the firmware, being what it is, messes up things at least
occasionally, so by using that interface you may end up having to deal
with a value that has been messed up by the firmware.

Now, the kernel is not entirely innocent here, because it sometimes
reports input events that it has not received to user space.  That
happens during system initialization and during resume from system
suspend and is generally problematic, so I'd prefer to get rid of that
behavior.  That, however, has nothing to do with the spec compliance
and/or the Windows' behavior.

> And the state of the LID switch has been correct for
> the majority of systems and devices for the past decade or so. The fact
> that this device means that the LID state isn't reliable anymore means
> that the kernel needs to communicate that to user-space.

The problem, though, is that the kernel has no idea about the value
being incorrect.  It just passes the value over to user space and has
no way to validate it.

> I'm volunteering to modify systemd and UPower to respect the fact that
> the LID switch state isn't available on those devices. If you want to
> find something to blame, blame the kernel for implementing an API that
> doesn't reflect what the hardware makes available.

The API works as I described: it passes the value reported by the
firmware to user space.  I has always worked this way.  Whether or not
that is a useful API is a good question.

I guess, however, that the fake input events reported by the kernel
are really problematic here, because had they not been reported, you
wouldn't have seen an incorrect lid switch state, most likely.

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

* Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume
  2016-05-18  1:25   ` Zheng, Lv
@ 2016-05-18 22:56     ` Rafael J. Wysocki
  2016-05-19  1:50       ` Zheng, Lv
  0 siblings, 1 reply; 66+ messages in thread
From: Rafael J. Wysocki @ 2016-05-18 22:56 UTC (permalink / raw)
  To: Zheng, Lv
  Cc: Rafael J. Wysocki, Wysocki, Rafael J, Rafael J. Wysocki, Brown,
	Len, Lv Zheng, Linux Kernel Mailing List, ACPI Devel Maling List,
	Bastien Nocera:

On Wed, May 18, 2016 at 3:25 AM, Zheng, Lv <lv.zheng@intel.com> wrote:
> Hi, Rafael
>
> Thanks for the review.
>
>> From: rjwysocki@gmail.com [mailto:rjwysocki@gmail.com] On Behalf Of
>> Rafael J. Wysocki
>> Sent: Wednesday, May 18, 2016 7:37 AM
>> To: Zheng, Lv <lv.zheng@intel.com>
>> Cc: Wysocki, Rafael J <rafael.j.wysocki@intel.com>; Rafael J. Wysocki
>> <rjw@rjwysocki.net>; Brown, Len <len.brown@intel.com>; Lv Zheng
>> <zetalog@gmail.com>; Linux Kernel Mailing List <linux-
>> kernel@vger.kernel.org>; ACPI Devel Maling List <linux-acpi@vger.kernel.org>;
>> Bastien Nocera: <hadess@hadess.net>
>> Subject: Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after
>> boot/resume
>>
>> On Tue, May 17, 2016 at 10:27 AM, Lv Zheng <lv.zheng@intel.com> wrote:
>> > (This patch hasn't been tested, it's sent for comments)
>>
>> I have a couple of concerns (see below).
>>
>> > Linux userspace (systemd-logind) keeps on rechecking lid state when the
>> > lid state is closed. If it failed to update the lid state to open after
>> > boot/resume, it could suspend the system. But as:
>> > 1. Traditional ACPI platform may not generate the lid open event after
>> >    resuming as the open event is actually handled by the BIOS and the system
>> >    is then resumed from a FACS vector.
>> > 2. The _LID control method's initial returning value is not reliable. The
>> >    _LID control method is described to return the "current" lid state,
>> >    however the word of "current" has ambiguity, many BIOSen return lid
>> >    state upon last lid notification while the developers may think the
>> >    BIOSen should always return the lid state upon last _LID evaluation.
>> >    There won't be difference when we evaluate _LID during the runtime, the
>> >    problem is the initial returning value of this function. When the BIOSen
>> >    implement this control method with cached value, the initial returning
>> >    value is likely not reliable.
>> > Thus there is no mean for the ACPI lid driver to provide such an event
>> > conveying correct current lid state. When there is no such an event or the
>> > event conveys wrong result, false suspending can be examined.
>> >
>> > The root cause of the issue is systemd itself, it could handle the ACPI
>> > control method lid device by implementing a special option like
>> > LidSwitchLevelTriggered=False when it detected the ACPI lid device. However
>> > there is no explicit documentation clarified the ambiguity, we need to
>> > work it around in the kernel before systemd changing its mind.
>>
>> The above doesn't explain how the issue is addressed here.
> [Lv Zheng]
> The story is a bit long.
> We can see several issues that some platform suspends right after boot/resume.
> We noticed that on that platforms, _LID is always implemented with cached lid state returned.
> And it's initial returning value may be "closed" after boot/resume.
>
> It appears the acpi_lid_send_state() sent after boot/resume is the culprit to report the wrong lid state to the userspace.
> But to our surprise, after delete the 2 lines, reporters still can see suspends after boot/resume.
> That's because of systemd implementation.
> It contains code logic that:
> When the lid state is closed, a re-checking mechanism is installed.
> So if we do not send any notification after boot/resume and the old lid state is "closed".
> systemd determines to suspend in the re-checking mechanism.

If that really is the case, it is plain silly and I don't think we can
do anything in the kernel to help here.

>>
>> > Link 1: https://lkml.org/2016/3/7/460
>> > Link 2: https://github.com/systemd/systemd/issues/2087
>> > Link 3: https://bugzilla.kernel.org/show_bug.cgi?id=89211
>> >         https://bugzilla.kernel.org/show_bug.cgi?id=106151
>> >         https://bugzilla.kernel.org/show_bug.cgi?id=106941
>> > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
>> > Cc: Bastien Nocera: <hadess@hadess.net>
>> > ---
>> >  drivers/acpi/button.c |   63
>> +++++++++++++++++++++++++++++++++++++++++++++----
>> >  1 file changed, 59 insertions(+), 4 deletions(-)
>> >
>> > diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
>> > index 5c3b091..bb14ca5 100644
>> > --- a/drivers/acpi/button.c
>> > +++ b/drivers/acpi/button.c
>> > @@ -53,6 +53,10 @@
>> >  #define ACPI_BUTTON_DEVICE_NAME_LID    "Lid Switch"
>> >  #define ACPI_BUTTON_TYPE_LID           0x05
>> >
>> > +#define ACPI_BUTTON_LID_INIT_IGNORE    0x00
>> > +#define ACPI_BUTTON_LID_INIT_OPEN      0x01
>> > +#define ACPI_BUTTON_LID_INIT_METHOD    0x02
>> > +
>> >  #define _COMPONENT             ACPI_BUTTON_COMPONENT
>> >  ACPI_MODULE_NAME("button");
>> >
>> > @@ -105,6 +109,7 @@ struct acpi_button {
>> >
>> >  static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
>> >  static struct acpi_device *lid_device;
>> > +static u8 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
>> >
>> >  /* --------------------------------------------------------------------------
>> >                                FS Interface (/proc)
>> > @@ -246,7 +251,8 @@ int acpi_lid_open(void)
>> >  }
>> >  EXPORT_SYMBOL(acpi_lid_open);
>> >
>> > -static int acpi_lid_send_state(struct acpi_device *device)
>> > +static int acpi_lid_send_state(struct acpi_device *device,
>> > +                              bool notify_init_state)
>> >  {
>> >         struct acpi_button *button = acpi_driver_data(device);
>> >         unsigned long long state;
>> > @@ -257,6 +263,10 @@ static int acpi_lid_send_state(struct acpi_device
>> *device)
>> >         if (ACPI_FAILURE(status))
>> >                 return -ENODEV;
>> >
>> > +       if (notify_init_state &&
>> > +           lid_init_state == ACPI_BUTTON_LID_INIT_OPEN)
>> > +               state = 1;
>> > +
>>
>> Why do we need to complicate this function?
>>
>> Can't we have a separate function for sending the fake "lid open" event?
> [Lv Zheng]
>
> Yes, we can.
> But I put the code here for reasons.
>
> I intentionally kept the _LID evaluation right after boot/resume.
> Because I validated Windows behavior.
> It seems Windows evaluates _LID right after boot.
> So I kept _LID evaluated right after boot to prevent compliance issues.

I don't quite see what compliance issues could result from skipping
the _LID evaluation after boot.

>>
>> >         /* input layer checks if event is redundant */
>> >         input_report_switch(button->input, SW_LID, !state);
>> >         input_sync(button->input);
>> > @@ -278,6 +288,13 @@ static int acpi_lid_send_state(struct acpi_device
>> *device)
>> >         return ret;
>> >  }
>> >
>> > +static int acpi_lid_send_init_state(struct acpi_device *device)
>> > +{
>> > +       if (lid_init_state != ACPI_BUTTON_LID_INIT_IGNORE)
>> > +               return acpi_lid_send_state(device, true);
>> > +       return 0;
>> > +}
>> > +
>> >  static void acpi_button_notify(struct acpi_device *device, u32 event)
>> >  {
>> >         struct acpi_button *button = acpi_driver_data(device);
>> > @@ -290,7 +307,7 @@ static void acpi_button_notify(struct acpi_device
>> *device, u32 event)
>> >         case ACPI_BUTTON_NOTIFY_STATUS:
>> >                 input = button->input;
>> >                 if (button->type == ACPI_BUTTON_TYPE_LID) {
>> > -                       acpi_lid_send_state(device);
>> > +                       acpi_lid_send_state(device, false);
>>
>> I wouldn't change this code at all.
>>
>> >                 } else {
>> >                         int keycode;
>> >
>> > @@ -335,7 +352,7 @@ static int acpi_button_resume(struct device *dev)
>> >
>> >         button->suspended = false;
>> >         if (button->type == ACPI_BUTTON_TYPE_LID)
>> > -               return acpi_lid_send_state(device);
>> > +               return acpi_lid_send_init_state(device);
>> >         return 0;
>> >  }
>> >  #endif
>> > @@ -416,7 +433,7 @@ static int acpi_button_add(struct acpi_device *device)
>> >         if (error)
>> >                 goto err_remove_fs;
>> >         if (button->type == ACPI_BUTTON_TYPE_LID) {
>> > -               acpi_lid_send_state(device);
>> > +               acpi_lid_send_init_state(device);
>> >                 /*
>> >                  * This assumes there's only one lid device, or if there are
>> >                  * more we only care about the last one...
>> > @@ -446,4 +463,42 @@ static int acpi_button_remove(struct acpi_device
>> *device)
>> >         return 0;
>> >  }
>> >
>> > +static int param_set_lid_init_state(const char *val, struct kernel_param *kp)
>> > +{
>> > +       int result = 0;
>> > +
>> > +       if (!strncmp(val, "open", sizeof("open") - 1)) {
>> > +               lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
>> > +               pr_info("Notify initial lid state as open\n");
>> > +       } else if (!strncmp(val, "method", sizeof("method") - 1)) {
>> > +               lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
>> > +               pr_info("Notify initial lid state with _LID return value\n");
>> > +       } else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) {
>> > +               lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE;
>> > +               pr_info("Do not notify initial lid state\n");
>> > +       } else
>> > +               result = -EINVAL;
>> > +       return result;
>> > +}
>> > +
>> > +static int param_get_lid_init_state(char *buffer, struct kernel_param *kp)
>> > +{
>> > +       switch (lid_init_state) {
>> > +       case ACPI_BUTTON_LID_INIT_OPEN:
>> > +               return sprintf(buffer, "open");
>> > +       case ACPI_BUTTON_LID_INIT_METHOD:
>> > +               return sprintf(buffer, "method");
>> > +       case ACPI_BUTTON_LID_INIT_IGNORE:
>> > +               return sprintf(buffer, "ignore");
>> > +       default:
>> > +               return sprintf(buffer, "invalid");
>> > +       }
>> > +       return 0;
>> > +}
>> > +
>> > +module_param_call(lid_init_state,
>> > +                 param_set_lid_init_state, param_get_lid_init_state,
>> > +                 NULL, 0644);
>> > +MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial
>> state");
>> > +
>>
>> I'm not seeing a particular value in having this command line switch
>> to be honest.  Apparently, the issue can be worked around from user
>> space in any case, so why do we need one more way to work around it?
>>
>> >  module_acpi_driver(acpi_button_driver);
>> > --
>>
>> The main concern is general, though.  Evidently, we send fake lid
>> input events to user space on init and resume.  I don't think this is
>> a good idea, because it may confuse systems like Chrome that want to
>> implement "dark resume" scenarios and may rely on input events to
>> decide whether to start a UI or suspend again.
>>
>> Thus it might be better to simply drop the sending of those fake input
>> events from the code.
> [Lv Zheng]
> If we did this right now, many other userspace could be broken.
> So we prepared the options to allow users to choose.

Do we have any evidence that any other user space stacks are affected?

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

* RE: [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume
  2016-05-18 22:56     ` Rafael J. Wysocki
@ 2016-05-19  1:50       ` Zheng, Lv
  2016-05-19 13:21         ` Rafael J. Wysocki
  0 siblings, 1 reply; 66+ messages in thread
From: Zheng, Lv @ 2016-05-19  1:50 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	Linux Kernel Mailing List, ACPI Devel Maling List,
	Bastien Nocera:

Hi,

> From: rjwysocki@gmail.com [mailto:rjwysocki@gmail.com] On Behalf Of
> Rafael J. Wysocki
> Subject: Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after
> boot/resume
> 
> On Wed, May 18, 2016 at 3:25 AM, Zheng, Lv <lv.zheng@intel.com> wrote:
> > Hi, Rafael
> >
> > Thanks for the review.
> >
> >> From: rjwysocki@gmail.com [mailto:rjwysocki@gmail.com] On Behalf Of
> >> Rafael J. Wysocki
> >> Sent: Wednesday, May 18, 2016 7:37 AM
> >> To: Zheng, Lv <lv.zheng@intel.com>
> >> Cc: Wysocki, Rafael J <rafael.j.wysocki@intel.com>; Rafael J. Wysocki
> >> <rjw@rjwysocki.net>; Brown, Len <len.brown@intel.com>; Lv Zheng
> >> <zetalog@gmail.com>; Linux Kernel Mailing List <linux-
> >> kernel@vger.kernel.org>; ACPI Devel Maling List <linux-
> acpi@vger.kernel.org>;
> >> Bastien Nocera: <hadess@hadess.net>
> >> Subject: Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after
> >> boot/resume
> >>
> >> On Tue, May 17, 2016 at 10:27 AM, Lv Zheng <lv.zheng@intel.com> wrote:
> >> > (This patch hasn't been tested, it's sent for comments)
> >>
> >> I have a couple of concerns (see below).
> >>
> >> > Linux userspace (systemd-logind) keeps on rechecking lid state when the
> >> > lid state is closed. If it failed to update the lid state to open after
> >> > boot/resume, it could suspend the system. But as:
> >> > 1. Traditional ACPI platform may not generate the lid open event after
> >> >    resuming as the open event is actually handled by the BIOS and the
> system
> >> >    is then resumed from a FACS vector.
> >> > 2. The _LID control method's initial returning value is not reliable. The
> >> >    _LID control method is described to return the "current" lid state,
> >> >    however the word of "current" has ambiguity, many BIOSen return lid
> >> >    state upon last lid notification while the developers may think the
> >> >    BIOSen should always return the lid state upon last _LID evaluation.
> >> >    There won't be difference when we evaluate _LID during the runtime,
> the
> >> >    problem is the initial returning value of this function. When the BIOSen
> >> >    implement this control method with cached value, the initial returning
> >> >    value is likely not reliable.
> >> > Thus there is no mean for the ACPI lid driver to provide such an event
> >> > conveying correct current lid state. When there is no such an event or the
> >> > event conveys wrong result, false suspending can be examined.
> >> >
> >> > The root cause of the issue is systemd itself, it could handle the ACPI
> >> > control method lid device by implementing a special option like
> >> > LidSwitchLevelTriggered=False when it detected the ACPI lid device.
> However
> >> > there is no explicit documentation clarified the ambiguity, we need to
> >> > work it around in the kernel before systemd changing its mind.
> >>
> >> The above doesn't explain how the issue is addressed here.
> > [Lv Zheng]
> > The story is a bit long.
> > We can see several issues that some platform suspends right after
> boot/resume.
> > We noticed that on that platforms, _LID is always implemented with cached
> lid state returned.
> > And it's initial returning value may be "closed" after boot/resume.
> >
> > It appears the acpi_lid_send_state() sent after boot/resume is the culprit to
> report the wrong lid state to the userspace.
> > But to our surprise, after delete the 2 lines, reporters still can see suspends
> after boot/resume.
> > That's because of systemd implementation.
> > It contains code logic that:
> > When the lid state is closed, a re-checking mechanism is installed.
> > So if we do not send any notification after boot/resume and the old lid state
> is "closed".
> > systemd determines to suspend in the re-checking mechanism.
> 
> If that really is the case, it is plain silly and I don't think we can
> do anything in the kernel to help here.
[Lv Zheng] 
The problem is:
If we just removed the 2 lines sending wrong lid state after boot/resume.
Problem couldn't be solved.
It could only be solved by changing both the systemd and the kernel (deleting the 2 lines).

> 
> >>
> >> > Link 1: https://lkml.org/2016/3/7/460
> >> > Link 2: https://github.com/systemd/systemd/issues/2087
> >> > Link 3: https://bugzilla.kernel.org/show_bug.cgi?id=89211
> >> >         https://bugzilla.kernel.org/show_bug.cgi?id=106151
> >> >         https://bugzilla.kernel.org/show_bug.cgi?id=106941
> >> > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> >> > Cc: Bastien Nocera: <hadess@hadess.net>
> >> > ---
> >> >  drivers/acpi/button.c |   63
> >> +++++++++++++++++++++++++++++++++++++++++++++----
> >> >  1 file changed, 59 insertions(+), 4 deletions(-)
> >> >
> >> > diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> >> > index 5c3b091..bb14ca5 100644
> >> > --- a/drivers/acpi/button.c
> >> > +++ b/drivers/acpi/button.c
> >> > @@ -53,6 +53,10 @@
> >> >  #define ACPI_BUTTON_DEVICE_NAME_LID    "Lid Switch"
> >> >  #define ACPI_BUTTON_TYPE_LID           0x05
> >> >
> >> > +#define ACPI_BUTTON_LID_INIT_IGNORE    0x00
> >> > +#define ACPI_BUTTON_LID_INIT_OPEN      0x01
> >> > +#define ACPI_BUTTON_LID_INIT_METHOD    0x02
> >> > +
> >> >  #define _COMPONENT             ACPI_BUTTON_COMPONENT
> >> >  ACPI_MODULE_NAME("button");
> >> >
> >> > @@ -105,6 +109,7 @@ struct acpi_button {
> >> >
> >> >  static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
> >> >  static struct acpi_device *lid_device;
> >> > +static u8 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
> >> >
> >> >  /* --------------------------------------------------------------------------
> >> >                                FS Interface (/proc)
> >> > @@ -246,7 +251,8 @@ int acpi_lid_open(void)
> >> >  }
> >> >  EXPORT_SYMBOL(acpi_lid_open);
> >> >
> >> > -static int acpi_lid_send_state(struct acpi_device *device)
> >> > +static int acpi_lid_send_state(struct acpi_device *device,
> >> > +                              bool notify_init_state)
> >> >  {
> >> >         struct acpi_button *button = acpi_driver_data(device);
> >> >         unsigned long long state;
> >> > @@ -257,6 +263,10 @@ static int acpi_lid_send_state(struct acpi_device
> >> *device)
> >> >         if (ACPI_FAILURE(status))
> >> >                 return -ENODEV;
> >> >
> >> > +       if (notify_init_state &&
> >> > +           lid_init_state == ACPI_BUTTON_LID_INIT_OPEN)
> >> > +               state = 1;
> >> > +
> >>
> >> Why do we need to complicate this function?
> >>
> >> Can't we have a separate function for sending the fake "lid open" event?
> > [Lv Zheng]
> >
> > Yes, we can.
> > But I put the code here for reasons.
> >
> > I intentionally kept the _LID evaluation right after boot/resume.
> > Because I validated Windows behavior.
> > It seems Windows evaluates _LID right after boot.
> > So I kept _LID evaluated right after boot to prevent compliance issues.
> 
> I don't quite see what compliance issues could result from skipping
> the _LID evaluation after boot.
[Lv Zheng] 
I'm not sure if there is a platform putting named object initialization code in _LID.
If you don't like it, we can stop evaluating _LID in the next version.

> 
> >>
> >> >         /* input layer checks if event is redundant */
> >> >         input_report_switch(button->input, SW_LID, !state);
> >> >         input_sync(button->input);
> >> > @@ -278,6 +288,13 @@ static int acpi_lid_send_state(struct acpi_device
> >> *device)
> >> >         return ret;
> >> >  }
> >> >
> >> > +static int acpi_lid_send_init_state(struct acpi_device *device)
> >> > +{
> >> > +       if (lid_init_state != ACPI_BUTTON_LID_INIT_IGNORE)
> >> > +               return acpi_lid_send_state(device, true);
> >> > +       return 0;
> >> > +}
> >> > +
> >> >  static void acpi_button_notify(struct acpi_device *device, u32 event)
> >> >  {
> >> >         struct acpi_button *button = acpi_driver_data(device);
> >> > @@ -290,7 +307,7 @@ static void acpi_button_notify(struct acpi_device
> >> *device, u32 event)
> >> >         case ACPI_BUTTON_NOTIFY_STATUS:
> >> >                 input = button->input;
> >> >                 if (button->type == ACPI_BUTTON_TYPE_LID) {
> >> > -                       acpi_lid_send_state(device);
> >> > +                       acpi_lid_send_state(device, false);
> >>
> >> I wouldn't change this code at all.
> >>
> >> >                 } else {
> >> >                         int keycode;
> >> >
> >> > @@ -335,7 +352,7 @@ static int acpi_button_resume(struct device *dev)
> >> >
> >> >         button->suspended = false;
> >> >         if (button->type == ACPI_BUTTON_TYPE_LID)
> >> > -               return acpi_lid_send_state(device);
> >> > +               return acpi_lid_send_init_state(device);
> >> >         return 0;
> >> >  }
> >> >  #endif
> >> > @@ -416,7 +433,7 @@ static int acpi_button_add(struct acpi_device
> *device)
> >> >         if (error)
> >> >                 goto err_remove_fs;
> >> >         if (button->type == ACPI_BUTTON_TYPE_LID) {
> >> > -               acpi_lid_send_state(device);
> >> > +               acpi_lid_send_init_state(device);
> >> >                 /*
> >> >                  * This assumes there's only one lid device, or if there are
> >> >                  * more we only care about the last one...
> >> > @@ -446,4 +463,42 @@ static int acpi_button_remove(struct acpi_device
> >> *device)
> >> >         return 0;
> >> >  }
> >> >
> >> > +static int param_set_lid_init_state(const char *val, struct kernel_param
> *kp)
> >> > +{
> >> > +       int result = 0;
> >> > +
> >> > +       if (!strncmp(val, "open", sizeof("open") - 1)) {
> >> > +               lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
> >> > +               pr_info("Notify initial lid state as open\n");
> >> > +       } else if (!strncmp(val, "method", sizeof("method") - 1)) {
> >> > +               lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
> >> > +               pr_info("Notify initial lid state with _LID return value\n");
> >> > +       } else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) {
> >> > +               lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE;
> >> > +               pr_info("Do not notify initial lid state\n");
> >> > +       } else
> >> > +               result = -EINVAL;
> >> > +       return result;
> >> > +}
> >> > +
> >> > +static int param_get_lid_init_state(char *buffer, struct kernel_param *kp)
> >> > +{
> >> > +       switch (lid_init_state) {
> >> > +       case ACPI_BUTTON_LID_INIT_OPEN:
> >> > +               return sprintf(buffer, "open");
> >> > +       case ACPI_BUTTON_LID_INIT_METHOD:
> >> > +               return sprintf(buffer, "method");
> >> > +       case ACPI_BUTTON_LID_INIT_IGNORE:
> >> > +               return sprintf(buffer, "ignore");
> >> > +       default:
> >> > +               return sprintf(buffer, "invalid");
> >> > +       }
> >> > +       return 0;
> >> > +}
> >> > +
> >> > +module_param_call(lid_init_state,
> >> > +                 param_set_lid_init_state, param_get_lid_init_state,
> >> > +                 NULL, 0644);
> >> > +MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial
> >> state");
> >> > +
> >>
> >> I'm not seeing a particular value in having this command line switch
> >> to be honest.  Apparently, the issue can be worked around from user
> >> space in any case, so why do we need one more way to work around it?
> >>
> >> >  module_acpi_driver(acpi_button_driver);
> >> > --
> >>
> >> The main concern is general, though.  Evidently, we send fake lid
> >> input events to user space on init and resume.  I don't think this is
> >> a good idea, because it may confuse systems like Chrome that want to
> >> implement "dark resume" scenarios and may rely on input events to
> >> decide whether to start a UI or suspend again.
> >>
> >> Thus it might be better to simply drop the sending of those fake input
> >> events from the code.
> > [Lv Zheng]
> > If we did this right now, many other userspace could be broken.
> > So we prepared the options to allow users to choose.
> 
> Do we have any evidence that any other user space stacks are affected?
[Lv Zheng] 
I didn't know any of such affections except the systemd.

Thanks and best regards
-Lv

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

* RE: [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume
  2016-05-18 12:57 ` Bastien Nocera
  2016-05-18 21:41   ` Rafael J. Wysocki
@ 2016-05-19  1:59   ` Zheng, Lv
  1 sibling, 0 replies; 66+ messages in thread
From: Zheng, Lv @ 2016-05-19  1:59 UTC (permalink / raw)
  To: Bastien Nocera, Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len
  Cc: Lv Zheng, linux-kernel, linux-acpi

Hi,

> From: Bastien Nocera [mailto:hadess@hadess.net]
> Subject: Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after
> boot/resume
> 
> On Tue, 2016-05-17 at 16:27 +0800, Lv Zheng wrote:
> > (This patch hasn't been tested, it's sent for comments)
> >
> > Linux userspace (systemd-logind) keeps on rechecking lid state when the
> > lid state is closed. If it failed to update the lid state to open after
> > boot/resume, it could suspend the system. But as:
> > 1. Traditional ACPI platform may not generate the lid open event after
> >    resuming as the open event is actually handled by the BIOS and the system
> >    is then resumed from a FACS vector.
> > 2. The _LID control method's initial returning value is not reliable. The
> >    _LID control method is described to return the "current" lid state,
> >    however the word of "current" has ambiguity, many BIOSen return lid
> >    state upon last lid notification while the developers may think the
> >    BIOSen should always return the lid state upon last _LID evaluation.
> >    There won't be difference when we evaluate _LID during the runtime, the
> >    problem is the initial returning value of this function. When the BIOSen
> >    implement this control method with cached value, the initial returning
> >    value is likely not reliable.
> > Thus there is no mean for the ACPI lid driver to provide such an event
> > conveying correct current lid state. When there is no such an event or the
> > event conveys wrong result, false suspending can be examined.
> >
> > The root cause of the issue is systemd itself, it could handle the ACPI
> > control method lid device by implementing a special option like
> > LidSwitchLevelTriggered=False when it detected the ACPI lid device. However
> > there is no explicit documentation clarified the ambiguity, we need to
> > work it around in the kernel before systemd changing its mind.
> >
> > Link 1: https://lkml.org/2016/3/7/460
> > Link 2: https://github.com/systemd/systemd/issues/2087
> > Link 3: https://bugzilla.kernel.org/show_bug.cgi?id=89211
> >         https://bugzilla.kernel.org/show_bug.cgi?id=106151
> >         https://bugzilla.kernel.org/show_bug.cgi?id=106941
> > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > Cc: Bastien Nocera: <hadess@hadess.net>
> 
> As mentioned previously, I'd be much happier if either:
> - a new system was put in place that matched the ACPI specs and the way
> they are used by Windows
[Lv Zheng] 
Then what about the old systems?
Surface Pro 1 and Surface 3 are MS platforms that should have already adapted to the Windows.
They are currently suffering from the same issue by running Linux.

> - an additional tag/property was added to show that the API offered by
> the LID switch is different from the one that existing since ACPI
> support was added to Linux.
> 
> And I'd really appreciate it if you stopped saying that it's systemd's
> fault.
[Lv Zheng] 
OK.
Instead of saying this is a fault, I'll say systemd may need an additional option to handle ACPI lid device.

> 
> The kernel has offered an API to user-space that included the state of
> the LID switch. And the state of the LID switch has been correct for
> the majority of systems and devices for the past decade or so. The fact
> that this device means that the LID state isn't reliable anymore means
> that the kernel needs to communicate that to user-space.
> 
> I'm volunteering to modify systemd and UPower to respect the fact that
> the LID switch state isn't available on those devices. If you want to
> find something to blame, blame the kernel for implementing an API that
> doesn't reflect what the hardware makes available. Though you can only
> say that with the benefit of hindsight.
> 
> So, NAK from me.
[Lv Zheng] 
I'm out of the context here.
This patch is generated to respect the current systemd behavior.
If not, we'd rather just delete the 2 wrong lines.
I know that you need a documentation clarification, we are putting effort on this.

Thanks and best regards
-Lv

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

* Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume
  2016-05-19  1:50       ` Zheng, Lv
@ 2016-05-19 13:21         ` Rafael J. Wysocki
  2016-05-26 13:31           ` Benjamin Tissoires
  0 siblings, 1 reply; 66+ messages in thread
From: Rafael J. Wysocki @ 2016-05-19 13:21 UTC (permalink / raw)
  To: Zheng, Lv
  Cc: Rafael J. Wysocki, Wysocki, Rafael J, Rafael J. Wysocki, Brown,
	Len, Lv Zheng, Linux Kernel Mailing List, ACPI Devel Maling List,
	Bastien Nocera:

On Thu, May 19, 2016 at 3:50 AM, Zheng, Lv <lv.zheng@intel.com> wrote:
> Hi,
>
>> From: rjwysocki@gmail.com [mailto:rjwysocki@gmail.com] On Behalf Of
>> Rafael J. Wysocki
>> Subject: Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after
>> boot/resume

[cut]

>> > That's because of systemd implementation.
>> > It contains code logic that:
>> > When the lid state is closed, a re-checking mechanism is installed.
>> > So if we do not send any notification after boot/resume and the old lid state
>> is "closed".
>> > systemd determines to suspend in the re-checking mechanism.
>>
>> If that really is the case, it is plain silly and I don't think we can
>> do anything in the kernel to help here.
>
> [Lv Zheng]
> The problem is:
> If we just removed the 2 lines sending wrong lid state after boot/resume.
> Problem couldn't be solved.
> It could only be solved by changing both the systemd and the kernel (deleting the 2 lines).

There are two things here, there's a kernel issue (sending the fake
input events) and there's a user-visible problem.  Yes, it may not be
possible to fix the user-visible problem by fixing the kernel issue
alone, but pretty much by definition we can only fix the kernel issue
in the kernel.

However, it looks like it may not be possible to fix the user-visible
problem without fixing the kernel issue in the first place, so maybe
we should do that and attach the additional user space patch to the
bug entries in question?

[cut]

>> > I intentionally kept the _LID evaluation right after boot/resume.
>> > Because I validated Windows behavior.
>> > It seems Windows evaluates _LID right after boot.
>> > So I kept _LID evaluated right after boot to prevent compliance issues.
>>
>> I don't quite see what compliance issues could result from skipping
>> the _LID evaluation after boot.
>
> [Lv Zheng]
> I'm not sure if there is a platform putting named object initialization code in _LID.
> If you don't like it, we can stop evaluating _LID in the next version.

Well, unless there is a well-documented reason for doing this, I'd at
least try to see what happens if we don't.

Doing things for unspecified reasons is not a very good idea overall IMO.

[cut]

>> > [Lv Zheng]
>> > If we did this right now, many other userspace could be broken.
>> > So we prepared the options to allow users to choose.
>>
>> Do we have any evidence that any other user space stacks are affected?
>
> [Lv Zheng]
> I didn't know any of such affections except the systemd.

So let's focus on this one until we actually find another example.

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

* Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume
  2016-05-19 13:21         ` Rafael J. Wysocki
@ 2016-05-26 13:31           ` Benjamin Tissoires
  2016-05-30  1:39             ` Zheng, Lv
  0 siblings, 1 reply; 66+ messages in thread
From: Benjamin Tissoires @ 2016-05-26 13:31 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Zheng, Lv, Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len,
	Lv Zheng, Linux Kernel Mailing List, ACPI Devel Maling List,
	Bastien Nocera:

[Jumping in the discussion at Bastien's request]

On Thu, May 19, 2016 at 3:21 PM, Rafael J. Wysocki <rafael@kernel.org> wrote:
> On Thu, May 19, 2016 at 3:50 AM, Zheng, Lv <lv.zheng@intel.com> wrote:
>> Hi,
>>
>>> From: rjwysocki@gmail.com [mailto:rjwysocki@gmail.com] On Behalf Of
>>> Rafael J. Wysocki
>>> Subject: Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after
>>> boot/resume
>
> [cut]
>
>>> > That's because of systemd implementation.
>>> > It contains code logic that:
>>> > When the lid state is closed, a re-checking mechanism is installed.
>>> > So if we do not send any notification after boot/resume and the old lid state
>>> is "closed".
>>> > systemd determines to suspend in the re-checking mechanism.
>>>
>>> If that really is the case, it is plain silly and I don't think we can
>>> do anything in the kernel to help here.
>>
>> [Lv Zheng]
>> The problem is:
>> If we just removed the 2 lines sending wrong lid state after boot/resume.
>> Problem couldn't be solved.
>> It could only be solved by changing both the systemd and the kernel (deleting the 2 lines).
>
> There are two things here, there's a kernel issue (sending the fake
> input events) and there's a user-visible problem.  Yes, it may not be
> possible to fix the user-visible problem by fixing the kernel issue
> alone, but pretty much by definition we can only fix the kernel issue
> in the kernel.
>
> However, it looks like it may not be possible to fix the user-visible
> problem without fixing the kernel issue in the first place, so maybe
> we should do that and attach the additional user space patch to the
> bug entries in question?
>
> [cut]
>
>>> > I intentionally kept the _LID evaluation right after boot/resume.
>>> > Because I validated Windows behavior.
>>> > It seems Windows evaluates _LID right after boot.
>>> > So I kept _LID evaluated right after boot to prevent compliance issues.
>>>
>>> I don't quite see what compliance issues could result from skipping
>>> the _LID evaluation after boot.
>>
>> [Lv Zheng]
>> I'm not sure if there is a platform putting named object initialization code in _LID.
>> If you don't like it, we can stop evaluating _LID in the next version.
>
> Well, unless there is a well-documented reason for doing this, I'd at
> least try to see what happens if we don't.
>
> Doing things for unspecified reasons is not a very good idea overall IMO.

I found an issue on the surface 3 which explains why the initial state
of the _LID switch is wrong.
In gpiolib-acpi, we initialize an operation region for the LID switch
to be controlled by a GPIO. This GPIO triggers an _E4C method when
changed (see https://bugzilla.kernel.org/attachment.cgi?id=187171 in
GPO0). This GPIO event actually sets the correct initial state of LIDB,
which is forwarded by _LID.

Now, on the surface 3, there is an other gpio event (_E10) which, when
triggered at boot seems to put the sensor hub (over i2c-hid) in a
better shape:
I used to receive a5 a5 a5 a5 a5.. (garbage) after enabling S0 on the
sensor and when requesting data from it. Now I get a nice
[  +0.000137] i2c_hid i2c-MSHW0102:00: report (len=17): 11 00 01 02 05 00 00 00 00 00 00 00 00 00 18 fc 00
which seems more sensible from a HID point of view.

The patch is the following:

---
>From 2c76d14a5ad089d0321a029edde3f91f3bc93ae3 Mon Sep 17 00:00:00 2001
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Date: Thu, 26 May 2016 15:29:10 +0200
Subject: [PATCH] gpiolib-acpi: make sure we trigger the events at least once
 on boot

The Surface 3 has its _LID state controlled by an ACPI operation region
triggered by a GPIO event:

 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)  // _Exx: Edge-Triggered GPE
 {
     If ((HELD == One))
     {
         ^^LID.LIDB = One
     }
     Else
     {
         ^^LID.LIDB = Zero
         Notify (LID, 0x80) // Status Change
     }

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

Currently, the state of LIDB is wrong until the user actually closes or
open the cover. We need to trigger the GPIO event once to update the
internal ACPI state.

Coincidentally, this also enables the integrated HID sensor hub which also
requires an ACPI gpio operation region to start initialization.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/gpio/gpiolib-acpi.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 2dc5258..71775a0 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -175,7 +175,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
 	irq_handler_t handler = NULL;
 	struct gpio_desc *desc;
 	unsigned long irqflags;
-	int ret, pin, irq;
+	int ret, pin, irq, value;
 
 	if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
 		return AE_OK;
@@ -214,6 +214,8 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
 
 	gpiod_direction_input(desc);
 
+	value = gpiod_get_value(desc);
+
 	ret = gpiochip_lock_as_irq(chip, pin);
 	if (ret) {
 		dev_err(chip->parent, "Failed to lock GPIO as interrupt\n");
@@ -266,6 +268,15 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
 	}
 
 	list_add_tail(&event->node, &acpi_gpio->events);
+
+	/*
+	 * Make sure we trigger the initial state of the IRQ when
+	 * using RISING or FALLING.
+	 */
+	if (((irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
+	    ((irqflags & IRQF_TRIGGER_FALLING) && value == 0))
+		handler(-1, event);
+
 	return AE_OK;
 
 fail_free_event:
-- 
2.5.0

---

Now, if I am not mistaken, we could simply check the value of _LID on
resume and if it differs from the previous state, force an input_event
from the _LID. That should at least re-trigger the LID close event
(sent by the ACPI) for the next attempt.

Cheers,
Benjamin

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

* [PATCH v2 0/3] ACPI / button: Clarify initial lid state
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
  2016-05-17 23:36 ` Rafael J. Wysocki
  2016-05-18 12:57 ` Bastien Nocera
@ 2016-05-27  7:15 ` Lv Zheng
  2016-05-27  7:15   ` [PATCH v2 1/3] ACPI / button: Remove initial lid state notification Lv Zheng
                     ` (3 more replies)
  2016-06-01 10:10 ` [PATCH v3 1/3] ACPI / button: Remove initial lid state notification Lv Zheng
                   ` (12 subsequent siblings)
  15 siblings, 4 replies; 66+ messages in thread
From: Lv Zheng @ 2016-05-27  7:15 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi

The initial _LID returning value is not reliable after boot/resume because
the BIOS vendors may implement it by returning a cached value that is only
updated when a lid notification is received.
This causes strange things happening after resuming. This patchset fixes
the issue according to this fact.

Lv Zheng (3):
  ACPI / button: Remove initial lid state notification
  ACPI / button: Refactor functions to eliminate redundant code
  ACPI / button: Send "open" state after boot/resume

 drivers/acpi/button.c |   96 ++++++++++++++++++++++++++-----------------------
 1 file changed, 52 insertions(+), 44 deletions(-)

-- 
1.7.10

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

* [PATCH v2 1/3] ACPI / button: Remove initial lid state notification
  2016-05-27  7:15 ` [PATCH v2 0/3] ACPI / button: Clarify initial lid state Lv Zheng
@ 2016-05-27  7:15   ` Lv Zheng
  2016-05-27  7:15   ` [PATCH v2 2/3] ACPI / button: Refactor functions to eliminate redundant code Lv Zheng
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 66+ messages in thread
From: Lv Zheng @ 2016-05-27  7:15 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi

The _LID control method's initial returning value is not reliable.

The _LID control method is described to return the "current" lid state.
However the word of "current" has ambiguity, many BIOSen 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 BIOSen implement this control method with cached
value, the initial returning value is likely not reliable. There are simply
so many examples retuning "close" as initial lid state (Link 1), sending
this state to the userspace causes suspending right after booting/resuming.

Since the lid state is implemented by the BIOSen, the kernel lid driver has
no idea how it can be correct, this patch stops sending the initial lid
state to the userspace to try to avoid sending the wrong lid state to the
userspace to trigger such kind of wrong suspending. This actually reverts
the following commit introduced for fixing a novell bug (Link 2):
  Commit: 23de5d9ef2a4bbc4f733f58311bcb7cf6239c813
  Subject: ACPI: button: send initial lid state after add and resume

Link 1: https://bugzilla.kernel.org/show_bug.cgi?id=89211
        https://bugzilla.kernel.org/show_bug.cgi?id=106151
        https://bugzilla.kernel.org/show_bug.cgi?id=106941
Link 2: https://bugzilla.novell.com/show_bug.cgi?id=326814
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
 drivers/acpi/button.c |    3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 5c3b091..9863278 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -334,8 +334,6 @@ static int acpi_button_resume(struct device *dev)
 	struct acpi_button *button = acpi_driver_data(device);
 
 	button->suspended = false;
-	if (button->type == ACPI_BUTTON_TYPE_LID)
-		return acpi_lid_send_state(device);
 	return 0;
 }
 #endif
@@ -416,7 +414,6 @@ static int acpi_button_add(struct acpi_device *device)
 	if (error)
 		goto err_remove_fs;
 	if (button->type == ACPI_BUTTON_TYPE_LID) {
-		acpi_lid_send_state(device);
 		/*
 		 * This assumes there's only one lid device, or if there are
 		 * more we only care about the last one...
-- 
1.7.10

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

* [PATCH v2 2/3] ACPI / button: Refactor functions to eliminate redundant code
  2016-05-27  7:15 ` [PATCH v2 0/3] ACPI / button: Clarify initial lid state Lv Zheng
  2016-05-27  7:15   ` [PATCH v2 1/3] ACPI / button: Remove initial lid state notification Lv Zheng
@ 2016-05-27  7:15   ` Lv Zheng
  2016-05-27  7:16   ` [PATCH v2 3/3] ACPI / button: Send "open" state after boot/resume Lv Zheng
  2016-05-27 22:10   ` [PATCH v2 0/3] ACPI / button: Clarify initial lid state Valdis.Kletnieks
  3 siblings, 0 replies; 66+ messages in thread
From: Lv Zheng @ 2016-05-27  7:15 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi

This patch simplies the code by merging the redundant code. No functional
changes.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
 drivers/acpi/button.c |   92 +++++++++++++++++++++++++++----------------------
 1 file changed, 50 insertions(+), 42 deletions(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 9863278..e706e4b 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -113,16 +113,53 @@ static struct acpi_device *lid_device;
 static struct proc_dir_entry *acpi_button_dir;
 static struct proc_dir_entry *acpi_lid_dir;
 
+static int acpi_lid_evaluate_state(struct acpi_device *device)
+{
+	unsigned long long lid_state;
+	acpi_status status;
+
+	status = acpi_evaluate_integer(device->handle, "_LID", NULL, &lid_state);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	return lid_state ? 1 : 0;
+}
+
+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 */
+	input_report_switch(button->input, SW_LID, !state);
+	input_sync(button->input);
+
+	if (state)
+		pm_wakeup_event(&device->dev, 0);
+
+	ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
+	if (ret == NOTIFY_DONE)
+		ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
+						   device);
+	if (ret == NOTIFY_DONE || ret == NOTIFY_OK) {
+		/*
+		 * It is also regarded as success if the notifier_chain
+		 * returns NOTIFY_OK or NOTIFY_DONE.
+		 */
+		ret = 0;
+	}
+	return ret;
+}
+
 static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
 {
 	struct acpi_device *device = seq->private;
-	acpi_status status;
-	unsigned long long state;
+	int state;
 
-	status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state);
+	state = acpi_lid_evaluate_state(device);
 	seq_printf(seq, "state:      %s\n",
-		   ACPI_FAILURE(status) ? "unsupported" :
-			(state ? "open" : "closed"));
+		   IS_ERR_VALUE(state) ? "unsupported" :
+		   (state ? "open" : "closed"));
 	return 0;
 }
 
@@ -231,51 +268,22 @@ EXPORT_SYMBOL(acpi_lid_notifier_unregister);
 
 int acpi_lid_open(void)
 {
-	acpi_status status;
-	unsigned long long state;
-
 	if (!lid_device)
 		return -ENODEV;
 
-	status = acpi_evaluate_integer(lid_device->handle, "_LID", NULL,
-				       &state);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
-
-	return !!state;
+	return acpi_lid_evaluate_state(lid_device);
 }
 EXPORT_SYMBOL(acpi_lid_open);
 
-static int acpi_lid_send_state(struct acpi_device *device)
+static int acpi_lid_update_state(struct acpi_device *device)
 {
-	struct acpi_button *button = acpi_driver_data(device);
-	unsigned long long state;
-	acpi_status status;
-	int ret;
-
-	status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
+	int state;
 
-	/* input layer checks if event is redundant */
-	input_report_switch(button->input, SW_LID, !state);
-	input_sync(button->input);
+	state = acpi_lid_evaluate_state(device);
+	if (IS_ERR_VALUE(state))
+		return state;
 
-	if (state)
-		pm_wakeup_event(&device->dev, 0);
-
-	ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
-	if (ret == NOTIFY_DONE)
-		ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
-						   device);
-	if (ret == NOTIFY_DONE || ret == NOTIFY_OK) {
-		/*
-		 * It is also regarded as success if the notifier_chain
-		 * returns NOTIFY_OK or NOTIFY_DONE.
-		 */
-		ret = 0;
-	}
-	return ret;
+	return acpi_lid_notify_state(device, state);
 }
 
 static void acpi_button_notify(struct acpi_device *device, u32 event)
@@ -290,7 +298,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
 	case ACPI_BUTTON_NOTIFY_STATUS:
 		input = button->input;
 		if (button->type == ACPI_BUTTON_TYPE_LID) {
-			acpi_lid_send_state(device);
+			acpi_lid_update_state(device);
 		} else {
 			int keycode;
 
-- 
1.7.10

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

* [PATCH v2 3/3] ACPI / button: Send "open" state after boot/resume
  2016-05-27  7:15 ` [PATCH v2 0/3] ACPI / button: Clarify initial lid state Lv Zheng
  2016-05-27  7:15   ` [PATCH v2 1/3] ACPI / button: Remove initial lid state notification Lv Zheng
  2016-05-27  7:15   ` [PATCH v2 2/3] ACPI / button: Refactor functions to eliminate redundant code Lv Zheng
@ 2016-05-27  7:16   ` Lv Zheng
  2016-05-30  8:10     ` Benjamin Tissoires
  2016-05-27 22:10   ` [PATCH v2 0/3] ACPI / button: Clarify initial lid state Valdis.Kletnieks
  3 siblings, 1 reply; 66+ messages in thread
From: Lv Zheng @ 2016-05-27  7:16 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi, Bastien Nocera:

Linux userspace (systemd-logind) keeps on rechecking lid state when the
lid state is closed. If it failed to update the lid state to open after
boot/resume, the system suspending right after the boot/resume could be
resulted.
Graphics drivers also uses the lid notifications to implment
MODESET_ON_LID_OPEN option.

Before the situation is improved from the userspace and from the graphics
driver, simply send initial "open" lid state to avoid issues. After this is
improved from the userspace and from the graphics driver, Linux kernel
could simply revert this minimal commit.

Link 1: https://lkml.org/2016/3/7/460
Link 2: https://github.com/systemd/systemd/issues/2087
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Cc: Bastien Nocera: <hadess@hadess.net>
---
 drivers/acpi/button.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index e706e4b..6e77312 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -342,6 +342,8 @@ static int acpi_button_resume(struct device *dev)
 	struct acpi_button *button = acpi_driver_data(device);
 
 	button->suspended = false;
+	if (button->type == ACPI_BUTTON_TYPE_LID)
+		return acpi_lid_notify_state(device, 1);
 	return 0;
 }
 #endif
@@ -422,6 +424,7 @@ static int acpi_button_add(struct acpi_device *device)
 	if (error)
 		goto err_remove_fs;
 	if (button->type == ACPI_BUTTON_TYPE_LID) {
+		(void)acpi_lid_notify_state(device, 1);
 		/*
 		 * This assumes there's only one lid device, or if there are
 		 * more we only care about the last one...
-- 
1.7.10

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

* Re: [PATCH v2 0/3] ACPI / button: Clarify initial lid state
  2016-05-27  7:15 ` [PATCH v2 0/3] ACPI / button: Clarify initial lid state Lv Zheng
                     ` (2 preceding siblings ...)
  2016-05-27  7:16   ` [PATCH v2 3/3] ACPI / button: Send "open" state after boot/resume Lv Zheng
@ 2016-05-27 22:10   ` Valdis.Kletnieks
  3 siblings, 0 replies; 66+ messages in thread
From: Valdis.Kletnieks @ 2016-05-27 22:10 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown, Lv Zheng,
	linux-kernel, linux-acpi

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

On Fri, 27 May 2016 15:15:43 +0800, Lv Zheng said:
> The initial _LID returning value is not reliable after boot/resume because
> the BIOS vendors may implement it by returning a cached value that is only
> updated when a lid notification is received.
> This causes strange things happening after resuming. This patchset fixes
> the issue according to this fact.
>
> Lv Zheng (3):
>   ACPI / button: Remove initial lid state notification
>   ACPI / button: Refactor functions to eliminate redundant code
>   ACPI / button: Send "open" state after boot/resume

If it sends an "open" status, what happens if the machine was in fact
suspended with lid open, but is then resumed in a dock with an external
monitor?

(I'd test it myself, but I don't have suspend/resume configured on my laptop)

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

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

* RE: [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume
  2016-05-26 13:31           ` Benjamin Tissoires
@ 2016-05-30  1:39             ` Zheng, Lv
  0 siblings, 0 replies; 66+ messages in thread
From: Zheng, Lv @ 2016-05-30  1:39 UTC (permalink / raw)
  To: Benjamin Tissoires, Rafael J. Wysocki
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	Linux Kernel Mailing List, ACPI Devel Maling List,
	Bastien Nocera:

Hi,

> From: Benjamin Tissoires [mailto:benjamin.tissoires@gmail.com]
> Subject: Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after
> boot/resume
> 
> [Jumping in the discussion at Bastien's request]
> 
> On Thu, May 19, 2016 at 3:21 PM, Rafael J. Wysocki <rafael@kernel.org>
> wrote:
> > On Thu, May 19, 2016 at 3:50 AM, Zheng, Lv <lv.zheng@intel.com>
> wrote:
> >> Hi,
> >>
> >>> From: rjwysocki@gmail.com [mailto:rjwysocki@gmail.com] On Behalf
> Of
> >>> Rafael J. Wysocki
> >>> Subject: Re: [RFC PATCH 1/2] ACPI / button: Send "open" state after
> >>> boot/resume
> >
> > [cut]
> >
> >>> > That's because of systemd implementation.
> >>> > It contains code logic that:
> >>> > When the lid state is closed, a re-checking mechanism is installed.
> >>> > So if we do not send any notification after boot/resume and the old
> lid state
> >>> is "closed".
> >>> > systemd determines to suspend in the re-checking mechanism.
> >>>
> >>> If that really is the case, it is plain silly and I don't think we can
> >>> do anything in the kernel to help here.
> >>
> >> [Lv Zheng]
> >> The problem is:
> >> If we just removed the 2 lines sending wrong lid state after
> boot/resume.
> >> Problem couldn't be solved.
> >> It could only be solved by changing both the systemd and the kernel
> (deleting the 2 lines).
> >
> > There are two things here, there's a kernel issue (sending the fake
> > input events) and there's a user-visible problem.  Yes, it may not be
> > possible to fix the user-visible problem by fixing the kernel issue
> > alone, but pretty much by definition we can only fix the kernel issue
> > in the kernel.
> >
> > However, it looks like it may not be possible to fix the user-visible
> > problem without fixing the kernel issue in the first place, so maybe
> > we should do that and attach the additional user space patch to the
> > bug entries in question?
> >
> > [cut]
> >
> >>> > I intentionally kept the _LID evaluation right after boot/resume.
> >>> > Because I validated Windows behavior.
> >>> > It seems Windows evaluates _LID right after boot.
> >>> > So I kept _LID evaluated right after boot to prevent compliance
> issues.
> >>>
> >>> I don't quite see what compliance issues could result from skipping
> >>> the _LID evaluation after boot.
> >>
> >> [Lv Zheng]
> >> I'm not sure if there is a platform putting named object initialization
> code in _LID.
> >> If you don't like it, we can stop evaluating _LID in the next version.
> >
> > Well, unless there is a well-documented reason for doing this, I'd at
> > least try to see what happens if we don't.
> >
> > Doing things for unspecified reasons is not a very good idea overall IMO.
> 
> I found an issue on the surface 3 which explains why the initial state
> of the _LID switch is wrong.
> In gpiolib-acpi, we initialize an operation region for the LID switch
> to be controlled by a GPIO. This GPIO triggers an _E4C method when
> changed (see https://bugzilla.kernel.org/attachment.cgi?id=187171 in
> GPO0). This GPIO event actually sets the correct initial state of LIDB,
> which is forwarded by _LID.
> 
> Now, on the surface 3, there is an other gpio event (_E10) which, when
> triggered at boot seems to put the sensor hub (over i2c-hid) in a
> better shape:
> I used to receive a5 a5 a5 a5 a5.. (garbage) after enabling S0 on the
> sensor and when requesting data from it. Now I get a nice
> [  +0.000137] i2c_hid i2c-MSHW0102:00: report (len=17): 11 00 01 02 05
> 00 00 00 00 00 00 00 00 00 18 fc 00
> which seems more sensible from a HID point of view.
[Lv Zheng] 
So the problem of Surface 3 is different.
Which is related to the gpio irq.

We still have several issues related to this:
1. https://bugzilla.kernel.org/show_bug.cgi?id=89211
2. https://bugzilla.kernel.org/show_bug.cgi?id=106151
The _LID methods in the 2 cases all use cached value, and there is no lid notification can be seen after resume, causing "close" sent to the userspace.
Maybe we should go back to check if there is a different root cause.

Thanks and best regards
-Lv


> 
> The patch is the following:
> 
> ---
> From 2c76d14a5ad089d0321a029edde3f91f3bc93ae3 Mon Sep 17
> 00:00:00 2001
> From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> Date: Thu, 26 May 2016 15:29:10 +0200
> Subject: [PATCH] gpiolib-acpi: make sure we trigger the events at least
> once
>  on boot
> 
> The Surface 3 has its _LID state controlled by an ACPI operation region
> triggered by a GPIO event:
> 
>  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)  // _Exx: Edge-Triggered GPE
>  {
>      If ((HELD == One))
>      {
>          ^^LID.LIDB = One
>      }
>      Else
>      {
>          ^^LID.LIDB = Zero
>          Notify (LID, 0x80) // Status Change
>      }
> 
>      Notify (^^PCI0.SPI1.NTRG, One) // Device Check
>  }
> 
> Currently, the state of LIDB is wrong until the user actually closes or
> open the cover. We need to trigger the GPIO event once to update the
> internal ACPI state.
> 
> Coincidentally, this also enables the integrated HID sensor hub which also
> requires an ACPI gpio operation region to start initialization.
> 
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> ---
>  drivers/gpio/gpiolib-acpi.c | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
> index 2dc5258..71775a0 100644
> --- a/drivers/gpio/gpiolib-acpi.c
> +++ b/drivers/gpio/gpiolib-acpi.c
> @@ -175,7 +175,7 @@ static acpi_status
> acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
>  	irq_handler_t handler = NULL;
>  	struct gpio_desc *desc;
>  	unsigned long irqflags;
> -	int ret, pin, irq;
> +	int ret, pin, irq, value;
> 
>  	if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
>  		return AE_OK;
> @@ -214,6 +214,8 @@ static acpi_status
> acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
> 
>  	gpiod_direction_input(desc);
> 
> +	value = gpiod_get_value(desc);
> +
>  	ret = gpiochip_lock_as_irq(chip, pin);
>  	if (ret) {
>  		dev_err(chip->parent, "Failed to lock GPIO as interrupt\n");
> @@ -266,6 +268,15 @@ static acpi_status
> acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
>  	}
> 
>  	list_add_tail(&event->node, &acpi_gpio->events);
> +
> +	/*
> +	 * Make sure we trigger the initial state of the IRQ when
> +	 * using RISING or FALLING.
> +	 */
> +	if (((irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
> +	    ((irqflags & IRQF_TRIGGER_FALLING) && value == 0))
> +		handler(-1, event);
> +
>  	return AE_OK;
> 
>  fail_free_event:
> --
> 2.5.0
> 
> ---
> 
> Now, if I am not mistaken, we could simply check the value of _LID on
> resume and if it differs from the previous state, force an input_event
> from the _LID. That should at least re-trigger the LID close event
> (sent by the ACPI) for the next attempt.
> 
> Cheers,
> Benjamin

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

* Re: [PATCH v2 3/3] ACPI / button: Send "open" state after boot/resume
  2016-05-27  7:16   ` [PATCH v2 3/3] ACPI / button: Send "open" state after boot/resume Lv Zheng
@ 2016-05-30  8:10     ` Benjamin Tissoires
  2016-05-31  2:55       ` Zheng, Lv
  0 siblings, 1 reply; 66+ messages in thread
From: Benjamin Tissoires @ 2016-05-30  8:10 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown, Lv Zheng,
	linux-kernel, ACPI Devel Maling List, Bastien Nocera:,
	Valdis.Kletnieks

On Fri, May 27, 2016 at 9:16 AM, Lv Zheng <lv.zheng@intel.com> wrote:
> Linux userspace (systemd-logind) keeps on rechecking lid state when the
> lid state is closed. If it failed to update the lid state to open after
> boot/resume, the system suspending right after the boot/resume could be
> resulted.
> Graphics drivers also uses the lid notifications to implment
> MODESET_ON_LID_OPEN option.
>
> Before the situation is improved from the userspace and from the graphics
> driver, simply send initial "open" lid state to avoid issues. After this is
> improved from the userspace and from the graphics driver, Linux kernel
> could simply revert this minimal commit.
>
> Link 1: https://lkml.org/2016/3/7/460
> Link 2: https://github.com/systemd/systemd/issues/2087
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Cc: Bastien Nocera: <hadess@hadess.net>
> ---
>  drivers/acpi/button.c |    3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> index e706e4b..6e77312 100644
> --- a/drivers/acpi/button.c
> +++ b/drivers/acpi/button.c
> @@ -342,6 +342,8 @@ static int acpi_button_resume(struct device *dev)
>         struct acpi_button *button = acpi_driver_data(device);
>
>         button->suspended = false;
> +       if (button->type == ACPI_BUTTON_TYPE_LID)
> +               return acpi_lid_notify_state(device, 1);

As Valdis replied on 0/3, I don't think this is a good solution (even
temporary). Linux should not assume the current state of a input
device, and sending unconditionally 1 here is wrong. If the device is
on a docking station, you will wake up the wrong monitor and screw the
user session (and this will be a regression).

How about we simply send the current LID state stored in the ACPI?
something like calling acpi_lid_send_state() directly?

[15 min later, after writing a long email]

Well, it looks like we already have that in the kernel and for a long
time apparently.

So, I think the issue is that Microsoft does not wake up the system by
lid opening (seen in one of the comments in the mentioned bugs and by
looking at the behavior on the surface devices). It must be just
querying it's state on resume or might even not care at all until it
receives a close event.

If I read correctly, we managed to get the 3 bogus devices to a
correct state at the ACPI level (/proc/acpi/button/lid/LID0/state),
but we did not get the notification. Given that the LID state is
triggered by an ACPI operation region, there is no guarantee that the
resume of the acpi/button.c driver will be called after the region has
been updated/called.

I propose as a workaround to enable a kthread that will monitor the
lid state and update the correct value to userspace (5 sec of polling
time should be enough given that systemd checks every 20 sec).
We should probably have this workaround only for a set of known
devices, as it might just be temporary for those until the actual
underlying problem is fixed (wrong DSDT in the Surface 3 case that
doesn't notify at all, issue in the EC for the Surface Pro 1 and the
Samsung N210).

Cheers,
Benjamin


>         return 0;
>  }
>  #endif
> @@ -422,6 +424,7 @@ static int acpi_button_add(struct acpi_device *device)
>         if (error)
>                 goto err_remove_fs;
>         if (button->type == ACPI_BUTTON_TYPE_LID) {
> +               (void)acpi_lid_notify_state(device, 1);
>                 /*
>                  * This assumes there's only one lid device, or if there are
>                  * more we only care about the last one...
> --
> 1.7.10
>
> --
> 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] 66+ messages in thread

* RE: [PATCH v2 3/3] ACPI / button: Send "open" state after boot/resume
  2016-05-30  8:10     ` Benjamin Tissoires
@ 2016-05-31  2:55       ` Zheng, Lv
  2016-05-31 14:47         ` Benjamin Tissoires
  0 siblings, 1 reply; 66+ messages in thread
From: Zheng, Lv @ 2016-05-31  2:55 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	linux-kernel, ACPI Devel Maling List, Bastien Nocera:,
	Valdis.Kletnieks

Hi,

> From: Benjamin Tissoires [mailto:benjamin.tissoires@gmail.com]
> Subject: Re: [PATCH v2 3/3] ACPI / button: Send "open" state after
> boot/resume
> 
> On Fri, May 27, 2016 at 9:16 AM, Lv Zheng <lv.zheng@intel.com> wrote:
> > Linux userspace (systemd-logind) keeps on rechecking lid state when the
> > lid state is closed. If it failed to update the lid state to open after
> > boot/resume, the system suspending right after the boot/resume could
> be
> > resulted.
> > Graphics drivers also uses the lid notifications to implment
> > MODESET_ON_LID_OPEN option.
> >
> > Before the situation is improved from the userspace and from the
> graphics
> > driver, simply send initial "open" lid state to avoid issues. After this is
> > improved from the userspace and from the graphics driver, Linux kernel
> > could simply revert this minimal commit.
> >
> > Link 1: https://lkml.org/2016/3/7/460
> > Link 2: https://github.com/systemd/systemd/issues/2087
> > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > Cc: Bastien Nocera: <hadess@hadess.net>
> > ---
> >  drivers/acpi/button.c |    3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> > index e706e4b..6e77312 100644
> > --- a/drivers/acpi/button.c
> > +++ b/drivers/acpi/button.c
> > @@ -342,6 +342,8 @@ static int acpi_button_resume(struct device
> *dev)
> >         struct acpi_button *button = acpi_driver_data(device);
> >
> >         button->suspended = false;
> > +       if (button->type == ACPI_BUTTON_TYPE_LID)
> > +               return acpi_lid_notify_state(device, 1);
> 
> As Valdis replied on 0/3, I don't think this is a good solution (even
> temporary). Linux should not assume the current state of a input
> device, and sending unconditionally 1 here is wrong. If the device is
> on a docking station, you will wake up the wrong monitor and screw the
> user session (and this will be a regression).
[Lv Zheng] 
We are doing the test to see how this behaves on several different platforms.

> 
> How about we simply send the current LID state stored in the ACPI?
> something like calling acpi_lid_send_state() directly?
[Lv Zheng] 
This is what we are going to eliminate in [PATCH 01].
We have several real bugs related to sending a wrong state to the userspace.
Userspace will suspend right after resume because of the 'close' state.


> 
> [15 min later, after writing a long email]
> 
> Well, it looks like we already have that in the kernel and for a long
> time apparently.
> 
> So, I think the issue is that Microsoft does not wake up the system by
> lid opening (seen in one of the comments in the mentioned bugs and by
> looking at the behavior on the surface devices). It must be just
> querying it's state on resume or might even not care at all until it
> receives a close event.
> 
> If I read correctly, we managed to get the 3 bogus devices to a
> correct state at the ACPI level (/proc/acpi/button/lid/LID0/state),
> but we did not get the notification. Given that the LID state is
> triggered by an ACPI operation region, there is no guarantee that the
> resume of the acpi/button.c driver will be called after the region has
> been updated/called.
[Lv Zheng] 
The understanding here is incorrect.
We have 3 bogus devices.
1 of them is surface 3 which is a hardware reduced platform.
The others are all traditional platforms.

=====
The facts are:

Both the platforms return cached lid state from _LID.
The cached value will be updated by lid irq (via GPIO IRQ, GPE, or EC event).
AML tables will send lid notification in the irq handler.

Some AML tables will update the cached value in _WAK (I'll describe why it is necessary below).
But updating the cached value in _WAK is not guaranteed by all AML tables.

For the 'close' state irq, all tables will send lid close notification.
For the 'open' state irq, it seems there are tables never sending lid open notification (sounds like Windows do not care about lid open).
=====

Surface 3 is entirely a different case.
It is a runtime idle system and hardware reduced.
On that kind of system, lid open is handled by OS not by BIOS.
Surface 3 is exactly the platform that doesn't send lid open notification.
I guess the AML is intentionally written in this way to be compliant to the traditional platforms.

While on the traditional platforms:
When lid is opened, BIOS handles the lid irq and wakes the system from the FACS waking vector.
So it is likely that there is no lid open irq after the system is resumed.
BIOS may forget to update the cached lid value in the _WAK or some other control methods that could be executed after resuming.
Then if we send _LID result to the user space, the cached value could apparently be 'close'.

That explains why there is no "lid open" configuration in the "Windows Device Manager".

> 
> I propose as a workaround to enable a kthread that will monitor the
> lid state and update the correct value to userspace (5 sec of polling
> time should be enough given that systemd checks every 20 sec).
> We should probably have this workaround only for a set of known
> devices, as it might just be temporary for those until the actual
> underlying problem is fixed (wrong DSDT in the Surface 3 case that
> doesn't notify at all, issue in the EC for the Surface Pro 1 and the
> Samsung N210).
[Lv Zheng] 
That cannot help to solve the issue/gap.

The problem is Linux userspace has a facility re-checking lid state when lid state is "close".
If it failed to update the lid state to "open" for a timeout period, it would suspend the platform.

We actually are recommending Linus userspace to introduce a new lid handling mode to only handle "lid close" event and ignore "lid open" event.
During the period this is not changed from the userspace, we have to send "open" after resume/boot in order not to trigger the timeout mechanism.

Thanks and best regards
-Lv

> 
> Cheers,
> Benjamin
> 
> 
> >         return 0;
> >  }
> >  #endif
> > @@ -422,6 +424,7 @@ static int acpi_button_add(struct acpi_device
> *device)
> >         if (error)
> >                 goto err_remove_fs;
> >         if (button->type == ACPI_BUTTON_TYPE_LID) {
> > +               (void)acpi_lid_notify_state(device, 1);
> >                 /*
> >                  * This assumes there's only one lid device, or if there are
> >                  * more we only care about the last one...
> > --
> > 1.7.10
> >
> > --
> > 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] 66+ messages in thread

* Re: [PATCH v2 3/3] ACPI / button: Send "open" state after boot/resume
  2016-05-31  2:55       ` Zheng, Lv
@ 2016-05-31 14:47         ` Benjamin Tissoires
  2016-06-01  1:17           ` Zheng, Lv
  0 siblings, 1 reply; 66+ messages in thread
From: Benjamin Tissoires @ 2016-05-31 14:47 UTC (permalink / raw)
  To: Zheng, Lv
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	linux-kernel, ACPI Devel Maling List, Bastien Nocera:,
	Valdis.Kletnieks

Hi Lv,

On Tue, May 31, 2016 at 4:55 AM, Zheng, Lv <lv.zheng@intel.com> wrote:
> Hi,
>
>> From: Benjamin Tissoires [mailto:benjamin.tissoires@gmail.com]
>> Subject: Re: [PATCH v2 3/3] ACPI / button: Send "open" state after
>> boot/resume
>>
>> On Fri, May 27, 2016 at 9:16 AM, Lv Zheng <lv.zheng@intel.com> wrote:
[snipped
]>> As Valdis replied on 0/3, I don't think this is a good solution (even
>> temporary). Linux should not assume the current state of a input
>> device, and sending unconditionally 1 here is wrong. If the device is
>> on a docking station, you will wake up the wrong monitor and screw the
>> user session (and this will be a regression).
> [Lv Zheng]
> We are doing the test to see how this behaves on several different platforms.
>
>>
>> How about we simply send the current LID state stored in the ACPI?
>> something like calling acpi_lid_send_state() directly?
> [Lv Zheng]
> This is what we are going to eliminate in [PATCH 01].
> We have several real bugs related to sending a wrong state to the userspace.
> Userspace will suspend right after resume because of the 'close' state.

On the other hand, you are trying to remove 23de5d9ef2a4bbc4f733f, a
patch that has been around for 9 years and we only start seeing
devices where this logic is not working...

I am not saying your approach is wrong, I am just saying that instead
of a plain revert, we should probably be more conservative and add a
quirk for those buggy machines. Ideally, we should try to understand
why there is such an issue that Windows doesn't have (the solution
might just be that given Windows doesn't care, we are screwed).

BTW, on the Surface 3, there is a WMI
(f7cc25ec-d20b-404c-8903-0ed4359c18ae -> WQHE) which returns the
actual value of the LID, without using PNP0C0D at all. I have a
feeling that Windows might use it when it is in trouble or in an
unsure state. I couldn't find this WMI on the 2 other systems so that
may also be just a one shot for the Surface 3.

[snipped]
> [Lv Zheng]
> The understanding here is incorrect.
> We have 3 bogus devices.
> 1 of them is surface 3 which is a hardware reduced platform.
> The others are all traditional platforms.
>
> =====
> The facts are:
>
> Both the platforms return cached lid state from _LID.
> The cached value will be updated by lid irq (via GPIO IRQ, GPE, or EC event).
> AML tables will send lid notification in the irq handler.
>
> Some AML tables will update the cached value in _WAK (I'll describe why it is necessary below).
> But updating the cached value in _WAK is not guaranteed by all AML tables.
>
> For the 'close' state irq, all tables will send lid close notification.
> For the 'open' state irq, it seems there are tables never sending lid open notification (sounds like Windows do not care about lid open).
> =====
>
> Surface 3 is entirely a different case.
> It is a runtime idle system and hardware reduced.
> On that kind of system, lid open is handled by OS not by BIOS.
> Surface 3 is exactly the platform that doesn't send lid open notification.
> I guess the AML is intentionally written in this way to be compliant to the traditional platforms.
>
> While on the traditional platforms:
> When lid is opened, BIOS handles the lid irq and wakes the system from the FACS waking vector.
> So it is likely that there is no lid open irq after the system is resumed.
> BIOS may forget to update the cached lid value in the _WAK or some other control methods that could be executed after resuming.
> Then if we send _LID result to the user space, the cached value could apparently be 'close'.
>
> That explains why there is no "lid open" configuration in the "Windows Device Manager".
>
>>
>> I propose as a workaround to enable a kthread that will monitor the
>> lid state and update the correct value to userspace (5 sec of polling
>> time should be enough given that systemd checks every 20 sec).
>> We should probably have this workaround only for a set of known
>> devices, as it might just be temporary for those until the actual
>> underlying problem is fixed (wrong DSDT in the Surface 3 case that
>> doesn't notify at all, issue in the EC for the Surface Pro 1 and the
>> Samsung N210).
> [Lv Zheng]
> That cannot help to solve the issue/gap.
>
> The problem is Linux userspace has a facility re-checking lid state when lid state is "close".
> If it failed to update the lid state to "open" for a timeout period, it would suspend the platform.
>
> We actually are recommending Linus userspace to introduce a new lid handling mode to only handle "lid close" event and ignore "lid open" event.
> During the period this is not changed from the userspace, we have to send "open" after resume/boot in order not to trigger the timeout mechanism.
>

I hear your points and I couldn't agree more that the only solution
for us is (sadly) to mimic Windows.

I am just disagreeing on the method used here: I'd rather have a
fallback mechanism where the lid is not sent to "one" at each boot
resume because this will mess us people using docking stations. The
problem is that Red Hat has a lot of them, and I foresee a lot of
complains to me if this is merged in its current state.

We could have a parameter (say "send_lid_open_on_resume" or
"use_bios_lid_value") in acpi/button.c which would allow people to
choose if they want the "new" behavior or the old one. And we could
also add some DMI matching for the messed up laptops/tablets where we
force one or the other quirk. When we agree that user space now
behaves gently with us, we could then remove entirely the quirk and
the dmi matching.

How does that sound?

Also, on the topic of the .notify not being sent by some BIOS, I have
seen something similar on the surface 3.

The ASL for the LID status change is the following:
---
            Method (_E4C, 0, Serialized)  // _Exx: Edge-Triggered GPE
            {
                If ((HELD == One))
                {
                    ^^LID.LIDB = One
                }
                Else
                {
                    ^^LID.LIDB = Zero
                    Notify (LID, 0x80) // Status Change
                }

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

I noticed I received the hotplug event on the touchscreen when the LID
state changed, and tried to initiate the notify on the LID acpi device
from within the touchscreen driver.
This works well, except that from time to time, on resume, I don't
even receive the hotplug notification. It is as if the notification is
lost while I receive it 80% of the time.

This might be completely unrelated, but I think it is worth mentioning
because there might be a common root at the state not being updated
correctly.

Cheers, and sorry for being annoying :)
Benjamin

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

* RE: [PATCH v2 3/3] ACPI / button: Send "open" state after boot/resume
  2016-05-31 14:47         ` Benjamin Tissoires
@ 2016-06-01  1:17           ` Zheng, Lv
  2016-06-01  7:51             ` Zheng, Lv
  0 siblings, 1 reply; 66+ messages in thread
From: Zheng, Lv @ 2016-06-01  1:17 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	linux-kernel, ACPI Devel Maling List, Bastien Nocera:,
	Valdis.Kletnieks

Hi,

> From: Benjamin Tissoires [mailto:benjamin.tissoires@gmail.com]
> Subject: Re: [PATCH v2 3/3] ACPI / button: Send "open" state after
> boot/resume
> 
> Hi Lv,
> 
> On Tue, May 31, 2016 at 4:55 AM, Zheng, Lv <lv.zheng@intel.com> wrote:
> > Hi,
> >
> >> From: Benjamin Tissoires [mailto:benjamin.tissoires@gmail.com]
> >> Subject: Re: [PATCH v2 3/3] ACPI / button: Send "open" state after
> >> boot/resume
> >>
> >> On Fri, May 27, 2016 at 9:16 AM, Lv Zheng <lv.zheng@intel.com>
> wrote:
> [snipped
> ]>> As Valdis replied on 0/3, I don't think this is a good solution (even
> >> temporary). Linux should not assume the current state of a input
> >> device, and sending unconditionally 1 here is wrong. If the device is
> >> on a docking station, you will wake up the wrong monitor and screw
> the
> >> user session (and this will be a regression).
> > [Lv Zheng]
> > We are doing the test to see how this behaves on several different
> platforms.
> >
> >>
> >> How about we simply send the current LID state stored in the ACPI?
> >> something like calling acpi_lid_send_state() directly?
> > [Lv Zheng]
> > This is what we are going to eliminate in [PATCH 01].
> > We have several real bugs related to sending a wrong state to the
> userspace.
> > Userspace will suspend right after resume because of the 'close' state.
> 
> On the other hand, you are trying to remove 23de5d9ef2a4bbc4f733f, a
> patch that has been around for 9 years and we only start seeing
> devices where this logic is not working...
> 
> I am not saying your approach is wrong, I am just saying that instead
> of a plain revert, we should probably be more conservative and add a
> quirk for those buggy machines. Ideally, we should try to understand
> why there is such an issue that Windows doesn't have (the solution
> might just be that given Windows doesn't care, we are screwed).
> 
> BTW, on the Surface 3, there is a WMI
> (f7cc25ec-d20b-404c-8903-0ed4359c18ae -> WQHE) which returns the
> actual value of the LID, without using PNP0C0D at all. I have a
> feeling that Windows might use it when it is in trouble or in an
> unsure state. I couldn't find this WMI on the 2 other systems so that
> may also be just a one shot for the Surface 3.
[Lv Zheng] 
Thanks for the information.
But it seems Surface 3 is not a good example for this.
It is a runtime idle platform.
And the root cause of the Surface 3 issue should be in the freeze code.
After waking the system up via LID irq, the irq is dropped.
But I guess it is risky to invoke irq handler right there, doing so could break may existing drivers.


> 
> [snipped]
> > [Lv Zheng]
> > The understanding here is incorrect.
> > We have 3 bogus devices.
> > 1 of them is surface 3 which is a hardware reduced platform.
> > The others are all traditional platforms.
> >
> > =====
> > The facts are:
> >
> > Both the platforms return cached lid state from _LID.
> > The cached value will be updated by lid irq (via GPIO IRQ, GPE, or EC
> event).
> > AML tables will send lid notification in the irq handler.
> >
> > Some AML tables will update the cached value in _WAK (I'll describe why
> it is necessary below).
> > But updating the cached value in _WAK is not guaranteed by all AML
> tables.
> >
> > For the 'close' state irq, all tables will send lid close notification.
> > For the 'open' state irq, it seems there are tables never sending lid open
> notification (sounds like Windows do not care about lid open).
> > =====
> >
> > Surface 3 is entirely a different case.
> > It is a runtime idle system and hardware reduced.
> > On that kind of system, lid open is handled by OS not by BIOS.
> > Surface 3 is exactly the platform that doesn't send lid open notification.
> > I guess the AML is intentionally written in this way to be compliant to
> the traditional platforms.
> >
> > While on the traditional platforms:
> > When lid is opened, BIOS handles the lid irq and wakes the system from
> the FACS waking vector.
> > So it is likely that there is no lid open irq after the system is resumed.
> > BIOS may forget to update the cached lid value in the _WAK or some
> other control methods that could be executed after resuming.
> > Then if we send _LID result to the user space, the cached value could
> apparently be 'close'.
> >
> > That explains why there is no "lid open" configuration in the "Windows
> Device Manager".
> >
> >>
> >> I propose as a workaround to enable a kthread that will monitor the
> >> lid state and update the correct value to userspace (5 sec of polling
> >> time should be enough given that systemd checks every 20 sec).
> >> We should probably have this workaround only for a set of known
> >> devices, as it might just be temporary for those until the actual
> >> underlying problem is fixed (wrong DSDT in the Surface 3 case that
> >> doesn't notify at all, issue in the EC for the Surface Pro 1 and the
> >> Samsung N210).
> > [Lv Zheng]
> > That cannot help to solve the issue/gap.
> >
> > The problem is Linux userspace has a facility re-checking lid state when
> lid state is "close".
> > If it failed to update the lid state to "open" for a timeout period, it would
> suspend the platform.
> >
> > We actually are recommending Linus userspace to introduce a new lid
> handling mode to only handle "lid close" event and ignore "lid open" event.
> > During the period this is not changed from the userspace, we have to
> send "open" after resume/boot in order not to trigger the timeout
> mechanism.
> >
> 
> I hear your points and I couldn't agree more that the only solution
> for us is (sadly) to mimic Windows.
> 
> I am just disagreeing on the method used here: I'd rather have a
> fallback mechanism where the lid is not sent to "one" at each boot
> resume because this will mess us people using docking stations. The
> problem is that Red Hat has a lot of them, and I foresee a lot of
> complains to me if this is merged in its current state.
> 
> We could have a parameter (say "send_lid_open_on_resume" or
> "use_bios_lid_value") in acpi/button.c which would allow people to
> choose if they want the "new" behavior or the old one. And we could
> also add some DMI matching for the messed up laptops/tablets where we
> force one or the other quirk. When we agree that user space now
> behaves gently with us, we could then remove entirely the quirk and
> the dmi matching.
> 
> How does that sound?
[Lv Zheng] 
The choices are in my first revision.
I could restore it back and re-send this series.
Also I need to update PATCH 02 to eliminate wrong IS_ERR_VALUE().

> 
> Also, on the topic of the .notify not being sent by some BIOS, I have
> seen something similar on the surface 3.
> 
> The ASL for the LID status change is the following:
> ---
>             Method (_E4C, 0, Serialized)  // _Exx: Edge-Triggered GPE
>             {
>                 If ((HELD == One))
>                 {
>                     ^^LID.LIDB = One
>                 }
>                 Else
>                 {
>                     ^^LID.LIDB = Zero
>                     Notify (LID, 0x80) // Status Change
>                 }
> 
>                 Notify (^^PCI0.SPI1.NTRG, One) // Device Check
>             }
> ---
> 
> I noticed I received the hotplug event on the touchscreen when the LID
> state changed, and tried to initiate the notify on the LID acpi device
> from within the touchscreen driver.
> This works well, except that from time to time, on resume, I don't
> even receive the hotplug notification. It is as if the notification is
> lost while I receive it 80% of the time.
[Lv Zheng] 
Probably this is because of the same reason as mentioned before.
I still think Surface 3 is a different example.

On those traditional platforms, we can see that:
1. There are platforms returning hardware state directly from _LID
2. There are platforms returning cached state from _LID and update it via lid irq, EC._REG, _WAK
3. There are platforms returning cached state from _LID and update it via lid irq

The fact is there are simply so many type 3 platforms.
You might be thinking there are only several such kind of bogus devices.
But actually our team has been working on customizing those platforms, enhancing their EC._REG/_WAK for years in order to make the AML tables working on Linux.
This looks like an endless work to me...

> 
> This might be completely unrelated, but I think it is worth mentioning
> because there might be a common root at the state not being updated
> correctly.
> 
> Cheers, and sorry for being annoying :)
[Lv Zheng] 
I didn't see anything annoying. :)

Cheers
-Lv

> Benjamin

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

* RE: [PATCH v2 3/3] ACPI / button: Send "open" state after boot/resume
  2016-06-01  1:17           ` Zheng, Lv
@ 2016-06-01  7:51             ` Zheng, Lv
  2016-06-01  8:07               ` Benjamin Tissoires
  0 siblings, 1 reply; 66+ messages in thread
From: Zheng, Lv @ 2016-06-01  7:51 UTC (permalink / raw)
  To: Zheng, Lv, Benjamin Tissoires
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	linux-kernel, ACPI Devel Maling List, Bastien Nocera:,
	Valdis.Kletnieks

Hi,

[cut]
> > We could have a parameter (say "send_lid_open_on_resume" or
> > "use_bios_lid_value") in acpi/button.c which would allow people to
> > choose if they want the "new" behavior or the old one. And we could
> > also add some DMI matching for the messed up laptops/tablets where
> we
> > force one or the other quirk. When we agree that user space now
> > behaves gently with us, we could then remove entirely the quirk and
> > the dmi matching.
> >
> > How does that sound?
> [Lv Zheng]
> The choices are in my first revision.
> I could restore it back and re-send this series.
> Also I need to update PATCH 02 to eliminate wrong IS_ERR_VALUE().
[Lv Zheng] 
I forgot to mention.
IMO, if the issue is because of uncertain gaps, not a confirmed BIOS bug, or a confirmed gap that has to be solved in a spirit of compromise, we should not add quirks.
We could just provide boot parameters for users to choose.
Because the quirk table could grow bigger and bigger, exceeding our control.

So I probably would just implement the parameter part, without adding the DMI entries.

Thanks and best regards
-Lv

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

* Re: [PATCH v2 3/3] ACPI / button: Send "open" state after boot/resume
  2016-06-01  7:51             ` Zheng, Lv
@ 2016-06-01  8:07               ` Benjamin Tissoires
  0 siblings, 0 replies; 66+ messages in thread
From: Benjamin Tissoires @ 2016-06-01  8:07 UTC (permalink / raw)
  To: Zheng, Lv
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	linux-kernel, ACPI Devel Maling List, Bastien Nocera:,
	Valdis.Kletnieks

On Wed, Jun 1, 2016 at 9:51 AM, Zheng, Lv <lv.zheng@intel.com> wrote:
> Hi,
>
> [cut]
>> > We could have a parameter (say "send_lid_open_on_resume" or
>> > "use_bios_lid_value") in acpi/button.c which would allow people to
>> > choose if they want the "new" behavior or the old one. And we could
>> > also add some DMI matching for the messed up laptops/tablets where
>> we
>> > force one or the other quirk. When we agree that user space now
>> > behaves gently with us, we could then remove entirely the quirk and
>> > the dmi matching.
>> >
>> > How does that sound?
>> [Lv Zheng]
>> The choices are in my first revision.
>> I could restore it back and re-send this series.
>> Also I need to update PATCH 02 to eliminate wrong IS_ERR_VALUE().
> [Lv Zheng]
> I forgot to mention.
> IMO, if the issue is because of uncertain gaps, not a confirmed BIOS bug, or a confirmed gap that has to be solved in a spirit of compromise, we should not add quirks.
> We could just provide boot parameters for users to choose.
> Because the quirk table could grow bigger and bigger, exceeding our control.
>
> So I probably would just implement the parameter part, without adding the DMI entries.
>

Works for me. I think in Fedora, we might default to keep the current
behavior, but document that some tablets need the parameter to be set.
As soon as systemd changes its policy, we can change the default
value.


As for the Surface3, I think the LID state and irq is just not enough
robust to be used through the ACPI node PNP0C0D. I get all the
information from the touchscreen ACPI Node and the WMI, so I think
there might be a way to remove the standard ACPI LID and use our own,
or simply override the ACPI call by a different one (through the WMI).
It's a shame logind only expects one LID event node :).

Cheers,
Benjamin

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

* [PATCH v3 1/3] ACPI / button: Remove initial lid state notification
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
                   ` (2 preceding siblings ...)
  2016-05-27  7:15 ` [PATCH v2 0/3] ACPI / button: Clarify initial lid state Lv Zheng
@ 2016-06-01 10:10 ` Lv Zheng
  2016-06-23  0:36   ` Rafael J. Wysocki
  2016-06-01 10:10 ` [PATCH v3 2/3] ACPI / button: Refactor functions to eliminate redundant code Lv Zheng
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 66+ messages in thread
From: Lv Zheng @ 2016-06-01 10:10 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi

The _LID control method's initial returning value is not reliable.

The _LID control method is described to return the "current" lid state.
However the word of "current" has ambiguity, many BIOSen 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 BIOSen implement this control method with cached
value, the initial returning value is likely not reliable. There are simply
so many examples retuning "close" as initial lid state (Link 1), sending
this state to the userspace causes suspending right after booting/resuming.

Since the lid state is implemented by the BIOSen, the kernel lid driver has
no idea how it can be correct, this patch stops sending the initial lid
state to the userspace to try to avoid sending the wrong lid state to the
userspace to trigger such kind of wrong suspending. This actually reverts
the following commit introduced for fixing a novell bug (Link 2):
  Commit: 23de5d9ef2a4bbc4f733f58311bcb7cf6239c813
  Subject: ACPI: button: send initial lid state after add and resume

Link 1: https://bugzilla.kernel.org/show_bug.cgi?id=89211
        https://bugzilla.kernel.org/show_bug.cgi?id=106151
        https://bugzilla.kernel.org/show_bug.cgi?id=106941
Link 2: https://bugzilla.novell.com/show_bug.cgi?id=326814
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
 drivers/acpi/button.c |    3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 5c3b091..9863278 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -334,8 +334,6 @@ static int acpi_button_resume(struct device *dev)
 	struct acpi_button *button = acpi_driver_data(device);
 
 	button->suspended = false;
-	if (button->type == ACPI_BUTTON_TYPE_LID)
-		return acpi_lid_send_state(device);
 	return 0;
 }
 #endif
@@ -416,7 +414,6 @@ static int acpi_button_add(struct acpi_device *device)
 	if (error)
 		goto err_remove_fs;
 	if (button->type == ACPI_BUTTON_TYPE_LID) {
-		acpi_lid_send_state(device);
 		/*
 		 * This assumes there's only one lid device, or if there are
 		 * more we only care about the last one...
-- 
1.7.10

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

* [PATCH v3 2/3] ACPI / button: Refactor functions to eliminate redundant code
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
                   ` (3 preceding siblings ...)
  2016-06-01 10:10 ` [PATCH v3 1/3] ACPI / button: Remove initial lid state notification Lv Zheng
@ 2016-06-01 10:10 ` Lv Zheng
  2016-06-01 10:10 ` [PATCH v3 3/3] ACPI / button: Add quirks for initial lid state notification Lv Zheng
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 66+ messages in thread
From: Lv Zheng @ 2016-06-01 10:10 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi

(Correct a wrong macro usage.)

This patch simplies the code by merging the redundant code. No functional
changes.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
 drivers/acpi/button.c |   91 ++++++++++++++++++++++++++-----------------------
 1 file changed, 49 insertions(+), 42 deletions(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 9863278..6e291c1 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -113,16 +113,52 @@ static struct acpi_device *lid_device;
 static struct proc_dir_entry *acpi_button_dir;
 static struct proc_dir_entry *acpi_lid_dir;
 
+static int acpi_lid_evaluate_state(struct acpi_device *device)
+{
+	unsigned long long lid_state;
+	acpi_status status;
+
+	status = acpi_evaluate_integer(device->handle, "_LID", NULL, &lid_state);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	return lid_state ? 1 : 0;
+}
+
+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 */
+	input_report_switch(button->input, SW_LID, !state);
+	input_sync(button->input);
+
+	if (state)
+		pm_wakeup_event(&device->dev, 0);
+
+	ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
+	if (ret == NOTIFY_DONE)
+		ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
+						   device);
+	if (ret == NOTIFY_DONE || ret == NOTIFY_OK) {
+		/*
+		 * It is also regarded as success if the notifier_chain
+		 * returns NOTIFY_OK or NOTIFY_DONE.
+		 */
+		ret = 0;
+	}
+	return ret;
+}
+
 static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
 {
 	struct acpi_device *device = seq->private;
-	acpi_status status;
-	unsigned long long state;
+	int state;
 
-	status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state);
+	state = acpi_lid_evaluate_state(device);
 	seq_printf(seq, "state:      %s\n",
-		   ACPI_FAILURE(status) ? "unsupported" :
-			(state ? "open" : "closed"));
+		   state < 0 ? "unsupported" : (state ? "open" : "closed"));
 	return 0;
 }
 
@@ -231,51 +267,22 @@ EXPORT_SYMBOL(acpi_lid_notifier_unregister);
 
 int acpi_lid_open(void)
 {
-	acpi_status status;
-	unsigned long long state;
-
 	if (!lid_device)
 		return -ENODEV;
 
-	status = acpi_evaluate_integer(lid_device->handle, "_LID", NULL,
-				       &state);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
-
-	return !!state;
+	return acpi_lid_evaluate_state(lid_device);
 }
 EXPORT_SYMBOL(acpi_lid_open);
 
-static int acpi_lid_send_state(struct acpi_device *device)
+static int acpi_lid_update_state(struct acpi_device *device)
 {
-	struct acpi_button *button = acpi_driver_data(device);
-	unsigned long long state;
-	acpi_status status;
-	int ret;
-
-	status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
+	int state;
 
-	/* input layer checks if event is redundant */
-	input_report_switch(button->input, SW_LID, !state);
-	input_sync(button->input);
+	state = acpi_lid_evaluate_state(device);
+	if (state < 0)
+		return state;
 
-	if (state)
-		pm_wakeup_event(&device->dev, 0);
-
-	ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
-	if (ret == NOTIFY_DONE)
-		ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
-						   device);
-	if (ret == NOTIFY_DONE || ret == NOTIFY_OK) {
-		/*
-		 * It is also regarded as success if the notifier_chain
-		 * returns NOTIFY_OK or NOTIFY_DONE.
-		 */
-		ret = 0;
-	}
-	return ret;
+	return acpi_lid_notify_state(device, state);
 }
 
 static void acpi_button_notify(struct acpi_device *device, u32 event)
@@ -290,7 +297,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
 	case ACPI_BUTTON_NOTIFY_STATUS:
 		input = button->input;
 		if (button->type == ACPI_BUTTON_TYPE_LID) {
-			acpi_lid_send_state(device);
+			acpi_lid_update_state(device);
 		} else {
 			int keycode;
 
-- 
1.7.10

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

* [PATCH v3 3/3] ACPI / button: Add quirks for initial lid state notification
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
                   ` (4 preceding siblings ...)
  2016-06-01 10:10 ` [PATCH v3 2/3] ACPI / button: Refactor functions to eliminate redundant code Lv Zheng
@ 2016-06-01 10:10 ` Lv Zheng
  2016-06-01 11:01   ` Bastien Nocera
  2016-07-19  8:11 ` [PATCH v4 1/2] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model Lv Zheng
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 66+ messages in thread
From: Lv Zheng @ 2016-06-01 10:10 UTC (permalink / raw)
  To: Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, Lv Zheng, linux-kernel, linux-acpi, Bastien Nocera:,
	Benjamin Tissoires

Linux userspace (systemd-logind) keeps on rechecking lid state when the
lid state is closed. If it failed to update the lid state to open after
boot/resume, the system suspending right after the boot/resume could be
resulted.
Graphics drivers also uses the lid notifications to implment
MODESET_ON_LID_OPEN option.

Before the situation is improved from the userspace and from the graphics
driver, users can simply configure ACPI button driver to send initial
"open" lid state using button.lid_init_state=open to avoid such kind of
issues. And our ultimate target should be making
button.lid_init_state=ignore the default behavior. This patch implements
the 2 options and keep the old behavior (button.lid_init_state=method).

Link 1: https://lkml.org/2016/3/7/460
Link 2: https://github.com/systemd/systemd/issues/2087
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Cc: Bastien Nocera: <hadess@hadess.net>
Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
---
 drivers/acpi/button.c |   61 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 6e291c1..148f4e5 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -53,6 +53,10 @@
 #define ACPI_BUTTON_DEVICE_NAME_LID	"Lid Switch"
 #define ACPI_BUTTON_TYPE_LID		0x05
 
+#define ACPI_BUTTON_LID_INIT_IGNORE	0x00
+#define ACPI_BUTTON_LID_INIT_OPEN	0x01
+#define ACPI_BUTTON_LID_INIT_METHOD	0x02
+
 #define _COMPONENT		ACPI_BUTTON_COMPONENT
 ACPI_MODULE_NAME("button");
 
@@ -105,6 +109,7 @@ struct acpi_button {
 
 static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
 static struct acpi_device *lid_device;
+static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
 
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
@@ -285,6 +290,21 @@ static int acpi_lid_update_state(struct acpi_device *device)
 	return acpi_lid_notify_state(device, state);
 }
 
+static void acpi_lid_initialize_state(struct acpi_device *device)
+{
+	switch (lid_init_state) {
+	case ACPI_BUTTON_LID_INIT_OPEN:
+		(void)acpi_lid_notify_state(device, 1);
+		break;
+	case ACPI_BUTTON_LID_INIT_METHOD:
+		(void)acpi_lid_update_state(device);
+		break;
+	case ACPI_BUTTON_LID_INIT_IGNORE:
+	default:
+		break;
+	}
+}
+
 static void acpi_button_notify(struct acpi_device *device, u32 event)
 {
 	struct acpi_button *button = acpi_driver_data(device);
@@ -341,6 +361,8 @@ static int acpi_button_resume(struct device *dev)
 	struct acpi_button *button = acpi_driver_data(device);
 
 	button->suspended = false;
+	if (button->type == ACPI_BUTTON_TYPE_LID)
+		acpi_lid_initialize_state(device);
 	return 0;
 }
 #endif
@@ -421,6 +443,7 @@ static int acpi_button_add(struct acpi_device *device)
 	if (error)
 		goto err_remove_fs;
 	if (button->type == ACPI_BUTTON_TYPE_LID) {
+		acpi_lid_initialize_state(device);
 		/*
 		 * This assumes there's only one lid device, or if there are
 		 * more we only care about the last one...
@@ -450,4 +473,42 @@ static int acpi_button_remove(struct acpi_device *device)
 	return 0;
 }
 
+static int param_set_lid_init_state(const char *val, struct kernel_param *kp)
+{
+	int result = 0;
+
+	if (!strncmp(val, "open", sizeof("open") - 1)) {
+		lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
+		pr_info("Notify initial lid state as open\n");
+	} else if (!strncmp(val, "method", sizeof("method") - 1)) {
+		lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
+		pr_info("Notify initial lid state with _LID return value\n");
+	} else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) {
+		lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE;
+		pr_info("Do not notify initial lid state\n");
+	} else
+		result = -EINVAL;
+	return result;
+}
+
+static int param_get_lid_init_state(char *buffer, struct kernel_param *kp)
+{
+	switch (lid_init_state) {
+	case ACPI_BUTTON_LID_INIT_OPEN:
+		return sprintf(buffer, "open");
+	case ACPI_BUTTON_LID_INIT_METHOD:
+		return sprintf(buffer, "method");
+	case ACPI_BUTTON_LID_INIT_IGNORE:
+		return sprintf(buffer, "ignore");
+	default:
+		return sprintf(buffer, "invalid");
+	}
+	return 0;
+}
+
+module_param_call(lid_init_state,
+		  param_set_lid_init_state, param_get_lid_init_state,
+		  NULL, 0644);
+MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial state");
+
 module_acpi_driver(acpi_button_driver);
-- 
1.7.10

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

* Re: [PATCH v3 3/3] ACPI / button: Add quirks for initial lid state notification
  2016-06-01 10:10 ` [PATCH v3 3/3] ACPI / button: Add quirks for initial lid state notification Lv Zheng
@ 2016-06-01 11:01   ` Bastien Nocera
  2016-06-02  1:08     ` Zheng, Lv
  0 siblings, 1 reply; 66+ messages in thread
From: Bastien Nocera @ 2016-06-01 11:01 UTC (permalink / raw)
  To: Lv Zheng, Rafael J. Wysocki, Rafael J. Wysocki, Len Brown
  Cc: Lv Zheng, linux-kernel, linux-acpi, Benjamin Tissoires

On Wed, 2016-06-01 at 18:10 +0800, Lv Zheng wrote:
> Linux userspace (systemd-logind) keeps on rechecking lid state when the
> lid state is closed. If it failed to update the lid state to open after
> boot/resume, the system suspending right after the boot/resume could be
> resulted.
> Graphics drivers also uses the lid notifications to implment
> MODESET_ON_LID_OPEN option.

"implement"

> Before the situation is improved from the userspace and from the graphics
> driver, users can simply configure ACPI button driver to send initial
> "open" lid state using button.lid_init_state=open to avoid such kind of
> issues. And our ultimate target should be making
> button.lid_init_state=ignore the default behavior. This patch implements
> the 2 options and keep the old behavior (button.lid_init_state=method).

I still don't think it's reasonable to expect any changes in user-space 
unless you start documenting what the API to user-space actually is.

(I work on UPower, which also exports that information, and which gets
used in gnome-settings-daemon in a number of ways)

> Link 1: https://lkml.org/2016/3/7/460
> Link 2: https://github.com/systemd/systemd/issues/2087
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Cc: Bastien Nocera: <hadess@hadess.net>
> Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> ---
>  drivers/acpi/button.c |   61
> +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 61 insertions(+)
> 
> diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> index 6e291c1..148f4e5 100644
> --- a/drivers/acpi/button.c
> +++ b/drivers/acpi/button.c
> @@ -53,6 +53,10 @@
>  #define ACPI_BUTTON_DEVICE_NAME_LID	"Lid Switch"
>  #define ACPI_BUTTON_TYPE_LID		0x05
>  
> +#define ACPI_BUTTON_LID_INIT_IGNORE	0x00
> +#define ACPI_BUTTON_LID_INIT_OPEN	0x01
> +#define ACPI_BUTTON_LID_INIT_METHOD	0x02
> +
>  #define _COMPONENT		ACPI_BUTTON_COMPONENT
>  ACPI_MODULE_NAME("button");
>  
> @@ -105,6 +109,7 @@ struct acpi_button {
>  
>  static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
>  static struct acpi_device *lid_device;
> +static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
>  
>  /* ---------------------------------------------------------------
> -----------
>                                FS Interface (/proc)
> @@ -285,6 +290,21 @@ static int acpi_lid_update_state(struct
> acpi_device *device)
>  	return acpi_lid_notify_state(device, state);
>  }
>  
> +static void acpi_lid_initialize_state(struct acpi_device *device)
> +{
> +	switch (lid_init_state) {
> +	case ACPI_BUTTON_LID_INIT_OPEN:
> +		(void)acpi_lid_notify_state(device, 1);
> +		break;
> +	case ACPI_BUTTON_LID_INIT_METHOD:
> +		(void)acpi_lid_update_state(device);
> +		break;
> +	case ACPI_BUTTON_LID_INIT_IGNORE:
> +	default:
> +		break;
> +	}
> +}
> +
>  static void acpi_button_notify(struct acpi_device *device, u32
> event)
>  {
>  	struct acpi_button *button = acpi_driver_data(device);
> @@ -341,6 +361,8 @@ static int acpi_button_resume(struct device *dev)
>  	struct acpi_button *button = acpi_driver_data(device);
>  
>  	button->suspended = false;
> +	if (button->type == ACPI_BUTTON_TYPE_LID)
> +		acpi_lid_initialize_state(device);
>  	return 0;
>  }
>  #endif
> @@ -421,6 +443,7 @@ static int acpi_button_add(struct acpi_device
> *device)
>  	if (error)
>  		goto err_remove_fs;
>  	if (button->type == ACPI_BUTTON_TYPE_LID) {
> +		acpi_lid_initialize_state(device);
>  		/*
>  		 * This assumes there's only one lid device, or if
> there are
>  		 * more we only care about the last one...
> @@ -450,4 +473,42 @@ static int acpi_button_remove(struct acpi_device
> *device)
>  	return 0;
>  }
>  
> +static int param_set_lid_init_state(const char *val, struct
> kernel_param *kp)
> +{
> +	int result = 0;
> +
> +	if (!strncmp(val, "open", sizeof("open") - 1)) {
> +		lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
> +		pr_info("Notify initial lid state as open\n");
> +	} else if (!strncmp(val, "method", sizeof("method") - 1)) {
> +		lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
> +		pr_info("Notify initial lid state with _LID return
> value\n");
> +	} else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) {
> +		lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE;
> +		pr_info("Do not notify initial lid state\n");
> +	} else
> +		result = -EINVAL;
> +	return result;
> +}
> +
> +static int param_get_lid_init_state(char *buffer, struct
> kernel_param *kp)
> +{
> +	switch (lid_init_state) {
> +	case ACPI_BUTTON_LID_INIT_OPEN:
> +		return sprintf(buffer, "open");
> +	case ACPI_BUTTON_LID_INIT_METHOD:
> +		return sprintf(buffer, "method");
> +	case ACPI_BUTTON_LID_INIT_IGNORE:
> +		return sprintf(buffer, "ignore");
> +	default:
> +		return sprintf(buffer, "invalid");
> +	}
> +	return 0;
> +}
> +
> +module_param_call(lid_init_state,
> +		  param_set_lid_init_state,
> param_get_lid_init_state,
> +		  NULL, 0644);
> +MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial
> state");
> +
>  module_acpi_driver(acpi_button_driver);

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

* RE: [PATCH v3 3/3] ACPI / button: Add quirks for initial lid state notification
  2016-06-01 11:01   ` Bastien Nocera
@ 2016-06-02  1:08     ` Zheng, Lv
  2016-06-02 14:01       ` Bastien Nocera
  0 siblings, 1 reply; 66+ messages in thread
From: Zheng, Lv @ 2016-06-02  1:08 UTC (permalink / raw)
  To: Bastien Nocera, Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len
  Cc: Lv Zheng, linux-kernel, linux-acpi, Benjamin Tissoires

Hi,

> From: Bastien Nocera [mailto:hadess@hadess.net]
> Subject: Re: [PATCH v3 3/3] ACPI / button: Add quirks for initial lid state
> notification
> 
> On Wed, 2016-06-01 at 18:10 +0800, Lv Zheng wrote:
> > Linux userspace (systemd-logind) keeps on rechecking lid state when the
> > lid state is closed. If it failed to update the lid state to open after
> > boot/resume, the system suspending right after the boot/resume could
> be
> > resulted.
> > Graphics drivers also uses the lid notifications to implment
> > MODESET_ON_LID_OPEN option.
> 
> "implement"
[Lv Zheng] 
Thanks for pointing out, I'll send an UPDATE to this.

> 
> > Before the situation is improved from the userspace and from the
> graphics
> > driver, users can simply configure ACPI button driver to send initial
> > "open" lid state using button.lid_init_state=open to avoid such kind of
> > issues. And our ultimate target should be making
> > button.lid_init_state=ignore the default behavior. This patch implements
> > the 2 options and keep the old behavior (button.lid_init_state=method).
> 
> I still don't think it's reasonable to expect any changes in user-space
> unless you start documenting what the API to user-space actually is.
[Lv Zheng] 
IMO, the ACPI lid driver should be responsible for sending lid key event (especially "close") to the user space.
So if someone need to implement an ACPI lid key event quirk, we could help to implement it from the kernel space.
And since the initial lid state is not stable, we have to stop doing quirks around it inside of the Linux kernel, or inside of the customized AML tables.
User space can still access /proc/acpi/button/lid/LID0/state, but should stop thinking that it is reliable.

These are what I can conclude from the bugs.

Thanks and best regards
-Lv

> 
> (I work on UPower, which also exports that information, and which gets
> used in gnome-settings-daemon in a number of ways)
> 
> > Link 1: https://lkml.org/2016/3/7/460
> > Link 2: https://github.com/systemd/systemd/issues/2087
> > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > Cc: Bastien Nocera: <hadess@hadess.net>
> > Cc: Benjamin Tissoires <benjamin.tissoires@gmail.com>
> > ---
> >  drivers/acpi/button.c |   61
> > +++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 61 insertions(+)
> >
> > diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> > index 6e291c1..148f4e5 100644
> > --- a/drivers/acpi/button.c
> > +++ b/drivers/acpi/button.c
> > @@ -53,6 +53,10 @@
> >  #define ACPI_BUTTON_DEVICE_NAME_LID	"Lid Switch"
> >  #define ACPI_BUTTON_TYPE_LID		0x05
> >
> > +#define ACPI_BUTTON_LID_INIT_IGNORE	0x00
> > +#define ACPI_BUTTON_LID_INIT_OPEN	0x01
> > +#define ACPI_BUTTON_LID_INIT_METHOD	0x02
> > +
> >  #define _COMPONENT		ACPI_BUTTON_COMPONENT
> >  ACPI_MODULE_NAME("button");
> >
> > @@ -105,6 +109,7 @@ struct acpi_button {
> >
> >  static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
> >  static struct acpi_device *lid_device;
> > +static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
> >
> >  /* ---------------------------------------------------------------
> > -----------
> >                                FS Interface (/proc)
> > @@ -285,6 +290,21 @@ static int acpi_lid_update_state(struct
> > acpi_device *device)
> >  	return acpi_lid_notify_state(device, state);
> >  }
> >
> > +static void acpi_lid_initialize_state(struct acpi_device *device)
> > +{
> > +	switch (lid_init_state) {
> > +	case ACPI_BUTTON_LID_INIT_OPEN:
> > +		(void)acpi_lid_notify_state(device, 1);
> > +		break;
> > +	case ACPI_BUTTON_LID_INIT_METHOD:
> > +		(void)acpi_lid_update_state(device);
> > +		break;
> > +	case ACPI_BUTTON_LID_INIT_IGNORE:
> > +	default:
> > +		break;
> > +	}
> > +}
> > +
> >  static void acpi_button_notify(struct acpi_device *device, u32
> > event)
> >  {
> >  	struct acpi_button *button = acpi_driver_data(device);
> > @@ -341,6 +361,8 @@ static int acpi_button_resume(struct device
> *dev)
> >  	struct acpi_button *button = acpi_driver_data(device);
> >
> >  	button->suspended = false;
> > +	if (button->type == ACPI_BUTTON_TYPE_LID)
> > +		acpi_lid_initialize_state(device);
> >  	return 0;
> >  }
> >  #endif
> > @@ -421,6 +443,7 @@ static int acpi_button_add(struct acpi_device
> > *device)
> >  	if (error)
> >  		goto err_remove_fs;
> >  	if (button->type == ACPI_BUTTON_TYPE_LID) {
> > +		acpi_lid_initialize_state(device);
> >  		/*
> >  		 * This assumes there's only one lid device, or if
> > there are
> >  		 * more we only care about the last one...
> > @@ -450,4 +473,42 @@ static int acpi_button_remove(struct
> acpi_device
> > *device)
> >  	return 0;
> >  }
> >
> > +static int param_set_lid_init_state(const char *val, struct
> > kernel_param *kp)
> > +{
> > +	int result = 0;
> > +
> > +	if (!strncmp(val, "open", sizeof("open") - 1)) {
> > +		lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
> > +		pr_info("Notify initial lid state as open\n");
> > +	} else if (!strncmp(val, "method", sizeof("method") - 1)) {
> > +		lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
> > +		pr_info("Notify initial lid state with _LID return
> > value\n");
> > +	} else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) {
> > +		lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE;
> > +		pr_info("Do not notify initial lid state\n");
> > +	} else
> > +		result = -EINVAL;
> > +	return result;
> > +}
> > +
> > +static int param_get_lid_init_state(char *buffer, struct
> > kernel_param *kp)
> > +{
> > +	switch (lid_init_state) {
> > +	case ACPI_BUTTON_LID_INIT_OPEN:
> > +		return sprintf(buffer, "open");
> > +	case ACPI_BUTTON_LID_INIT_METHOD:
> > +		return sprintf(buffer, "method");
> > +	case ACPI_BUTTON_LID_INIT_IGNORE:
> > +		return sprintf(buffer, "ignore");
> > +	default:
> > +		return sprintf(buffer, "invalid");
> > +	}
> > +	return 0;
> > +}
> > +
> > +module_param_call(lid_init_state,
> > +		  param_set_lid_init_state,
> > param_get_lid_init_state,
> > +		  NULL, 0644);
> > +MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial
> > state");
> > +
> >  module_acpi_driver(acpi_button_driver);

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

* Re: [PATCH v3 3/3] ACPI / button: Add quirks for initial lid state notification
  2016-06-02  1:08     ` Zheng, Lv
@ 2016-06-02 14:01       ` Bastien Nocera
  2016-06-02 15:25         ` Benjamin Tissoires
  0 siblings, 1 reply; 66+ messages in thread
From: Bastien Nocera @ 2016-06-02 14:01 UTC (permalink / raw)
  To: Zheng, Lv, Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len
  Cc: Lv Zheng, linux-kernel, linux-acpi, Benjamin Tissoires

On Thu, 2016-06-02 at 01:08 +0000, Zheng, Lv wrote:
> Hi,
> 
> > From: Bastien Nocera [mailto:hadess@hadess.net]
> > Subject: Re: [PATCH v3 3/3] ACPI / button: Add quirks for initial
> > lid state
> > notification
> > 
> > On Wed, 2016-06-01 at 18:10 +0800, Lv Zheng wrote:
> > > Linux userspace (systemd-logind) keeps on rechecking lid state
> > > when the
> > > lid state is closed. If it failed to update the lid state to open
> > > after
> > > boot/resume, the system suspending right after the boot/resume
> > > could
> > be
> > > resulted.
> > > Graphics drivers also uses the lid notifications to implment
> > > MODESET_ON_LID_OPEN option.
> > 
> > "implement"
> [Lv Zheng] 
> Thanks for pointing out, I'll send an UPDATE to this.
> 
> > 
> > > Before the situation is improved from the userspace and from the
> > graphics
> > > driver, users can simply configure ACPI button driver to send
> > > initial
> > > "open" lid state using button.lid_init_state=open to avoid such
> > > kind of
> > > issues. And our ultimate target should be making
> > > button.lid_init_state=ignore the default behavior. This patch
> > > implements
> > > the 2 options and keep the old behavior
> > > (button.lid_init_state=method).
> > 
> > I still don't think it's reasonable to expect any changes in user-
> > space
> > unless you start documenting what the API to user-space actually
> > is.
> [Lv Zheng] 
> IMO, the ACPI lid driver should be responsible for sending lid key
> event (especially "close") to the user space.
> So if someone need to implement an ACPI lid key event quirk, we could
> help to implement it from the kernel space.
> And since the initial lid state is not stable, we have to stop doing
> quirks around it inside of the Linux kernel, or inside of the
> customized AML tables.
> User space can still access /proc/acpi/button/lid/LID0/state, but
> should stop thinking that it is reliable.
> 
> These are what I can conclude from the bugs.

There's still no documentation for user-space in the patch, and no way
to disable the "legacy" support (disabling access to the cached LID
state, especially through the input layer which is what logind and
upower use).

You can't expect user-space to change in major ways for those few
devices if the API doesn't force them to, through deprecation notices
and documentation.

Cheers

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

* Re: [PATCH v3 3/3] ACPI / button: Add quirks for initial lid state notification
  2016-06-02 14:01       ` Bastien Nocera
@ 2016-06-02 15:25         ` Benjamin Tissoires
  2016-06-03  0:41           ` Zheng, Lv
  0 siblings, 1 reply; 66+ messages in thread
From: Benjamin Tissoires @ 2016-06-02 15:25 UTC (permalink / raw)
  To: Bastien Nocera
  Cc: Zheng, Lv, Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len,
	Lv Zheng, linux-kernel, linux-acpi

On Thu, Jun 2, 2016 at 4:01 PM, Bastien Nocera <hadess@hadess.net> wrote:
> On Thu, 2016-06-02 at 01:08 +0000, Zheng, Lv wrote:
>> Hi,
>>
>> > From: Bastien Nocera [mailto:hadess@hadess.net]
>> > Subject: Re: [PATCH v3 3/3] ACPI / button: Add quirks for initial
>> > lid state
>> > notification
>> >
>> > On Wed, 2016-06-01 at 18:10 +0800, Lv Zheng wrote:
>> > > Linux userspace (systemd-logind) keeps on rechecking lid state
>> > > when the
>> > > lid state is closed. If it failed to update the lid state to open
>> > > after
>> > > boot/resume, the system suspending right after the boot/resume
>> > > could
>> > be
>> > > resulted.
>> > > Graphics drivers also uses the lid notifications to implment
>> > > MODESET_ON_LID_OPEN option.
>> >
>> > "implement"
>> [Lv Zheng]
>> Thanks for pointing out, I'll send an UPDATE to this.
>>
>> >
>> > > Before the situation is improved from the userspace and from the
>> > graphics
>> > > driver, users can simply configure ACPI button driver to send
>> > > initial
>> > > "open" lid state using button.lid_init_state=open to avoid such
>> > > kind of
>> > > issues. And our ultimate target should be making
>> > > button.lid_init_state=ignore the default behavior. This patch
>> > > implements
>> > > the 2 options and keep the old behavior
>> > > (button.lid_init_state=method).
>> >
>> > I still don't think it's reasonable to expect any changes in user-
>> > space
>> > unless you start documenting what the API to user-space actually
>> > is.
>> [Lv Zheng]
>> IMO, the ACPI lid driver should be responsible for sending lid key
>> event (especially "close") to the user space.
>> So if someone need to implement an ACPI lid key event quirk, we could
>> help to implement it from the kernel space.
>> And since the initial lid state is not stable, we have to stop doing
>> quirks around it inside of the Linux kernel, or inside of the
>> customized AML tables.
>> User space can still access /proc/acpi/button/lid/LID0/state, but
>> should stop thinking that it is reliable.
>>
>> These are what I can conclude from the bugs.

After further thoughts, I also think it is a bad idea to request user
space to change behavior with respect to the LID switch event we
forward from the keyboard:
- it looks like Windows doesn't care about LID open on some
(entry-level) platforms: the Samsung N210 is one of the first netbooks
from 2010. The Surface (pro or not) are tablets. On these low cost
systems, we can easily assume that the user needs to have the LID open
to have the system working. You can't connect a docking station, and
they are probably not used in a professional environment.
- for the high end machines (think professional), we actually need to
have a valid LID state given that the machines can be used on a
docking station, so LID closed. If we do not send a reliable LID state
for those laptops we will break user space and more likely annoy
users: we might light up the closed internal monitor and migrate all
the currently open applications to this screen.

So I think Windows might be able to detect those 2 categories of
environments and behave accordingly.

Then, if we want to express to user space that the LID switch state is
not reliable, we should stop setting it up as an input device with a
EV_SWITCH in it. The kernel has to be reliable, and we can't start
saying that this particular switch in a system might not be reliable.
In this, I join Bastien's point of view where we need to start
deprecating and document what needs to be done, and introduce a new
way of reporting the LID events to user space (by using a
KEY_LID_CLOSE for instance).

I still think this patch is necessary. Until we manage to understand
what is going on on Windows for the non reliable LID state, we can
always ask users to use the button.lid_init_state=open to prevent the
freeze loops they are seeing.
The deprecation process could be to send the open state at resume on
the SW_LID event, and send both the close and a KEY_LID_CLOSE event on
close (no KEY_* on open).

For professional laptops (with docking capability), I can't see how we
could avoid forwarding a reliable state, and we need them to stick to
button.lid_init_state=method (keep SW_LID and not send the
KEY_LID_CLOSE event so userspace knows it's reliable).

Hope this helps,
Benjamin


>
> There's still no documentation for user-space in the patch, and no way
> to disable the "legacy" support (disabling access to the cached LID
> state, especially through the input layer which is what logind and
> upower use).
>
> You can't expect user-space to change in major ways for those few
> devices if the API doesn't force them to, through deprecation notices
> and documentation.
>
> Cheers

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

* RE: [PATCH v3 3/3] ACPI / button: Add quirks for initial lid state notification
  2016-06-02 15:25         ` Benjamin Tissoires
@ 2016-06-03  0:41           ` Zheng, Lv
  0 siblings, 0 replies; 66+ messages in thread
From: Zheng, Lv @ 2016-06-03  0:41 UTC (permalink / raw)
  To: Benjamin Tissoires, Bastien Nocera
  Cc: Wysocki, Rafael J, Rafael J. Wysocki, Brown, Len, Lv Zheng,
	linux-kernel, linux-acpi

Hi,

> From: Benjamin Tissoires [mailto:benjamin.tissoires@gmail.com]
> Subject: Re: [PATCH v3 3/3] ACPI / button: Add quirks for initial lid state
> notification
> 
> On Thu, Jun 2, 2016 at 4:01 PM, Bastien Nocera <hadess@hadess.net>
> wrote:
> > On Thu, 2016-06-02 at 01:08 +0000, Zheng, Lv wrote:
> >> Hi,
> >>
> >> > From: Bastien Nocera [mailto:hadess@hadess.net]
> >> > Subject: Re: [PATCH v3 3/3] ACPI / button: Add quirks for initial
> >> > lid state
> >> > notification
> >> >
> >> > On Wed, 2016-06-01 at 18:10 +0800, Lv Zheng wrote:
> >> > > Linux userspace (systemd-logind) keeps on rechecking lid state
> >> > > when the
> >> > > lid state is closed. If it failed to update the lid state to open
> >> > > after
> >> > > boot/resume, the system suspending right after the boot/resume
> >> > > could
> >> > be
> >> > > resulted.
> >> > > Graphics drivers also uses the lid notifications to implment
> >> > > MODESET_ON_LID_OPEN option.
> >> >
> >> > "implement"
> >> [Lv Zheng]
> >> Thanks for pointing out, I'll send an UPDATE to this.
> >>
> >> >
> >> > > Before the situation is improved from the userspace and from the
> >> > graphics
> >> > > driver, users can simply configure ACPI button driver to send
> >> > > initial
> >> > > "open" lid state using button.lid_init_state=open to avoid such
> >> > > kind of
> >> > > issues. And our ultimate target should be making
> >> > > button.lid_init_state=ignore the default behavior. This patch
> >> > > implements
> >> > > the 2 options and keep the old behavior
> >> > > (button.lid_init_state=method).
> >> >
> >> > I still don't think it's reasonable to expect any changes in user-
> >> > space
> >> > unless you start documenting what the API to user-space actually
> >> > is.
> >> [Lv Zheng]
> >> IMO, the ACPI lid driver should be responsible for sending lid key
> >> event (especially "close") to the user space.
> >> So if someone need to implement an ACPI lid key event quirk, we could
> >> help to implement it from the kernel space.
> >> And since the initial lid state is not stable, we have to stop doing
> >> quirks around it inside of the Linux kernel, or inside of the
> >> customized AML tables.
> >> User space can still access /proc/acpi/button/lid/LID0/state, but
> >> should stop thinking that it is reliable.
> >>
> >> These are what I can conclude from the bugs.
> 
> After further thoughts, I also think it is a bad idea to request user
> space to change behavior with respect to the LID switch event we
> forward from the keyboard:
> - it looks like Windows doesn't care about LID open on some
> (entry-level) platforms: the Samsung N210 is one of the first netbooks
> from 2010. The Surface (pro or not) are tablets. On these low cost
> systems, we can easily assume that the user needs to have the LID open
> to have the system working. You can't connect a docking station, and
> they are probably not used in a professional environment.
> - for the high end machines (think professional), we actually need to
> have a valid LID state given that the machines can be used on a
> docking station, so LID closed. If we do not send a reliable LID state
> for those laptops we will break user space and more likely annoy
> users: we might light up the closed internal monitor and migrate all
> the currently open applications to this screen.
> 
> So I think Windows might be able to detect those 2 categories of
> environments and behave accordingly.
> 
> Then, if we want to express to user space that the LID switch state is
> not reliable, we should stop setting it up as an input device with a
> EV_SWITCH in it. The kernel has to be reliable, and we can't start
> saying that this particular switch in a system might not be reliable.
> In this, I join Bastien's point of view where we need to start
> deprecating and document what needs to be done, and introduce a new
> way of reporting the LID events to user space (by using a
> KEY_LID_CLOSE for instance).
> 
> I still think this patch is necessary. Until we manage to understand
> what is going on on Windows for the non reliable LID state, we can
> always ask users to use the button.lid_init_state=open to prevent the
> freeze loops they are seeing.
> The deprecation process could be to send the open state at resume on
> the SW_LID event, and send both the close and a KEY_LID_CLOSE event on
> close (no KEY_* on open).
> 
> For professional laptops (with docking capability), I can't see how we
> could avoid forwarding a reliable state, and we need them to stick to
> button.lid_init_state=method (keep SW_LID and not send the
> KEY_LID_CLOSE event so userspace knows it's reliable).
[Lv Zheng] 
All sound reasonable to me.
We'll discuss this internally before making further changes.

For the documentation work.
I'm planning to send several documents around ACPICA release, ACPICA debugger, and probing de-facto standard ACPI behavior.
So I can help to add one for "ACPI control method lid device" to clarify this in the same series.

Thanks and best regards
-Lv

> 
> Hope this helps,
> Benjamin
> 
> 
> >
> > There's still no documentation for user-space in the patch, and no way
> > to disable the "legacy" support (disabling access to the cached LID
> > state, especially through the input layer which is what logind and
> > upower use).
> >
> > You can't expect user-space to change in major ways for those few
> > devices if the API doesn't force them to, through deprecation notices
> > and documentation.
> >
> > Cheers

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

* Re: [PATCH v3 1/3] ACPI / button: Remove initial lid state notification
  2016-06-01 10:10 ` [PATCH v3 1/3] ACPI / button: Remove initial lid state notification Lv Zheng
@ 2016-06-23  0:36   ` Rafael J. Wysocki
  2016-06-23  0:57     ` Zheng, Lv
  0 siblings, 1 reply; 66+ messages in thread
From: Rafael J. Wysocki @ 2016-06-23  0:36 UTC (permalink / raw)
  To: Lv Zheng; +Cc: Rafael J. Wysocki, Len Brown, Lv Zheng, linux-kernel, linux-acpi

On Wednesday, June 01, 2016 06:10:34 PM Lv Zheng wrote:
> The _LID control method's initial returning value is not reliable.
> 
> The _LID control method is described to return the "current" lid state.
> However the word of "current" has ambiguity, many BIOSen 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 BIOSen implement this control method with cached
> value, the initial returning value is likely not reliable. There are simply
> so many examples retuning "close" as initial lid state (Link 1), sending
> this state to the userspace causes suspending right after booting/resuming.
> 
> Since the lid state is implemented by the BIOSen, the kernel lid driver has
> no idea how it can be correct, this patch stops sending the initial lid
> state to the userspace to try to avoid sending the wrong lid state to the
> userspace to trigger such kind of wrong suspending. This actually reverts
> the following commit introduced for fixing a novell bug (Link 2):
>   Commit: 23de5d9ef2a4bbc4f733f58311bcb7cf6239c813
>   Subject: ACPI: button: send initial lid state after add and resume
> 
> Link 1: https://bugzilla.kernel.org/show_bug.cgi?id=89211
>         https://bugzilla.kernel.org/show_bug.cgi?id=106151
>         https://bugzilla.kernel.org/show_bug.cgi?id=106941
> Link 2: https://bugzilla.novell.com/show_bug.cgi?id=326814
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>

I've applied [1-3/3] from this series, but I'm not sure if the last patch
is the latest version.  Can you please verify in linux-next?

Thanks,
Rafael

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

* RE: [PATCH v3 1/3] ACPI / button: Remove initial lid state notification
  2016-06-23  0:36   ` Rafael J. Wysocki
@ 2016-06-23  0:57     ` Zheng, Lv
  0 siblings, 0 replies; 66+ messages in thread
From: Zheng, Lv @ 2016-06-23  0:57 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Wysocki, Rafael J, Brown, Len, Lv Zheng, linux-kernel, linux-acpi

Hi, Rafael

> From: Rafael J. Wysocki [mailto:rjw@rjwysocki.net]
> Subject: Re: [PATCH v3 1/3] ACPI / button: Remove initial lid state
> notification
> 
> On Wednesday, June 01, 2016 06:10:34 PM Lv Zheng wrote:
> > The _LID control method's initial returning value is not reliable.
> >
> > The _LID control method is described to return the "current" lid state.
> > However the word of "current" has ambiguity, many BIOSen 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 BIOSen implement this control method with
> cached
> > value, the initial returning value is likely not reliable. There are simply
> > so many examples retuning "close" as initial lid state (Link 1), sending
> > this state to the userspace causes suspending right after
> booting/resuming.
> >
> > Since the lid state is implemented by the BIOSen, the kernel lid driver has
> > no idea how it can be correct, this patch stops sending the initial lid
> > state to the userspace to try to avoid sending the wrong lid state to the
> > userspace to trigger such kind of wrong suspending. This actually reverts
> > the following commit introduced for fixing a novell bug (Link 2):
> >   Commit: 23de5d9ef2a4bbc4f733f58311bcb7cf6239c813
> >   Subject: ACPI: button: send initial lid state after add and resume
> >
> > Link 1: https://bugzilla.kernel.org/show_bug.cgi?id=89211
> >         https://bugzilla.kernel.org/show_bug.cgi?id=106151
> >         https://bugzilla.kernel.org/show_bug.cgi?id=106941
> > Link 2: https://bugzilla.novell.com/show_bug.cgi?id=326814
> > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> 
> I've applied [1-3/3] from this series, but I'm not sure if the last patch
> is the latest version.  Can you please verify in linux-next?

[Lv Zheng] 
I confirmed, the patch in linux-next is the latest version.

And just for your information.
I still have things to do with the lid driver to address Bastien and Benjamin's request:
1. ABI documentation
2. new key event ABI for acpi lid close event (for example, PM_LID)
That's not related to this quirk.
And I'll go back to that after I finish my current pending work.

Thanks and best regards
-Lv

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

* [PATCH v4 1/2] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
                   ` (5 preceding siblings ...)
  2016-06-01 10:10 ` [PATCH v3 3/3] ACPI / button: Add quirks for initial lid state notification Lv Zheng
@ 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)
  15 siblings, 2 replies; 66+ 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] 66+ messages in thread

* [PATCH v4 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
                   ` (6 preceding siblings ...)
  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)
  15 siblings, 2 replies; 66+ 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] 66+ 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; 66+ 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, 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] 66+ 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; 66+ 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, 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] 66+ 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; 66+ 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] 66+ 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; 66+ 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] 66+ 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; 66+ 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] 66+ 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; 66+ 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, linux-acpi, Benjamin Tissoires, Bastien Nocera:,
	linux-input

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] 66+ 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; 66+ 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, linux-acpi, Benjamin Tissoires, Bastien Nocera:,
	linux-input

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] 66+ messages in thread

* [PATCH v5 1/3] ACPI / button: Add missing event to keep SW_LID running without additional event loss
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
                   ` (7 preceding siblings ...)
  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)
  15 siblings, 2 replies; 66+ 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] 66+ messages in thread

* [PATCH v5 2/3] ACPI / button: Add KEY_LID_OPEN/KEY_LID_CLOSE for new usage model
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
                   ` (8 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)
  15 siblings, 0 replies; 66+ 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] 66+ messages in thread

* [PATCH v5 3/3] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
                   ` (9 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)
  15 siblings, 0 replies; 66+ 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] 66+ 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; 66+ 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, linux-acpi, Bastien Nocera:,
	linux-input

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] 66+ 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; 66+ 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, linux-acpi, Benjamin Tissoires, Bastien Nocera:,
	linux-input

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] 66+ 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; 66+ 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, linux-acpi, Bastien Nocera:,
	linux-input

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] 66+ 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; 66+ 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,
	linux-acpi, Bastien Nocera:,
	linux-input

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] 66+ 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; 66+ 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,
	linux-acpi, Bastien Nocera:,
	linux-input

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] 66+ 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; 66+ 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, linux-acpi, Dmitry Torokhov,
	Benjamin Tissoires, Bastien Nocera:,
	linux-input

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] 66+ 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; 66+ 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, linux-acpi, Bastien Nocera:,
	linux-input

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] 66+ 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; 66+ 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, linux-acpi, Benjamin Tissoires, Bastien Nocera:,
	linux-input

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] 66+ 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; 66+ 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, linux-acpi, Benjamin Tissoires, Bastien Nocera:,
	linux-input

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] 66+ 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; 66+ 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, linux-acpi, Bastien Nocera:,
	linux-input

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] 66+ 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; 66+ 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] 66+ 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; 66+ 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,
	linux-acpi, linux-input

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] 66+ 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; 66+ 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,
	linux-acpi, Dmitry Torokhov, Benjamin Tissoires, Bastien Nocera:,
	linux-input

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] 66+ 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; 66+ 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,
	linux-acpi, linux-input

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] 66+ messages in thread

* [PATCH v6] ACPI / button: Fix an issue that the platform triggered "close" event may not be delivered to the userspace
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
                   ` (10 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)
  15 siblings, 0 replies; 66+ 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] 66+ 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
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
                   ` (11 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)
  15 siblings, 1 reply; 66+ 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] 66+ messages in thread

* [PATCH v7 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
                   ` (12 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
  15 siblings, 0 replies; 66+ 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] 66+ 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; 66+ 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] 66+ 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; 66+ 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,
	linux-acpi, Benjamin Tissoires, Bastien Nocera:,
	linux-input

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] 66+ messages in thread

* [PATCH v8 1/2] ACPI / button: Fix an issue in button.lid_init_state=ignore mode
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
                   ` (13 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
  15 siblings, 1 reply; 66+ 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] 66+ messages in thread

* [PATCH v8 2/2] ACPI / button: Add document for ACPI control method lid device restrictions
  2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
                   ` (14 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
  15 siblings, 0 replies; 66+ 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] 66+ 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; 66+ 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] 66+ messages in thread

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

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-17  8:27 [RFC PATCH 1/2] ACPI / button: Send "open" state after boot/resume Lv Zheng
2016-05-17 23:36 ` Rafael J. Wysocki
2016-05-18  1:25   ` Zheng, Lv
2016-05-18 22:56     ` Rafael J. Wysocki
2016-05-19  1:50       ` Zheng, Lv
2016-05-19 13:21         ` Rafael J. Wysocki
2016-05-26 13:31           ` Benjamin Tissoires
2016-05-30  1:39             ` Zheng, Lv
2016-05-18 12:57 ` Bastien Nocera
2016-05-18 21:41   ` Rafael J. Wysocki
2016-05-19  1:59   ` Zheng, Lv
2016-05-27  7:15 ` [PATCH v2 0/3] ACPI / button: Clarify initial lid state Lv Zheng
2016-05-27  7:15   ` [PATCH v2 1/3] ACPI / button: Remove initial lid state notification Lv Zheng
2016-05-27  7:15   ` [PATCH v2 2/3] ACPI / button: Refactor functions to eliminate redundant code Lv Zheng
2016-05-27  7:16   ` [PATCH v2 3/3] ACPI / button: Send "open" state after boot/resume Lv Zheng
2016-05-30  8:10     ` Benjamin Tissoires
2016-05-31  2:55       ` Zheng, Lv
2016-05-31 14:47         ` Benjamin Tissoires
2016-06-01  1:17           ` Zheng, Lv
2016-06-01  7:51             ` Zheng, Lv
2016-06-01  8:07               ` Benjamin Tissoires
2016-05-27 22:10   ` [PATCH v2 0/3] ACPI / button: Clarify initial lid state Valdis.Kletnieks
2016-06-01 10:10 ` [PATCH v3 1/3] ACPI / button: Remove initial lid state notification Lv Zheng
2016-06-23  0:36   ` Rafael J. Wysocki
2016-06-23  0:57     ` Zheng, Lv
2016-06-01 10:10 ` [PATCH v3 2/3] ACPI / button: Refactor functions to eliminate redundant code Lv Zheng
2016-06-01 10:10 ` [PATCH v3 3/3] ACPI / button: Add quirks for initial lid state notification Lv Zheng
2016-06-01 11:01   ` Bastien Nocera
2016-06-02  1:08     ` Zheng, Lv
2016-06-02 14:01       ` Bastien Nocera
2016-06-02 15:25         ` Benjamin Tissoires
2016-06-03  0:41           ` Zheng, Lv
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).