Skip to content

Commit 5063578

Browse files
committed
Merge tag 'spi-fix-v6.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi fixes from Mark Brown: "Several fixes that came in since the merge window, the major one being a fix for the spi-mux driver which was broken by the performance optimisations due to it peering inside the core's data structures more than it should" * tag 'spi-fix-v6.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: spi: Fix queue hang if previous transfer failed spi: mux: Fix mux interaction with fast path optimisations spi: cadence-quadspi: Disable irqs during indirect reads spi: bitbang: Fix lsb-first Rx
2 parents c5e68c4 + 9c9c9da commit 5063578

File tree

5 files changed

+43
-9
lines changed

5 files changed

+43
-9
lines changed

drivers/spi/spi-bitbang-txrx.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ bitbang_txrx_le_cpha0(struct spi_device *spi,
116116
{
117117
/* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
118118

119+
u8 rxbit = bits - 1;
119120
u32 oldbit = !(word & 1);
120121
/* clock starts at inactive polarity */
121122
for (; likely(bits); bits--) {
@@ -135,7 +136,7 @@ bitbang_txrx_le_cpha0(struct spi_device *spi,
135136
/* sample LSB (from slave) on leading edge */
136137
word >>= 1;
137138
if ((flags & SPI_MASTER_NO_RX) == 0)
138-
word |= getmiso(spi) << (bits - 1);
139+
word |= getmiso(spi) << rxbit;
139140
setsck(spi, cpol);
140141
}
141142
return word;
@@ -148,6 +149,7 @@ bitbang_txrx_le_cpha1(struct spi_device *spi,
148149
{
149150
/* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
150151

152+
u8 rxbit = bits - 1;
151153
u32 oldbit = !(word & 1);
152154
/* clock starts at inactive polarity */
153155
for (; likely(bits); bits--) {
@@ -168,7 +170,7 @@ bitbang_txrx_le_cpha1(struct spi_device *spi,
168170
/* sample LSB (from slave) on trailing edge */
169171
word >>= 1;
170172
if ((flags & SPI_MASTER_NO_RX) == 0)
171-
word |= getmiso(spi) << (bits - 1);
173+
word |= getmiso(spi) << rxbit;
172174
}
173175
return word;
174176
}

drivers/spi/spi-cadence-quadspi.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#define CQSPI_DISABLE_DAC_MODE BIT(1)
4040
#define CQSPI_SUPPORT_EXTERNAL_DMA BIT(2)
4141
#define CQSPI_NO_SUPPORT_WR_COMPLETION BIT(3)
42+
#define CQSPI_SLOW_SRAM BIT(4)
4243

4344
/* Capabilities */
4445
#define CQSPI_SUPPORTS_OCTAL BIT(0)
@@ -87,6 +88,7 @@ struct cqspi_st {
8788
bool use_dma_read;
8889
u32 pd_dev_id;
8990
bool wr_completion;
91+
bool slow_sram;
9092
};
9193

9294
struct cqspi_driver_platdata {
@@ -333,7 +335,10 @@ static irqreturn_t cqspi_irq_handler(int this_irq, void *dev)
333335
}
334336
}
335337

336-
irq_status &= CQSPI_IRQ_MASK_RD | CQSPI_IRQ_MASK_WR;
338+
else if (!cqspi->slow_sram)
339+
irq_status &= CQSPI_IRQ_MASK_RD | CQSPI_IRQ_MASK_WR;
340+
else
341+
irq_status &= CQSPI_REG_IRQ_WATERMARK | CQSPI_IRQ_MASK_WR;
337342

338343
if (irq_status)
339344
complete(&cqspi->transfer_complete);
@@ -673,7 +678,18 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
673678
/* Clear all interrupts. */
674679
writel(CQSPI_IRQ_STATUS_MASK, reg_base + CQSPI_REG_IRQSTATUS);
675680

676-
writel(CQSPI_IRQ_MASK_RD, reg_base + CQSPI_REG_IRQMASK);
681+
/*
682+
* On SoCFPGA platform reading the SRAM is slow due to
683+
* hardware limitation and causing read interrupt storm to CPU,
684+
* so enabling only watermark interrupt to disable all read
685+
* interrupts later as we want to run "bytes to read" loop with
686+
* all the read interrupts disabled for max performance.
687+
*/
688+
689+
if (!cqspi->slow_sram)
690+
writel(CQSPI_IRQ_MASK_RD, reg_base + CQSPI_REG_IRQMASK);
691+
else
692+
writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK);
677693

678694
reinit_completion(&cqspi->transfer_complete);
679695
writel(CQSPI_REG_INDIRECTRD_START_MASK,
@@ -684,6 +700,13 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
684700
msecs_to_jiffies(CQSPI_READ_TIMEOUT_MS)))
685701
ret = -ETIMEDOUT;
686702

703+
/*
704+
* Disable all read interrupts until
705+
* we are out of "bytes to read"
706+
*/
707+
if (cqspi->slow_sram)
708+
writel(0x0, reg_base + CQSPI_REG_IRQMASK);
709+
687710
bytes_to_read = cqspi_get_rd_sram_level(cqspi);
688711

689712
if (ret && bytes_to_read == 0) {
@@ -715,8 +738,11 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
715738
bytes_to_read = cqspi_get_rd_sram_level(cqspi);
716739
}
717740

718-
if (remaining > 0)
741+
if (remaining > 0) {
719742
reinit_completion(&cqspi->transfer_complete);
743+
if (cqspi->slow_sram)
744+
writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK);
745+
}
720746
}
721747

