Google
  Web www.spinics.net

[PATCH 13/17] NAND: make ->check_bad more user friendly

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


Currently to implement a custom ->check_bad one need to call
nand_get_device, nand_release_device.
Also it not possible to use mtd->read_oob because they call
nand_get_device too.
Refactor the code, so check_bad now always has to do nand_get_device
Thus it can use plain mtd->read_oob

Signed-off-by: Maxim Levitsky <maximlevitsky@xxxxxxxxx>
---
 drivers/mtd/nand/cafe_nand.c  |    2 +-
 drivers/mtd/nand/diskonchip.c |    2 +-
 drivers/mtd/nand/nand_base.c  |   74 ++++++++++++++++++++++++++---------------
 include/linux/mtd/nand.h      |    2 +-
 4 files changed, 50 insertions(+), 30 deletions(-)

diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index c828d9a..8211197 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -577,7 +577,7 @@ static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 	return 0;
 }
 
-static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs)
 {
 	return 0;
 }
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index b126cf8..ea3a3c9 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -854,7 +854,7 @@ static int doc200x_dev_ready(struct mtd_info *mtd)
 	}
 }
 
-static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs)
 {
 	/* This is our last resort if we couldn't find or create a BBT.  Just
 	   pretend all blocks are good. */
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index c393df3..86fa40a 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -312,22 +312,18 @@ static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
  *
  * Check, if the block is bad.
  */
-static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
 {
 	int page, chipnr, res = 0;
 	struct nand_chip *chip = mtd->priv;
 	u16 bad;
 
 	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
+	chipnr = (int)(ofs >> chip->chip_shift);
+	nand_get_device(chip, mtd, FL_READING);
 
-	if (getchip) {
-		chipnr = (int)(ofs >> chip->chip_shift);
-
-		nand_get_device(chip, mtd, FL_READING);
-
-		/* Select the NAND device */
-		chip->select_chip(mtd, chipnr);
-	}
+	/* Select the NAND device */
+	chip->select_chip(mtd, chipnr);
 
 	if (chip->options & NAND_BUSWIDTH_16) {
 		chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE,
@@ -343,9 +339,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 			res = 1;
 	}
 
-	if (getchip)
-		nand_release_device(mtd);
-
+	nand_release_device(mtd);
 	return res;
 }
 
@@ -410,19 +404,17 @@ static int nand_check_wp(struct mtd_info *mtd)
  * nand_block_checkbad - [GENERIC] Check if a block is marked bad
  * @mtd:	MTD device structure
  * @ofs:	offset from device start
- * @getchip:	0, if the chip is already selected
  * @allowbbt:	1, if its allowed to access the bbt area
  *
  * Check, if the block is bad. Either by reading the bad block table or
  * calling of the scan function.
  */
-static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
-			       int allowbbt)
+static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt)
 {
 	struct nand_chip *chip = mtd->priv;
 
 	if (!chip->bbt)
-		return chip->block_bad(mtd, ofs, getchip);
+		return chip->block_bad(mtd, ofs);
 
 	/* Return info from the table */
 	return nand_isbad_bbt(mtd, ofs, allowbbt);
@@ -2277,6 +2269,40 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
 	return nand_erase_nand(mtd, instr, 0);
 }
 
+/**
+ * nand_erase_nand - [Internal] check to see if range contains bad blocks
+ * @mtd:	MTD device structure
+ * @offs:	start offset
+ * @len:	length of the range
+ * @allowbbt:	allow access to bbt
+ *
+ * Sanity check before doing the erase
+ */
+static int nand_check_range(struct mtd_info *mtd, loff_t offs, loff_t len,
+			int allow_bbt)
+{
+	struct nand_chip *chip = mtd->priv;
+	int page = offs >> chip->page_shift;
+	int mask = (1 << chip->page_shift) - 1;
+
+	if (len & mask || offs & mask) {
+		DEBUG(MTD_DEBUG_LEVEL0, "%s Unaligned access\n", __func__);
+		return -EINVAL;
+	}
+
+	while (offs < len) {
+		if (nand_block_checkbad(mtd, offs, allow_bbt)) {
+			printk(KERN_WARNING "%s: attempt to erase a bad block "
+					"at page 0x%08x\n", __func__, page);
+				return -EIO;
+		}
+
+		offs += (1 < chip->page_shift);
+		page++;
+	}
+	return 0;
+}
+
 #define BBT_PAGE_MASK	0xffffff3f
 /**
  * nand_erase_nand - [Internal] erase block(s)
@@ -2321,6 +2347,10 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 
 	instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
 
+	/* See if we were asked to erase bad blocks */
+	if (nand_check_range(mtd, instr->addr, instr->len, allowbbt))
+		return -EINVAL;
+
 	/* Grab the lock and see if the device is available */
 	nand_get_device(chip, mtd, FL_ERASING);
 
