Skip to content

Commit f5e6c33

Browse files
committed
Merge tag 'spi-fix-v5.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi fixes from Mark Brown: "A couple of core fixes here, both to do with handling of drivers which don't report their maximum speed since we factored some of the handling for transfer speeds out into the core in the previous release. There's also some driver specific fixes, including a relatively large set for some races around timeouts in spi-geni-qcom" * tag 'spi-fix-v5.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: fix the divide by 0 error when calculating xfer waiting time spi: Fix the clamping of spi->max_speed_hz spi: altera: fix return value for altera_spi_txrx() spi: stm32: FIFO threshold level - fix align packet size spi: spi-geni-qcom: Print an error when we timeout setting the CS spi: spi-geni-qcom: Don't try to set CS if an xfer is pending spi: spi-geni-qcom: Fail new xfers if xfer/cancel/abort pending spi: spi-geni-qcom: Fix geni_spi_isr() NULL dereference in timeout case
2 parents a1a7b4f + 6170d07 commit f5e6c33

File tree

4 files changed

+104
-21
lines changed

4 files changed

+104
-21
lines changed

drivers/spi/spi-altera.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -189,24 +189,26 @@ static int altera_spi_txrx(struct spi_master *master,
189189

190190
/* send the first byte */
191191
altera_spi_tx_word(hw);
192-
} else {
193-
while (hw->count < hw->len) {
194-
altera_spi_tx_word(hw);
195192

196-
for (;;) {
197-
altr_spi_readl(hw, ALTERA_SPI_STATUS, &val);
198-
if (val & ALTERA_SPI_STATUS_RRDY_MSK)
199-
break;
193+
return 1;
194+
}
195+
196+
while (hw->count < hw->len) {
197+
altera_spi_tx_word(hw);
200198

201-
cpu_relax();
202-
}
199+
for (;;) {
200+
altr_spi_readl(hw, ALTERA_SPI_STATUS, &val);
201+
if (val & ALTERA_SPI_STATUS_RRDY_MSK)
202+
break;
203203

204-
altera_spi_rx_word(hw);
204+
cpu_relax();
205205
}
206-
spi_finalize_current_transfer(master);
206+
207+
altera_spi_rx_word(hw);
207208
}
209+
spi_finalize_current_transfer(master);
208210

209-
return t->len;
211+
return 0;
210212
}
211213

212214
static irqreturn_t altera_spi_irq(int irq, void *dev)

drivers/spi/spi-geni-qcom.c

Lines changed: 80 additions & 4 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,10 +200,21 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
158200
if (set_flag == mas->cs_flag)
159201
return;
160202

161-
mas->cs_flag = set_flag;
162-
163203
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+
164210
spin_lock_irq(&mas->lock);
211+
if (mas->cur_xfer) {
212+
dev_err(mas->dev, "Can't set CS when prev xfer running\n");
213+
spin_unlock_irq(&mas->lock);
214+
goto exit;
215+
}
216+
217+
mas->cs_flag = set_flag;
165218
reinit_completion(&mas->cs_done);
166219
if (set_flag)
167220
geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0);
@@ -170,9 +223,12 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
170223
spin_unlock_irq(&mas->lock);
171224

172225
time_left = wait_for_completion_timeout(&mas->cs_done, HZ);
173-
if (!time_left)
226+
if (!time_left) {
227+
dev_warn(mas->dev, "Timeout setting chip select\n");
174228
handle_fifo_timeout(spi, NULL);
229+
}
175230

231+
exit:
176232
pm_runtime_put(mas->dev);
177233
}
178234

