From patchwork Fri Mar 4 17:01:59 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 350 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:41:53 -0000 Delivered-To: patches@linaro.org Received: by 10.224.60.68 with SMTP id o4cs21441qah; Fri, 4 Mar 2011 09:02:06 -0800 (PST) Received: by 10.216.202.147 with SMTP id d19mr752975weo.23.1299258125579; Fri, 04 Mar 2011 09:02:05 -0800 (PST) Received: from mail-wy0-f178.google.com (mail-wy0-f178.google.com [74.125.82.178]) by mx.google.com with ESMTPS id f60si3505776wej.119.2011.03.04.09.02.05 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 04 Mar 2011 09:02:05 -0800 (PST) Received-SPF: neutral (google.com: 74.125.82.178 is neither permitted nor denied by best guess record for domain of lee.jones@linaro.org) client-ip=74.125.82.178; Authentication-Results: mx.google.com; spf=neutral (google.com: 74.125.82.178 is neither permitted nor denied by best guess record for domain of lee.jones@linaro.org) smtp.mail=lee.jones@linaro.org Received: by mail-wy0-f178.google.com with SMTP id 28so2726741wyf.37 for ; Fri, 04 Mar 2011 09:02:05 -0800 (PST) Received: by 10.227.182.6 with SMTP id ca6mr755651wbb.134.1299258125195; Fri, 04 Mar 2011 09:02:05 -0800 (PST) Received: from [192.168.0.2] (cpc2-aztw21-0-0-cust264.aztw.cable.virginmedia.com [77.100.97.9]) by mx.google.com with ESMTPS id y29sm1008955wbd.10.2011.03.04.09.02.03 (version=SSLv3 cipher=OTHER); Fri, 04 Mar 2011 09:02:04 -0800 (PST) Message-ID: <4D711B07.8050203@linaro.org> Date: Fri, 04 Mar 2011 17:01:59 +0000 From: Lee Jones User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.14) Gecko/20110223 Lightning/1.0b2 Thunderbird/3.1.8 MIME-Version: 1.0 To: patches@linaro.org Subject: [PATCH 2/2] pl011: factor our FIFO to TTY code From: Linus Walleij This piece of code was just slightly different between the DMA and IRQ paths, in DMA mode we surely shouldn't read more than 256 character either, so factor this out in its own function and use for both DMA and PIO mode. Tested on Ux500 and U300. Signed-off-by: Linus Walleij --- drivers/tty/serial/amba-pl011.c | 157 ++++++++++++++++---------------------- 1 files changed, 66 insertions(+), 91 deletions(-) *uap, struct pl011_sgbuf *sgbuf = use_buf_b ? &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a; struct device *dev = uap->dmarx.chan->device->dev; - unsigned int status, ch, flag; int dma_count = 0; u32 fifotaken = 0; /* only used for vdbg() */ @@ -671,56 +726,16 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap, /* * If we read all the DMA'd characters, and we had an - * incomplete buffer, that could be due to an rx error, - * or maybe we just timed out. Read any pending chars - * and check the error status. + * incomplete buffer, that could be due to an rx error, or + * maybe we just timed out. Read any pending chars and check + * the error status. + * + * Error conditions will only occur in the FIFO, these will + * trigger an immediate interrupt and stop the DMA job, so we + * will always find the error in the FIFO, never in the DMA + * buffer. */ - while (1) { - status = readw(uap->port.membase + UART01x_FR); - if (status & UART01x_FR_RXFE) - break; - - /* Take chars from the FIFO and update status */ - ch = readw(uap->port.membase + UART01x_DR) | - UART_DUMMY_DR_RX; - flag = TTY_NORMAL; - uap->port.icount.rx++; - fifotaken++; - - /* - * Error conditions will only occur in the FIFO, - * these will trigger an immediate interrupt and - * stop the DMA job, so we will always find the - * error in the FIFO, never in the DMA buffer. - */ - if (unlikely(ch & UART_DR_ERROR)) { - if (ch & UART011_DR_BE) { - ch &= ~(UART011_DR_FE | UART011_DR_PE); - uap->port.icount.brk++; - if (uart_handle_break(&uap->port)) - continue; - } else if (ch & UART011_DR_PE) - uap->port.icount.parity++; - else if (ch & UART011_DR_FE) - uap->port.icount.frame++; - if (ch & UART011_DR_OE) - uap->port.icount.overrun++; - - ch &= uap->port.read_status_mask; - - if (ch & UART011_DR_BE) - flag = TTY_BREAK; - else if (ch & UART011_DR_PE) - flag = TTY_PARITY; - else if (ch & UART011_DR_FE) - flag = TTY_FRAME; - } - - if (uart_handle_sysrq_char(&uap->port, ch & 255)) - continue; - - uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag); - } + fifotaken = pl011_fifo_to_tty(uap); } spin_unlock(&uap->port.lock); @@ -1036,49 +1051,9 @@ static void pl011_enable_ms(struct uart_port *port) static void pl011_rx_chars(struct uart_amba_port *uap) { struct tty_struct *tty = uap->port.state->port.tty; - unsigned int status, ch, flag, max_count = 256; - status = readw(uap->port.membase + UART01x_FR); - while ((status & UART01x_FR_RXFE) == 0 && max_count--) { - ch = readw(uap->port.membase + UART01x_DR) | UART_DUMMY_DR_RX; - flag = TTY_NORMAL; - uap->port.icount.rx++; + pl011_fifo_to_tty(uap); - /* - * Note that the error handling code is - * out of the main execution path - */ - if (unlikely(ch & UART_DR_ERROR)) { - if (ch & UART011_DR_BE) { - ch &= ~(UART011_DR_FE | UART011_DR_PE); - uap->port.icount.brk++; - if (uart_handle_break(&uap->port)) - goto ignore_char; - } else if (ch & UART011_DR_PE) - uap->port.icount.parity++; - else if (ch & UART011_DR_FE) - uap->port.icount.frame++; - if (ch & UART011_DR_OE) - uap->port.icount.overrun++; - - ch &= uap->port.read_status_mask; - - if (ch & UART011_DR_BE) - flag = TTY_BREAK; - else if (ch & UART011_DR_PE) - flag = TTY_PARITY; - else if (ch & UART011_DR_FE) - flag = TTY_FRAME; - } - - if (uart_handle_sysrq_char(&uap->port, ch & 255)) - goto ignore_char; - - uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag); - - ignore_char: - status = readw(uap->port.membase + UART01x_FR); - } spin_unlock(&uap->port.lock); tty_flip_buffer_push(tty); /* diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index cb45136..faa16ee 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -144,6 +144,62 @@ struct uart_amba_port { }; /* + * Reads up to 256 characters from the FIFO or until it's empty and + * inserts them into the TTY layer. Returns the number of characters + * read from the FIFO. + */ +static int pl011_fifo_to_tty(struct uart_amba_port *uap) +{ + u16 status, ch; + unsigned int flag, max_count = 256; + int fifotaken = 0; + + while (max_count--) { + status = readw(uap->port.membase + UART01x_FR); + if (status & UART01x_FR_RXFE) + break; + + /* Take chars from the FIFO and update status */ + ch = readw(uap->port.membase + UART01x_DR) | + UART_DUMMY_DR_RX; + flag = TTY_NORMAL; + uap->port.icount.rx++; + fifotaken++; + + if (unlikely(ch & UART_DR_ERROR)) { + if (ch & UART011_DR_BE) { + ch &= ~(UART011_DR_FE | UART011_DR_PE); + uap->port.icount.brk++; + if (uart_handle_break(&uap->port)) + continue; + } else if (ch & UART011_DR_PE) + uap->port.icount.parity++; + else if (ch & UART011_DR_FE) + uap->port.icount.frame++; + if (ch & UART011_DR_OE) + uap->port.icount.overrun++; + + ch &= uap->port.read_status_mask; + + if (ch & UART011_DR_BE) + flag = TTY_BREAK; + else if (ch & UART011_DR_PE) + flag = TTY_PARITY; + else if (ch & UART011_DR_FE) + flag = TTY_FRAME; + } + + if (uart_handle_sysrq_char(&uap->port, ch & 255)) + continue; + + uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag); + } + + return fifotaken; +} + + +/* * All the DMA operation mode stuff goes inside this ifdef. * This assumes that you have a generic DMA device interface, * no custom DMA interfaces are supported. @@ -634,7 +690,6 @@ static void pl011_dma_rx_chars(struct uart_amba_port