2017-03-13 12:30:10 +00:00
|
|
|
From 0f32f976ebaa7d8643fcd9419f12bc801ba14407 Mon Sep 17 00:00:00 2001
|
2017-02-16 11:25:25 +00:00
|
|
|
From: Matthew McClintock <mmcclint@codeaurora.org>
|
|
|
|
Date: Thu, 10 Mar 2016 16:44:55 -0600
|
2017-03-13 12:30:10 +00:00
|
|
|
Subject: [PATCH 07/69] spi: qup: properly detect extra interrupts
|
2017-02-16 11:25:25 +00:00
|
|
|
|
|
|
|
It's possible for a SPI transaction to complete and get another
|
|
|
|
interrupt and have it processed on the same spi_transfer before the
|
|
|
|
transfer_one can set it to NULL.
|
|
|
|
|
|
|
|
This masks unexpected interrupts, so let's set the spi_transfer to
|
|
|
|
NULL in the interrupt once the transaction is done. So we can
|
|
|
|
properly detect these bad interrupts and print warning messages.
|
|
|
|
|
|
|
|
Signed-off-by: Matthew McClintock <mmcclint@codeaurora.org>
|
|
|
|
---
|
2017-03-13 12:30:10 +00:00
|
|
|
drivers/spi/spi-qup.c | 15 +++++++++------
|
2017-02-16 11:25:25 +00:00
|
|
|
1 file changed, 9 insertions(+), 6 deletions(-)
|
|
|
|
|
|
|
|
--- a/drivers/spi/spi-qup.c
|
|
|
|
+++ b/drivers/spi/spi-qup.c
|
|
|
|
@@ -507,6 +507,7 @@ static irqreturn_t spi_qup_qup_irq(int i
|
|
|
|
u32 opflags, qup_err, spi_err;
|
|
|
|
unsigned long flags;
|
|
|
|
int error = 0;
|
|
|
|
+ bool done = 0;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&controller->lock, flags);
|
|
|
|
xfer = controller->xfer;
|
|
|
|
@@ -565,16 +566,19 @@ static irqreturn_t spi_qup_qup_irq(int i
|
|
|
|
spi_qup_write(controller, xfer);
|
|
|
|
}
|
|
|
|
|
|
|
|
- spin_lock_irqsave(&controller->lock, flags);
|
|
|
|
- controller->error = error;
|
|
|
|
- controller->xfer = xfer;
|
|
|
|
- spin_unlock_irqrestore(&controller->lock, flags);
|
|
|
|
-
|
|
|
|
/* re-read opflags as flags may have changed due to actions above */
|
|
|
|
opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
|
|
|
|
|
|
|
|
if ((controller->rx_bytes == xfer->len &&
|
|
|
|
(opflags & QUP_OP_MAX_INPUT_DONE_FLAG)) || error)
|
|
|
|
+ done = true;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&controller->lock, flags);
|
|
|
|
+ controller->error = error;
|
|
|
|
+ controller->xfer = done ? NULL : xfer;
|
|
|
|
+ spin_unlock_irqrestore(&controller->lock, flags);
|
|
|
|
+
|
|
|
|
+ if (done)
|
|
|
|
complete(&controller->done);
|
|
|
|
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
@@ -767,7 +771,6 @@ static int spi_qup_transfer_one(struct s
|
|
|
|
exit:
|
|
|
|
spi_qup_set_state(controller, QUP_STATE_RESET);
|
|
|
|
spin_lock_irqsave(&controller->lock, flags);
|
|
|
|
- controller->xfer = NULL;
|
|
|
|
if (!ret)
|
|
|
|
ret = controller->error;
|
|
|
|
spin_unlock_irqrestore(&controller->lock, flags);
|