Skip to content

Commit d9fde26

Browse files
committed
Merge tag 'mtd/fixes-for-4.14-rc2' of git://git.infradead.org/linux-mtd
Pull mtd fixes from Boris Brezillon: "SPI NOR: - Fix the SFDP parsing code (bugs reported by Geert Uytterhoeven) NAND: - Fix a resource leak in the lpc32xx_mlc driver - Fix a build warning in the core" * tag 'mtd/fixes-for-4.14-rc2' of git://git.infradead.org/linux-mtd: mtd: nand: remove unused blockmask variable mtd: nand: lpc32xx_mlc: Fix an error handling path in lpc32xx_nand_probe() mtd: spi-nor: fix DMA unsafe buffer issue in spi_nor_read_sfdp() mtd: spi-nor: Check consistency of the memory size extracted from the SFDP
2 parents b6e78a6 + 73600b6 commit d9fde26

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

drivers/mtd/nand/lpc32xx_mlc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
707707
}
708708
res = clk_prepare_enable(host->clk);
709709
if (res)
710-
goto err_exit1;
710+
goto err_put_clk;
711711

712712
nand_chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl;
713713
nand_chip->dev_ready = lpc32xx_nand_device_ready;
@@ -814,6 +814,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
814814
dma_release_channel(host->dma_chan);
815815
err_exit2:
816816
clk_disable_unprepare(host->clk);
817+
err_put_clk:
817818
clk_put(host->clk);
818819
err_exit1:
819820
lpc32xx_wp_enable(host);

drivers/mtd/nand/nand_base.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2668,7 +2668,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
26682668
static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
26692669
struct mtd_oob_ops *ops)
26702670
{
2671-
int chipnr, realpage, page, blockmask, column;
2671+
int chipnr, realpage, page, column;
26722672
struct nand_chip *chip = mtd_to_nand(mtd);
26732673
uint32_t writelen = ops->len;
26742674

@@ -2704,7 +2704,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
27042704

27052705
realpage = (int)(to >> chip->page_shift);
27062706
page = realpage & chip->pagemask;
2707-
blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
27082707

27092708
/* Invalidate the page cache, when we write to the cached page */
27102709
if (to <= ((loff_t)chip->pagebuf << chip->page_shift) &&

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

Lines changed: 42 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

@@ -2127,6 +2157,15 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
21272157
params->size = bfpt.dwords[BFPT_DWORD(2)];
21282158
if (params->size & BIT(31)) {
21292159
params->size &= ~BIT(31);
2160+
2161+
/*
2162+
* Prevent overflows on params->size. Anyway, a NOR of 2^64
2163+
* bits is unlikely to exist so this error probably means
2164+
* the BFPT we are reading is corrupted/wrong.
2165+
*/
2166+
if (params->size > 63)
2167+
return -EINVAL;
2168+
21302169
params->size = 1ULL << params->size;
21312170
} else {
21322171
params->size++;
@@ -2243,7 +2282,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
22432282
int i, err;
22442283

22452284
/* Get the SFDP header. */
2246-
err = spi_nor_read_sfdp(nor, 0, sizeof(header), &header);
2285+
err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(header), &header);
22472286
if (err < 0)
22482287
return err;
22492288

0 commit comments

Comments
 (0)