Skip to content

Commit d5bb4b8

Browse files
committed
Merge tag 'spi-fix-v6.5-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi fixes from Mark Brown: "A bunch of fixes for the Qualcomm QSPI driver, fixing multiple issues with the newly added DMA mode - it had a number of issues exposed when tested in a wider range of use cases, both race condition style issues and issues with different inputs to those that had been used in test" * tag 'spi-fix-v6.5-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: spi-qcom-qspi: Add mem_ops to avoid PIO for badly sized reads spi: spi-qcom-qspi: Fallback to PIO for xfers that aren't multiples of 4 bytes spi: spi-qcom-qspi: Add DMA_CHAIN_DONE to ALL_IRQS spi: spi-qcom-qspi: Call dma_wmb() after setting up descriptors spi: spi-qcom-qspi: Use GFP_ATOMIC flag while allocating for descriptor spi: spi-qcom-qspi: Ignore disabled interrupts' status in isr
2 parents 3dfe688 + cc71c42 commit d5bb4b8

File tree

1 file changed

+49
-5
lines changed

1 file changed

+49
-5
lines changed

drivers/spi/spi-qcom-qspi.c

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
WR_FIFO_OVERRUN)
7070
#define QSPI_ALL_IRQS (QSPI_ERR_IRQS | RESP_FIFO_RDY | \
7171
WR_FIFO_EMPTY | WR_FIFO_FULL | \
72-
TRANSACTION_DONE)
72+
TRANSACTION_DONE | DMA_CHAIN_DONE)
7373

7474
#define PIO_XFER_CTRL 0x0014
7575
#define REQUEST_COUNT_MSK 0xffff
@@ -308,9 +308,11 @@ static int qcom_qspi_alloc_desc(struct qcom_qspi *ctrl, dma_addr_t dma_ptr,
308308
dma_addr_t dma_cmd_desc;
309309

310310
/* allocate for dma cmd descriptor */
311-
virt_cmd_desc = dma_pool_alloc(ctrl->dma_cmd_pool, GFP_KERNEL | __GFP_ZERO, &dma_cmd_desc);
312-
if (!virt_cmd_desc)
313-
return -ENOMEM;
311+
virt_cmd_desc = dma_pool_alloc(ctrl->dma_cmd_pool, GFP_ATOMIC | __GFP_ZERO, &dma_cmd_desc);
312+
if (!virt_cmd_desc) {
313+
dev_warn_once(ctrl->dev, "Couldn't find memory for descriptor\n");
314+
return -EAGAIN;
315+
}
314316

315317
ctrl->virt_cmd_desc[ctrl->n_cmd_desc] = virt_cmd_desc;
316318
ctrl->dma_cmd_desc[ctrl->n_cmd_desc] = dma_cmd_desc;
@@ -355,10 +357,22 @@ static int qcom_qspi_setup_dma_desc(struct qcom_qspi *ctrl,
355357

356358
for (i = 0; i < sgt->nents; i++) {
357359
dma_ptr_sg = sg_dma_address(sgt->sgl + i);
360+
dma_len_sg = sg_dma_len(sgt->sgl + i);
358361
if (!IS_ALIGNED(dma_ptr_sg, QSPI_ALIGN_REQ)) {
359362
dev_warn_once(ctrl->dev, "dma_address not aligned to %d\n", QSPI_ALIGN_REQ);
360363
return -EAGAIN;
361364
}
365+
/*
366+
* When reading with DMA the controller writes to memory 1 word
367+
* at a time. If the length isn't a multiple of 4 bytes then
368+
* the controller can clobber the things later in memory.
369+
* Fallback to PIO to be safe.
370+
*/
371+
if (ctrl->xfer.dir == QSPI_READ && (dma_len_sg & 0x03)) {
372+
dev_warn_once(ctrl->dev, "fallback to PIO for read of size %#010x\n",
373+
dma_len_sg);
374+
return -EAGAIN;
375+
}
362376
}
363377

364378
for (i = 0; i < sgt->nents; i++) {
@@ -441,8 +455,10 @@ static int qcom_qspi_transfer_one(struct spi_master *master,
441455

442456
ret = qcom_qspi_setup_dma_desc(ctrl, xfer);
443457
if (ret != -EAGAIN) {
444-
if (!ret)
458+
if (!ret) {
459+
dma_wmb();
445460
qcom_qspi_dma_xfer(ctrl);
461+
}
446462
goto exit;
447463
}
448464
dev_warn_once(ctrl->dev, "DMA failure, falling back to PIO\n");
@@ -603,6 +619,9 @@ static irqreturn_t qcom_qspi_irq(int irq, void *dev_id)
603619
int_status = readl(ctrl->base + MSTR_INT_STATUS);
604620
writel(int_status, ctrl->base + MSTR_INT_STATUS);
605621

622+
/* Ignore disabled interrupts */
623+
int_status &= readl(ctrl->base + MSTR_INT_EN);
624+
606625
/* PIO mode handling */
607626
if (ctrl->xfer.dir == QSPI_WRITE) {
608627
if (int_status & WR_FIFO_EMPTY)
@@ -647,6 +666,30 @@ static irqreturn_t qcom_qspi_irq(int irq, void *dev_id)
647666
return ret;
648667
}
649668

669+
static int qcom_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
670+
{
671+
/*
672+
* If qcom_qspi_can_dma() is going to return false we don't need to
673+
* adjust anything.
674+
*/
675+
if (op->data.nbytes <= QSPI_MAX_BYTES_FIFO)
676+
return 0;
677+
678+
/*
679+
* When reading, the transfer needs to be a multiple of 4 bytes so
680+
* shrink the transfer if that's not true. The caller will then do a
681+
* second transfer to finish things up.
682+
*/
683+
if (op->data.dir == SPI_MEM_DATA_IN && (op->data.nbytes & 0x3))
684+
op->data.nbytes &= ~0x3;
685+
686+
return 0;
687+
}
688+
689+
static const struct spi_controller_mem_ops qcom_qspi_mem_ops = {
690+
.adjust_op_size = qcom_qspi_adjust_op_size,
691+
};
692+
650693
static int qcom_qspi_probe(struct platform_device *pdev)
651694
{
652695
int ret;
@@ -731,6 +774,7 @@ static int qcom_qspi_probe(struct platform_device *pdev)
731774
if (of_property_read_bool(pdev->dev.of_node, "iommus"))
732775
master->can_dma = qcom_qspi_can_dma;
733776
master->auto_runtime_pm = true;
777+
master->mem_ops = &qcom_qspi_mem_ops;
734778

735779
ret = devm_pm_opp_set_clkname(&pdev->dev, "core");
736780
if (ret)

0 commit comments

Comments
 (0)