[3.13.y.z extended stable] Patch "serial: omap: Fix missing pm_runtime_resume handling by simplifying code" has been added to staging queue

Kamal Mostafa kamal at canonical.com
Tue Jun 10 16:37:36 UTC 2014


This is a note to let you know that I have just added a patch titled

    serial: omap: Fix missing pm_runtime_resume handling by simplifying code

to the linux-3.13.y-queue branch of the 3.13.y.z extended stable tree 
which can be found at:

 http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.13.y-queue

This patch is scheduled to be released in version 3.13.11.3.

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.13.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Kamal

------

>From 62a983dc812008a93f4340100122e2a043c70b45 Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony at atomide.com>
Date: Tue, 25 Mar 2014 11:48:47 -0700
Subject: serial: omap: Fix missing pm_runtime_resume handling by simplifying
 code

commit d758c9c1b36b4d9a141c2146c70398d756167ed1 upstream.

The lack of pm_runtime_resume handling for the device state leads into
device wake-up interrupts not working after a while for runtime PM.

Also, serial-omap is confused about the use of device_may_wakeup.
The checks for device_may_wakeup should only be done for suspend and
resume, not for pm_runtime_suspend and pm_runtime_resume. The wake-up
events for PM runtime should always be enabled.

The lack of pm_runtime_resume handling leads into device wake-up
interrupts not working after a while for runtime PM.

Rather than try to patch over the issue of adding complex tests to
the pm_runtime_resume, let's fix the issues properly:

1. Make serial_omap_enable_wakeup deal with all internal PM state
   handling so we don't need to test for up->wakeups_enabled elsewhere.

   Later on once omap3 boots in device tree only mode we can also
   remove the up->wakeups_enabled flag and rely on the wake-up
   interrupt enable/disable state alone.

2. Do the device_may_wakeup checks in suspend and resume only,
   for runtime PM the wake-up events need to be always enabled.

3. Finally just call serial_omap_enable_wakeup and make sure we
   call it also in pm_runtime_resume.

4. Note that we also have to use disable_irq_nosync as serial_omap_irq
   calls pm_runtime_get_sync.

Fixes: 2a0b965cfb6e (serial: omap: Add support for optional wake-up)
Signed-off-by: Tony Lindgren <tony at atomide.com>
Acked-by: Felipe Balbi <balbi at ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
---
 drivers/tty/serial/omap-serial.c | 29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 2051581..f5d0720 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -225,14 +225,19 @@ static inline void serial_omap_enable_wakeirq(struct uart_omap_port *up,
 	if (enable)
 		enable_irq(up->wakeirq);
 	else
-		disable_irq(up->wakeirq);
+		disable_irq_nosync(up->wakeirq);
 }

 static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
 {
 	struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);

+	if (enable == up->wakeups_enabled)
+		return;
+
 	serial_omap_enable_wakeirq(up, enable);
+	up->wakeups_enabled = enable;
+
 	if (!pdata || !pdata->enable_wakeup)
 		return;

@@ -1488,6 +1493,11 @@ static int serial_omap_suspend(struct device *dev)
 	uart_suspend_port(&serial_omap_reg, &up->port);
 	flush_work(&up->qos_work);

+	if (device_may_wakeup(dev))
+		serial_omap_enable_wakeup(up, true);
+	else
+		serial_omap_enable_wakeup(up, false);
+
 	return 0;
 }

@@ -1495,6 +1505,9 @@ static int serial_omap_resume(struct device *dev)
 {
 	struct uart_omap_port *up = dev_get_drvdata(dev);

+	if (device_may_wakeup(dev))
+		serial_omap_enable_wakeup(up, false);
+
 	uart_resume_port(&serial_omap_reg, &up->port);

 	return 0;
@@ -1867,17 +1880,7 @@ static int serial_omap_runtime_suspend(struct device *dev)

 	up->context_loss_cnt = serial_omap_get_context_loss_count(up);

-	if (device_may_wakeup(dev)) {
-		if (!up->wakeups_enabled) {
-			serial_omap_enable_wakeup(up, true);
-			up->wakeups_enabled = true;
-		}
-	} else {
-		if (up->wakeups_enabled) {
-			serial_omap_enable_wakeup(up, false);
-			up->wakeups_enabled = false;
-		}
-	}
+	serial_omap_enable_wakeup(up, true);

 	up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
 	schedule_work(&up->qos_work);
@@ -1891,6 +1894,8 @@ static int serial_omap_runtime_resume(struct device *dev)

 	int loss_cnt = serial_omap_get_context_loss_count(up);

+	serial_omap_enable_wakeup(up, false);
+
 	if (loss_cnt < 0) {
 		dev_dbg(dev, "serial_omap_get_context_loss_count failed : %d\n",
 			loss_cnt);
--
1.9.1





More information about the kernel-team mailing list