Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759770AbbKTOHG (ORCPT ); Fri, 20 Nov 2015 09:07:06 -0500 Received: from mail-bl2nam02on0048.outbound.protection.outlook.com ([104.47.38.48]:6144 "EHLO NAM02-BL2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1758649AbbKTOHC (ORCPT ); Fri, 20 Nov 2015 09:07:02 -0500 X-Greylist: delayed 1036 seconds by postgrey-1.27 at vger.kernel.org; Fri, 20 Nov 2015 09:07:01 EST Authentication-Results: spf=pass (sender IP is 149.199.60.83) smtp.mailfrom=xilinx.com; vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=bestguesspass action=none header.from=xilinx.com; From: Nava kishore Manne To: , , , CC: , , , Nava kishore Manne Subject: [PATCH v2 1/3] serial: xuartps: Spliting the ISR into smaller routines. Date: Fri, 20 Nov 2015 19:04:36 +0530 Message-ID: <1448026478-22131-1-git-send-email-navam@xilinx.com> X-Mailer: git-send-email 2.1.2 X-RCIS-Action: ALLOW X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.0.0.1202-21952.006 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:149.199.60.83;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(438002)(189002)(199003)(5008740100001)(90966002)(92566002)(36756003)(50466002)(46386002)(586003)(48376002)(87936001)(45336002)(5007970100001)(2201001)(6806005)(42186005)(52956003)(63266004)(4001430100002)(36386004)(103686003)(50986999)(106466001)(33646002)(19580405001)(50226001)(229853001)(19580395003)(5001920100001)(11100500001)(5001960100002)(4001450100002)(575784001)(107886002)(86362001)(47776003)(81156007)(5003940100001)(5001770100001)(189998001)(107986001);DIR:OUT;SFP:1101;SCL:1;SRVR:SN1NAM02HT002;H:xsj-pvapsmtpgw01;FPR:;SPF:Pass;PTR:unknown-60-83.xilinx.com;MX:1;A:1;LANG:en; MIME-Version: 1.0 Content-Type: text/plain X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(8251501001);SRVR:SN1NAM02HT002; X-Microsoft-Antispam-PRVS: <71f14a5e92a840e3a0fdbf61cb8566ea@SN1NAM02HT002.eop-nam02.prod.protection.outlook.com> X-Exchange-Antispam-Report-Test: UriScan:(192813158149592); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(520078)(5005006)(8121501046)(3002001)(10201501046);SRVR:SN1NAM02HT002;BCL:0;PCL:0;RULEID:;SRVR:SN1NAM02HT002; X-Forefront-PRVS: 07665BE9D1 X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Nov 2015 13:34:51.2938 (UTC) X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c;Ip=[149.199.60.83];Helo=[xsj-pvapsmtpgw01] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1NAM02HT002 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 9033 Lines: 300 Breaking the single big ISR that has both Rx and Tx in a single function into smaller ones Signed-off-by: Nava kishore Manne --- Changes for v2: --Splits up the ISR without any functional changes as suggested by Peter Hurley drivers/tty/serial/xilinx_uartps.c | 247 ++++++++++++++++++++----------------- 1 file changed, 135 insertions(+), 112 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 009e0db..2e1b0a8 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -172,6 +172,9 @@ struct cdns_uart { #define to_cdns_uart(_nb) container_of(_nb, struct cdns_uart, \ clk_rate_change_nb); +static void cdns_uart_handle_tx(void *dev_id); +static void cdns_uart_handle_rx(void *dev_id, unsigned int isrstatus); + /** * cdns_uart_isr - Interrupt handler * @irq: Irq number @@ -183,9 +186,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) { struct uart_port *port = (struct uart_port *)dev_id; unsigned long flags; - unsigned int isrstatus, numbytes; - unsigned int data; - char status = TTY_NORMAL; + unsigned int isrstatus; spin_lock_irqsave(&port->lock, flags); @@ -194,116 +195,12 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) */ isrstatus = readl(port->membase + CDNS_UART_ISR_OFFSET); - /* - * There is no hardware break detection, so we interpret framing - * error with all-zeros data as a break sequence. Most of the time, - * there's another non-zero byte at the end of the sequence. - */ - if (isrstatus & CDNS_UART_IXR_FRAMING) { - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & - CDNS_UART_SR_RXEMPTY)) { - if (!readl(port->membase + CDNS_UART_FIFO_OFFSET)) { - port->read_status_mask |= CDNS_UART_IXR_BRK; - isrstatus &= ~CDNS_UART_IXR_FRAMING; - } - } - writel(CDNS_UART_IXR_FRAMING, - port->membase + CDNS_UART_ISR_OFFSET); - } - - /* drop byte with parity error if IGNPAR specified */ - if (isrstatus & port->ignore_status_mask & CDNS_UART_IXR_PARITY) - isrstatus &= ~(CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT); - - isrstatus &= port->read_status_mask; - isrstatus &= ~port->ignore_status_mask; - - if ((isrstatus & CDNS_UART_IXR_TOUT) || - (isrstatus & CDNS_UART_IXR_RXTRIG)) { - /* Receive Timeout Interrupt */ - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & - CDNS_UART_SR_RXEMPTY)) { - data = readl(port->membase + CDNS_UART_FIFO_OFFSET); - - /* Non-NULL byte after BREAK is garbage (99%) */ - if (data && (port->read_status_mask & - CDNS_UART_IXR_BRK)) { - port->read_status_mask &= ~CDNS_UART_IXR_BRK; - port->icount.brk++; - if (uart_handle_break(port)) - continue; - } - -#ifdef SUPPORT_SYSRQ - /* - * uart_handle_sysrq_char() doesn't work if - * spinlocked, for some reason - */ - if (port->sysrq) { - spin_unlock(&port->lock); - if (uart_handle_sysrq_char(port, - (unsigned char)data)) { - spin_lock(&port->lock); - continue; - } - spin_lock(&port->lock); - } -#endif - - port->icount.rx++; - - if (isrstatus & CDNS_UART_IXR_PARITY) { - port->icount.parity++; - status = TTY_PARITY; - } else if (isrstatus & CDNS_UART_IXR_FRAMING) { - port->icount.frame++; - status = TTY_FRAME; - } else if (isrstatus & CDNS_UART_IXR_OVERRUN) { - port->icount.overrun++; - } - - uart_insert_char(port, isrstatus, CDNS_UART_IXR_OVERRUN, - data, status); - } - spin_unlock(&port->lock); - tty_flip_buffer_push(&port->state->port); - spin_lock(&port->lock); - } - - /* Dispatch an appropriate handler */ - if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY) { - if (uart_circ_empty(&port->state->xmit)) { - writel(CDNS_UART_IXR_TXEMPTY, - port->membase + CDNS_UART_IDR_OFFSET); - } else { - numbytes = port->fifosize; - /* Break if no more data available in the UART buffer */ - while (numbytes--) { - if (uart_circ_empty(&port->state->xmit)) - break; - /* Get the data from the UART circular buffer - * and write it to the cdns_uart's TX_FIFO - * register. - */ - writel(port->state->xmit.buf[ - port->state->xmit.tail], - port->membase + CDNS_UART_FIFO_OFFSET); - - port->icount.tx++; - - /* Adjust the tail of the UART buffer and wrap - * the buffer if it reaches limit. - */ - port->state->xmit.tail = - (port->state->xmit.tail + 1) & - (UART_XMIT_SIZE - 1); - } - - if (uart_circ_chars_pending( - &port->state->xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); - } + if (isrstatus & CDNS_UART_IXR_TXEMPTY) { + cdns_uart_handle_tx(dev_id); + isrstatus &= ~CDNS_UART_IXR_TXEMPTY; } + if (isrstatus & CDNS_UART_IXR_MASK) + cdns_uart_handle_rx(dev_id, isrstatus); writel(isrstatus, port->membase + CDNS_UART_ISR_OFFSET); @@ -408,6 +305,132 @@ static unsigned int cdns_uart_set_baud_rate(struct uart_port *port, return calc_baud; } +/** + * cdns_uart_handle_tx - Handle the bytes to be Txed. + * @dev_id: Id of the UART port + * Return: None + */ +static void cdns_uart_handle_tx(void *dev_id) +{ + struct uart_port *port = (struct uart_port *)dev_id; + unsigned int numbytes; + + if (uart_circ_empty(&port->state->xmit)) { + writel(CDNS_UART_IXR_TXEMPTY, + port->membase + CDNS_UART_IDR_OFFSET); + } else { + numbytes = port->fifosize; + /* Break if no more data available in the UART buffer */ + while (numbytes--) { + if (uart_circ_empty(&port->state->xmit)) + break; + /* Get the data from the UART circular buffer + * and write it to the cdns_uart's TX_FIFO + * register. + */ + writel(port->state->xmit.buf[port->state->xmit.tail], + port->membase + CDNS_UART_FIFO_OFFSET); + port->icount.tx++; + + /* Adjust the tail of the UART buffer and wrap + * the buffer if it reaches limit. + */ + port->state->xmit.tail = (port->state->xmit.tail + 1) & + (UART_XMIT_SIZE - 1); + } + + if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + } +} + +/** + * cdns_uart_handle_rx - Handle the received bytes along with Rx errors. + * @dev_id: Id of the UART port + * @isrstatus: The interrupt status register value as read + * Return: None + */ +static void cdns_uart_handle_rx(void *dev_id, unsigned int isrstatus) +{ + struct uart_port *port = (struct uart_port *)dev_id; + unsigned int data; + char status = TTY_NORMAL; + + /* + * There is no hardware break detection, so we interpret framing + * error with all-zeros data as a break sequence. Most of the time, + * there's another non-zero byte at the end of the sequence. + */ + if (isrstatus & CDNS_UART_IXR_FRAMING) { + while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & + CDNS_UART_SR_RXEMPTY)) { + if (!readl(port->membase + CDNS_UART_FIFO_OFFSET)) { + port->read_status_mask |= CDNS_UART_IXR_BRK; + isrstatus &= ~CDNS_UART_IXR_FRAMING; + } + } + writel(CDNS_UART_IXR_FRAMING, + port->membase + CDNS_UART_ISR_OFFSET); + } + + /* drop byte with parity error if IGNPAR specified */ + if (isrstatus & port->ignore_status_mask & CDNS_UART_IXR_PARITY) + isrstatus &= ~(CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT); + + isrstatus &= port->read_status_mask; + isrstatus &= ~port->ignore_status_mask; + if ((isrstatus & CDNS_UART_IXR_TOUT) || + (isrstatus & CDNS_UART_IXR_RXTRIG)) { + /* Receive Timeout Interrupt */ + while ((readl(port->membase + CDNS_UART_SR_OFFSET) & + CDNS_UART_SR_RXEMPTY) != CDNS_UART_SR_RXEMPTY) { + data = readl(port->membase + CDNS_UART_FIFO_OFFSET); + + /* Non-NULL byte after BREAK is garbage (99%) */ + if (data && (port->read_status_mask + &CDNS_UART_IXR_BRK)) { + port->read_status_mask &= ~CDNS_UART_IXR_BRK; + port->icount.brk++; + if (uart_handle_break(port)) + continue; + } + +#ifdef SUPPORT_SYSRQ + /* + * uart_handle_sysrq_char() doesn't work if + * spinlocked, for some reason + */ + if (port->sysrq) { + spin_unlock(&port->lock); + if (uart_handle_sysrq_char(port, + (unsigned char)data)) { + spin_lock(&port->lock); + continue; + } + spin_lock(&port->lock); + } +#endif + + port->icount.rx++; + + if (isrstatus & CDNS_UART_IXR_PARITY) { + port->icount.parity++; + status = TTY_PARITY; + } else if (isrstatus & CDNS_UART_IXR_FRAMING) { + port->icount.frame++; + status = TTY_FRAME; + } else if (isrstatus & CDNS_UART_IXR_OVERRUN) { + port->icount.overrun++; + } + + uart_insert_char(port, isrstatus, CDNS_UART_IXR_OVERRUN, + data, status); + } + spin_unlock(&port->lock); + tty_flip_buffer_push(&port->state->port); + spin_lock(&port->lock); +} +} #ifdef CONFIG_COMMON_CLK /** * cdns_uart_clk_notitifer_cb - Clock notifier callback -- 2.1.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/