Skip to content

Commit 690d8b9

Browse files
diandersbroonie
authored andcommitted
spi: spi-geni-qcom: Fail new xfers if xfer/cancel/abort pending
If we got a timeout when trying to send an abort command then it means that we just got 3 timeouts in a row: 1. The original timeout that caused handle_fifo_timeout() to be called. 2. A one second timeout waiting for the cancel command to finish. 3. A one second timeout waiting for the abort command to finish. SPI is clocked by the controller, so nothing (aside from a hardware fault or a totally broken sequencer) should be causing the actual commands to fail in hardware. However, even though the hardware itself is not expected to fail (and it'd be hard to predict how we should handle things if it did), it's easy to hit the timeout case by simply blocking our interrupt handler from running for a long period of time. Obviously the system is in pretty bad shape if a interrupt handler is blocked for > 2 seconds, but there are certainly bugs (even bugs in other unrelated drivers) that can make this happen. Let's make things a bit more robust against this case. If we fail to abort we'll set a flag and then we'll block all future transfers until we have no more interrupts pending. Fixes: 561de45 ("spi: spi-geni-qcom: Add SPI driver support for GENI based QUP") Signed-off-by: Douglas Anderson <dianders@chromium.org> Reviewed-by: Stephen Boyd <swboyd@chromium.org> Link: https://lore.kernel.org/r/20201217142842.v3.2.Ibade998ed587e070388b4bf58801f1107a40eb53@changeid Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 4aa1464 commit 690d8b9

1 file changed

Lines changed: 57 additions & 2 deletions

File tree

drivers/spi/spi-geni-qcom.c

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ struct spi_geni_master {
8383
spinlock_t lock;
8484
int irq;
8585
bool cs_flag;
86+
bool abort_failed;
8687
};
8788

8889
static int get_spi_clk_cfg(unsigned int speed_hz,
@@ -141,8 +142,49 @@ static void handle_fifo_timeout(struct spi_master *spi,
141142
spin_unlock_irq(&mas->lock);
142143

143144
time_left = wait_for_completion_timeout(&mas->abort_done, HZ);
144-
if (!time_left)
145+
if (!time_left) {
145146
dev_err(mas->dev, "Failed to cancel/abort m_cmd\n");
147+
148+
/*
149+
* No need for a lock since SPI core has a lock and we never
150+
* access this from an interrupt.
151+
*/
152+
mas->abort_failed = true;
153+
}
154+
}
155+
156+
static bool spi_geni_is_abort_still_pending(struct spi_geni_master *mas)
157+
{
158+
struct geni_se *se = &mas->se;
159+
u32 m_irq, m_irq_en;
160+
161+
if (!mas->abort_failed)
162+
return false;
163+
164+
/*
165+
* The only known case where a transfer times out and then a cancel
166+
* times out then an abort times out is if something is blocking our
167+
* interrupt handler from running. Avoid starting any new transfers
168+
* until that sorts itself out.
169+
*/
170+
spin_lock_irq(&mas->lock);
171+
m_irq = readl(se->base + SE_GENI_M_IRQ_STATUS);
172+
m_irq_en = readl(se->base + SE_GENI_M_IRQ_EN);
173+
spin_unlock_irq(&mas->lock);
174+
175+
if (m_irq & m_irq_en) {
176+
dev_err(mas->dev, "Interrupts pending after abort: %#010x\n",
177+
m_irq & m_irq_en);
178+
return true;
179+
}
180+
181+
/*
182+
* If we're here the problem resolved itself so no need to check more
183+
* on future transfers.
184+
*/
185+
mas->abort_failed = false;
186+
187+
return false;
146188
}
147189

148190
static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
@@ -158,9 +200,15 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
158200
if (set_flag == mas->cs_flag)
159201
return;
160202

203+
pm_runtime_get_sync(mas->dev);
204+
205+
if (spi_geni_is_abort_still_pending(mas)) {
206+
dev_err(mas->dev, "Can't set chip select\n");
207+
goto exit;
208+
}
209+
161210
mas->cs_flag = set_flag;
162211

163-
pm_runtime_get_sync(mas->dev);
164212
spin_lock_irq(&mas->lock);
165213
reinit_completion(&mas->cs_done);
166214
if (set_flag)
@@ -173,6 +221,7 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
173221
if (!time_left)
174222
handle_fifo_timeout(spi, NULL);
175223

224+
exit:
176225
pm_runtime_put(mas->dev);
177226
}
178227

@@ -280,6 +329,9 @@ static int spi_geni_prepare_message(struct spi_master *spi,
280329
int ret;
281330
struct spi_geni_master *mas = spi_master_get_devdata(spi);
282331

332+
if (spi_geni_is_abort_still_pending(mas))
333+
return -EBUSY;
334+
283335
ret = setup_fifo_params(spi_msg->spi, spi);
284336
if (ret)
285337
dev_err(mas->dev, "Couldn't select mode %d\n", ret);
@@ -509,6 +561,9 @@ static int spi_geni_transfer_one(struct spi_master *spi,
509561
{
510562
struct spi_geni_master *mas = spi_master_get_devdata(spi);
511563

564+
if (spi_geni_is_abort_still_pending(mas))
565+
return -EBUSY;
566+
512567
/* Terminate and return success for 0 byte length transfer */
513568
if (!xfer->len)
514569
return 0;

0 commit comments

Comments
 (0)