From patchwork Wed Oct 28 15:16:02 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Ribalda Delgado X-Patchwork-Id: 7513031 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id F41279F40A for ; Wed, 28 Oct 2015 15:16:10 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0336F205E5 for ; Wed, 28 Oct 2015 15:16:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0FF8720606 for ; Wed, 28 Oct 2015 15:16:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755963AbbJ1PQH (ORCPT ); Wed, 28 Oct 2015 11:16:07 -0400 Received: from mail-lf0-f54.google.com ([209.85.215.54]:34704 "EHLO mail-lf0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754713AbbJ1PQG (ORCPT ); Wed, 28 Oct 2015 11:16:06 -0400 Received: by lfaz124 with SMTP id z124so5313451lfa.1; Wed, 28 Oct 2015 08:16:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=kd2Mm9i+5p+EbnnVlnztV7orXC5/nw3GdaN1QftYT8E=; b=hPqhdhLG+LCJXJfl10kDGhapGE7iU15xPNNQ2L/owyd05Kukuba1ymQAETtqAdnlS8 q+EkSM78K9Wryt9AVVJLvcFeY6GBJqk3COdxEUjDQV4uun89zWAMsGwGqKZcJv35f/Nt zMJY5pPuN7sg4e5gYDq5GxIleAe9EqrG4CxEJNQC+Yqt8WsiQ3mxyaiVk4DBen1U34YC iPKMUEffsIdqcm962tva0mRE0c1nfroUhoZMyjh3huPyPE2D2mJ5PJGjP0Yy+27F5Pg5 W/qqUJNPSbX7GuNdfYmDWSV+pkmZJ4piDmOi41Pt4smlUylMNL70lqxKoAmWzj7Bf9OF 3yUQ== X-Received: by 10.25.165.84 with SMTP id o81mr15649587lfe.80.1446045364692; Wed, 28 Oct 2015 08:16:04 -0700 (PDT) Received: from neopili.qtec.com (cpe.xe-3-0-1-778.vbrnqe10.dk.customer.tdc.net. [80.197.57.18]) by smtp.gmail.com with ESMTPSA id b142sm4532277lfb.46.2015.10.28.08.16.03 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 28 Oct 2015 08:16:03 -0700 (PDT) From: Ricardo Ribalda Delgado To: Mark Brown , Michal Simek , =?UTF-8?q?S=C3=B6ren=20Brinkmann?= , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, Edward Kigwana , Lars-Peter Clausen Cc: Ricardo Ribalda Delgado Subject: [PATCH] spi/spi-xilinx: Fix race condition on last word read Date: Wed, 28 Oct 2015 16:16:02 +0100 Message-Id: <1446045362-13650-1-git-send-email-ricardo.ribalda@gmail.com> X-Mailer: git-send-email 2.6.1 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.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, 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 Some users have reported that in polled mode the driver fails randomly to read the last word of the transfer. The end condition used for the transmissions (in polled and irq mode) has been the TX_EMPTY flag. But Lars-Peter Clausen has identified a delay from the TX_EMPTY to the actual end of the data rx. I believe that this race condition has not been detected until now because of the latency added by the IRQ handler or the PCIe bridge. This bugs affects setups with low latency access to the spi core. This patch replaces the readout logic: For all the words, except the last one, the TX_EMPTY flag is used (and cached). If !TX_EMPY or is the last word. The status register is read and the RX_EMPTY flag is used. The performance is not affected: there is an extra read of the Status Register, but the readout can start as soon as there is a word in the buffer. Reported-by: Edward Kigwana Initial-fix-by: Lars-Peter Clausen Cc: Edward Kigwana Signed-off-by: Ricardo Ribalda Delgado --- drivers/spi/spi-xilinx.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index a339c1e9997a..3009121173cd 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -270,6 +270,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) while (remaining_words) { int n_words, tx_words, rx_words; + u32 sr; n_words = min(remaining_words, xspi->buffer_size); @@ -284,24 +285,33 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) if (use_irq) { xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); wait_for_completion(&xspi->done); - } else - while (!(xspi->read_fn(xspi->regs + XSPI_SR_OFFSET) & - XSPI_SR_TX_EMPTY_MASK)) - ; - - /* A transmit has just completed. Process received data and - * check for more data to transmit. Always inhibit the - * transmitter while the Isr refills the transmit register/FIFO, - * or make sure it is stopped if we're done. - */ - if (use_irq) + /* A transmit has just completed. Process received data + * and check for more data to transmit. Always inhibit + * the transmitter while the Isr refills the transmit + * register/FIFO, or make sure it is stopped if we're + * done. + */ xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, - xspi->regs + XSPI_CR_OFFSET); + xspi->regs + XSPI_CR_OFFSET); + sr = XSPI_SR_TX_EMPTY_MASK; + } else + sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); /* Read out all the data from the Rx FIFO */ rx_words = n_words; - while (rx_words--) - xilinx_spi_rx(xspi); + while (rx_words) { + if ((sr & XSPI_SR_TX_EMPTY_MASK) && (rx_words > 1)) { + xilinx_spi_rx(xspi); + rx_words--; + continue; + } + + sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); + if (!(sr & XSPI_SR_RX_EMPTY_MASK)) { + xilinx_spi_rx(xspi); + rx_words--; + } + } remaining_words -= n_words; }