722748
/* Check indirect done status */
@@ -1667,6 +1693,8 @@ static int cqspi_probe(struct platform_device *pdev)
16671693
cqspi->use_dma_read = true;
16681694
if (ddata->quirks & CQSPI_NO_SUPPORT_WR_COMPLETION)
16691695
cqspi->wr_completion = false;
1696+
if (ddata->quirks & CQSPI_SLOW_SRAM)
1697+
cqspi->slow_sram = true;
16701698

16711699
if (of_device_is_compatible(pdev->dev.of_node,
16721700
"xlnx,versal-ospi-1.0"))
@@ -1779,7 +1807,9 @@ static const struct cqspi_driver_platdata intel_lgm_qspi = {
17791807
};
17801808

17811809
static const struct cqspi_driver_platdata socfpga_qspi = {
1782-
.quirks = CQSPI_DISABLE_DAC_MODE | CQSPI_NO_SUPPORT_WR_COMPLETION,
1810+
.quirks = CQSPI_DISABLE_DAC_MODE
1811+
| CQSPI_NO_SUPPORT_WR_COMPLETION
1812+
| CQSPI_SLOW_SRAM,
17831813
};
17841814

17851815
static const struct cqspi_driver_platdata versal_ospi = {

drivers/spi/spi-mux.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ static int spi_mux_probe(struct spi_device *spi)
161161
ctlr->num_chipselect = mux_control_states(priv->mux);
162162
ctlr->bus_num = -1;
163163
ctlr->dev.of_node = spi->dev.of_node;
164+
ctlr->must_async = true;
164165

165166
ret = devm_spi_register_controller(&spi->dev, ctlr);
166167
if (ret)

drivers/spi/spi.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,8 +1727,7 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread)
17271727
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
17281728

17291729
ret = __spi_pump_transfer_message(ctlr, msg, was_busy);
1730-
if (!ret)
1731-
kthread_queue_work(ctlr->kworker, &ctlr->pump_messages);
1730+
kthread_queue_work(ctlr->kworker, &ctlr->pump_messages);
17321731

17331732
ctlr->cur_msg = NULL;
17341733
ctlr->fallback = false;
@@ -4033,7 +4032,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message)
40334032
* guard against reentrancy from a different context. The io_mutex
40344033
* will catch those cases.
40354034
*/
4036-
if (READ_ONCE(ctlr->queue_empty)) {
4035+
if (READ_ONCE(ctlr->queue_empty) && !ctlr->must_async) {
40374036
message->actual_length = 0;
40384037
message->status = -EINPROGRESS;
40394038

include/linux/spi/spi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,7 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
469469
* SPI_TRANS_FAIL_NO_START.
470470
* @queue_empty: signal green light for opportunistically skipping the queue
471471
* for spi_sync transfers.
472+
* @must_async: disable all fast paths in the core
472473
*
473474
* Each SPI controller can communicate with one or more @spi_device
474475
* children. These make a small bus, sharing MOSI, MISO and SCK signals
@@ -690,6 +691,7 @@ struct spi_controller {
690691

691692
/* Flag for enabling opportunistic skipping of the queue in spi_sync */
692693
bool queue_empty;
694+
bool must_async;
693695
};
694696

695697
static inline void *spi_controller_get_devdata(struct spi_controller *ctlr)

0 commit comments

Comments
 (0)