From patchwork Fri Jul 10 13:12:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sumit Garg X-Patchwork-Id: 235234 Delivered-To: patches@linaro.org Received: by 2002:a92:d244:0:0:0:0:0 with SMTP id v4csp442787ilg; Fri, 10 Jul 2020 06:12:45 -0700 (PDT) X-Received: by 2002:a62:e119:: with SMTP id q25mr45766186pfh.300.1594386765570; Fri, 10 Jul 2020 06:12:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1594386765; cv=none; d=google.com; s=arc-20160816; b=qQqoMx/UwD6TkcGc0T1i+KeYjkjj+xXumjpEGWpoLi5+UmcAsC67NwkYR+e/oJbjOa /Gbdbd9JLZPmxYbU1w+tS1O6Y/8N4ILpQIlSoQ17ZOQZLHKtx7it+sr6jb7zdNkwVGKP UgUO+i8QbOqSYRGrSv/AsxUxJUCaf+RgAfSLMdtE9EMctbFvSK1PmEXQH5kNuQ8T+XLT ZpSbGlr59coCmF5Sl0FQ0oCA4Rk9Ge+OtP+K2UUo+NTFF11vikyDqMVzyTa64tTrRgVe Y5h/HEFR1G4lLvk983YxbNiNaq0hk1lHBewid652jS71iKi0D4IGkj8psTqSDxJ0cGgP 5Xhg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=UmTx7X0+S/l8Ncd1/nl65s9vcMmDlzDE1V+od3xcrvs=; b=A9QKt3TIowRJm+Lw3ZuWHQwrzVLDeUTLAy0xXAoJXApPRUeIUUIIGrV9ZF3hTNbxWs JxmrLoyd7LqOGHYjJXFMd99nwnCRwasGJeikWcVb+ITZdLhn1eYsG++U8pX398+C85j4 NZuFtd03YarvDshyS0c+hQnWfeW+3cr8TCZoykOUg1eUueY1XmwKPpKMM9uUk4KenlyE h7sh0t4xvR70JkiTTdXScLSFv3jF8BXB00Ej53oM/uOF0uXT3Vms/y3N1nUWI0orlibo Tggfz39b+fAWQWphA3NvYo26M1Lt792Y3aZdg4U04coZ+cW75PF7QKZIK/rF6SrmL7Ku Sgjw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dj8Vfhpl; spf=pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=sumit.garg@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id a22sor7415433pfg.30.2020.07.10.06.12.45 for (Google Transport Security); Fri, 10 Jul 2020 06:12:45 -0700 (PDT) Received-SPF: pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dj8Vfhpl; spf=pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=sumit.garg@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=UmTx7X0+S/l8Ncd1/nl65s9vcMmDlzDE1V+od3xcrvs=; b=dj8VfhplPnNoybWDgUFQwCTiXpGojlfgZVLcuWJUzIwk2B2AaomdJgKipIDEfsRoxQ LqRQk4Aj1781zoeNe+kJ4G7NRdjNgBW+PN2Dv7vEDXhzLJYjgAyaBJJy0dZfzwAHXwTw KV47uuhdihdvloquZgk7dI8SJC/yg5JhdKqNyFMM1GIFMseb5hEoFUIG3R7T0aNPgivz BHYT5fU5uoqo40RWSXPCQNMP7u2NK8wqjCacAMpxyNSCuhL1VXvYWjomBmZpu0nbetx8 nDjI4SOgV3SxlTxCPDWTlll5KnelkHFIs5RINiO/VR9G6cb72b+s2+Tb5ibnvAY7aGKN r7tA== 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:in-reply-to :references; bh=UmTx7X0+S/l8Ncd1/nl65s9vcMmDlzDE1V+od3xcrvs=; b=nsZtjSe9cwPQkuhB1Ka2KX+sPFZpxR18xJJKSeGoOwpbua51ifN1r9Lpb4qvLN7i+Q OmclXASfpzUf1b75XxON1Sr/myXHiNQyYPRtnldU6pkudvJEGfXF24c6maItxch2osjK 7Cue2XbAK7imSyAHUM6gKKV7mfWmqtpdElRdX3RhlFVG2rCwqfR1YFUY3xC8qptPUFYO 0FpICZWivT5xajLAU6AaMkUz7QSnoCOdy9CMBLtLckxN5zqk1w1pX05+gJ5vDefRxMf0 OBVGXjj5ClsdZ+rsawBIkEGWARsMgSe7J/6F5n1rArzodZXBOaU9KwG8cfnhszl1IN2V iGPg== X-Gm-Message-State: AOAM532TPtNWOs44TLnlXCc1pWvX4Lx4LFQtdBPmgS43IO066AC7SgE4 0olJgiMzVHWTICiUk44VSPWYdo/H X-Google-Smtp-Source: ABdhPJwuonh0EHODmNag6KdVTi9ZpoRBazcuJwakSmLdlDqaHCM4TSJh38JpdqOW3AdPNV4fud9XyQ== X-Received: by 2002:aa7:970a:: with SMTP id a10mr50492486pfg.319.1594386765171; Fri, 10 Jul 2020 06:12:45 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([117.210.211.230]) by smtp.gmail.com with ESMTPSA id d25sm5553279pgn.2.2020.07.10.06.12.41 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 10 Jul 2020 06:12:44 -0700 (PDT) From: Sumit Garg To: daniel.thompson@linaro.org Cc: patches@linaro.org, Sumit Garg Subject: [RFC INTERNAL v2 4/4] serial: amba-pl011: Enable NMI aware polling mode Date: Fri, 10 Jul 2020 18:42:05 +0530 Message-Id: <1594386725-10346-5-git-send-email-sumit.garg@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1594386725-10346-1-git-send-email-sumit.garg@linaro.org> References: <1594386725-10346-1-git-send-email-sumit.garg@linaro.org> Allow serial interrupt to be requested as an NMI in polling mode. Currently this NMI aware polling mode only supports NMI driven RX and TX data. DMA operation isn't supported. Also, while operating in NMI mode, RX always remains active irrespective of whether corresponding TTY port is active or not. So we directly bail out of startup, shutdown and rx_stop APIs if NMI mode is active. Signed-off-by: Sumit Garg --- drivers/tty/serial/amba-pl011.c | 133 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 122 insertions(+), 11 deletions(-) -- 2.7.4 diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 0983c5e..71d1325 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include "amba-pl011.h" @@ -347,6 +349,16 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) if (uart_handle_sysrq_char(&uap->port, ch & 255)) continue; + if (in_nmi()) { + struct uart_nmi_rx_data rx_data; + + rx_data.ch = ch; + rx_data.overrun = UART011_DR_OE; + rx_data.flag = flag; + uart_nmi_handle_rx_data(&uap->port, &rx_data); + continue; + } + uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag); } @@ -1316,6 +1328,9 @@ static void pl011_stop_rx(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); + if (uart_nmi_active(port)) + return; + uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM| UART011_PEIM|UART011_BEIM|UART011_OEIM); pl011_write(uap->im, uap, REG_IMSC); @@ -1604,13 +1619,6 @@ static int pl011_hwinit(struct uart_port *port) UART011_FEIS | UART011_RTIS | UART011_RXIS, uap, REG_ICR); - /* - * Save interrupts enable mask, and enable RX interrupts in case if - * the interrupt is used for NMI entry. - */ - uap->im = pl011_read(uap, REG_IMSC); - pl011_write(UART011_RTIM | UART011_RXIM, uap, REG_IMSC); - if (dev_get_platdata(uap->port.dev)) { struct amba_pl011_data *plat; @@ -1711,6 +1719,99 @@ static void pl011_put_poll_char(struct uart_port *port, pl011_write(ch, uap, REG_DR); } +static void pl011_nmi_rx_chars(struct uart_amba_port *uap) +{ + pl011_fifo_to_tty(uap); + irq_work_queue(&uap->port.nmi_state.rx_work); +} + +static irqreturn_t pl011_nmi_int(int irq, void *dev_id) +{ + struct uart_amba_port *uap = dev_id; + unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; + int handled = 0; + + status = pl011_read(uap, REG_MIS); + if (status) { + do { + check_apply_cts_event_workaround(uap); + + pl011_write(status, uap, REG_ICR); + + if (status & (UART011_RTIS|UART011_RXIS)) + pl011_nmi_rx_chars(uap); + + if (status & UART011_TXIS) + irq_work_queue(&uap->port.nmi_state.tx_work); + + if (pass_counter-- == 0) + break; + + status = pl011_read(uap, REG_MIS); + } while (status != 0); + handled = 1; + } + + return IRQ_RETVAL(handled); +} + +static int pl011_allocate_nmi(struct uart_amba_port *uap) +{ + int ret; + + irq_set_status_flags(uap->port.irq, IRQ_NOAUTOEN); + ret = request_nmi(uap->port.irq, pl011_nmi_int, IRQF_PERCPU, + "uart-pl011", uap); + if (ret) { + irq_clear_status_flags(uap->port.irq, IRQ_NOAUTOEN); + return ret; + } + + enable_irq(uap->port.irq); + + return ret; +} + +static void pl011_tx_irq_callback(struct uart_port *port) +{ + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); + + spin_lock(&port->lock); + pl011_tx_chars(uap, true); + spin_unlock(&port->lock); +} + +static int pl011_poll_init(struct uart_port *port) +{ + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); + int retval; + + retval = pl011_hwinit(port); + goto clk_dis; + + /* In case NMI isn't supported, fallback to normal interrupt mode */ + retval = pl011_allocate_nmi(uap); + if (retval) + return 0; + + retval = uart_nmi_state_init(port); + if (retval) + goto clk_dis; + + port->nmi_state.tx_irq_callback = pl011_tx_irq_callback; + uart_set_nmi_active(port, true); + + pl011_enable_interrupts(uap); + + return 0; + + clk_dis: + clk_disable_unprepare(uap->clk); + return retval; +} + #endif /* CONFIG_CONSOLE_POLL */ static bool pl011_split_lcrh(const struct uart_amba_port *uap) @@ -1736,8 +1837,6 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) static int pl011_allocate_irq(struct uart_amba_port *uap) { - pl011_write(uap->im, uap, REG_IMSC); - return request_irq(uap->port.irq, pl011_int, IRQF_SHARED, "uart-pl011", uap); } @@ -1748,6 +1847,9 @@ static int pl011_startup(struct uart_port *port) unsigned int cr; int retval; + if (uart_nmi_active(port)) + return 0; + retval = pl011_hwinit(port); if (retval) goto clk_dis; @@ -1790,6 +1892,9 @@ static int sbsa_uart_startup(struct uart_port *port) container_of(port, struct uart_amba_port, port); int retval; + if (uart_nmi_active(port)) + return 0; + retval = pl011_hwinit(port); if (retval) return retval; @@ -1859,6 +1964,9 @@ static void pl011_shutdown(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); + if (uart_nmi_active(port)) + return; + pl011_disable_interrupts(uap); pl011_dma_shutdown(uap); @@ -1891,6 +1999,9 @@ static void sbsa_uart_shutdown(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); + if (uart_nmi_active(port)) + return; + pl011_disable_interrupts(uap); free_irq(uap->port.irq, uap); @@ -2142,7 +2253,7 @@ static const struct uart_ops amba_pl011_pops = { .config_port = pl011_config_port, .verify_port = pl011_verify_port, #ifdef CONFIG_CONSOLE_POLL - .poll_init = pl011_hwinit, + .poll_init = pl011_poll_init, .poll_get_char = pl011_get_poll_char, .poll_put_char = pl011_put_poll_char, #endif @@ -2173,7 +2284,7 @@ static const struct uart_ops sbsa_uart_pops = { .config_port = pl011_config_port, .verify_port = pl011_verify_port, #ifdef CONFIG_CONSOLE_POLL - .poll_init = pl011_hwinit, + .poll_init = pl011_poll_init, .poll_get_char = pl011_get_poll_char, .poll_put_char = pl011_put_poll_char, #endif