@@ -2357,16 +2387,6 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 	instr->state = MTD_ERASING;
 
 	while (len) {
-		/*
-		 * heck if we have a bad block, we do not erase bad blocks !
-		 */
-		if (nand_block_checkbad(mtd, ((loff_t) page) <<
-					chip->page_shift, 0, allowbbt)) {
-			printk(KERN_WARNING "%s: attempt to erase a bad block "
-					"at page 0x%08x\n", __func__, page);
-			instr->state = MTD_ERASE_FAILED;
-			goto erase_exit;
-		}
 
 		/*
 		 * Invalidate the page cache, if we erase the block which
@@ -2490,7 +2510,7 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
 	if (offs > mtd->size)
 		return -EINVAL;
 
-	return nand_block_checkbad(mtd, offs, 1, 0);
+	return nand_block_checkbad(mtd, offs, 0);
 }
 
 /**
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index ccab9df..921f24b 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -364,7 +364,7 @@ struct nand_chip {
 	void		(*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
 	int		(*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
 	void		(*select_chip)(struct mtd_info *mtd, int chip);
-	int		(*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
+	int		(*block_bad)(struct mtd_info *mtd, loff_t ofs);
 	int		(*block_markbad)(struct mtd_info *mtd, loff_t ofs);
 	void		(*cmd_ctrl)(struct mtd_info *mtd, int dat,
 				    unsigned int ctrl);
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Site Home]     [Other Archives]     [Linux Kernel Newbies]     [Linux Driver Development]     [Fedora Kernel]     [Linux Kernel Testers]     [Linux SH]     [Linux Omap]     [Linux Kbuild]     [Linux Tape]     [Linux Input]     [Linux Kernel Janitors]     [Linux Kernel Packagers]     [Linux Doc]     [Linux Man Pages]     [Linux API]     [Linux Memory Management]     [Linux Modules]     [Linux Standards]     [Kernel Announce]     [Memory]     [Netdev]     [Git]     [Linux PCI]     [Linux I2C]     [Linux RDMA]     [Linux NUMA]     [Netfilter]     [Netfilter Devel]     [SELinux]     [Bugtraq]     [FIO]     [Linux Perf Users]     [Linux Serial]     [Linux PPP]     [Linux ISDN]     [Linux Next]     [Kernel Stable Commits]     [Linux Tip Commits]     [Kernel MM Commits]     [Linux Security Module]     [Ext3]     [Ext4]     [Linux BTRFS]     [Linux XFS]     [Linux NFS]     [Linux NILFS]     [Linux Cachefs]     [Reiser FS]     [Initramfs]     [Fastboot]     [Linux RT Users]     [eCos]     [Linux Virtualization]     [LVS Devel]     [Hot Plug]     [KVM]     [KVM PPC]     [KVM ia64]     [Linux Containers]     [Util Linux NG]     [Sk Drivers]     [Wireless]     [Linux Bluetooth]     [Bluez Devel]     [Ethernet Bridging]     [LM Sensors]     [Embedded Linux]     [Barebox]     [Linux MMC]     [Sparse]     [Linux Arch]     [Linux ACPI]     [Linux IBM ACPI]     [Linux FB Devel]     [Linux OpenGL]     [CPU Freq]     [Linux Power Management]     [Linux DCCP]     [Linux SCTP]     [ALSA Devel]     [Linux USB]     [Large Format Photos]     [DVD Store]     [Tux]     [Gimp]     [Yosemite National Park Information & Advice]     [Linux PA RISC]     [Linux Samsung SOC]     [MIPS Linux]     [IBM S/390 Linux]     [ARM Linux]     [ARM Kernel]     [ARM MSM]     [Sparc Linux]     [Linux Security]     [Linux Sound]     [Linux Media]     [Video 4 Linux]     [Linux IRDA Users]     [Linux for the blind]     [Linux RAID]     [Linux ATA RAID]     [Device Mapper]     [Linux Clusters]     [Linux SCSI]     [Linux SCSI Target Infrastructure]     [Linux IDE]     [Linux SMP]     [Linux AXP]     [Linux Alpha]     [Linux M68K]     [Linux ia64]     [Linux 8086]     [Linux x86_64]     [Linux Config]     [Linux Apps]     [Linux MSDOS]     [Linux X.25]     [Linux Crypto]     [DM Crypt]     [Linux Btrace]     [Utrace Devel]     [Yosemite Photos]     [Linux C Programming]     [Linux Assembly]     [Dash]     [DWARVES]     [Hail Devel]     [Gcc Help]     [Older Kernel Mail]

Add to Google Powered by Linux