From patchwork Sat Oct 6 12:43:04 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Russell King X-Patchwork-Id: 1557631 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id BE10C3FD56 for ; Sat, 6 Oct 2012 12:58:45 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TKTvC-0006Ks-55; Sat, 06 Oct 2012 12:55:59 +0000 Received: from [2002:4e20:1eda::1] (helo=caramon.arm.linux.org.uk) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TKTiq-0002s7-5A for linux-arm-kernel@lists.infradead.org; Sat, 06 Oct 2012 12:43:13 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=arm.linux.org.uk; s=caramon; h=Date:Sender:Message-Id:Subject:Cc:To:From:References:In-Reply-To; bh=szuhS99qwjSUAIqJarDgGe5f7KzyPIiAXCXq+ZodjyY=; b=GgjT8kolB7FsEGBFmhmESowJDF3Nx3zJWdZIk1KseSZOsGLKk4+utwm96QB66h6P/304QQDcPardB7HnTPRznnOyngO01+ky1kbRHif6QtPtqpeIFuvmQTrpYQOibRwB2HRAQgLLhDMOMlAJHshZSy9FJozlOVwilIA866tPeNI=; Received: from e0022681537dd.dyn.arm.linux.org.uk ([2002:4e20:1eda:1:222:68ff:fe15:37dd]:39603 helo=rmk-PC.arm.linux.org.uk) by caramon.arm.linux.org.uk with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.76) (envelope-from ) id 1TKTij-00088C-Mv; Sat, 06 Oct 2012 13:43:05 +0100 Received: from rmk by rmk-PC.arm.linux.org.uk with local (Exim 4.76) (envelope-from ) id 1TKTii-0002nC-SV; Sat, 06 Oct 2012 13:43:05 +0100 In-Reply-To: <20121006123803.GD15246@n2100.arm.linux.org.uk> References: <20121006123803.GD15246@n2100.arm.linux.org.uk> From: Russell King To: Tony Lindgren , Alan Cox , Greg Kroah-Hartman Subject: [RFC 12/24] SERIAL: omap: fix hardware assisted flow control Message-Id: Date: Sat, 06 Oct 2012 13:43:04 +0100 X-Bad-Reply: References and In-Reply-To but no 'Re:' in Subject. X-Spam-Note: CRM114 invocation failed X-Spam-Score: -1.2 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.8 RDNS_NONE Delivered to internal network by a host with no rDNS X-Mailman-Approved-At: Sat, 06 Oct 2012 08:53:03 -0400 Cc: linux-omap@vger.kernel.org, linux-serial@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org When the UART device has hardware flow control enabled, it ignores the MCR RTS bit in the MCR register, and keeps RTS asserted as long as we continue to read characters from the UART receiver FIFO. This means that when the TTY buffers become full, the UART doesn't tell the remote end to stop sending, which causes the TTY layer to start dropping characters. A similar problem exists with software flow control. We need the FIFO register to fill when software flow control is enabled to provoke the UART to send the XOFF character. Fix this by implementing the throttle/unthrottle callbacks, and use these to disable receiver interrupts. This in turn means that the UART FIFO will fill, which will then cause the UART's hardware to deassert the RTS signal and/or send the XOFF character, stopping the remote end. Signed-off-by: Russell King --- drivers/tty/serial/omap-serial.c | 31 +++++++++++++++++++++++++++++++ 1 files changed, 31 insertions(+), 0 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 6314827..ab5a5e0 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -373,6 +373,34 @@ static void serial_omap_start_tx(struct uart_port *port) omap_start_dma(up->uart_dma.tx_dma_channel); } +static void serial_omap_throttle(struct uart_port *port) +{ + struct uart_omap_port *up = (struct uart_omap_port *)port; + unsigned long flags; + + pm_runtime_get_sync(&up->pdev->dev); + spin_lock_irqsave(&up->port.lock, flags); + up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); + serial_out(up, UART_IER, up->ier); + spin_unlock_irqrestore(&up->port.lock, flags); + pm_runtime_mark_last_busy(&up->pdev->dev); + pm_runtime_put_autosuspend(&up->pdev->dev); +} + +static void serial_omap_unthrottle(struct uart_port *port) +{ + struct uart_omap_port *up = (struct uart_omap_port *)port; + unsigned long flags; + + pm_runtime_get_sync(&up->pdev->dev); + spin_lock_irqsave(&up->port.lock, flags); + up->ier |= UART_IER_RLSI | UART_IER_RDI; + serial_out(up, UART_IER, up->ier); + spin_unlock_irqrestore(&up->port.lock, flags); + pm_runtime_mark_last_busy(&up->pdev->dev); + pm_runtime_put_autosuspend(&up->pdev->dev); +} + static unsigned int check_modem_status(struct uart_omap_port *up) { unsigned int status; @@ -985,6 +1013,7 @@ static void serial_omap_config_port(struct uart_port *port, int flags) dev_dbg(up->port.dev, "serial_omap_config_port+%d\n", up->port.line); up->port.type = PORT_OMAP; + up->port.flags |= UPF_SOFT_FLOW | UPF_HARD_FLOW; } static int @@ -1181,6 +1210,8 @@ static struct uart_ops serial_omap_pops = { .get_mctrl = serial_omap_get_mctrl, .stop_tx = serial_omap_stop_tx, .start_tx = serial_omap_start_tx, + .throttle = serial_omap_throttle, + .unthrottle = serial_omap_unthrottle, .stop_rx = serial_omap_stop_rx, .enable_ms = serial_omap_enable_ms, .break_ctl = serial_omap_break_ctl,