Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 245131e2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'mtd/fixes-for-4.17-rc3' of git://git.infradead.org/linux-mtd

Pull mtd fixes from Boris Brezillon:

 - Fix nanddev_mtd_erase() function to match the changes done in
   e7bfb3fd ("mtd: Stop updating erase_info->state and calling
   mtd_erase_callback()")

 - Fix a memory leak in the Tango NAND controller driver

 - Fix read/write to a suspended erase block in the CFI driver

 - Fix the DT parsing logic in the Marvell NAND controller driver

* tag 'mtd/fixes-for-4.17-rc3' of git://git.infradead.org/linux-mtd:
  mtd: rawnand: marvell: fix the chip-select DT parsing logic
  mtd: cfi: cmdset_0002: Do not allow read/write to suspend erase block.
  mtd: cfi: cmdset_0001: Workaround Micron Erase suspend bug.
  mtd: cfi: cmdset_0001: Do not allow read/write to suspend erase block.
  mtd: spi-nor: cadence-quadspi: Fix page fault kernel panic
  mtd: nand: Fix nanddev_mtd_erase()
  mtd: rawnand: tango: Fix struct clk memory leak
parents 0f940fac f6997bec
Loading
Loading
Loading
Loading
+28 −5
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#define I82802AB	0x00ad
#define I82802AC	0x00ac
#define PF38F4476	0x881c
#define M28F00AP30	0x8963
/* STMicroelectronics chips */
#define M50LPW080       0x002F
#define M50FLW080A	0x0080
@@ -375,6 +376,17 @@ static void cfi_fixup_major_minor(struct cfi_private *cfi,
		extp->MinorVersion = '1';
}

static int cfi_is_micron_28F00AP30(struct cfi_private *cfi, struct flchip *chip)
{
	/*
	 * Micron(was Numonyx) 1Gbit bottom boot are buggy w.r.t
	 * Erase Supend for their small Erase Blocks(0x8000)
	 */
	if (cfi->mfr == CFI_MFR_INTEL && cfi->id == M28F00AP30)
		return 1;
	return 0;
}

static inline struct cfi_pri_intelext *
read_pri_intelext(struct map_info *map, __u16 adr)
{
@@ -831,21 +843,30 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long
		     (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1))))
			goto sleep;

		/* Do not allow suspend iff read/write to EB address */
		if ((adr & chip->in_progress_block_mask) ==
		    chip->in_progress_block_addr)
			goto sleep;

		/* do not suspend small EBs, buggy Micron Chips */
		if (cfi_is_micron_28F00AP30(cfi, chip) &&
		    (chip->in_progress_block_mask == ~(0x8000-1)))
			goto sleep;

		/* Erase suspend */
		map_write(map, CMD(0xB0), adr);
		map_write(map, CMD(0xB0), chip->in_progress_block_addr);

		/* If the flash has finished erasing, then 'erase suspend'
		 * appears to make some (28F320) flash devices switch to
		 * 'read' mode.  Make sure that we switch to 'read status'
		 * mode so we get the right data. --rmk
		 */
		map_write(map, CMD(0x70), adr);
		map_write(map, CMD(0x70), chip->in_progress_block_addr);
		chip->oldstate = FL_ERASING;
		chip->state = FL_ERASE_SUSPENDING;
		chip->erase_suspended = 1;
		for (;;) {
			status = map_read(map, adr);
			status = map_read(map, chip->in_progress_block_addr);
			if (map_word_andequal(map, status, status_OK, status_OK))
			        break;

@@ -1041,8 +1062,8 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
		   sending the 0x70 (Read Status) command to an erasing
		   chip and expecting it to be ignored, that's what we
		   do. */
		map_write(map, CMD(0xd0), adr);
		map_write(map, CMD(0x70), adr);
		map_write(map, CMD(0xd0), chip->in_progress_block_addr);
		map_write(map, CMD(0x70), chip->in_progress_block_addr);
		chip->oldstate = FL_READY;
		chip->state = FL_ERASING;
		break;
@@ -1933,6 +1954,8 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
	map_write(map, CMD(0xD0), adr);
	chip->state = FL_ERASING;
	chip->erase_suspended = 0;
	chip->in_progress_block_addr = adr;
	chip->in_progress_block_mask = ~(len - 1);

	ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
				   adr, len,
+6 −3
Original line number Diff line number Diff line
@@ -816,9 +816,10 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
		    (mode == FL_WRITING && (cfip->EraseSuspend & 0x2))))
			goto sleep;

		/* We could check to see if we're trying to access the sector
		 * that is currently being erased. However, no user will try
		 * anything like that so we just wait for the timeout. */
		/* Do not allow suspend iff read/write to EB address */
		if ((adr & chip->in_progress_block_mask) ==
		    chip->in_progress_block_addr)
			goto sleep;

		/* Erase suspend */
		/* It's harmless to issue the Erase-Suspend and Erase-Resume
@@ -2267,6 +2268,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
	chip->state = FL_ERASING;
	chip->erase_suspended = 0;
	chip->in_progress_block_addr = adr;
	chip->in_progress_block_mask = ~(map->size - 1);

	INVALIDATE_CACHE_UDELAY(map, chip,
				adr, map->size,
@@ -2356,6 +2358,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
	chip->state = FL_ERASING;
	chip->erase_suspended = 0;
	chip->in_progress_block_addr = adr;
	chip->in_progress_block_mask = ~(len - 1);

	INVALIDATE_CACHE_UDELAY(map, chip,
				adr, len,
+0 −3
Original line number Diff line number Diff line
@@ -162,7 +162,6 @@ int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo)
		ret = nanddev_erase(nand, &pos);
		if (ret) {
			einfo->fail_addr = nanddev_pos_to_offs(nand, &pos);
			einfo->state = MTD_ERASE_FAILED;

			return ret;
		}
@@ -170,8 +169,6 @@ int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo)
		nanddev_pos_next_eraseblock(nand, &pos);
	}

	einfo->state = MTD_ERASE_DONE;

	return 0;
}
EXPORT_SYMBOL_GPL(nanddev_mtd_erase);
+8 −17
Original line number Diff line number Diff line
@@ -2299,29 +2299,20 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
	/*
	 * The legacy "num-cs" property indicates the number of CS on the only
	 * chip connected to the controller (legacy bindings does not support
	 * more than one chip). CS are only incremented one by one while the RB
	 * pin is always the #0.
	 * more than one chip). The CS and RB pins are always the #0.
	 *
	 * When not using legacy bindings, a couple of "reg" and "nand-rb"
	 * properties must be filled. For each chip, expressed as a subnode,
	 * "reg" points to the CS lines and "nand-rb" to the RB line.
	 */
	if (pdata) {
	if (pdata || nfc->caps->legacy_of_bindings) {
		nsels = 1;
	} else if (nfc->caps->legacy_of_bindings &&
		   !of_get_property(np, "num-cs", &nsels)) {
		dev_err(dev, "missing num-cs property\n");
		return -EINVAL;
	} else if (!of_get_property(np, "reg", &nsels)) {
		dev_err(dev, "missing reg property\n");
	} else {
		nsels = of_property_count_elems_of_size(np, "reg", sizeof(u32));
		if (nsels <= 0) {
			dev_err(dev, "missing/invalid reg property\n");
			return -EINVAL;
		}

	if (!pdata)
		nsels /= sizeof(u32);
	if (!nsels) {
		dev_err(dev, "invalid reg property size\n");
		return -EINVAL;
	}

	/* Alloc the nand chip structure */
+1 −1
Original line number Diff line number Diff line
@@ -645,7 +645,7 @@ static int tango_nand_probe(struct platform_device *pdev)

	writel_relaxed(MODE_RAW, nfc->pbus_base + PBUS_PAD_MODE);

	clk = clk_get(&pdev->dev, NULL);
	clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(clk))
		return PTR_ERR(clk);

Loading