From patchwork Fri Mar 23 22:10:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Karthikeyan Ramasubramanian X-Patchwork-Id: 10305653 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 021C6600CC for ; Fri, 23 Mar 2018 22:10:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DF8A5291CE for ; Fri, 23 Mar 2018 22:10:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DDEDA291D6; Fri, 23 Mar 2018 22:10:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 12BCE291CE for ; Fri, 23 Mar 2018 22:10:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751880AbeCWWKu (ORCPT ); Fri, 23 Mar 2018 18:10:50 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:57424 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751677AbeCWWKt (ORCPT ); Fri, 23 Mar 2018 18:10:49 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id C4A50607A2; Fri, 23 Mar 2018 22:10:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1521843048; bh=UrKK9Mb9tZ+EvObFNBioKhxl4b+diBkYXIJZ4Z/m70w=; h=From:To:Cc:Subject:Date:From; b=Vlc6QIrQMk1zX3XOO4qDPxfcUhnpgePCKPsTfsZmcPNO/GlFU9ibCdyw8uEhPrXfu YtVj0us3QlbZR3Y7WKYewk7M5hSTaKxnldTR1kVuNQTcVJG2AOYZDIiKUyxi26Q5mX 7/Nz9fesDxmhh16inm+UVfho/nX9oURphbNEOpmo= Received: from codeaurora.org (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: kramasub@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id E925E607A2; Fri, 23 Mar 2018 22:10:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1521843047; bh=UrKK9Mb9tZ+EvObFNBioKhxl4b+diBkYXIJZ4Z/m70w=; h=From:To:Cc:Subject:Date:From; b=av8io7QoWacyEQZwaOFwHAPcdUo0mAUhEHwr6Gxa1Uh44GoTqPj+SU8E0ruK1YgcJ +n2gY/nqWTbAdR3gjd9rMam/cc9m9tfARr3/vQKVngismWCS8bq6WCRhNJk2Fo0JcP e653lcQBrotAsDSvkXjknijj851uVwYQJfWBMlRU= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org E925E607A2 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=kramasub@codeaurora.org From: Karthikeyan Ramasubramanian To: gregkh@linuxfoundation.org, jslaby@suse.com Cc: Karthikeyan Ramasubramanian , linux-arm-msm@vger.kernel.org, linux-serial@vger.kernel.org, evgreen@chromium.org, acourbot@chromium.org, swboyd@chromium.org, dianders@chromium.org Subject: [PATCH] tty: serial: qcom_geni_serial: Address follow-up comments Date: Fri, 23 Mar 2018 16:10:38 -0600 Message-Id: <1521843038-19903-1-git-send-email-kramasub@codeaurora.org> X-Mailer: git-send-email 1.9.1 Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The driver has some follow-up comments right after it got merged. This patch addresses those comments that got missed out. * Document reason for newline character counting in console_write * Document reason for disabling IRQ in the system resume operation * Use min3 to find the minimum of 3 values * Remove unnecessary casting while using min_t * Use iowrite32_rep to write to the hardware FIFO * Initialize the console port statically * Fine-tune memory barrier usage Signed-off-by: Karthikeyan Ramasubramanian --- drivers/tty/serial/qcom_geni_serial.c | 84 ++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 1442777..f5b9cb8 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -105,7 +105,7 @@ struct qcom_geni_serial_port { bool brk; }; -static const struct uart_ops qcom_geni_serial_pops; +static const struct uart_ops qcom_geni_console_pops; static struct uart_driver qcom_geni_console_driver; static int handle_rx_console(struct uart_port *uport, u32 bytes, bool drop); static unsigned int qcom_geni_serial_tx_empty(struct uart_port *port); @@ -118,7 +118,14 @@ struct qcom_geni_serial_port { #define to_dev_port(ptr, member) \ container_of(ptr, struct qcom_geni_serial_port, member) -static struct qcom_geni_serial_port qcom_geni_console_port; +static struct qcom_geni_serial_port qcom_geni_console_port = { + .uport = { + .iotype = UPIO_MEM, + .ops = &qcom_geni_console_pops, + .flags = UPF_BOOT_AUTOCONF, + .line = 0, + }, +}; static int qcom_geni_serial_request_port(struct uart_port *uport) { @@ -173,8 +180,12 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport, unsigned int fifo_bits; unsigned long timeout_us = 20000; - /* Ensure polling is not re-ordered before the prior writes/reads */ - mb(); + /* + * Ensure polling is not re-ordered before the prior writes/reads. + * Just invoke the write memory barrier here, since readl_poll* + * performs readl which invokes the read memory barrier. + */ + wmb(); if (uport->private_data) { port = to_dev_port(uport, uport); @@ -286,6 +297,10 @@ static void qcom_geni_serial_wr_char(struct uart_port *uport, int ch) u32 bytes_to_send = count; for (i = 0; i < count; i++) { + /* + * uart_console_write() adds a carriage return for each newline. + * Account for additional bytes to be written. + */ if (s[i] == '\n') bytes_to_send++; } @@ -305,7 +320,7 @@ static void qcom_geni_serial_wr_char(struct uart_port *uport, int ch) if (!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, M_TX_FIFO_WATERMARK_EN, true)) break; - chars_to_write = min_t(size_t, (size_t)(count - i), avail / 2); + chars_to_write = min_t(size_t, count - i, avail / 2); uart_console_write(uport, s + i, chars_to_write, qcom_geni_serial_wr_char); writel_relaxed(M_TX_FIFO_WATERMARK_EN, uport->membase + @@ -406,20 +421,18 @@ static void qcom_geni_serial_start_tx(struct uart_port *uport) u32 status; if (port->xfer_mode == GENI_SE_FIFO) { - status = readl_relaxed(uport->membase + SE_GENI_STATUS); + /* + * readl ensures reading & writing of IRQ_EN register + * is not re-ordered before checking the status of the + * Serial Engine. + */ + status = readl(uport->membase + SE_GENI_STATUS); if (status & M_GENI_CMD_ACTIVE) return; if (!qcom_geni_serial_tx_empty(uport)) return; - /* - * Ensure writing to IRQ_EN & watermark registers are not - * re-ordered before checking the status of the Serial - * Engine and TX FIFO - */ - mb(); - irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN; @@ -582,11 +595,7 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport) avail = (port->tx_fifo_depth - port->tx_wm) * port->tx_bytes_pw; tail = (xmit->tail + port->xmit_size) & (UART_XMIT_SIZE - 1); - if (chunk > (UART_XMIT_SIZE - tail)) - chunk = UART_XMIT_SIZE - tail; - if (chunk > avail) - chunk = avail; - + chunk = min3((size_t)chunk, UART_XMIT_SIZE - tail, avail); if (!chunk) goto out_write_wakeup; @@ -595,15 +604,15 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport) remaining = chunk; for (i = 0; i < chunk; ) { unsigned int tx_bytes; - unsigned int buf = 0; + u8 buf[sizeof(u32)]; int c; + memset(buf, 0, ARRAY_SIZE(buf)); tx_bytes = min_t(size_t, remaining, (size_t)port->tx_bytes_pw); for (c = 0; c < tx_bytes ; c++) - buf |= (xmit->buf[tail + c] << (c * BITS_PER_BYTE)); - - writel_relaxed(buf, uport->membase + SE_GENI_TX_FIFOn); + buf[c] = xmit->buf[tail + c]; + iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1); i += tx_bytes; tail = (tail + tx_bytes) & (UART_XMIT_SIZE - 1); uport->icount.tx += tx_bytes; @@ -627,7 +636,7 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev) struct qcom_geni_serial_port *port = to_dev_port(uport, uport); if (uport->suspended) - return IRQ_HANDLED; + return IRQ_NONE; spin_lock_irqsave(&uport->lock, flags); m_irq_status = readl_relaxed(uport->membase + SE_GENI_M_IRQ_STATUS); @@ -671,9 +680,6 @@ static int get_tx_fifo_size(struct qcom_geni_serial_port *port) { struct uart_port *uport; - if (!port) - return -ENODEV; - uport = &port->uport; port->tx_fifo_depth = geni_se_get_tx_fifo_depth(&port->se); port->tx_fifo_width = geni_se_get_tx_fifo_width(&port->se); @@ -702,7 +708,6 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport) /* Stop the console before stopping the current tx */ console_stop(uport->cons); - disable_irq(uport->irq); free_irq(uport->irq, uport); spin_lock_irqsave(&uport->lock, flags); qcom_geni_serial_stop_tx(uport); @@ -892,7 +897,7 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, static unsigned int qcom_geni_serial_tx_empty(struct uart_port *uport) { - return !readl_relaxed(uport->membase + SE_GENI_TX_FIFO_STATUS); + return !readl(uport->membase + SE_GENI_TX_FIFO_STATUS); } #ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE @@ -910,7 +915,7 @@ static int __init qcom_geni_console_setup(struct console *co, char *options) port = get_port_from_line(co->index); if (IS_ERR(port)) { - pr_err("Invalid line %d(%d)\n", co->index, (int)PTR_ERR(port)); + pr_err("Invalid line %d\n", co->index); return PTR_ERR(port); } @@ -1025,16 +1030,13 @@ static int qcom_geni_serial_probe(struct platform_device *pdev) if (pdev->dev.of_node) line = of_alias_get_id(pdev->dev.of_node, "serial"); - else - line = pdev->id; if (line < 0 || line >= GENI_UART_CONS_PORTS) return -ENXIO; port = get_port_from_line(line); if (IS_ERR(port)) { - ret = PTR_ERR(port); - dev_err(&pdev->dev, "Invalid line %d(%d)\n", line, ret); - return ret; + dev_err(&pdev->dev, "Invalid line %d\n", line); + return PTR_ERR(port); } uport = &port->uport; @@ -1070,7 +1072,6 @@ static int qcom_geni_serial_probe(struct platform_device *pdev) uport->private_data = &qcom_geni_console_driver; platform_set_drvdata(pdev, port); port->handle_rx = handle_rx_console; - port->setup = false; return uart_add_one_port(&qcom_geni_console_driver, uport); } @@ -1101,6 +1102,14 @@ static int __maybe_unused qcom_geni_serial_sys_resume_noirq(struct device *dev) if (console_suspend_enabled && uport->suspended) { uart_resume_port(uport->private_data, uport); + /* + * uart_suspend_port() invokes port shutdown which in turn + * frees the irq. uart_resume_port invokes port startup which + * performs request_irq. The request_irq auto-enables the IRQ. + * In addition, resume_noirq implicitly enables the IRQ and + * leads to an unbalanced IRQ enable warning. Disable the IRQ + * before returning so that the warning is suppressed. + */ disable_irq(uport->irq); } return 0; @@ -1131,11 +1140,6 @@ static int __init qcom_geni_serial_init(void) { int ret; - qcom_geni_console_port.uport.iotype = UPIO_MEM; - qcom_geni_console_port.uport.ops = &qcom_geni_console_pops; - qcom_geni_console_port.uport.flags = UPF_BOOT_AUTOCONF; - qcom_geni_console_port.uport.line = 0; - ret = console_register(&qcom_geni_console_driver); if (ret) return ret;