The SPI regions cannot be accessed in parallel because for each
region the region selector has to be set. Add a mutex to prevent
parallel access.

Cc: Rodrigo Vivi <rodrigo.v...@intel.com>
Cc: Lucas De Marchi <lucas.demar...@intel.com>
Signed-off-by: Alexander Usyskin <alexander.usys...@intel.com>
Signed-off-by: Tomas Winkler <tomas.wink...@intel.com>
---
 drivers/gpu/drm/i915/spi/intel_spi_drv.c | 32 +++++++++++++++++++++---
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/spi/intel_spi_drv.c 
b/drivers/gpu/drm/i915/spi/intel_spi_drv.c
index 1e8a40339e6d..9de49d00297d 100644
--- a/drivers/gpu/drm/i915/spi/intel_spi_drv.c
+++ b/drivers/gpu/drm/i915/spi/intel_spi_drv.c
@@ -20,6 +20,7 @@
 
 struct i915_spi {
        struct mtd_info mtd;
+       struct mutex lock; /* region access lock */
        void __iomem *base;
        size_t size;
        unsigned int nregions;
@@ -354,6 +355,7 @@ static int i915_spi_erase(struct mtd_info *mtd, struct 
erase_info *info)
        loff_t from;
        size_t len;
        size_t total_len;
+       int ret = 0;
 
        if (!mtd || !info)
                return -EINVAL;
@@ -370,18 +372,23 @@ static int i915_spi_erase(struct mtd_info *mtd, struct 
erase_info *info)
        total_len = info->len;
        addr = info->addr;
 
+       if (!mutex_trylock(&spi->lock))
+               return -EBUSY;
+
        while (total_len > 0) {
                if (!IS_ALIGNED(addr, SZ_4K) || !IS_ALIGNED(total_len, SZ_4K)) {
                        dev_err(&mtd->dev, "unaligned erase %llx %zx\n", addr, 
total_len);
                        info->fail_addr = addr;
-                       return -ERANGE;
+                       ret = -ERANGE;
+                       goto out;
                }
 
                idx = spi_get_region(spi, addr);
                if (idx >= spi->nregions) {
                        dev_err(&mtd->dev, "out of range");
                        info->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
-                       return -ERANGE;
+                       ret = -ERANGE;
+                       goto out;
                }
 
                from = addr - spi->regions[idx].offset;
@@ -397,14 +404,17 @@ static int i915_spi_erase(struct mtd_info *mtd, struct 
erase_info *info)
                if (bytes < 0) {
                        dev_dbg(&mtd->dev, "erase failed with %zd\n", bytes);
                        info->fail_addr += spi->regions[idx].offset;
-                       return bytes;
+                       ret = bytes;
+                       goto out;
                }
 
                addr += len;
                total_len -= len;
        }
 
-       return 0;
+out:
+       mutex_unlock(&spi->lock);
+       return ret;
 }
 
 static int i915_spi_read(struct mtd_info *mtd, loff_t from, size_t len,
@@ -440,14 +450,19 @@ static int i915_spi_read(struct mtd_info *mtd, loff_t 
from, size_t len,
        if (len > spi->regions[idx].size - from)
                len = spi->regions[idx].size - from;
 
+       if (!mutex_trylock(&spi->lock))
+               return -EBUSY;
+
        ret = spi_read(spi, region, from, len, buf);
        if (ret < 0) {
                dev_dbg(&mtd->dev, "read failed with %zd\n", ret);
+               mutex_unlock(&spi->lock);
                return ret;
        }
 
        *retlen = ret;
 
+       mutex_unlock(&spi->lock);
        return 0;
 }
 
@@ -484,14 +499,19 @@ static int i915_spi_write(struct mtd_info *mtd, loff_t 
to, size_t len,
        if (len > spi->regions[idx].size - to)
                len = spi->regions[idx].size - to;
 
+       if (!mutex_trylock(&spi->lock))
+               return -EBUSY;
+
        ret = spi_write(spi, region, to, len, buf);
        if (ret < 0) {
                dev_dbg(&mtd->dev, "write failed with %zd\n", ret);
+               mutex_unlock(&spi->lock);
                return ret;
        }
 
        *retlen = ret;
 
+       mutex_unlock(&spi->lock);
        return 0;
 }
 
@@ -505,6 +525,8 @@ static int i915_spi_init_mtd(struct i915_spi *spi, struct 
device *device,
 
        dev_dbg(device, "registering with mtd\n");
 
+       mutex_init(&spi->lock);
+
        spi->mtd.owner = THIS_MODULE;
        spi->mtd.dev.parent = device;
        spi->mtd.flags = MTD_CAP_NORFLASH | MTD_WRITEABLE;
@@ -630,6 +652,8 @@ static int i915_spi_remove(struct platform_device *platdev)
 
        mtd_device_unregister(&spi->mtd);
 
+       mutex_destroy(&spi->lock);
+
        platform_set_drvdata(platdev, NULL);
 
        return 0;
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to