From: Boris Brezillon <boris.brezillon@free-electrons.com> To: Thomas Gleixner <tglx@linutronix.de>, Jason Cooper <jason@lakedaemon.net>, Peter Zijlstra <peterz@infradead.org>, Mark Rutland <mark.rutland@arm.com>, "Rafael J. Wysocki" <rjw@rjwysocki.net> Cc: Len Brown <len.brown@intel.com>, Pavel Machek <pavel@ucw.cz>, linux-pm@vger.kernel.org, Wim Van Sebroeck <wim@iguana.be>, linux-watchdog@vger.kernel.org, Alessandro Zummo <a.zummo@towertech.it>, rtc-linux@googlegroups.com, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Jiri Slaby <jslaby@suse.cz>, linux-serial@vger.kernel.org, Mike Turquette <mturquette@linaro.org>, linux-kernel@vger.kernel.org, Nicolas Ferre <nicolas.ferre@atmel.com>, Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>, Alexandre Belloni <alexandre.belloni@free-electrons.com>, linux-arm-kernel@lists.infradead.org, Boris Brezillon <boris.brezillon@free-electrons.com> Subject: [PATCH v2 6/6] tty: serial: atmel: rework interrupt and wakeup handling Date: Mon, 2 Mar 2015 10:18:18 +0100 [thread overview] Message-ID: <1425287898-15093-7-git-send-email-boris.brezillon@free-electrons.com> (raw) In-Reply-To: <1425287898-15093-1-git-send-email-boris.brezillon@free-electrons.com> The IRQ line connected to the DBGU UART is often shared with a timer device which request the IRQ with IRQF_NO_SUSPEND. Since the UART driver is correctly disabling IRQs when entering suspend we can safely request the IRQ with IRQF_COND_SUSPEND so that irq core will not complain about mixing IRQF_NO_SUSPEND and !IRQF_NO_SUSPEND. Rework the interrupt handler to wake the system up when an interrupt happens on the DEBUG_UART while the system is suspended. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> --- drivers/tty/serial/atmel_serial.c | 49 +++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 846552b..4e959c4 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -47,6 +47,7 @@ #include <linux/gpio/consumer.h> #include <linux/err.h> #include <linux/irq.h> +#include <linux/suspend.h> #include <asm/io.h> #include <asm/ioctls.h> @@ -173,6 +174,12 @@ struct atmel_uart_port { bool ms_irq_enabled; bool is_usart; /* usart or uart */ struct timer_list uart_timer; /* uart timer */ + + bool suspended; + unsigned int pending; + unsigned int pending_status; + spinlock_t lock_suspended; + int (*prepare_rx)(struct uart_port *port); int (*prepare_tx)(struct uart_port *port); void (*schedule_rx)(struct uart_port *port); @@ -1179,12 +1186,15 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) { struct uart_port *port = dev_id; struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - unsigned int status, pending, pass_counter = 0; + unsigned int status, pending, mask, pass_counter = 0; bool gpio_handled = false; + spin_lock(&atmel_port->lock_suspended); + do { status = atmel_get_lines_status(port); - pending = status & UART_GET_IMR(port); + mask = UART_GET_IMR(port); + pending = status & mask; if (!gpio_handled) { /* * Dealing with GPIO interrupt @@ -1206,11 +1216,21 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) if (!pending) break; + if (atmel_port->suspended) { + atmel_port->pending |= pending; + atmel_port->pending_status = status; + UART_PUT_IDR(port, mask); + pm_system_wakeup(); + break; + } + atmel_handle_receive(port, pending); atmel_handle_status(port, pending, status); atmel_handle_transmit(port, pending); } while (pass_counter++ < ATMEL_ISR_PASS_LIMIT); + spin_unlock(&atmel_port->lock_suspended); + return pass_counter ? IRQ_HANDLED : IRQ_NONE; } @@ -1742,7 +1762,8 @@ static int atmel_startup(struct uart_port *port) /* * Allocate the IRQ */ - retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED, + retval = request_irq(port->irq, atmel_interrupt, + IRQF_SHARED | IRQF_COND_SUSPEND, tty ? tty->name : "atmel_serial", port); if (retval) { dev_err(port->dev, "atmel_startup - Can't get irq\n"); @@ -2513,8 +2534,14 @@ static int atmel_serial_suspend(struct platform_device *pdev, /* we can not wake up if we're running on slow clock */ atmel_port->may_wakeup = device_may_wakeup(&pdev->dev); - if (atmel_serial_clk_will_stop()) + if (atmel_serial_clk_will_stop()) { + unsigned long flags; + + spin_lock_irqsave(&atmel_port->lock_suspended, flags); + atmel_port->suspended = true; + spin_unlock_irqrestore(&atmel_port->lock_suspended, flags); device_set_wakeup_enable(&pdev->dev, 0); + } uart_suspend_port(&atmel_uart, port); @@ -2525,6 +2552,18 @@ static int atmel_serial_resume(struct platform_device *pdev) { struct uart_port *port = platform_get_drvdata(pdev); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + unsigned long flags; + + spin_lock_irqsave(&atmel_port->lock_suspended, flags); + if (atmel_port->pending) { + atmel_handle_receive(port, atmel_port->pending); + atmel_handle_status(port, atmel_port->pending, + atmel_port->pending_status); + atmel_handle_transmit(port, atmel_port->pending); + atmel_port->pending = 0; + } + atmel_port->suspended = false; + spin_unlock_irqrestore(&atmel_port->lock_suspended, flags); uart_resume_port(&atmel_uart, port); device_set_wakeup_enable(&pdev->dev, atmel_port->may_wakeup); @@ -2593,6 +2632,8 @@ static int atmel_serial_probe(struct platform_device *pdev) port->backup_imr = 0; port->uart.line = ret; + spin_lock_init(&port->lock_suspended); + ret = atmel_init_gpios(port, &pdev->dev); if (ret < 0) dev_err(&pdev->dev, "%s", -- 1.9.1
WARNING: multiple messages have this Message-ID (diff)
From: boris.brezillon@free-electrons.com (Boris Brezillon) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 6/6] tty: serial: atmel: rework interrupt and wakeup handling Date: Mon, 2 Mar 2015 10:18:18 +0100 [thread overview] Message-ID: <1425287898-15093-7-git-send-email-boris.brezillon@free-electrons.com> (raw) In-Reply-To: <1425287898-15093-1-git-send-email-boris.brezillon@free-electrons.com> The IRQ line connected to the DBGU UART is often shared with a timer device which request the IRQ with IRQF_NO_SUSPEND. Since the UART driver is correctly disabling IRQs when entering suspend we can safely request the IRQ with IRQF_COND_SUSPEND so that irq core will not complain about mixing IRQF_NO_SUSPEND and !IRQF_NO_SUSPEND. Rework the interrupt handler to wake the system up when an interrupt happens on the DEBUG_UART while the system is suspended. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> --- drivers/tty/serial/atmel_serial.c | 49 +++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 846552b..4e959c4 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -47,6 +47,7 @@ #include <linux/gpio/consumer.h> #include <linux/err.h> #include <linux/irq.h> +#include <linux/suspend.h> #include <asm/io.h> #include <asm/ioctls.h> @@ -173,6 +174,12 @@ struct atmel_uart_port { bool ms_irq_enabled; bool is_usart; /* usart or uart */ struct timer_list uart_timer; /* uart timer */ + + bool suspended; + unsigned int pending; + unsigned int pending_status; + spinlock_t lock_suspended; + int (*prepare_rx)(struct uart_port *port); int (*prepare_tx)(struct uart_port *port); void (*schedule_rx)(struct uart_port *port); @@ -1179,12 +1186,15 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) { struct uart_port *port = dev_id; struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - unsigned int status, pending, pass_counter = 0; + unsigned int status, pending, mask, pass_counter = 0; bool gpio_handled = false; + spin_lock(&atmel_port->lock_suspended); + do { status = atmel_get_lines_status(port); - pending = status & UART_GET_IMR(port); + mask = UART_GET_IMR(port); + pending = status & mask; if (!gpio_handled) { /* * Dealing with GPIO interrupt @@ -1206,11 +1216,21 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) if (!pending) break; + if (atmel_port->suspended) { + atmel_port->pending |= pending; + atmel_port->pending_status = status; + UART_PUT_IDR(port, mask); + pm_system_wakeup(); + break; + } + atmel_handle_receive(port, pending); atmel_handle_status(port, pending, status); atmel_handle_transmit(port, pending); } while (pass_counter++ < ATMEL_ISR_PASS_LIMIT); + spin_unlock(&atmel_port->lock_suspended); + return pass_counter ? IRQ_HANDLED : IRQ_NONE; } @@ -1742,7 +1762,8 @@ static int atmel_startup(struct uart_port *port) /* * Allocate the IRQ */ - retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED, + retval = request_irq(port->irq, atmel_interrupt, + IRQF_SHARED | IRQF_COND_SUSPEND, tty ? tty->name : "atmel_serial", port); if (retval) { dev_err(port->dev, "atmel_startup - Can't get irq\n"); @@ -2513,8 +2534,14 @@ static int atmel_serial_suspend(struct platform_device *pdev, /* we can not wake up if we're running on slow clock */ atmel_port->may_wakeup = device_may_wakeup(&pdev->dev); - if (atmel_serial_clk_will_stop()) + if (atmel_serial_clk_will_stop()) { + unsigned long flags; + + spin_lock_irqsave(&atmel_port->lock_suspended, flags); + atmel_port->suspended = true; + spin_unlock_irqrestore(&atmel_port->lock_suspended, flags); device_set_wakeup_enable(&pdev->dev, 0); + } uart_suspend_port(&atmel_uart, port); @@ -2525,6 +2552,18 @@ static int atmel_serial_resume(struct platform_device *pdev) { struct uart_port *port = platform_get_drvdata(pdev); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + unsigned long flags; + + spin_lock_irqsave(&atmel_port->lock_suspended, flags); + if (atmel_port->pending) { + atmel_handle_receive(port, atmel_port->pending); + atmel_handle_status(port, atmel_port->pending, + atmel_port->pending_status); + atmel_handle_transmit(port, atmel_port->pending); + atmel_port->pending = 0; + } + atmel_port->suspended = false; + spin_unlock_irqrestore(&atmel_port->lock_suspended, flags); uart_resume_port(&atmel_uart, port); device_set_wakeup_enable(&pdev->dev, atmel_port->may_wakeup); @@ -2593,6 +2632,8 @@ static int atmel_serial_probe(struct platform_device *pdev) port->backup_imr = 0; port->uart.line = ret; + spin_lock_init(&port->lock_suspended); + ret = atmel_init_gpios(port, &pdev->dev); if (ret < 0) dev_err(&pdev->dev, "%s", -- 1.9.1
next prev parent reply other threads:[~2015-03-02 9:19 UTC|newest] Thread overview: 180+ messages / expand[flat|nested] mbox.gz Atom feed top 2015-03-02 9:18 [PATCH v2 0/6] ARM: at91: fix irq_pm_install_action WARNING Boris Brezillon 2015-03-02 9:18 ` Boris Brezillon 2015-03-02 9:18 ` Boris Brezillon 2015-03-02 9:18 ` [PATCH v2 1/6] PM / wakeup: export pm_system_wakeup symbol Boris Brezillon 2015-03-02 9:18 ` Boris Brezillon 2015-03-02 9:18 ` [PATCH v2 2/6] rtc: at91sam9: rework wakeup and interrupt handling Boris Brezillon 2015-03-02 9:18 ` Boris Brezillon 2015-03-02 9:18 ` Boris Brezillon 2015-03-04 18:23 ` Mark Rutland 2015-03-04 18:23 ` Mark Rutland 2015-03-04 18:23 ` Mark Rutland 2015-03-04 18:23 ` Mark Rutland 2015-03-02 9:18 ` [PATCH v2 3/6] rtc: at91rm9200: " Boris Brezillon 2015-03-02 9:18 ` Boris Brezillon 2015-03-02 9:18 ` [PATCH v2 4/6] clk: at91: implement suspend/resume for the PMC irqchip Boris Brezillon 2015-03-02 9:18 ` Boris Brezillon 2015-03-02 9:18 ` Boris Brezillon 2015-03-09 22:34 ` Mike Turquette 2015-03-09 22:34 ` Mike Turquette 2015-03-09 22:34 ` Mike Turquette 2015-03-09 22:34 ` Mike Turquette 2015-03-02 9:18 ` [PATCH v2 5/6] watchdog: at91sam9: request the irq with IRQF_NO_SUSPEND Boris Brezillon 2015-03-02 9:18 ` Boris Brezillon 2015-03-02 9:18 ` Boris Brezillon 2015-03-02 14:10 ` Guenter Roeck 2015-03-02 14:10 ` Guenter Roeck 2015-03-04 18:38 ` Mark Rutland 2015-03-04 18:38 ` Mark Rutland 2015-03-04 18:38 ` Mark Rutland 2015-03-04 18:38 ` Mark Rutland 2015-03-04 21:41 ` Rafael J. Wysocki 2015-03-04 21:41 ` Rafael J. Wysocki 2015-03-04 21:41 ` Rafael J. Wysocki 2015-03-04 21:41 ` Rafael J. Wysocki 2015-03-05 10:57 ` Mark Rutland 2015-03-05 10:57 ` Mark Rutland 2015-03-05 10:57 ` Mark Rutland 2015-03-05 10:57 ` Mark Rutland 2015-03-05 15:10 ` Rafael J. Wysocki 2015-03-05 15:10 ` Rafael J. Wysocki 2015-03-05 15:10 ` Rafael J. Wysocki 2015-03-05 15:10 ` Rafael J. Wysocki 2015-03-05 16:32 ` Mark Rutland 2015-03-05 16:32 ` Mark Rutland 2015-03-05 16:32 ` Mark Rutland 2015-03-05 16:32 ` Mark Rutland 2015-03-06 0:29 ` Rafael J. Wysocki 2015-03-06 0:29 ` Rafael J. Wysocki 2015-03-06 0:29 ` Rafael J. Wysocki 2015-03-06 0:29 ` Rafael J. Wysocki 2015-03-06 11:06 ` Mark Rutland 2015-03-06 11:06 ` Mark Rutland 2015-03-06 11:06 ` Mark Rutland 2015-03-06 11:06 ` Mark Rutland 2015-03-06 12:39 ` Rafael J. Wysocki 2015-03-06 12:39 ` Rafael J. Wysocki 2015-03-06 12:39 ` Rafael J. Wysocki 2015-03-06 12:39 ` Rafael J. Wysocki 2015-03-06 13:10 ` Mark Rutland 2015-03-06 13:10 ` Mark Rutland 2015-03-06 13:10 ` Mark Rutland 2015-03-06 13:10 ` Mark Rutland 2015-03-07 9:12 ` Peter Zijlstra 2015-03-07 9:12 ` Peter Zijlstra 2015-03-07 9:12 ` Peter Zijlstra 2015-03-07 9:12 ` Peter Zijlstra 2015-03-07 9:06 ` Peter Zijlstra 2015-03-07 9:06 ` Peter Zijlstra 2015-03-07 9:06 ` Peter Zijlstra 2015-03-07 9:06 ` Peter Zijlstra 2015-03-05 8:53 ` Boris Brezillon 2015-03-05 8:53 ` Boris Brezillon 2015-03-05 8:53 ` Boris Brezillon 2015-03-05 8:53 ` Boris Brezillon 2015-03-05 10:53 ` Mark Rutland 2015-03-05 10:53 ` Mark Rutland 2015-03-05 10:53 ` Mark Rutland 2015-03-05 10:53 ` Mark Rutland 2015-03-05 11:17 ` Boris Brezillon 2015-03-05 11:17 ` Boris Brezillon 2015-03-05 11:17 ` Boris Brezillon 2015-03-05 11:17 ` Boris Brezillon 2015-03-05 11:31 ` Boris Brezillon 2015-03-05 11:31 ` Boris Brezillon 2015-03-05 11:31 ` Boris Brezillon 2015-03-05 11:31 ` Boris Brezillon 2015-03-05 11:53 ` Mark Rutland 2015-03-05 11:53 ` Mark Rutland 2015-03-05 11:53 ` Mark Rutland 2015-03-05 11:53 ` Mark Rutland 2015-03-07 9:18 ` Peter Zijlstra 2015-03-07 9:18 ` Peter Zijlstra 2015-03-07 9:18 ` Peter Zijlstra 2015-03-07 9:18 ` Peter Zijlstra 2015-03-07 10:20 ` Sylvain Rochet 2015-03-07 10:20 ` Sylvain Rochet 2015-03-07 10:20 ` Sylvain Rochet 2015-03-07 10:20 ` Sylvain Rochet 2015-03-07 10:39 ` Pavel Machek 2015-03-07 10:39 ` Pavel Machek 2015-03-07 10:39 ` Pavel Machek 2015-03-07 10:39 ` Pavel Machek 2015-03-07 10:59 ` Sylvain Rochet 2015-03-07 10:59 ` Sylvain Rochet 2015-03-07 10:59 ` Sylvain Rochet 2015-03-07 10:59 ` Sylvain Rochet 2015-03-07 11:06 ` Alexandre Belloni 2015-03-07 11:06 ` Alexandre Belloni 2015-03-07 11:06 ` Alexandre Belloni 2015-03-07 11:06 ` Alexandre Belloni 2015-03-07 11:29 ` Pavel Machek 2015-03-07 11:29 ` Pavel Machek 2015-03-07 11:29 ` Pavel Machek 2015-03-07 11:29 ` Pavel Machek 2015-03-07 11:46 ` Sylvain Rochet 2015-03-07 11:46 ` Sylvain Rochet 2015-03-07 11:46 ` Sylvain Rochet 2015-03-07 11:46 ` Sylvain Rochet 2015-03-08 1:12 ` Rafael J. Wysocki 2015-03-08 1:12 ` Rafael J. Wysocki 2015-03-08 1:12 ` Rafael J. Wysocki 2015-03-08 1:12 ` Rafael J. Wysocki 2015-03-09 7:55 ` Alexandre Belloni 2015-03-09 7:55 ` Alexandre Belloni 2015-03-09 7:55 ` Alexandre Belloni 2015-03-09 7:55 ` Alexandre Belloni 2015-03-09 14:30 ` Rafael J. Wysocki 2015-03-09 14:30 ` Rafael J. Wysocki 2015-03-09 14:30 ` Rafael J. Wysocki 2015-03-09 14:30 ` Rafael J. Wysocki 2015-03-10 21:33 ` Alexandre Belloni 2015-03-10 21:33 ` Alexandre Belloni 2015-03-10 21:33 ` Alexandre Belloni 2015-03-10 21:33 ` Alexandre Belloni 2015-03-10 22:31 ` Rafael J. Wysocki 2015-03-10 22:31 ` Rafael J. Wysocki 2015-03-10 22:31 ` Rafael J. Wysocki 2015-03-10 22:31 ` Rafael J. Wysocki 2015-03-10 22:33 ` Alexandre Belloni 2015-03-10 22:33 ` Alexandre Belloni 2015-03-10 22:33 ` Alexandre Belloni 2015-03-10 22:33 ` Alexandre Belloni 2015-03-11 1:03 ` Rafael J. Wysocki 2015-03-11 1:03 ` Rafael J. Wysocki 2015-03-11 1:03 ` Rafael J. Wysocki 2015-03-11 1:03 ` Rafael J. Wysocki 2015-03-11 7:33 ` Boris Brezillon 2015-03-11 7:33 ` Boris Brezillon 2015-03-11 7:33 ` Boris Brezillon 2015-03-11 7:33 ` Boris Brezillon 2015-03-08 1:11 ` Rafael J. Wysocki 2015-03-08 1:11 ` Rafael J. Wysocki 2015-03-08 1:11 ` Rafael J. Wysocki 2015-03-08 1:11 ` Rafael J. Wysocki 2015-03-11 8:38 ` Boris Brezillon 2015-03-11 8:38 ` Boris Brezillon 2015-03-11 8:38 ` Boris Brezillon 2015-03-11 8:38 ` Boris Brezillon 2015-03-11 11:17 ` Nicolas Ferre 2015-03-11 11:17 ` Nicolas Ferre 2015-03-11 11:17 ` Nicolas Ferre 2015-03-11 11:17 ` Nicolas Ferre 2015-03-11 11:17 ` Nicolas Ferre 2015-03-02 9:18 ` Boris Brezillon [this message] 2015-03-02 9:18 ` [PATCH v2 6/6] tty: serial: atmel: rework interrupt and wakeup handling Boris Brezillon 2015-03-03 8:56 ` [PATCH v2 0/6] ARM: at91: fix irq_pm_install_action WARNING Alexandre Belloni 2015-03-03 8:56 ` Alexandre Belloni 2015-03-03 8:56 ` Alexandre Belloni 2015-03-03 15:35 ` Nicolas Ferre 2015-03-03 15:35 ` Nicolas Ferre 2015-03-03 15:35 ` Nicolas Ferre 2015-03-03 15:35 ` Nicolas Ferre 2015-03-04 1:43 ` Rafael J. Wysocki 2015-03-04 1:43 ` Rafael J. Wysocki 2015-03-04 1:43 ` Rafael J. Wysocki 2015-03-04 1:43 ` Rafael J. Wysocki 2015-03-04 18:43 ` Mark Rutland 2015-03-04 18:43 ` Mark Rutland 2015-03-04 18:43 ` Mark Rutland 2015-03-04 18:43 ` Mark Rutland
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1425287898-15093-7-git-send-email-boris.brezillon@free-electrons.com \ --to=boris.brezillon@free-electrons.com \ --cc=a.zummo@towertech.it \ --cc=alexandre.belloni@free-electrons.com \ --cc=gregkh@linuxfoundation.org \ --cc=jason@lakedaemon.net \ --cc=jslaby@suse.cz \ --cc=len.brown@intel.com \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-pm@vger.kernel.org \ --cc=linux-serial@vger.kernel.org \ --cc=linux-watchdog@vger.kernel.org \ --cc=mark.rutland@arm.com \ --cc=mturquette@linaro.org \ --cc=nicolas.ferre@atmel.com \ --cc=pavel@ucw.cz \ --cc=peterz@infradead.org \ --cc=plagnioj@jcrosoft.com \ --cc=rjw@rjwysocki.net \ --cc=rtc-linux@googlegroups.com \ --cc=tglx@linutronix.de \ --cc=wim@iguana.be \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.