From patchwork Wed Sep 5 20:11:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Douglas Anderson X-Patchwork-Id: 10589381 X-Patchwork-Delegate: agross@codeaurora.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 624E75A4 for ; Wed, 5 Sep 2018 20:12:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 53D222AB22 for ; Wed, 5 Sep 2018 20:12:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 462B42AB2E; Wed, 5 Sep 2018 20:12:14 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 B99822AB22 for ; Wed, 5 Sep 2018 20:12:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727674AbeIFAn4 (ORCPT ); Wed, 5 Sep 2018 20:43:56 -0400 Received: from mail-pg1-f194.google.com ([209.85.215.194]:33509 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727494AbeIFAn4 (ORCPT ); Wed, 5 Sep 2018 20:43:56 -0400 Received: by mail-pg1-f194.google.com with SMTP id s7-v6so3989334pgc.0 for ; Wed, 05 Sep 2018 13:12:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=aED8WBvFuaDXsWIn/cMHY20Vmk+mx3p7TF8ggA2zkyo=; b=YMJIiTDDv//Q22XDlwK3SY9MDSnSxzItcdFU0M6vgacth60S1Xk6jtCIqvZzW7lAIB 5TMN2CO1Z1qxWED11Ef/XloOD9EGyguserEJV4FEB2rW/AErXOfJcTUY51MsLEJWlPAH kFi9w3R/T+DKVq+znWgfugjynhjTSqge8FBPg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=aED8WBvFuaDXsWIn/cMHY20Vmk+mx3p7TF8ggA2zkyo=; b=IvPdxrCMsSi653z1Vtv/ZpITdq5aJoLK+sDJYTkHntK2fZ+hQMK9rg5L6xdYprTgFV 8ULXMcX/+8Sfyrzs6Nd1PPJlv5J1c/q8MhvI8OiFot8hYUeIinEgrM7S3hunXzXOklsL qZLw90H0ovLypdGd1YP4dmNp8DtW3laG0qB3Werc0H/AF851oA8UN0Deo60K7vxvX+0L qlBbG4bkhdpysvhtB41BWnoLU4nMY31bBDlKG7rkyKzIaFSSOnzkYN25+DAD5XPR8Ryp jvyjWYaAHo1bOQw/uYCyZX1hPRVdOsVMEwPAvGgOUBF7qWrrzIGvyCWOSMQwC+w8QvUA HhAA== X-Gm-Message-State: APzg51BIZml6XSOug+JLhOIbQZzMKo6ioQwAdH432GgbGnSg97CZpKT3 HgKMWALIT0IRYGf5iIzS62HU8g== X-Google-Smtp-Source: ANB0VdYJusZIniK2wOtzhsC4M8MINVlye9AUqfo2z34aP4g/ddjZSlqMQzoo8ZByWY3jHy9UIneT5g== X-Received: by 2002:a62:f5c1:: with SMTP id b62-v6mr42879296pfm.158.1536178329495; Wed, 05 Sep 2018 13:12:09 -0700 (PDT) Received: from tictac2.mtv.corp.google.com ([2620:15c:202:1:c8e0:70d7:4be7:a36]) by smtp.gmail.com with ESMTPSA id l3-v6sm3505100pff.8.2018.09.05.13.12.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 05 Sep 2018 13:12:08 -0700 (PDT) From: Douglas Anderson To: gregkh@linuxfoundation.org Cc: linux-arm-msm@vger.kernel.org, mka@chromium.org, evgreen@chromium.org, swboyd@chromium.org, Douglas Anderson , linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, Jiri Slaby Subject: [PATCH] tty: serial: qcom_geni_serial: Fix serial when not used as console Date: Wed, 5 Sep 2018 13:11:46 -0700 Message-Id: <20180905201146.261438-1-dianders@chromium.org> X-Mailer: git-send-email 2.19.0.rc1.350.ge57e33dbd1-goog MIME-Version: 1.0 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 If you've got the "console" serial port setup to use just as a UART (AKA there is no "console=ttyMSMX" on the kernel command line) then certain initialization is skipped. When userspace later tries to do something with the port then things go boom (specifically, on my system, some sort of exception hit that caused the system to reboot itself w/ no error messages). Let's cleanup / refactor the init so that we always run the same init code regardless of whether we're using the console. To make this work, we make rely on qcom_geni_serial_pm doing its job to turn resources on. For the record, here is a trace of the order of things (after this patch) when console= is specified on the command line and we have an agetty on the port: qcom_geni_serial_pm: 4 (undefined) => 0 (on) qcom_geni_console_setup qcom_geni_serial_port_setup qcom_geni_serial_console_write qcom_geni_serial_startup qcom_geni_serial_start_tx ...and here is the order of things (after this patch) when console= is _NOT_ specified on the command line and we have an agetty port: qcom_geni_serial_pm: 4 => 0 qcom_geni_serial_pm: 0 => 3 qcom_geni_serial_pm: 3 => 0 qcom_geni_serial_startup qcom_geni_serial_port_setup qcom_geni_serial_pm: 0 => 3 qcom_geni_serial_pm: 3 => 0 qcom_geni_serial_startup qcom_geni_serial_start_tx Fixes: c4f528795d1a ("tty: serial: msm_geni_serial: Add serial driver support for GENI based QUP") Signed-off-by: Douglas Anderson Reviewed-by: Matthias Kaehlcke --- drivers/tty/serial/qcom_geni_serial.c | 55 +++++++++++++-------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 29ec34387246..99103c67e1dc 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -851,6 +851,23 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) { struct qcom_geni_serial_port *port = to_dev_port(uport, uport); unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; + u32 proto; + + if (uart_console(uport)) + port->tx_bytes_pw = 1; + else + port->tx_bytes_pw = 4; + port->rx_bytes_pw = RX_BYTES_PW; + + proto = geni_se_read_proto(&port->se); + if (proto != GENI_SE_UART) { + dev_err(uport->dev, "Invalid FW loaded, proto: %d\n", proto); + return -ENXIO; + } + + qcom_geni_serial_stop_rx(uport); + + get_tx_fifo_size(port); set_rfr_wm(port); writel_relaxed(rxstale, uport->membase + SE_UART_RX_STALE_CNT); @@ -874,30 +891,19 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) return -ENOMEM; } port->setup = true; + return 0; } static int qcom_geni_serial_startup(struct uart_port *uport) { int ret; - u32 proto; struct qcom_geni_serial_port *port = to_dev_port(uport, uport); scnprintf(port->name, sizeof(port->name), "qcom_serial_%s%d", (uart_console(uport) ? "console" : "uart"), uport->line); - if (!uart_console(uport)) { - port->tx_bytes_pw = 4; - port->rx_bytes_pw = RX_BYTES_PW; - } - proto = geni_se_read_proto(&port->se); - if (proto != GENI_SE_UART) { - dev_err(uport->dev, "Invalid FW loaded, proto: %d\n", proto); - return -ENXIO; - } - - get_tx_fifo_size(port); if (!port->setup) { ret = qcom_geni_serial_port_setup(uport); if (ret) @@ -1056,6 +1062,7 @@ static int __init qcom_geni_console_setup(struct console *co, char *options) int bits = 8; int parity = 'n'; int flow = 'n'; + int ret; if (co->index >= GENI_UART_CONS_PORTS || co->index < 0) return -ENXIO; @@ -1071,21 +1078,10 @@ static int __init qcom_geni_console_setup(struct console *co, char *options) if (unlikely(!uport->membase)) return -ENXIO; - if (geni_se_resources_on(&port->se)) { - dev_err(port->se.dev, "Error turning on resources\n"); - return -ENXIO; - } - - if (unlikely(geni_se_read_proto(&port->se) != GENI_SE_UART)) { - geni_se_resources_off(&port->se); - return -ENXIO; - } - if (!port->setup) { - port->tx_bytes_pw = 1; - port->rx_bytes_pw = RX_BYTES_PW; - qcom_geni_serial_stop_rx(uport); - qcom_geni_serial_port_setup(uport); + ret = qcom_geni_serial_port_setup(uport); + if (ret) + return ret; } if (options) @@ -1203,11 +1199,12 @@ static void qcom_geni_serial_pm(struct uart_port *uport, { struct qcom_geni_serial_port *port = to_dev_port(uport, uport); + /* If we've never been called, treat it as off */ + if (old_state == UART_PM_STATE_UNDEFINED) + old_state = UART_PM_STATE_OFF; + if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF) geni_se_resources_on(&port->se); - else if (!uart_console(uport) && (new_state == UART_PM_STATE_ON && - old_state == UART_PM_STATE_UNDEFINED)) - geni_se_resources_on(&port->se); else if (new_state == UART_PM_STATE_OFF && old_state == UART_PM_STATE_ON) geni_se_resources_off(&port->se);