Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp2907490ybi; Mon, 10 Jun 2019 00:23:23 -0700 (PDT) X-Google-Smtp-Source: APXvYqw0DhkL9kRjz3a0vxE2gfrgNpkVNS+8zouQ/+QGxR+4jxX2Th6rjpYEu7S96KM4Tt+crqSF X-Received: by 2002:a17:902:bd06:: with SMTP id p6mr68007049pls.112.1560151403719; Mon, 10 Jun 2019 00:23:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1560151403; cv=none; d=google.com; s=arc-20160816; b=dWW39wX2uVJK7y8PcC0q/HJ7pCUDdSplTV3yI4KRwSPdpbX1otG8A2RED2mQZ0t7iz TklJhgupFrU8vJ7n0kh7de2c+9Jg6vRB14mElLB4vkKRLOBfmeD24d7SgXqnDmus5NVs ATIut5nxzdgczUNlCkYFmWrosrhehVRXWYuk92KsibgqQGtM7F6N4Lcp29TRMPKBXmLm 738B2rtI105LDHDqHok5WLGBevxaNWzOvgrg4fbyBT6PeJGapW6U7R5S8c5R5kl9hqzN B+kr8axQM0BqJFeFWMXtxG/ljNiVziBhXQQMTkrH5Uv5M/5y4nOV72fAHJrOJJN/v4Tp rK7A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=jbLxpWuUonBzNVgnD/xYkcw7GrDlHMS37R/RDa4E2Kg=; b=JREmwoYW5I4F2d2xL8Ah+j0q305NlqX84/rcgcd3JmhA2ECWp3e41OC+AA7qGWb0Pd Iv+htOBN7AJFJwb7j8mlqKWXYuPyrLz6+jU/SjMXfpeKpfobd9y5PhRa7HnNENPwofbP qExG9xPLC2iQwgEsPDHTOv2hmNavs9MSMQ3Mem8pOneNUGK9Dv6w4jd+E7HfHGjK6QWJ 7L19Xv8mEcwBjtRk5LzGNSz9Mv1iwDgvzhXY3TWEmZMqmb/oSeW7X2+S/bdETW3dxtY7 Gjj9vRHCdSmdUpu5ZHixDvFEz0pQcXo8DzMoUp61jV+B0xvQFXTNZ5rBfPfUZM5LlOyh bToA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=abcOHs1o; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id cd17si10423145plb.210.2019.06.10.00.23.09; Mon, 10 Jun 2019 00:23:23 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=abcOHs1o; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387966AbfFJHWu (ORCPT + 99 others); Mon, 10 Jun 2019 03:22:50 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:34331 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387893AbfFJHWu (ORCPT ); Mon, 10 Jun 2019 03:22:50 -0400 Received: by mail-wr1-f65.google.com with SMTP id e16so8040522wrn.1 for ; Mon, 10 Jun 2019 00:22:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=jbLxpWuUonBzNVgnD/xYkcw7GrDlHMS37R/RDa4E2Kg=; b=abcOHs1oSH8mEsGUMSJzy5b1RaEKPt7RkL3pIvcDpv2/Oh1dFwoc/BMA9x2X7NGuaU 8BakLflGRhZ+v7Y2Sai9DDGqdZCjRGFLOaU7hwveLAXKQ2dSBTr+7P9N2dQlWWMx3fMw 6FnwUAfnPZa8o8RPcbm3PRlnj+nvkvPfHYD0hbiSX2lafD7Q641AJSoxEAnYBOscYGlD ZgU4LxAwRd8A20yrnIphC2fra/0ugdtvIuay4c+RJ+ABZ64movos5GBB2Fm+D1Tf5VkN MySvEsSsERbcPD6s4EOyp9rdNyA3RjB5HHhv+Bz7cSxLEG9/5FqmI0MZEcZQIK8e5wyR 2I4A== 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:mime-version :content-transfer-encoding; bh=jbLxpWuUonBzNVgnD/xYkcw7GrDlHMS37R/RDa4E2Kg=; b=YnthWai0QCxN1UU0sNxayc9RGCRhpniNld1SI+73VPn3GWth3zz7jskyPjzPRGkcZD 92Rk7x45ZiWNk7SDBS3FK4+P79kiTbOReDoOSN7vOo1PzgEeTkpZoiHtEVSTbneMLvnY Qw1zl4Ccm0/kAzJByqqKzTJAwN9UWz++dhEkSCP8b+1q6d8y9tpH5N2nZP1l+KxUv4rT ogvH0lMRp9dKeJhoBQa79dqHA3QwWkd3vxKcCoZA62dp21N1/x+Buha/WKdW1y2KS56n HsWdUAEFWCSlNSomU2sU8DPTSNCxjVqvyaR92Hyod+m0Wx2vpxu4R6fxzft40yVsAE+s FeOQ== X-Gm-Message-State: APjAAAW2pYe7tHGRNnJCkF2LvJToj2vWQaYy9GSZUc6n7vSX2T+CMdw0 IQeYoDsvm0kfcW+Z0HRWsufzZg== X-Received: by 2002:a5d:4cc3:: with SMTP id c3mr17499958wrt.259.1560151367402; Mon, 10 Jun 2019 00:22:47 -0700 (PDT) Received: from localhost.localdomain (233.red-79-146-84.dynamicip.rima-tde.net. [79.146.84.233]) by smtp.gmail.com with ESMTPSA id y9sm12587654wma.1.2019.06.10.00.22.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 10 Jun 2019 00:22:46 -0700 (PDT) From: Jorge Ramirez-Ortiz To: jorge.ramirez-ortiz@linaro.org, agross@kernel.org, david.brown@linaro.org, broonie@kernel.org Cc: linux-arm-msm@vger.kernel.org, linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, bjorn.andersson@linaro.org, khasim.mohammed@linaro.org Subject: [PATCH] spi: qup: fix PIO/DMA transfers. Date: Mon, 10 Jun 2019 09:22:43 +0200 Message-Id: <20190610072243.19710-1-jorge.ramirez-ortiz@linaro.org> X-Mailer: git-send-email 2.21.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org - DMA/PIO: If an error IRQ occurred during PIO or DMA mode make sure to log it so on completion the transfer can be marked as an error. - PIO: Do not complete a transaction until all data has been transferred or an error IRQ was flagged. 1) If there was no error IRQ, ignore the done flag IRQ (QUP_OP_MAX_INPUT_DONE_FLAG) until all data for the transfer has been processed: not doing so risks completing the transfer returning uninitialized data in the buffers. 2) Under stress testing we have identified the need to protect read/write operations against spurious IN/OUT service events. Signed-off-by: Jorge Ramirez-Ortiz --- drivers/spi/spi-qup.c | 51 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 974a8ce58b68..0a2ffd2f968a 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -281,6 +281,9 @@ static void spi_qup_read(struct spi_qup *controller, u32 *opflags) writel_relaxed(QUP_OP_IN_SERVICE_FLAG, controller->base + QUP_OPERATIONAL); + if (!remainder) + goto exit; + if (is_block_mode) { num_words = (remainder > words_per_block) ? words_per_block : remainder; @@ -310,11 +313,13 @@ static void spi_qup_read(struct spi_qup *controller, u32 *opflags) * to refresh opflags value because MAX_INPUT_DONE_FLAG may now be * present and this is used to determine if transaction is complete */ - *opflags = readl_relaxed(controller->base + QUP_OPERATIONAL); - if (is_block_mode && *opflags & QUP_OP_MAX_INPUT_DONE_FLAG) - writel_relaxed(QUP_OP_IN_SERVICE_FLAG, - controller->base + QUP_OPERATIONAL); - +exit: + if (!remainder) { + *opflags = readl_relaxed(controller->base + QUP_OPERATIONAL); + if (is_block_mode && *opflags & QUP_OP_MAX_INPUT_DONE_FLAG) + writel_relaxed(QUP_OP_IN_SERVICE_FLAG, + controller->base + QUP_OPERATIONAL); + } } static void spi_qup_write_to_fifo(struct spi_qup *controller, u32 num_words) @@ -362,6 +367,10 @@ static void spi_qup_write(struct spi_qup *controller) writel_relaxed(QUP_OP_OUT_SERVICE_FLAG, controller->base + QUP_OPERATIONAL); + /* make sure the interrupt is valid */ + if (!remainder) + return; + if (is_block_mode) { num_words = (remainder > words_per_block) ? words_per_block : remainder; @@ -575,10 +584,24 @@ static int spi_qup_do_pio(struct spi_device *spi, struct spi_transfer *xfer, return 0; } +static bool spi_qup_data_pending(struct spi_qup *controller) +{ + unsigned int remainder_tx, remainder_rx; + + remainder_tx = DIV_ROUND_UP(spi_qup_len(controller) - + controller->tx_bytes, controller->w_size); + + remainder_rx = DIV_ROUND_UP(spi_qup_len(controller) - + controller->rx_bytes, controller->w_size); + + return remainder_tx || remainder_rx; +} + static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) { struct spi_qup *controller = dev_id; u32 opflags, qup_err, spi_err; + unsigned long flags; int error = 0; qup_err = readl_relaxed(controller->base + QUP_ERROR_FLAGS); @@ -610,6 +633,11 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) error = -EIO; } + spin_lock_irqsave(&controller->lock, flags); + if (!controller->error) + controller->error = error; + spin_unlock_irqrestore(&controller->lock, flags); + if (spi_qup_is_dma_xfer(controller->mode)) { writel_relaxed(opflags, controller->base + QUP_OPERATIONAL); } else { @@ -618,11 +646,22 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) if (opflags & QUP_OP_OUT_SERVICE_FLAG) spi_qup_write(controller); + + if (!spi_qup_data_pending(controller)) + complete(&controller->done); } - if ((opflags & QUP_OP_MAX_INPUT_DONE_FLAG) || error) + if (error) complete(&controller->done); + if (opflags & QUP_OP_MAX_INPUT_DONE_FLAG) { + if (!spi_qup_is_dma_xfer(controller->mode)) { + if (spi_qup_data_pending(controller)) + return IRQ_HANDLED; + } + complete(&controller->done); + } + return IRQ_HANDLED; } -- 2.21.0