diff mbox series

[2/2] spi: spi-qcom-qspi: Add mem_ops to avoid PIO for badly sized reads

Message ID 20230725110226.2.Id4a39804e01e4a06dae9b73fd2a5194c4c7ea453@changeid (mailing list archive)
State Accepted
Commit cc71c42b3dc1085d3e72dfa5603e827b9eb59da1
Headers show
Series [1/2] spi: spi-qcom-qspi: Fallback to PIO for xfers that aren't multiples of 4 bytes | expand

Commit Message

Doug Anderson July 25, 2023, 6:02 p.m. UTC
In the patch ("spi: spi-qcom-qspi: Fallback to PIO for xfers that
aren't multiples of 4 bytes") we detect reads that we can't handle
properly and fallback to PIO mode. While that's correct behavior, we
can do better by adding "spi_controller_mem_ops" for our
controller. Once we do this then the caller will give us a transfer
that's a multiple of 4-bytes so we can DMA.

Fixes: b5762d95607e ("spi: spi-qcom-qspi: Add DMA mode support")
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---

 drivers/spi/spi-qcom-qspi.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

Comments

Mark Brown July 25, 2023, 6:24 p.m. UTC | #1
On Tue, Jul 25, 2023 at 11:02:27AM -0700, Douglas Anderson wrote:
> In the patch ("spi: spi-qcom-qspi: Fallback to PIO for xfers that
> aren't multiples of 4 bytes") we detect reads that we can't handle
> properly and fallback to PIO mode. While that's correct behavior, we
> can do better by adding "spi_controller_mem_ops" for our
> controller. Once we do this then the caller will give us a transfer
> that's a multiple of 4-bytes so we can DMA.

This is more of an optimisation for the case where we're using flash -
if someone has hung some other hardware off the controller (which seems
reasonable enough if they don't need it for flash) then we'll not use
the mem_ops.
Doug Anderson July 25, 2023, 6:30 p.m. UTC | #2
Hi,

On Tue, Jul 25, 2023 at 11:24 AM Mark Brown <broonie@kernel.org> wrote:
>
> On Tue, Jul 25, 2023 at 11:02:27AM -0700, Douglas Anderson wrote:
> > In the patch ("spi: spi-qcom-qspi: Fallback to PIO for xfers that
> > aren't multiples of 4 bytes") we detect reads that we can't handle
> > properly and fallback to PIO mode. While that's correct behavior, we
> > can do better by adding "spi_controller_mem_ops" for our
> > controller. Once we do this then the caller will give us a transfer
> > that's a multiple of 4-bytes so we can DMA.
>
> This is more of an optimisation for the case where we're using flash -
> if someone has hung some other hardware off the controller (which seems
> reasonable enough if they don't need it for flash) then we'll not use
> the mem_ops.

Right. That's why I also have the first patch in the series too. The
first patch ensures correctness and the second patch makes things more
optimal for when we're using flash. Do you want me to re-submit the
patch with wording that makes this more obvious?

Note that it's pretty likely someone wouldn't use this SPI controller
for anything other than SPI flash. While it's theoretically possible,
the controller is intended for SPI flash (supports dual and quad SPI
modes) and is only half duplex.

-Doug
Mark Brown July 25, 2023, 6:48 p.m. UTC | #3
On Tue, Jul 25, 2023 at 11:30:30AM -0700, Doug Anderson wrote:

> Note that it's pretty likely someone wouldn't use this SPI controller
> for anything other than SPI flash. While it's theoretically possible,
> the controller is intended for SPI flash (supports dual and quad SPI
> modes) and is only half duplex.

TBH most devices are half duplex so it's not *that* big a restriction,
and dual/quad mode are obviously attractive if you need to transfer
large quantities of data.
Vijaya Krishna Nivarthi July 26, 2023, 7:27 a.m. UTC | #4
On 7/25/2023 11:32 PM, Douglas Anderson wrote:
> In the patch ("spi: spi-qcom-qspi: Fallback to PIO for xfers that
> aren't multiples of 4 bytes") we detect reads that we can't handle
> properly and fallback to PIO mode. While that's correct behavior, we
> can do better by adding "spi_controller_mem_ops" for our
> controller. Once we do this then the caller will give us a transfer
> that's a multiple of 4-bytes so we can DMA.
>
> Fixes: b5762d95607e ("spi: spi-qcom-qspi: Add DMA mode support")
> Signed-off-by: Douglas Anderson <dianders@chromium.org>

I checked with a couple of folks here and seemingly the POR for QSPI 
controller is for storage device only, so in all likelihood we should be 
having a spi-flash at the other end.

For other devices there is QUP anyway.

Hence personally I am happy with this change.

Thank you...


Reviewed-by: Vijaya Krishna Nivarthi <quic_vnivarth@quicinc.com>


> ---
>
>   drivers/spi/spi-qcom-qspi.c | 25 +++++++++++++++++++++++++
>   1 file changed, 25 insertions(+)
>
> diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c
> index 39b4d8a8107a..b2bbcfd93637 100644
> --- a/drivers/spi/spi-qcom-qspi.c
> +++ b/drivers/spi/spi-qcom-qspi.c
> @@ -659,6 +659,30 @@ static irqreturn_t qcom_qspi_irq(int irq, void *dev_id)
>   	return ret;
>   }
>   
> +static int qcom_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
> +{
> +	/*
> +	 * If qcom_qspi_can_dma() is going to return false we don't need to
> +	 * adjust anything.
> +	 */
> +	if (op->data.nbytes <= QSPI_MAX_BYTES_FIFO)
> +		return 0;
> +
> +	/*
> +	 * When reading, the transfer needs to be a multiple of 4 bytes so
> +	 * shrink the transfer if that's not true. The caller will then do a
> +	 * second transfer to finish things up.
> +	 */
> +	if (op->data.dir == SPI_MEM_DATA_IN && (op->data.nbytes & 0x3))
> +		op->data.nbytes &= ~0x3;
> +
> +	return 0;
> +}
> +
> +static const struct spi_controller_mem_ops qcom_qspi_mem_ops = {
> +	.adjust_op_size = qcom_qspi_adjust_op_size,
> +};
> +
>   static int qcom_qspi_probe(struct platform_device *pdev)
>   {
>   	int ret;
> @@ -743,6 +767,7 @@ static int qcom_qspi_probe(struct platform_device *pdev)
>   	if (of_property_read_bool(pdev->dev.of_node, "iommus"))
>   		master->can_dma = qcom_qspi_can_dma;
>   	master->auto_runtime_pm = true;
> +	master->mem_ops = &qcom_qspi_mem_ops;
>   
>   	ret = devm_pm_opp_set_clkname(&pdev->dev, "core");
>   	if (ret)
diff mbox series

Patch

diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c
index 39b4d8a8107a..b2bbcfd93637 100644
--- a/drivers/spi/spi-qcom-qspi.c
+++ b/drivers/spi/spi-qcom-qspi.c
@@ -659,6 +659,30 @@  static irqreturn_t qcom_qspi_irq(int irq, void *dev_id)
 	return ret;
 }
 
+static int qcom_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
+{
+	/*
+	 * If qcom_qspi_can_dma() is going to return false we don't need to
+	 * adjust anything.
+	 */
+	if (op->data.nbytes <= QSPI_MAX_BYTES_FIFO)
+		return 0;
+
+	/*
+	 * When reading, the transfer needs to be a multiple of 4 bytes so
+	 * shrink the transfer if that's not true. The caller will then do a
+	 * second transfer to finish things up.
+	 */
+	if (op->data.dir == SPI_MEM_DATA_IN && (op->data.nbytes & 0x3))
+		op->data.nbytes &= ~0x3;
+
+	return 0;
+}
+
+static const struct spi_controller_mem_ops qcom_qspi_mem_ops = {
+	.adjust_op_size = qcom_qspi_adjust_op_size,
+};
+
 static int qcom_qspi_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -743,6 +767,7 @@  static int qcom_qspi_probe(struct platform_device *pdev)
 	if (of_property_read_bool(pdev->dev.of_node, "iommus"))
 		master->can_dma = qcom_qspi_can_dma;
 	master->auto_runtime_pm = true;
+	master->mem_ops = &qcom_qspi_mem_ops;
 
 	ret = devm_pm_opp_set_clkname(&pdev->dev, "core");
 	if (ret)