Skip to content

Commit bfa4133

Browse files
CyrillePitchenBoris Brezillon
authored andcommitted
mtd: spi-nor: fix DMA unsafe buffer issue in spi_nor_read_sfdp()
spi_nor_read_sfdp() calls nor->read() to read the SFDP data. When the m25p80 driver is used (pretty common case), nor->read() is then implemented by the m25p80_read() function, which is likely to initialize a 'struct spi_transfer' from its buf argument before appending this structure inside the 'struct spi_message' argument of spi_sync(). Besides the SPI sub-system states that both .tx_buf and .rx_buf members of 'struct spi_transfer' must point into dma-safe memory. However, two of the three calls of spi_nor_read_sfdp() were given pointers to stack allocated memory as buf argument, hence not in a dma-safe area. Hopefully, the third and last call of spi_nor_read_sfdp() was already given a kmalloc'ed buffer argument, hence dma-safe. So this patch fixes this issue by introducing a spi_nor_read_sfdp_dma_unsafe() function which simply wraps the existing spi_nor_read_sfdp() function and uses some kmalloc'ed memory as a bounce buffer. Fixes: f384b35 ("mtd: spi-nor: parse Serial Flash Discoverable Parameters (SFDP) tables") Reported-by: Geert Uytterhoeven <[email protected]> Signed-off-by: Cyrille Pitchen <[email protected]> Signed-off-by: Boris Brezillon <[email protected]>
1 parent b8f3911 commit bfa4133

File tree

1 file changed

+33
-3
lines changed

1 file changed

+33
-3
lines changed

drivers/mtd/spi-nor/spi-nor.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1784,7 +1784,7 @@ spi_nor_set_pp_settings(struct spi_nor_pp_command *pp,
17841784
* @nor: pointer to a 'struct spi_nor'
17851785
* @addr: offset in the SFDP area to start reading data from
17861786
* @len: number of bytes to read
1787-
* @buf: buffer where the SFDP data are copied into
1787+
* @buf: buffer where the SFDP data are copied into (dma-safe memory)
17881788
*
17891789
* Whatever the actual numbers of bytes for address and dummy cycles are
17901790
* for (Fast) Read commands, the Read SFDP (5Ah) instruction is always
@@ -1829,6 +1829,36 @@ static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr,
18291829
return ret;
18301830
}
18311831

1832+
/**
1833+
* spi_nor_read_sfdp_dma_unsafe() - read Serial Flash Discoverable Parameters.
1834+
* @nor: pointer to a 'struct spi_nor'
1835+
* @addr: offset in the SFDP area to start reading data from
1836+
* @len: number of bytes to read
1837+
* @buf: buffer where the SFDP data are copied into
1838+
*
1839+
* Wrap spi_nor_read_sfdp() using a kmalloc'ed bounce buffer as @buf is now not
1840+
* guaranteed to be dma-safe.
1841+
*
1842+
* Return: -ENOMEM if kmalloc() fails, the return code of spi_nor_read_sfdp()
1843+
* otherwise.
1844+
*/
1845+
static int spi_nor_read_sfdp_dma_unsafe(struct spi_nor *nor, u32 addr,
1846+
size_t len, void *buf)
1847+
{
1848+
void *dma_safe_buf;
1849+
int ret;
1850+
1851+
dma_safe_buf = kmalloc(len, GFP_KERNEL);
1852+
if (!dma_safe_buf)
1853+
return -ENOMEM;
1854+
1855+
ret = spi_nor_read_sfdp(nor, addr, len, dma_safe_buf);
1856+
memcpy(buf, dma_safe_buf, len);
1857+
kfree(dma_safe_buf);
1858+
1859+
return ret;
1860+
}
1861+
18321862
struct sfdp_parameter_header {
18331863
u8 id_lsb;
18341864
u8 minor;
@@ -2101,7 +2131,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
21012131
bfpt_header->length * sizeof(u32));
21022132
addr = SFDP_PARAM_HEADER_PTP(bfpt_header);
21032133
memset(&bfpt, 0, sizeof(bfpt));
2104-
err = spi_nor_read_sfdp(nor, addr, len, &bfpt);
2134+
err = spi_nor_read_sfdp_dma_unsafe(nor, addr, len, &bfpt);
21052135
if (err < 0)
21062136
return err;
21072137

@@ -2252,7 +2282,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
22522282
int i, err;
22532283

22542284
/* Get the SFDP header. */
2255-
err = spi_nor_read_sfdp(nor, 0, sizeof(header), &header);
2285+
err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(header), &header);
22562286
if (err < 0)
22572287
return err;
22582288

0 commit comments

Comments
 (0)