* [PATCH v7 1/5] mtd: introduce function max_bad_blocks
2017-01-06 19:14 [PATCH v7 0/5] mtd: use ONFI bad blocks per LUN to calculate UBI bad PEB limit Zach Brown
@ 2017-01-06 19:14 ` Zach Brown
2017-01-06 19:14 ` [PATCH v7 2/5] mtd: ubi: use 'max_bad_blocks' to compute bad_peb_limit if available Zach Brown
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Zach Brown @ 2017-01-06 19:14 UTC (permalink / raw)
To: dwmw2
Cc: computersforpeace, boris.brezillon, richard, dedekind1, linux-mtd,
linux-kernel
From: Jeff Westfahl <jeff.westfahl@ni.com>
If implemented, 'max_bad_blocks' returns the maximum number of bad
blocks to reserve for a MTD. An implementation for NAND is coming soon.
Signed-off-by: Jeff Westfahl <jeff.westfahl@ni.com>
Signed-off-by: Zach Brown <zach.brown@ni.com>
Acked-by: Boris Brezillon <boris.brezillon@free-electron.com>
Acked-by: Brian Norris <computersforpeace@gmail.com>
---
drivers/mtd/mtdpart.c | 10 ++++++++++
include/linux/mtd/mtd.h | 13 +++++++++++++
2 files changed, 23 insertions(+)
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index fccdd49..08925bb 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -349,6 +349,14 @@ static const struct mtd_ooblayout_ops part_ooblayout_ops = {
.free = part_ooblayout_free,
};
+static int part_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ struct mtd_part *part = mtd_to_part(mtd);
+
+ return part->master->_max_bad_blocks(part->master,
+ ofs + part->offset, len);
+}
+
static inline void free_partition(struct mtd_part *p)
{
kfree(p->mtd.name);
@@ -475,6 +483,8 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
slave->mtd._block_isbad = part_block_isbad;
if (master->_block_markbad)
slave->mtd._block_markbad = part_block_markbad;
+ if (master->_max_bad_blocks)
+ slave->mtd._max_bad_blocks = part_max_bad_blocks;
if (master->_get_device)
slave->mtd._get_device = part_get_device;
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 13f8052..5bb42c6 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -322,6 +322,7 @@ struct mtd_info {
int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs);
int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
+ int (*_max_bad_blocks) (struct mtd_info *mtd, loff_t ofs, size_t len);
int (*_suspend) (struct mtd_info *mtd);
void (*_resume) (struct mtd_info *mtd);
void (*_reboot) (struct mtd_info *mtd);
@@ -397,6 +398,18 @@ static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
}
+static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
+ loff_t ofs, size_t len)
+{
+ if (!mtd->_max_bad_blocks)
+ return -ENOTSUPP;
+
+ if (mtd->size < (len + ofs) || ofs < 0)
+ return -EINVAL;
+
+ return mtd->_max_bad_blocks(mtd, ofs, len);
+}
+
int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
struct mtd_pairing_info *info);
int mtd_pairing_info_to_wunit(struct mtd_info *mtd,
--
2.7.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v7 2/5] mtd: ubi: use 'max_bad_blocks' to compute bad_peb_limit if available
2017-01-06 19:14 [PATCH v7 0/5] mtd: use ONFI bad blocks per LUN to calculate UBI bad PEB limit Zach Brown
2017-01-06 19:14 ` [PATCH v7 1/5] mtd: introduce function max_bad_blocks Zach Brown
@ 2017-01-06 19:14 ` Zach Brown
2017-01-06 19:14 ` [PATCH v7 3/5] mtd: nand: Add max_bb_per_die and blocks_per_die fields to nand_chip Zach Brown
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Zach Brown @ 2017-01-06 19:14 UTC (permalink / raw)
To: dwmw2
Cc: computersforpeace, boris.brezillon, richard, dedekind1, linux-mtd,
linux-kernel
From: Jeff Westfahl <jeff.westfahl@ni.com>
If the user has not set max_beb_per1024 using either the cmdline or
Kconfig options for doing so, use the MTD function 'max_bad_blocks' to
compute the UBI bad_peb_limit.
Signed-off-by: Jeff Westfahl <jeff.westfahl@ni.com>
Signed-off-by: Zach Brown <zach.brown@ni.com>
Acked-by: Boris Brezillon <boris.brezillon@free-electron.com>
---
drivers/mtd/ubi/build.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 85d54f3..3029219 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -584,8 +584,17 @@ static int get_bad_peb_limit(const struct ubi_device *ubi, int max_beb_per1024)
int limit, device_pebs;
uint64_t device_size;
- if (!max_beb_per1024)
- return 0;
+ if (!max_beb_per1024) {
+ /*
+ * Since max_beb_per1024 has not been set by the user in either
+ * the cmdline or Kconfig, use mtd_max_bad_blocks to set the
+ * limit if it is supported by the device.
+ */
+ limit = mtd_max_bad_blocks(ubi->mtd, 0, ubi->mtd->size);
+ if (limit < 0)
+ return 0;
+ return limit;
+ }
/*
* Here we are using size of the entire flash chip and
--
2.7.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v7 3/5] mtd: nand: Add max_bb_per_die and blocks_per_die fields to nand_chip
2017-01-06 19:14 [PATCH v7 0/5] mtd: use ONFI bad blocks per LUN to calculate UBI bad PEB limit Zach Brown
2017-01-06 19:14 ` [PATCH v7 1/5] mtd: introduce function max_bad_blocks Zach Brown
2017-01-06 19:14 ` [PATCH v7 2/5] mtd: ubi: use 'max_bad_blocks' to compute bad_peb_limit if available Zach Brown
@ 2017-01-06 19:14 ` Zach Brown
2017-01-06 19:14 ` [PATCH v7 4/5] mtd: nand: implement 'max_bad_blocks' mtd function Zach Brown
2017-01-06 19:14 ` [PATCH v7 5/5] mtd: nand: set max_bb_per_die and blocks_per_die for ONFI compliant chips Zach Brown
4 siblings, 0 replies; 7+ messages in thread
From: Zach Brown @ 2017-01-06 19:14 UTC (permalink / raw)
To: dwmw2
Cc: computersforpeace, boris.brezillon, richard, dedekind1, linux-mtd,
linux-kernel
The fields max_bb_per_die and blocks_per_die are useful determining the
number of bad blocks a MTD needs to allocate. How they are set will
depend on if the chip is ONFI, JEDEC or a full-id entry in the nand_ids
table.
Signed-off-by: Zach Brown <zach.brown@ni.com>
Acked-by: Boris Brezillon <boris.brezillon@free-electron.com>
Acked-by: Brian Norris <computersforpeace@gmail.com>
---
include/linux/mtd/nand.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index c5f3a01..4e1b441 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -801,6 +801,9 @@ nand_get_sdr_timings(const struct nand_data_interface *conf)
* supported, 0 otherwise.
* @jedec_params: [INTERN] holds the JEDEC parameter page when JEDEC is
* supported, 0 otherwise.
+ * @max_bb_per_die: [INTERN] the max number of bad blocks each die of a
+ * this nand device will encounter their life times.
+ * @blocks_per_die: [INTERN] The number of PEBs in a die
* @read_retries: [INTERN] the number of read retry modes supported
* @onfi_set_features: [REPLACEABLE] set the features for ONFI nand
* @onfi_get_features: [REPLACEABLE] get the features for ONFI nand
@@ -883,6 +886,8 @@ struct nand_chip {
struct nand_onfi_params onfi_params;
struct nand_jedec_params jedec_params;
};
+ u16 max_bb_per_die;
+ u32 blocks_per_die;
struct nand_data_interface *data_interface;
--
2.7.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v7 4/5] mtd: nand: implement 'max_bad_blocks' mtd function
2017-01-06 19:14 [PATCH v7 0/5] mtd: use ONFI bad blocks per LUN to calculate UBI bad PEB limit Zach Brown
` (2 preceding siblings ...)
2017-01-06 19:14 ` [PATCH v7 3/5] mtd: nand: Add max_bb_per_die and blocks_per_die fields to nand_chip Zach Brown
@ 2017-01-06 19:14 ` Zach Brown
2017-01-08 15:46 ` Boris Brezillon
2017-01-06 19:14 ` [PATCH v7 5/5] mtd: nand: set max_bb_per_die and blocks_per_die for ONFI compliant chips Zach Brown
4 siblings, 1 reply; 7+ messages in thread
From: Zach Brown @ 2017-01-06 19:14 UTC (permalink / raw)
To: dwmw2
Cc: computersforpeace, boris.brezillon, richard, dedekind1, linux-mtd,
linux-kernel
Implement the new mtd function 'max_bad_blocks'. Using the chip's
max_bb_per_die and blocks_per_die fields to determine the maximum bad
blocks to reserve for an MTD.
Signed-off-by: Jeff Westfahl <jeff.westfahl@ni.com>
Signed-off-by: Zach Brown <zach.brown@ni.com>
Acked-by: Boris Brezillon <boris.brezillon@free-electron.com>
Acked-by: Brian Norris <computersforpeace@gmail.com>
---
drivers/mtd/nand/nand_base.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index ec1c28a..587cd42 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3263,6 +3263,42 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
}
/**
+ * nand_max_bad_blocks - [MTD Interface] Max number of bad blocks for an mtd
+ * @mtd: MTD device structure
+ * @ofs: offset relative to mtd start
+ * @len: length of mtd
+ */
+static int nand_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ uint32_t part_start_block;
+ uint32_t part_end_block;
+ uint32_t part_start_die;
+ uint32_t part_end_die;
+
+ /*
+ * max_bb_per_die and blocks_per_die used to determine
+ * the maximum bad block count.
+ */
+ if (!chip->max_bb_per_die || !chip->blocks_per_die)
+ return -ENOTSUPP;
+
+ /* Get the start and end of the partition in erase blocks. */
+ part_start_block = mtd_div_by_eb(ofs, mtd);
+ part_end_block = mtd_div_by_eb(len, mtd) + part_start_block - 1;
+
+ /* Get the start and end LUNs of the partition. */
+ part_start_die = part_start_block / chip->blocks_per_die;
+ part_end_die = part_end_block / chip->blocks_per_die;
+
+ /*
+ * Look up the bad blocks per unit and multiply by the number of units
+ * that the partition spans.
+ */
+ return chip->max_bb_per_die * (part_end_die - part_start_die + 1);
+}
+
+/**
* nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand
* @mtd: MTD device structure
* @chip: nand chip info structure
@@ -4815,6 +4851,7 @@ int nand_scan_tail(struct mtd_info *mtd)
mtd->_block_isreserved = nand_block_isreserved;
mtd->_block_isbad = nand_block_isbad;
mtd->_block_markbad = nand_block_markbad;
+ mtd->_max_bad_blocks = nand_max_bad_blocks;
mtd->writebufsize = mtd->writesize;
/*
--
2.7.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v7 4/5] mtd: nand: implement 'max_bad_blocks' mtd function
2017-01-06 19:14 ` [PATCH v7 4/5] mtd: nand: implement 'max_bad_blocks' mtd function Zach Brown
@ 2017-01-08 15:46 ` Boris Brezillon
0 siblings, 0 replies; 7+ messages in thread
From: Boris Brezillon @ 2017-01-08 15:46 UTC (permalink / raw)
To: Zach Brown, computersforpeace, richard
Cc: dwmw2, dedekind1, linux-mtd, linux-kernel
On Fri, 6 Jan 2017 13:14:45 -0600
Zach Brown <zach.brown@ni.com> wrote:
> Implement the new mtd function 'max_bad_blocks'. Using the chip's
> max_bb_per_die and blocks_per_die fields to determine the maximum bad
> blocks to reserve for an MTD.
>
> Signed-off-by: Jeff Westfahl <jeff.westfahl@ni.com>
> Signed-off-by: Zach Brown <zach.brown@ni.com>
> Acked-by: Boris Brezillon <boris.brezillon@free-electron.com>
> Acked-by: Brian Norris <computersforpeace@gmail.com>
> ---
> drivers/mtd/nand/nand_base.c | 37 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
>
> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
> index ec1c28a..587cd42 100644
> --- a/drivers/mtd/nand/nand_base.c
> +++ b/drivers/mtd/nand/nand_base.c
> @@ -3263,6 +3263,42 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
> }
>
> /**
> + * nand_max_bad_blocks - [MTD Interface] Max number of bad blocks for an mtd
> + * @mtd: MTD device structure
> + * @ofs: offset relative to mtd start
> + * @len: length of mtd
> + */
> +static int nand_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len)
> +{
> + struct nand_chip *chip = mtd_to_nand(mtd);
> + uint32_t part_start_block;
> + uint32_t part_end_block;
> + uint32_t part_start_die;
> + uint32_t part_end_die;
I missed these ones -> s/uint32_t/u32/.
Brian, Richard, if you're fine with this version, I'd like to take the
whole series in the nand tree (I have other changes which might
conflict with these ones).
> +
> + /*
> + * max_bb_per_die and blocks_per_die used to determine
> + * the maximum bad block count.
> + */
> + if (!chip->max_bb_per_die || !chip->blocks_per_die)
> + return -ENOTSUPP;
> +
> + /* Get the start and end of the partition in erase blocks. */
> + part_start_block = mtd_div_by_eb(ofs, mtd);
> + part_end_block = mtd_div_by_eb(len, mtd) + part_start_block - 1;
> +
> + /* Get the start and end LUNs of the partition. */
> + part_start_die = part_start_block / chip->blocks_per_die;
> + part_end_die = part_end_block / chip->blocks_per_die;
> +
> + /*
> + * Look up the bad blocks per unit and multiply by the number of units
> + * that the partition spans.
> + */
> + return chip->max_bb_per_die * (part_end_die - part_start_die + 1);
> +}
> +
> +/**
> * nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand
> * @mtd: MTD device structure
> * @chip: nand chip info structure
> @@ -4815,6 +4851,7 @@ int nand_scan_tail(struct mtd_info *mtd)
> mtd->_block_isreserved = nand_block_isreserved;
> mtd->_block_isbad = nand_block_isbad;
> mtd->_block_markbad = nand_block_markbad;
> + mtd->_max_bad_blocks = nand_max_bad_blocks;
> mtd->writebufsize = mtd->writesize;
>
> /*
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v7 5/5] mtd: nand: set max_bb_per_die and blocks_per_die for ONFI compliant chips
2017-01-06 19:14 [PATCH v7 0/5] mtd: use ONFI bad blocks per LUN to calculate UBI bad PEB limit Zach Brown
` (3 preceding siblings ...)
2017-01-06 19:14 ` [PATCH v7 4/5] mtd: nand: implement 'max_bad_blocks' mtd function Zach Brown
@ 2017-01-06 19:14 ` Zach Brown
4 siblings, 0 replies; 7+ messages in thread
From: Zach Brown @ 2017-01-06 19:14 UTC (permalink / raw)
To: dwmw2
Cc: computersforpeace, boris.brezillon, richard, dedekind1, linux-mtd,
linux-kernel
ONFI compliant chips contain the values for the max_bb_per_die and
blocks_per_die fields in the parameter page. When the ONFI paged is
retrieved/parsed the chip's fields are set by the corresponding fields
in the param page.
Signed-off-by: Zach Brown <zach.brown@ni.com>
Acked-by: Boris Brezillon <boris.brezillon@free-electron.com>
Acked-by: Brian Norris <computersforpeace@gmail.com>
---
drivers/mtd/nand/nand_base.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 587cd42..11bc2c4 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3628,6 +3628,9 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
chip->bits_per_cell = p->bits_per_cell;
+ chip->max_bb_per_die = le16_to_cpu(p->bb_per_lun);
+ chip->blocks_per_die = le32_to_cpu(p->blocks_per_lun);
+
if (onfi_feature(chip) & ONFI_FEATURE_16_BIT_BUS)
*busw = NAND_BUSWIDTH_16;
else
--
2.7.4
^ permalink raw reply related [flat|nested] 7+ messages in thread