From patchwork Mon May 2 16:49:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Marc Kleine-Budde X-Patchwork-Id: 12834477 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3004BC433EF for ; Mon, 2 May 2022 16:55:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=RkHCzFsJHUorfWd8f4LMOVM1YF2wbSyrTPkMwnq0LTY=; b=tAuP5vX28pj+/p YEK+/SIm681oWKE6olpgXm1MPE2ZK4DXdaqbOLmUm1TBboF4veWt904G3ap4oiF6aUw0daIfZ+az7 uSVkzhv3w83iJ4HpMn4phtOyBiJH4QvygXogr5LN9yWzEs5d7ylcimSoPxU2tEWavelrx8/tp2em8 T2kiNWZgPhtgNxh1MZL6p3OkBmQqyvz+3tG0POHgWv1E+/tys8PYE8hrJjYbXa4bIpvaAC9YnixRC oHD//LhG1UIXaE7Y6npwvqPoLFqGXQBF8yG3tlyZ9GDmyG0hUW/oMGyxjfG3+W2JRRQ42DZ2HUFtF 0kfWlx6VPC6gIk2On1hg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nlZJk-001qu8-AT; Mon, 02 May 2022 16:54:36 +0000 Received: from metis.ext.pengutronix.de ([2001:67c:670:201:290:27ff:fe1d:cc33]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nlZFD-001oKl-TO for linux-arm-kernel@lists.infradead.org; Mon, 02 May 2022 16:50:00 +0000 Received: from gallifrey.ext.pengutronix.de ([2001:67c:670:201:5054:ff:fe8d:eefb] helo=bjornoya.blackshift.org) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nlZFC-0002ue-Jp for linux-arm-kernel@lists.infradead.org; Mon, 02 May 2022 18:49:54 +0200 Received: from dspam.blackshift.org (localhost [127.0.0.1]) by bjornoya.blackshift.org (Postfix) with SMTP id 4E681734B1 for ; Mon, 2 May 2022 16:49:53 +0000 (UTC) Received: from hardanger.blackshift.org (unknown [172.20.34.65]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by bjornoya.blackshift.org (Postfix) with ESMTPS id 7914E73494; Mon, 2 May 2022 16:49:50 +0000 (UTC) Received: from blackshift.org (localhost [::1]) by hardanger.blackshift.org (OpenSMTPD) with ESMTP id 2eddc598; Mon, 2 May 2022 16:49:32 +0000 (UTC) From: Marc Kleine-Budde To: inux-spi@vger.kernel.org, Fabio Estevam , Marek Vasut Cc: kernel@pengutronix.de, linux-imx@nxp.com, Mark Brown , linux-arm-kernel@lists.infradead.org, Marc Kleine-Budde , David Jander Subject: [RFC 8/9] spi: spi-imx: add PIO polling support Date: Mon, 2 May 2022 18:49:30 +0200 Message-Id: <20220502164931.1956137-9-mkl@pengutronix.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220502164931.1956137-1-mkl@pengutronix.de> References: <20220502164931.1956137-1-mkl@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:201:5054:ff:fe8d:eefb X-SA-Exim-Mail-From: mkl@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-arm-kernel@lists.infradead.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220502_094956_001363_D95C1699 X-CRM114-Status: GOOD ( 23.39 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The driver supports several modes, one of them is PIO/IRQ "spi_imx_pio_transfer()". The data is exchanged with the IP core using PIO, an IRQ is setup to signal empty/full FIFOs and the end of the transfer. The IRQ and scheduling overhead for short transfers is significant. Using polling instead of IRQs can be beneficial to reduce the overall CPU load, especially on small transfer workloads. On an imx6 single core, a given RX workload of the mcp251xfd driver results in 40% CPU load. Using polling mode reduces the CPU load to 30%. This patch adds PIO polling support to the driver. For transfers with a duration of less than 30 µs the polling mode instead of IRQ based PIO mode is used. 30 µs seems to be a good compromise, which is used the by the SPI drivers for the raspberry Pi (spi-bcm2835, spi-bcm2835), too. Co-developed-by: David Jander Signed-off-by: David Jander Signed-off-by: Marc Kleine-Budde --- drivers/spi/spi-imx.c | 66 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index ec6758e032ff..798a5182b849 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -31,6 +31,12 @@ static bool use_dma = true; module_param(use_dma, bool, 0644); MODULE_PARM_DESC(use_dma, "Enable usage of DMA when available (default)"); +/* define polling limits */ +static unsigned int polling_limit_us = 30; +module_param(polling_limit_us, uint, 0664); +MODULE_PARM_DESC(polling_limit_us, + "time in us to run a transfer in polling mode\n"); + #define MXC_RPM_TIMEOUT 2000 /* 2000ms */ #define MXC_CSPIRXDATA 0x00 @@ -1469,6 +1475,54 @@ static int spi_imx_pio_transfer(struct spi_device *spi, return 0; } +static int spi_imx_poll_transfer(struct spi_device *spi, + struct spi_transfer *transfer) +{ + struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller); + unsigned long timeout; + + spi_imx->tx_buf = transfer->tx_buf; + spi_imx->rx_buf = transfer->rx_buf; + spi_imx->count = transfer->len; + spi_imx->txfifo = 0; + spi_imx->remainder = 0; + + /* fill in the fifo before timeout calculations if we are + * interrupted here, then the data is getting transferred by + * the HW while we are interrupted + */ + spi_imx_push(spi_imx); + + timeout = spi_imx_calculate_timeout(spi_imx, transfer->len) + jiffies; + while (spi_imx->txfifo) { + /* RX */ + while (spi_imx->txfifo && + spi_imx->devtype_data->rx_available(spi_imx)) { + spi_imx->rx(spi_imx); + spi_imx->txfifo--; + } + + /* TX */ + if (spi_imx->count) { + spi_imx_push(spi_imx); + continue; + } + + if (spi_imx->txfifo && + time_after(jiffies, timeout)) { + + dev_err_ratelimited(&spi->dev, + "timeout period reached: jiffies: %lu- falling back to interrupt mode\n", + jiffies - timeout); + + /* fall back to interrupt mode */ + return spi_imx_pio_transfer(spi, transfer); + } + } + + return 0; +} + static int spi_imx_pio_transfer_slave(struct spi_device *spi, struct spi_transfer *transfer) { @@ -1518,6 +1572,7 @@ static int spi_imx_transfer_one(struct spi_controller *controller, struct spi_transfer *transfer) { struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller); + unsigned long hz_per_byte, byte_limit; spi_imx_setupxfer(spi, transfer); transfer->effective_speed_hz = spi_imx->spi_bus_clk; @@ -1529,6 +1584,17 @@ static int spi_imx_transfer_one(struct spi_controller *controller, if (spi_imx->slave_mode) return spi_imx_pio_transfer_slave(spi, transfer); + /* + * Calculate the estimated time in us the transfer runs. Find + * the number of Hz per byte per polling limit. + */ + hz_per_byte = polling_limit_us ? ((8 + 4) * USEC_PER_SEC) / polling_limit_us : 0; + byte_limit = hz_per_byte ? transfer->effective_speed_hz / hz_per_byte : 1; + + /* run in polling mode for short transfers */ + if (transfer->len < byte_limit) + return spi_imx_poll_transfer(spi, transfer); + if (spi_imx->usedma) return spi_imx_dma_transfer(spi_imx, transfer);