From patchwork Sun Mar 29 14:03:27 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sperl X-Patchwork-Id: 6117041 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 56146BF4A6 for ; Sun, 29 Mar 2015 14:03:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6C25420165 for ; Sun, 29 Mar 2015 14:03:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4E7462026D for ; Sun, 29 Mar 2015 14:03:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753410AbbC2ODy (ORCPT ); Sun, 29 Mar 2015 10:03:54 -0400 Received: from 212-186-180-163.dynamic.surfer.at ([212.186.180.163]:58074 "EHLO cgate.sperl.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752804AbbC2ODx convert rfc822-to-8bit (ORCPT ); Sun, 29 Mar 2015 10:03:53 -0400 Received: from msmac.intern.sperl.org (account martin@sperl.org [10.10.10.11] verified) by sperl.org (CommuniGate Pro SMTP 6.1.2) with ESMTPSA id 6290424; Sun, 29 Mar 2015 14:03:46 +0000 From: Martin Sperl Subject: [PATCH 5/6] spi: bcm2835: add polling mode for transfers below 30us Message-Id: <808DC596-35BB-4A08-8CF4-DFAB6294636E@martin.sperl.org> Date: Sun, 29 Mar 2015 16:03:27 +0200 To: Mark Brown , Stephen Warren , lee@kernel.org, linux-spi@vger.kernel.org, linux-rpi-kernel Mime-Version: 1.0 (Mac OS X Mail 8.2 \(2070.6\)) X-Mailer: Apple Mail (2.2070.6) Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In cases of short transfer times the CPU is spending lots of time in the interrupt handler and scheduler to reschedule the worker thread. Measurements show that we have times where it takes 29.32us to between the last clock change and the time that the worker-thread is running again returning from wait_for_completion_timeout(). During this time the interrupt-handler is running calling complete() and then also the scheduler is rescheduling the worker thread. This time can vary depending on how much of the code is still in CPU-caches, when there is a burst of spi transfers the subsequent delays are in the order of 25us, so the value of 30us seems reasonable. With polling the whole transfer of 4 bytes at 10MHz finishes after 6.16us (CS down to up) with the real transfer (clock running) taking 3.56us. So the efficiency has much improved and also freeing CPU cycles, reducing interrupts and context switches. Because of the above 30us seems to be a reasonable limit for polling. Signed-off-by: Martin Sperl Tested-by: Martin Sperl --- drivers/spi/spi-bcm2835.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) Applies against topic/bcm2835 and only after patch 3. diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 601fc5e..1d731b8 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -68,7 +68,8 @@ #define BCM2835_SPI_CS_CS_10 0x00000002 #define BCM2835_SPI_CS_CS_01 0x00000001 -#define BCM2835_SPI_TIMEOUT_MS 30000 +#define BCM2835_SPI_TIMEOUT_MS 30000 +#define BCM2835_SPI_POLLING_LIMIT_US 30 #define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ | SPI_NO_CS | SPI_3WIRE) @@ -163,6 +164,7 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, { struct bcm2835_spi *bs = spi_master_get_devdata(master); unsigned long spi_hz, clk_hz, cdiv; + unsigned long spi_used_hz, xfer_time_us, timeout; u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); /* set clock */ @@ -181,6 +183,7 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, } else { cdiv = 0; /* 0 is the slowest we can go */ } + spi_used_hz = (cdiv) ? (clk_hz / cdiv) : (clk_hz / 65536); bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); /* handle all the modes */ @@ -204,6 +207,37 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, bs->tx_len = tfr->len; bs->rx_len = tfr->len; + /* check if we shall run in polling mode */ + xfer_time_us = tfr->len * 9 * 1000000 / spi_used_hz; + if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US) { + /* enable HW block */ + bcm2835_wr(bs, BCM2835_SPI_CS, + cs | BCM2835_SPI_CS_TA); + /* set timeout to 4x the expected time, or 2 jiffies */ + timeout = jiffies + + max(4 * xfer_time_us * HZ / 1000000, 2uL); + /* loop until finished the transfer */ + while (bs->rx_len) { + /* read from fifo as much as possible */ + bcm2835_rd_fifo(bs); + /* fill in tx fifo as much as possible */ + bcm2835_wr_fifo(bs); + /* if we still expect some data after the read, + * check for a possible timeout + */ + if ((bs->rx_len) && (time_after(jiffies, timeout))) { + /* Transfer complete - reset SPI HW */ + bcm2835_spi_reset_hw(master); + /* and return timeout */ + return -ETIMEDOUT; + } + } + /* Transfer complete - reset SPI HW */ + bcm2835_spi_reset_hw(master); + /* and return without waiting for completion */ + return 0; + } + /* fill in fifo if we have gpio-cs * note that there have been rare events where the native-CS * flapped for <1us which may change the behaviour