Commit d9fde269 authored by Linus Torvalds's avatar Linus Torvalds

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
parents b6e78a6f 73600b61
...@@ -707,7 +707,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) ...@@ -707,7 +707,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
} }
res = clk_prepare_enable(host->clk); res = clk_prepare_enable(host->clk);
if (res) if (res)
goto err_exit1; goto err_put_clk;
nand_chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl; nand_chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl;
nand_chip->dev_ready = lpc32xx_nand_device_ready; nand_chip->dev_ready = lpc32xx_nand_device_ready;
...@@ -814,6 +814,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) ...@@ -814,6 +814,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
dma_release_channel(host->dma_chan); dma_release_channel(host->dma_chan);
err_exit2: err_exit2:
clk_disable_unprepare(host->clk); clk_disable_unprepare(host->clk);
err_put_clk:
clk_put(host->clk); clk_put(host->clk);
err_exit1: err_exit1:
lpc32xx_wp_enable(host); lpc32xx_wp_enable(host);
......
...@@ -2668,7 +2668,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, ...@@ -2668,7 +2668,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops) struct mtd_oob_ops *ops)
{ {
int chipnr, realpage, page, blockmask, column; int chipnr, realpage, page, column;
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
uint32_t writelen = ops->len; uint32_t writelen = ops->len;
...@@ -2704,7 +2704,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, ...@@ -2704,7 +2704,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
realpage = (int)(to >> chip->page_shift); realpage = (int)(to >> chip->page_shift);
page = realpage & chip->pagemask; page = realpage & chip->pagemask;
blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
/* Invalidate the page cache, when we write to the cached page */ /* Invalidate the page cache, when we write to the cached page */
if (to <= ((loff_t)chip->pagebuf << chip->page_shift) && if (to <= ((loff_t)chip->pagebuf << chip->page_shift) &&
......
...@@ -1784,7 +1784,7 @@ spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, ...@@ -1784,7 +1784,7 @@ spi_nor_set_pp_settings(struct spi_nor_pp_command *pp,
* @nor: pointer to a 'struct spi_nor' * @nor: pointer to a 'struct spi_nor'
* @addr: offset in the SFDP area to start reading data from * @addr: offset in the SFDP area to start reading data from
* @len: number of bytes to read * @len: number of bytes to read
* @buf: buffer where the SFDP data are copied into * @buf: buffer where the SFDP data are copied into (dma-safe memory)
* *
* Whatever the actual numbers of bytes for address and dummy cycles are * Whatever the actual numbers of bytes for address and dummy cycles are
* for (Fast) Read commands, the Read SFDP (5Ah) instruction is always * 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, ...@@ -1829,6 +1829,36 @@ static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr,
return ret; return ret;
} }
/**
* spi_nor_read_sfdp_dma_unsafe() - read Serial Flash Discoverable Parameters.
* @nor: pointer to a 'struct spi_nor'
* @addr: offset in the SFDP area to start reading data from
* @len: number of bytes to read
* @buf: buffer where the SFDP data are copied into
*
* Wrap spi_nor_read_sfdp() using a kmalloc'ed bounce buffer as @buf is now not
* guaranteed to be dma-safe.
*
* Return: -ENOMEM if kmalloc() fails, the return code of spi_nor_read_sfdp()
* otherwise.
*/
static int spi_nor_read_sfdp_dma_unsafe(struct spi_nor *nor, u32 addr,
size_t len, void *buf)
{
void *dma_safe_buf;
int ret;
dma_safe_buf = kmalloc(len, GFP_KERNEL);
if (!dma_safe_buf)
return -ENOMEM;
ret = spi_nor_read_sfdp(nor, addr, len, dma_safe_buf);
memcpy(buf, dma_safe_buf, len);
kfree(dma_safe_buf);
return ret;
}
struct sfdp_parameter_header { struct sfdp_parameter_header {
u8 id_lsb; u8 id_lsb;
u8 minor; u8 minor;
...@@ -2101,7 +2131,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, ...@@ -2101,7 +2131,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
bfpt_header->length * sizeof(u32)); bfpt_header->length * sizeof(u32));
addr = SFDP_PARAM_HEADER_PTP(bfpt_header); addr = SFDP_PARAM_HEADER_PTP(bfpt_header);
memset(&bfpt, 0, sizeof(bfpt)); memset(&bfpt, 0, sizeof(bfpt));
err = spi_nor_read_sfdp(nor, addr, len, &bfpt); err = spi_nor_read_sfdp_dma_unsafe(nor, addr, len, &bfpt);
if (err < 0) if (err < 0)
return err; return err;
...@@ -2127,6 +2157,15 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, ...@@ -2127,6 +2157,15 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
params->size = bfpt.dwords[BFPT_DWORD(2)]; params->size = bfpt.dwords[BFPT_DWORD(2)];
if (params->size & BIT(31)) { if (params->size & BIT(31)) {
params->size &= ~BIT(31); params->size &= ~BIT(31);
/*
* Prevent overflows on params->size. Anyway, a NOR of 2^64
* bits is unlikely to exist so this error probably means
* the BFPT we are reading is corrupted/wrong.
*/
if (params->size > 63)
return -EINVAL;
params->size = 1ULL << params->size; params->size = 1ULL << params->size;
} else { } else {
params->size++; params->size++;
...@@ -2243,7 +2282,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor, ...@@ -2243,7 +2282,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
int i, err; int i, err;
/* Get the SFDP header. */ /* Get the SFDP header. */
err = spi_nor_read_sfdp(nor, 0, sizeof(header), &header); err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(header), &header);
if (err < 0) if (err < 0)
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment