diff mbox

[RFC,v3,3/3] input: i8042: Avoid resetting controller on system suspend/resume

Message ID 3385784.1Q539YNd1G@vostro.rjw.lan
State Not Applicable
Headers show

Commit Message

Rafael J. Wysocki Oct. 6, 2015, 10:53 p.m. UTC
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

If the upcoming system suspend is not going to be handled by the
platform firmware, like in the suspend-to-idle case, it is not
necessary to reset the controller in i8042_pm_suspend(), so avoid
doing that.

Moreover, if the system resume currently in progress has not been
started by the platform firmware, like in the suspend-to-idle case,
i8042_controller_resume() need not be called by i8042_pm_resume(),
so avoid doing that too in that case.

Additionally, try to catch the event that woke up the system by
calling the interrupt handler early during system resume if it has
not been started by the platform firmware.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/input/serio/i8042.c |   15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)


--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Dmitry Torokhov Oct. 6, 2015, 10:34 p.m. UTC | #1
On Wed, Oct 07, 2015 at 12:53:49AM +0200, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> If the upcoming system suspend is not going to be handled by the
> platform firmware, like in the suspend-to-idle case, it is not
> necessary to reset the controller in i8042_pm_suspend(), so avoid
> doing that.
> 
> Moreover, if the system resume currently in progress has not been
> started by the platform firmware, like in the suspend-to-idle case,
> i8042_controller_resume() need not be called by i8042_pm_resume(),
> so avoid doing that too in that case.
> 
> Additionally, try to catch the event that woke up the system by
> calling the interrupt handler early during system resume if it has
> not been started by the platform firmware.
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/input/serio/i8042.c |   15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
> 
> Index: linux-pm/drivers/input/serio/i8042.c
> ===================================================================
> --- linux-pm.orig/drivers/input/serio/i8042.c
> +++ linux-pm/drivers/input/serio/i8042.c
> @@ -24,6 +24,7 @@
>  #include <linux/platform_device.h>
>  #include <linux/i8042.h>
>  #include <linux/slab.h>
> +#include <linux/suspend.h>
>  
>  #include <asm/io.h>
>  
> @@ -1170,7 +1171,8 @@ static int i8042_pm_suspend(struct devic
>  {
>  	int i;
>  
> -	i8042_controller_reset(true);
> +	if (pm_suspend_via_firmware())
> +		i8042_controller_reset(true);
>  
>  	/* Set up serio interrupts for system wakeup. */
>  	for (i = 0; i < I8042_NUM_PORTS; i++) {
> @@ -1183,6 +1185,14 @@ static int i8042_pm_suspend(struct devic
>  	return 0;
>  }
>  
> +static int i8042_pm_resume_noirq(struct device *dev)
> +{
> +	if (!pm_resume_via_firmware())
> +		i8042_interrupt(0, NULL);
> +
> +	return 0;
> +}
> +
>  static int i8042_pm_resume(struct device *dev)
>  {
>  	int i;
> @@ -1199,7 +1209,7 @@ static int i8042_pm_resume(struct device
>  	 * to bring it in a sane state. (In case of S2D we expect
>  	 * BIOS to reset the controller for us.)
>  	 */
> -	return i8042_controller_resume(true);
> +	return pm_resume_via_firmware() ? i8042_controller_resume(true) : 0;

What happens if we were going to suspend via firmware so we reset the
controller but then we got wakeup condition and we actually did not
suspend. What pm_resume_via_firmware() will return in this case?

Thanks.
Dmitry Torokhov Oct. 6, 2015, 10:43 p.m. UTC | #2
On Wed, Oct 07, 2015 at 01:08:30AM +0200, Rafael J. Wysocki wrote:
> On Tuesday, October 06, 2015 03:34:42 PM Dmitry Torokhov wrote:
> > On Wed, Oct 07, 2015 at 12:53:49AM +0200, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > 
> > > If the upcoming system suspend is not going to be handled by the
> > > platform firmware, like in the suspend-to-idle case, it is not
> > > necessary to reset the controller in i8042_pm_suspend(), so avoid
> > > doing that.
> > > 
> > > Moreover, if the system resume currently in progress has not been
> > > started by the platform firmware, like in the suspend-to-idle case,
> > > i8042_controller_resume() need not be called by i8042_pm_resume(),
> > > so avoid doing that too in that case.
> > > 
> > > Additionally, try to catch the event that woke up the system by
> > > calling the interrupt handler early during system resume if it has
> > > not been started by the platform firmware.
> > > 
> > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > ---
> > >  drivers/input/serio/i8042.c |   15 +++++++++++++--
> > >  1 file changed, 13 insertions(+), 2 deletions(-)
> > > 
> > > Index: linux-pm/drivers/input/serio/i8042.c
> > > ===================================================================
> > > --- linux-pm.orig/drivers/input/serio/i8042.c
> > > +++ linux-pm/drivers/input/serio/i8042.c
> > > @@ -24,6 +24,7 @@
> > >  #include <linux/platform_device.h>
> > >  #include <linux/i8042.h>
> > >  #include <linux/slab.h>
> > > +#include <linux/suspend.h>
> > >  
> > >  #include <asm/io.h>
> > >  
> > > @@ -1170,7 +1171,8 @@ static int i8042_pm_suspend(struct devic
> > >  {
> > >  	int i;
> > >  
> > > -	i8042_controller_reset(true);
> > > +	if (pm_suspend_via_firmware())
> > > +		i8042_controller_reset(true);
> > >  
> > >  	/* Set up serio interrupts for system wakeup. */
> > >  	for (i = 0; i < I8042_NUM_PORTS; i++) {
> > > @@ -1183,6 +1185,14 @@ static int i8042_pm_suspend(struct devic
> > >  	return 0;
> > >  }
> > >  
> > > +static int i8042_pm_resume_noirq(struct device *dev)
> > > +{
> > > +	if (!pm_resume_via_firmware())
> > > +		i8042_interrupt(0, NULL);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >  static int i8042_pm_resume(struct device *dev)
> > >  {
> > >  	int i;
> > > @@ -1199,7 +1209,7 @@ static int i8042_pm_resume(struct device
> > >  	 * to bring it in a sane state. (In case of S2D we expect
> > >  	 * BIOS to reset the controller for us.)
> > >  	 */
> > > -	return i8042_controller_resume(true);
> > > +	return pm_resume_via_firmware() ? i8042_controller_resume(true) : 0;
> > 
> > What happens if we were going to suspend via firmware so we reset the
> > controller but then we got wakeup condition and we actually did not
> > suspend. What pm_resume_via_firmware() will return in this case?
> 
> It will return 'false'.  Do we need to resume the controller then?

Yes.

>  But I guess
> 'false' should be passed to i8042_controller_resume() in that case?

Yes, we do not need to reset the controller in this case, just
reactivate multiplexing mode, etc.

Thanks.
Rafael J. Wysocki Oct. 6, 2015, 11:08 p.m. UTC | #3
On Tuesday, October 06, 2015 03:34:42 PM Dmitry Torokhov wrote:
> On Wed, Oct 07, 2015 at 12:53:49AM +0200, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > 
> > If the upcoming system suspend is not going to be handled by the
> > platform firmware, like in the suspend-to-idle case, it is not
> > necessary to reset the controller in i8042_pm_suspend(), so avoid
> > doing that.
> > 
> > Moreover, if the system resume currently in progress has not been
> > started by the platform firmware, like in the suspend-to-idle case,
> > i8042_controller_resume() need not be called by i8042_pm_resume(),
> > so avoid doing that too in that case.
> > 
> > Additionally, try to catch the event that woke up the system by
> > calling the interrupt handler early during system resume if it has
> > not been started by the platform firmware.
> > 
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >  drivers/input/serio/i8042.c |   15 +++++++++++++--
> >  1 file changed, 13 insertions(+), 2 deletions(-)
> > 
> > Index: linux-pm/drivers/input/serio/i8042.c
> > ===================================================================
> > --- linux-pm.orig/drivers/input/serio/i8042.c
> > +++ linux-pm/drivers/input/serio/i8042.c
> > @@ -24,6 +24,7 @@
> >  #include <linux/platform_device.h>
> >  #include <linux/i8042.h>
> >  #include <linux/slab.h>
> > +#include <linux/suspend.h>
> >  
> >  #include <asm/io.h>
> >  
> > @@ -1170,7 +1171,8 @@ static int i8042_pm_suspend(struct devic
> >  {
> >  	int i;
> >  
> > -	i8042_controller_reset(true);
> > +	if (pm_suspend_via_firmware())
> > +		i8042_controller_reset(true);
> >  
> >  	/* Set up serio interrupts for system wakeup. */
> >  	for (i = 0; i < I8042_NUM_PORTS; i++) {
> > @@ -1183,6 +1185,14 @@ static int i8042_pm_suspend(struct devic
> >  	return 0;
> >  }
> >  
> > +static int i8042_pm_resume_noirq(struct device *dev)
> > +{
> > +	if (!pm_resume_via_firmware())
> > +		i8042_interrupt(0, NULL);
> > +
> > +	return 0;
> > +}
> > +
> >  static int i8042_pm_resume(struct device *dev)
> >  {
> >  	int i;
> > @@ -1199,7 +1209,7 @@ static int i8042_pm_resume(struct device
> >  	 * to bring it in a sane state. (In case of S2D we expect
> >  	 * BIOS to reset the controller for us.)
> >  	 */
> > -	return i8042_controller_resume(true);
> > +	return pm_resume_via_firmware() ? i8042_controller_resume(true) : 0;
> 
> What happens if we were going to suspend via firmware so we reset the
> controller but then we got wakeup condition and we actually did not
> suspend. What pm_resume_via_firmware() will return in this case?

It will return 'false'.  Do we need to resume the controller then?  But I guess
'false' should be passed to i8042_controller_resume() in that case?

Rafael

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

Index: linux-pm/drivers/input/serio/i8042.c
===================================================================
--- linux-pm.orig/drivers/input/serio/i8042.c
+++ linux-pm/drivers/input/serio/i8042.c
@@ -24,6 +24,7 @@ 
 #include <linux/platform_device.h>
 #include <linux/i8042.h>
 #include <linux/slab.h>
+#include <linux/suspend.h>
 
 #include <asm/io.h>
 
@@ -1170,7 +1171,8 @@  static int i8042_pm_suspend(struct devic
 {
 	int i;
 
-	i8042_controller_reset(true);
+	if (pm_suspend_via_firmware())
+		i8042_controller_reset(true);
 
 	/* Set up serio interrupts for system wakeup. */
 	for (i = 0; i < I8042_NUM_PORTS; i++) {
@@ -1183,6 +1185,14 @@  static int i8042_pm_suspend(struct devic
 	return 0;
 }
 
+static int i8042_pm_resume_noirq(struct device *dev)
+{
+	if (!pm_resume_via_firmware())
+		i8042_interrupt(0, NULL);
+
+	return 0;
+}
+
 static int i8042_pm_resume(struct device *dev)
 {
 	int i;
@@ -1199,7 +1209,7 @@  static int i8042_pm_resume(struct device
 	 * to bring it in a sane state. (In case of S2D we expect
 	 * BIOS to reset the controller for us.)
 	 */
-	return i8042_controller_resume(true);
+	return pm_resume_via_firmware() ? i8042_controller_resume(true) : 0;
 }
 
 static int i8042_pm_thaw(struct device *dev)
@@ -1223,6 +1233,7 @@  static int i8042_pm_restore(struct devic
 
 static const struct dev_pm_ops i8042_pm_ops = {
 	.suspend	= i8042_pm_suspend,
+	.resume_noirq	= i8042_pm_resume_noirq,
 	.resume		= i8042_pm_resume,
 	.thaw		= i8042_pm_thaw,
 	.poweroff	= i8042_pm_reset,