Commit 7ba9bdcb authored by Douglas Anderson's avatar Douglas Anderson Committed by Mark Brown

spi: spi-geni-qcom: Don't keep a local state variable

The variable "cur_mcmd" kept track of our current state (idle, xfer,
cs, cancel).  We don't really need it, so get rid of it.  Instead:
* Use separate condition variables for "chip select done", "cancel
  done", and "abort done".  This is important so that if a "done"
  comes through (perhaps some previous interrupt finally came through)
  it can't confuse the cancel/abort function.
* Use the "done" interrupt only for when a chip select or transfer is
  done and we can tell the difference by looking at whether "cur_xfer"
  is NULL.

This is mostly a no-op change.  However, it is possible it could fix
an issue where a super delayed interrupt for a cancel command could
have confused our waiting for an abort command.
Signed-off-by: default avatarDouglas Anderson <dianders@chromium.org>
Reviewed-by: default avatarStephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/20200618080459.v4.5.Ib1e6855405fc9c99916ab7c7dee84d73a8bf3d68@changeidSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 902481a7
...@@ -63,13 +63,6 @@ ...@@ -63,13 +63,6 @@
#define TIMESTAMP_AFTER BIT(3) #define TIMESTAMP_AFTER BIT(3)
#define POST_CMD_DELAY BIT(4) #define POST_CMD_DELAY BIT(4)
enum spi_m_cmd_opcode {
CMD_NONE,
CMD_XFER,
CMD_CS,
CMD_CANCEL,
};
struct spi_geni_master { struct spi_geni_master {
struct geni_se se; struct geni_se se;
struct device *dev; struct device *dev;
...@@ -81,10 +74,11 @@ struct spi_geni_master { ...@@ -81,10 +74,11 @@ struct spi_geni_master {
unsigned int tx_rem_bytes; unsigned int tx_rem_bytes;
unsigned int rx_rem_bytes; unsigned int rx_rem_bytes;
const struct spi_transfer *cur_xfer; const struct spi_transfer *cur_xfer;
struct completion xfer_done; struct completion cs_done;
struct completion cancel_done;
struct completion abort_done;
unsigned int oversampling; unsigned int oversampling;
spinlock_t lock; spinlock_t lock;
enum spi_m_cmd_opcode cur_mcmd;
int irq; int irq;
}; };
...@@ -126,20 +120,23 @@ static void handle_fifo_timeout(struct spi_master *spi, ...@@ -126,20 +120,23 @@ static void handle_fifo_timeout(struct spi_master *spi,
struct geni_se *se = &mas->se; struct geni_se *se = &mas->se;
spin_lock_irq(&mas->lock); spin_lock_irq(&mas->lock);
reinit_completion(&mas->xfer_done); reinit_completion(&mas->cancel_done);
mas->cur_mcmd = CMD_CANCEL;
geni_se_cancel_m_cmd(se);
writel(0, se->base + SE_GENI_TX_WATERMARK_REG); writel(0, se->base + SE_GENI_TX_WATERMARK_REG);
mas->cur_xfer = NULL;
mas->tx_rem_bytes = mas->rx_rem_bytes = 0;
geni_se_cancel_m_cmd(se);
spin_unlock_irq(&mas->lock); spin_unlock_irq(&mas->lock);
time_left = wait_for_completion_timeout(&mas->xfer_done, HZ);
time_left = wait_for_completion_timeout(&mas->cancel_done, HZ);
if (time_left) if (time_left)
return; return;
spin_lock_irq(&mas->lock); spin_lock_irq(&mas->lock);
reinit_completion(&mas->xfer_done); reinit_completion(&mas->abort_done);
geni_se_abort_m_cmd(se); geni_se_abort_m_cmd(se);
spin_unlock_irq(&mas->lock); spin_unlock_irq(&mas->lock);
time_left = wait_for_completion_timeout(&mas->xfer_done, HZ);
time_left = wait_for_completion_timeout(&mas->abort_done, HZ);
if (!time_left) if (!time_left)
dev_err(mas->dev, "Failed to cancel/abort m_cmd\n"); dev_err(mas->dev, "Failed to cancel/abort m_cmd\n");
} }
...@@ -156,15 +153,14 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) ...@@ -156,15 +153,14 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
set_flag = !set_flag; set_flag = !set_flag;
spin_lock_irq(&mas->lock); spin_lock_irq(&mas->lock);
reinit_completion(&mas->xfer_done); reinit_completion(&mas->cs_done);
mas->cur_mcmd = CMD_CS;
if (set_flag) if (set_flag)
geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0); geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0);
else else
geni_se_setup_m_cmd(se, SPI_CS_DEASSERT, 0); geni_se_setup_m_cmd(se, SPI_CS_DEASSERT, 0);
spin_unlock_irq(&mas->lock); spin_unlock_irq(&mas->lock);
time_left = wait_for_completion_timeout(&mas->xfer_done, HZ); time_left = wait_for_completion_timeout(&mas->cs_done, HZ);
if (!time_left) if (!time_left)
handle_fifo_timeout(spi, NULL); handle_fifo_timeout(spi, NULL);
...@@ -383,7 +379,6 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, ...@@ -383,7 +379,6 @@ static void setup_fifo_xfer(struct spi_transfer *xfer,
mas->rx_rem_bytes = xfer->len; mas->rx_rem_bytes = xfer->len;
} }
writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG); writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG);
mas->cur_mcmd = CMD_XFER;
/* /*
* Lock around right before we start the transfer since our * Lock around right before we start the transfer since our
...@@ -520,11 +515,13 @@ static irqreturn_t geni_spi_isr(int irq, void *data) ...@@ -520,11 +515,13 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
geni_spi_handle_tx(mas); geni_spi_handle_tx(mas);
if (m_irq & M_CMD_DONE_EN) { if (m_irq & M_CMD_DONE_EN) {
if (mas->cur_mcmd == CMD_XFER) if (mas->cur_xfer) {
spi_finalize_current_transfer(spi); spi_finalize_current_transfer(spi);
else if (mas->cur_mcmd == CMD_CS) mas->cur_xfer = NULL;
complete(&mas->xfer_done); } else {
mas->cur_mcmd = CMD_NONE; complete(&mas->cs_done);
}
/* /*
* If this happens, then a CMD_DONE came before all the Tx * If this happens, then a CMD_DONE came before all the Tx
* buffer bytes were sent out. This is unusual, log this * buffer bytes were sent out. This is unusual, log this
...@@ -546,10 +543,10 @@ static irqreturn_t geni_spi_isr(int irq, void *data) ...@@ -546,10 +543,10 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
mas->rx_rem_bytes, mas->cur_bits_per_word); mas->rx_rem_bytes, mas->cur_bits_per_word);
} }
if ((m_irq & M_CMD_CANCEL_EN) || (m_irq & M_CMD_ABORT_EN)) { if (m_irq & M_CMD_CANCEL_EN)
mas->cur_mcmd = CMD_NONE; complete(&mas->cancel_done);
complete(&mas->xfer_done); if (m_irq & M_CMD_ABORT_EN)
} complete(&mas->abort_done);
/* /*
* It's safe or a good idea to Ack all of our our interrupts at the * It's safe or a good idea to Ack all of our our interrupts at the
...@@ -617,7 +614,9 @@ static int spi_geni_probe(struct platform_device *pdev) ...@@ -617,7 +614,9 @@ static int spi_geni_probe(struct platform_device *pdev)
spi->handle_err = handle_fifo_timeout; spi->handle_err = handle_fifo_timeout;
spi->set_cs = spi_geni_set_cs; spi->set_cs = spi_geni_set_cs;
init_completion(&mas->xfer_done); init_completion(&mas->cs_done);
init_completion(&mas->cancel_done);
init_completion(&mas->abort_done);
spin_lock_init(&mas->lock); spin_lock_init(&mas->lock);
pm_runtime_enable(dev); pm_runtime_enable(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment