diff options
author | Boris Brezillon <boris.brezillon@bootlin.com> | 2018-09-17 10:31:30 -0400 |
---|---|---|
committer | Boris Brezillon <boris.brezillon@bootlin.com> | 2018-09-18 04:17:48 -0400 |
commit | 4a3e85f2674cbfb81052059107d0165269778e2f (patch) | |
tree | 88e32db1e0460c11dda408086e7f3d9c1399ef43 | |
parent | 85516a9881a31e2c7a8d10f4697f3adcccc7cef1 (diff) |
mtd: devices: m25p80: Make sure the buffer passed in op is DMA-able
As documented in spi-mem.h, spi_mem_op->data.buf.{in,out} must be
DMA-able, and commit 4120f8d158ef ("mtd: spi-nor: Use the spi_mem_xx()
API") failed to follow this rule as buffers passed to
->{read,write}_reg() are usually placed on the stack.
Fix that by allocating a scratch buffer and copying the data around.
Fixes: 4120f8d158ef ("mtd: spi-nor: Use the spi_mem_xx() API")
Reported-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Reviewed-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
-rw-r--r-- | drivers/mtd/devices/m25p80.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index cbfafc453274..270d3c9580c5 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -39,13 +39,23 @@ static int m25p80_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len) | |||
39 | struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(code, 1), | 39 | struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(code, 1), |
40 | SPI_MEM_OP_NO_ADDR, | 40 | SPI_MEM_OP_NO_ADDR, |
41 | SPI_MEM_OP_NO_DUMMY, | 41 | SPI_MEM_OP_NO_DUMMY, |
42 | SPI_MEM_OP_DATA_IN(len, val, 1)); | 42 | SPI_MEM_OP_DATA_IN(len, NULL, 1)); |
43 | void *scratchbuf; | ||
43 | int ret; | 44 | int ret; |
44 | 45 | ||
46 | scratchbuf = kmalloc(len, GFP_KERNEL); | ||
47 | if (!scratchbuf) | ||
48 | return -ENOMEM; | ||
49 | |||
50 | op.data.buf.in = scratchbuf; | ||
45 | ret = spi_mem_exec_op(flash->spimem, &op); | 51 | ret = spi_mem_exec_op(flash->spimem, &op); |
46 | if (ret < 0) | 52 | if (ret < 0) |
47 | dev_err(&flash->spimem->spi->dev, "error %d reading %x\n", ret, | 53 | dev_err(&flash->spimem->spi->dev, "error %d reading %x\n", ret, |
48 | code); | 54 | code); |
55 | else | ||
56 | memcpy(val, scratchbuf, len); | ||
57 | |||
58 | kfree(scratchbuf); | ||
49 | 59 | ||
50 | return ret; | 60 | return ret; |
51 | } | 61 | } |
@@ -56,9 +66,19 @@ static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) | |||
56 | struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 1), | 66 | struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 1), |
57 | SPI_MEM_OP_NO_ADDR, | 67 | SPI_MEM_OP_NO_ADDR, |
58 | SPI_MEM_OP_NO_DUMMY, | 68 | SPI_MEM_OP_NO_DUMMY, |
59 | SPI_MEM_OP_DATA_OUT(len, buf, 1)); | 69 | SPI_MEM_OP_DATA_OUT(len, NULL, 1)); |
70 | void *scratchbuf; | ||
71 | int ret; | ||
60 | 72 | ||
61 | return spi_mem_exec_op(flash->spimem, &op); | 73 | scratchbuf = kmemdup(buf, len, GFP_KERNEL); |
74 | if (!scratchbuf) | ||
75 | return -ENOMEM; | ||
76 | |||
77 | op.data.buf.out = scratchbuf; | ||
78 | ret = spi_mem_exec_op(flash->spimem, &op); | ||
79 | kfree(scratchbuf); | ||
80 | |||
81 | return ret; | ||
62 | } | 82 | } |
63 | 83 | ||
64 | static ssize_t m25p80_write(struct spi_nor *nor, loff_t to, size_t len, | 84 | static ssize_t m25p80_write(struct spi_nor *nor, loff_t to, size_t len, |