From patchwork Thu Feb 15 12:02:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulrich Hecht X-Patchwork-Id: 10220981 X-Patchwork-Delegate: geert@linux-m68k.org 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 5DE4960467 for ; Thu, 15 Feb 2018 12:02:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4E3FD2880D for ; Thu, 15 Feb 2018 12:02:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 412372882C; Thu, 15 Feb 2018 12:02:49 +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_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, 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 B04C62880D for ; Thu, 15 Feb 2018 12:02:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S967960AbeBOMCs (ORCPT ); Thu, 15 Feb 2018 07:02:48 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:33697 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S967843AbeBOMCq (ORCPT ); Thu, 15 Feb 2018 07:02:46 -0500 Received: by mail-wm0-f68.google.com with SMTP id x4so861606wmc.0; Thu, 15 Feb 2018 04:02:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id; bh=bSV92DeP1aNCJ0O9OVNu7niPFa0/N4c9N2q0YuhJjcc=; b=ND6dysIWuF+vYR3SI6P89SpeImt5D/zw3uDTwkBx1uoX37UVYiLBh8+iXSeIbzMTSm MbsfOQxOnanaP23Q8DXEMpsnHBskLKLPXd9dGICTizLg19wvg/xRrIZ/YbJ5WND5dEzC 0PAkwHc0TqVSizy5t2PguPDUaGmOVn+1k5XoNP+uKMuRMXS0KQAAeqicIp7HamawGTxd AjrMyscd0Yhhe6iXRqRq7XvrssKYldTzHqXPhyDNf4F6qojBG1A+t8GAmHkmdZv6OQjo oY25W6xbzNMCYsibC79hI/mgygDJd1Ki1Ao4CHD0cyEJ5XrYE7Uoem+juQPNlCUIh31E wriQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id; bh=bSV92DeP1aNCJ0O9OVNu7niPFa0/N4c9N2q0YuhJjcc=; b=an8s/5mfxz+Tt7n2sxN/V9wR8Q1/6HoQsJJkN6O73Qiw/2EohwTqGph+nvGTbznQm7 0Wlfda8wAqMZmEtfQuIeDEKu6CbKJYPuTk5E3/8w+LBSvwMSQZi38WVHdSAQ2oUeLhjb pNCuUsiMZ+eTZPwivDgzIHO9AyF/2WsZK6hz4dJlJrCxaukHztKBVhKXi3HRA5r8ZvsO B7F5XnZGqx74AQzoe6h6v/7rHgbLzySIhpxmDxS3U6a2/MbbeeOhzAEaH/mr7XJiEjt7 FSqzsCcMYvr7dK91QdRx5j58sdSZgNTX8Rs6ecbr65d3NVhsW21jG1RzH2pZM6NgPqsW ckUg== X-Gm-Message-State: APf1xPAcKy8RtBWzqQn12jeKJFWQzPRptTaDQ1E7fQdG/s9+rCCzfexh h1CFb4P2oZwoyc4UGtxQDeZpZP4= X-Google-Smtp-Source: AH8x226RJkP2VK3MjRmDPOqrkij+1TTjBBAXciWXnhR+1fsVB8oUMzd58/jQoPqqlIToQ4dSk1b43A== X-Received: by 10.28.229.68 with SMTP id c65mr2031161wmh.76.1518696165188; Thu, 15 Feb 2018 04:02:45 -0800 (PST) Received: from groucho.site (ipbcc3b860.dynamic.kabel-deutschland.de. [188.195.184.96]) by smtp.gmail.com with ESMTPSA id e7sm3619704wrd.17.2018.02.15.04.02.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 15 Feb 2018 04:02:44 -0800 (PST) From: Ulrich Hecht To: linux-renesas-soc@vger.kernel.org, linux-serial@vger.kernel.org Cc: wsa@the-dreams.de, geert@linux-m68k.org, yoshihiro.shimoda.uh@renesas.com, Ulrich Hecht Subject: [PATCH] serial: sh-sci: use hrtimer for receive timeout Date: Thu, 15 Feb 2018 13:02:41 +0100 Message-Id: <1518696161-23866-1-git-send-email-ulrich.hecht+renesas@gmail.com> X-Mailer: git-send-email 2.7.4 Sender: linux-renesas-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP High latencies of classic timers cause performance issues for high- speed serial transmissions. This patch transforms rx_timer into an hrtimer to reduce the minimum latency. Signed-off-by: Ulrich Hecht --- drivers/tty/serial/sh-sci.c | 47 +++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index d9f399c..553f30c 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -143,8 +144,8 @@ struct sci_port { void *rx_buf[2]; size_t buf_len_rx; struct work_struct work_tx; - struct timer_list rx_timer; - unsigned int rx_timeout; + struct hrtimer rx_timer; + unsigned int rx_timeout; /* microseconds */ #endif unsigned int rx_frame; int rx_trigger; @@ -1229,6 +1230,15 @@ static void sci_rx_dma_release(struct sci_port *s, bool enable_pio) } } +static void start_hrtimer_us(struct hrtimer *hrt, unsigned long usec) +{ + long sec = usec / 1000000; + long nsec = (usec % 1000000) * 1000; + ktime_t t = ktime_set(sec, nsec); + + hrtimer_start(hrt, t, HRTIMER_MODE_REL); +} + static void sci_dma_rx_complete(void *arg) { struct sci_port *s = arg; @@ -1247,7 +1257,7 @@ static void sci_dma_rx_complete(void *arg) if (active >= 0) count = sci_dma_rx_push(s, s->rx_buf[active], s->buf_len_rx); - mod_timer(&s->rx_timer, jiffies + s->rx_timeout); + start_hrtimer_us(&s->rx_timer, s->rx_timeout); if (count) tty_flip_buffer_push(&port->state->port); @@ -1391,9 +1401,9 @@ static void work_fn_tx(struct work_struct *work) dma_async_issue_pending(chan); } -static void rx_timer_fn(struct timer_list *t) +static enum hrtimer_restart rx_timer_fn(struct hrtimer *t) { - struct sci_port *s = from_timer(s, t, rx_timer); + struct sci_port *s = container_of(t, struct sci_port, rx_timer); struct dma_chan *chan = s->chan_rx; struct uart_port *port = &s->port; struct dma_tx_state state; @@ -1410,7 +1420,7 @@ static void rx_timer_fn(struct timer_list *t) active = sci_dma_rx_find_active(s); if (active < 0) { spin_unlock_irqrestore(&port->lock, flags); - return; + return HRTIMER_NORESTART; } status = dmaengine_tx_status(s->chan_rx, s->active_rx, &state); @@ -1420,7 +1430,7 @@ static void rx_timer_fn(struct timer_list *t) s->active_rx, active); /* Let packet complete handler take care of the packet */ - return; + return HRTIMER_NORESTART; } dmaengine_pause(chan); @@ -1435,7 +1445,7 @@ static void rx_timer_fn(struct timer_list *t) if (status == DMA_COMPLETE) { spin_unlock_irqrestore(&port->lock, flags); dev_dbg(port->dev, "Transaction complete after DMA engine was stopped"); - return; + return HRTIMER_NORESTART; } /* Handle incomplete DMA receive */ @@ -1460,6 +1470,8 @@ static void rx_timer_fn(struct timer_list *t) serial_port_out(port, SCSCR, scr | SCSCR_RIE); spin_unlock_irqrestore(&port->lock, flags); + + return HRTIMER_NORESTART; } static struct dma_chan *sci_request_dma_chan(struct uart_port *port, @@ -1571,7 +1583,8 @@ static void sci_request_dma(struct uart_port *port) dma += s->buf_len_rx; } - timer_setup(&s->rx_timer, rx_timer_fn, 0); + hrtimer_init(&s->rx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + s->rx_timer.function = rx_timer_fn; if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) sci_submit_rx(s); @@ -1630,9 +1643,9 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) /* Clear current interrupt */ serial_port_out(port, SCxSR, ssr & ~(SCIF_DR | SCxSR_RDxF(port))); - dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n", + dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u us\n", jiffies, s->rx_timeout); - mod_timer(&s->rx_timer, jiffies + s->rx_timeout); + start_hrtimer_us(&s->rx_timer, s->rx_timeout); return IRQ_HANDLED; } @@ -1643,7 +1656,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) scif_set_rtrg(port, s->rx_trigger); mod_timer(&s->rx_fifo_timer, jiffies + DIV_ROUND_UP( - s->rx_frame * s->rx_fifo_timeout, 1000)); + s->rx_frame * HZ * s->rx_fifo_timeout, 1000000)); } /* I think sci_receive_chars has to be called irrespective @@ -2079,7 +2092,7 @@ static void sci_shutdown(struct uart_port *port) if (s->chan_rx) { dev_dbg(port->dev, "%s(%d) deleting rx_timer\n", __func__, port->line); - del_timer_sync(&s->rx_timer); + hrtimer_cancel(&s->rx_timer); } #endif @@ -2480,11 +2493,11 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, if (termios->c_cflag & PARENB) bits++; - s->rx_frame = (100 * bits * HZ) / (baud / 10); + s->rx_frame = (10000 * bits) / (baud / 100); #ifdef CONFIG_SERIAL_SH_SCI_DMA - s->rx_timeout = DIV_ROUND_UP(s->buf_len_rx * 2 * s->rx_frame, 1000); - if (s->rx_timeout < msecs_to_jiffies(20)) - s->rx_timeout = msecs_to_jiffies(20); + s->rx_timeout = s->buf_len_rx * 2 * s->rx_frame; + if (s->rx_timeout < 20) + s->rx_timeout = 20; #endif if ((termios->c_cflag & CREAD) != 0)