@@ -280,6 +336,9 @@ static int spi_geni_prepare_message(struct spi_master *spi,
280336
int ret;
281337
struct spi_geni_master *mas = spi_master_get_devdata(spi);
282338

339+
if (spi_geni_is_abort_still_pending(mas))
340+
return -EBUSY;
341+
283342
ret = setup_fifo_params(spi_msg->spi, spi);
284343
if (ret)
285344
dev_err(mas->dev, "Couldn't select mode %d\n", ret);
@@ -354,6 +413,12 @@ static bool geni_spi_handle_tx(struct spi_geni_master *mas)
354413
unsigned int bytes_per_fifo_word = geni_byte_per_fifo_word(mas);
355414
unsigned int i = 0;
356415

416+
/* Stop the watermark IRQ if nothing to send */
417+
if (!mas->cur_xfer) {
418+
writel(0, se->base + SE_GENI_TX_WATERMARK_REG);
419+
return false;
420+
}
421+
357422
max_bytes = (mas->tx_fifo_depth - mas->tx_wm) * bytes_per_fifo_word;
358423
if (mas->tx_rem_bytes < max_bytes)
359424
max_bytes = mas->tx_rem_bytes;
@@ -396,6 +461,14 @@ static void geni_spi_handle_rx(struct spi_geni_master *mas)
396461
if (rx_last_byte_valid && rx_last_byte_valid < 4)
397462
rx_bytes -= bytes_per_fifo_word - rx_last_byte_valid;
398463
}
464+
465+
/* Clear out the FIFO and bail if nowhere to put it */
466+
if (!mas->cur_xfer) {
467+
for (i = 0; i < DIV_ROUND_UP(rx_bytes, bytes_per_fifo_word); i++)
468+
readl(se->base + SE_GENI_RX_FIFOn);
469+
return;
470+
}
471+
399472
if (mas->rx_rem_bytes < rx_bytes)
400473
rx_bytes = mas->rx_rem_bytes;
401474

@@ -495,6 +568,9 @@ static int spi_geni_transfer_one(struct spi_master *spi,
495568
{
496569
struct spi_geni_master *mas = spi_master_get_devdata(spi);
497570

571+
if (spi_geni_is_abort_still_pending(mas))
572+
return -EBUSY;
573+
498574
/* Terminate and return success for 0 byte length transfer */
499575
if (!xfer->len)
500576
return 0;

drivers/spi/spi-stm32.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -493,9 +493,9 @@ static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi, u32 xfer_len)
493493

494494
/* align packet size with data registers access */
495495
if (spi->cur_bpw > 8)
496-
fthlv -= (fthlv % 2); /* multiple of 2 */
496+
fthlv += (fthlv % 2) ? 1 : 0;
497497
else
498-
fthlv -= (fthlv % 4); /* multiple of 4 */
498+
fthlv += (fthlv % 4) ? (4 - (fthlv % 4)) : 0;
499499

500500
if (!fthlv)
501501
fthlv = 1;

drivers/spi/spi.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,7 @@ static int spi_transfer_wait(struct spi_controller *ctlr,
11081108
{
11091109
struct spi_statistics *statm = &ctlr->statistics;
11101110
struct spi_statistics *stats = &msg->spi->statistics;
1111+
u32 speed_hz = xfer->speed_hz;
11111112
unsigned long long ms;
11121113

11131114
if (spi_controller_is_slave(ctlr)) {
@@ -1116,8 +1117,11 @@ static int spi_transfer_wait(struct spi_controller *ctlr,
11161117
return -EINTR;
11171118
}
11181119
} else {
1120+
if (!speed_hz)
1121+
speed_hz = 100000;
1122+
11191123
ms = 8LL * 1000LL * xfer->len;
1120-
do_div(ms, xfer->speed_hz);
1124+
do_div(ms, speed_hz);
11211125
ms += ms + 200; /* some tolerance */
11221126

11231127
if (ms > UINT_MAX)
@@ -3378,8 +3382,9 @@ int spi_setup(struct spi_device *spi)
33783382
if (status)
33793383
return status;
33803384

3381-
if (!spi->max_speed_hz ||
3382-
spi->max_speed_hz > spi->controller->max_speed_hz)
3385+
if (spi->controller->max_speed_hz &&
3386+
(!spi->max_speed_hz ||
3387+
spi->max_speed_hz > spi->controller->max_speed_hz))
33833388
spi->max_speed_hz = spi->controller->max_speed_hz;
33843389

33853390
mutex_lock(&spi->controller->io_mutex);

0 commit comments

Comments
 (0)