| From ca54db7cd2e13b2e8bc24380119c73a85bded64f Mon Sep 17 00:00:00 2001 |
| From: Tudor Ambarus <tudor.ambarus@microchip.com> |
| Date: Fri, 28 Feb 2020 15:55:32 +0000 |
| Subject: [PATCH] spi: atmel-quadspi: fix possible MMIO window size overrun |
| |
| commit 8e093ea4d3593379be46b845b9e823179558047e upstream. |
| |
| The QSPI controller memory space is limited to 128MB: |
| 0x9000_00000-0x9800_00000/0XD000_0000--0XD800_0000. |
| |
| There are nor flashes that are bigger in size than the memory size |
| supported by the controller: Micron MT25QL02G (256 MB). |
| |
| Check if the address exceeds the MMIO window size. An improvement |
| would be to add support for regular SPI mode and fall back to it |
| when the flash memories overrun the controller's memory space. |
| |
| Fixes: 0e6aae08e9ae ("spi: Add QuadSPI driver for Atmel SAMA5D2") |
| Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com> |
| Link: https://lore.kernel.org/r/20200228155437.1558219-1-tudor.ambarus@microchip.com |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c |
| index 9f24d5f0b431..a9023f26efc3 100644 |
| --- a/drivers/spi/atmel-quadspi.c |
| +++ b/drivers/spi/atmel-quadspi.c |
| @@ -149,6 +149,7 @@ struct atmel_qspi { |
| struct clk *qspick; |
| struct platform_device *pdev; |
| const struct atmel_qspi_caps *caps; |
| + resource_size_t mmap_size; |
| u32 pending; |
| u32 mr; |
| struct completion cmd_completion; |
| @@ -328,6 +329,14 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) |
| u32 sr, offset; |
| int err; |
| |
| + /* |
| + * Check if the address exceeds the MMIO window size. An improvement |
| + * would be to add support for regular SPI mode and fall back to it |
| + * when the flash memories overrun the controller's memory space. |
| + */ |
| + if (op->addr.val + op->data.nbytes > aq->mmap_size) |
| + return -ENOTSUPP; |
| + |
| err = atmel_qspi_set_cfg(aq, op, &offset); |
| if (err) |
| return err; |
| @@ -481,6 +490,8 @@ static int atmel_qspi_probe(struct platform_device *pdev) |
| goto exit; |
| } |
| |
| + aq->mmap_size = resource_size(res); |
| + |
| /* Get the peripheral clock */ |
| aq->pclk = devm_clk_get(&pdev->dev, "pclk"); |
| if (IS_ERR(aq->pclk)) |
| -- |
| 2.7.4 |
| |