Commit 65b99c74 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'upstream-3.7-rc1' of git://git.infradead.org/linux-ubi

Pull UBI changes from Artem Bityutskiy:
 "The main change is the way we reserve eraseblocks for bad blocks
  handling.  We used to reserve 2% of the partition, but now we are more
  aggressive and we reserve 2% of the entire chip, which is what
  actually manufacturers specify in data sheets.  We introduced an
  option to users to override the default, though.

  There are a couple of fixes as well, and a number of cleanups."

* tag 'upstream-3.7-rc1' of git://git.infradead.org/linux-ubi: (24 commits)
  UBI: fix trivial typo 'it' => 'is'
  UBI: load after mtd device drivers
  UBI: print less
  UBI: use pr_ helper instead of printk
  UBI: comply with coding style
  UBI: erase free PEB with bitflip in EC header
  UBI: fix autoresize handling in R/O mode
  UBI: add max_beb_per1024 to attach ioctl
  UBI: allow specifying bad PEBs limit using module parameter
  UBI: check max_beb_per1024 value in ubi_attach_mtd_dev
  UBI: prepare for max_beb_per1024 module parameter addition
  UBI: introduce MTD_PARAM_MAX_COUNT
  UBI: separate bad_peb_limit in a function
  arm: sam9_l9260_defconfig: correct CONFIG_MTD_UBI_BEB_LIMIT
  UBI: use the whole MTD device size to get bad_peb_limit
  mtd: mtdparts: introduce mtd_get_device_size
  mtd: mark mtd_is_partition argument as constant
  arm: sam9_l9260_defconfig: remove non-existing config option
  UBI: kill CONFIG_MTD_UBI_BEB_RESERVE
  UBI: limit amount of reserved eraseblocks for bad PEB handling
  ...
parents 782c3fb2 55393ba1
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -39,7 +39,7 @@ CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_ATMEL=y
CONFIG_MTD_NAND_ATMEL=y
CONFIG_MTD_NAND_PLATFORM=y
CONFIG_MTD_NAND_PLATFORM=y
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_BEB_RESERVE=3
CONFIG_MTD_UBI_BEB_LIMIT=25
CONFIG_MTD_UBI_GLUEBI=y
CONFIG_MTD_UBI_GLUEBI=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM=y
+11 −1
Original line number Original line Diff line number Diff line
@@ -744,7 +744,7 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
	return ret;
	return ret;
}
}


int mtd_is_partition(struct mtd_info *mtd)
int mtd_is_partition(const struct mtd_info *mtd)
{
{
	struct mtd_part *part;
	struct mtd_part *part;
	int ispart = 0;
	int ispart = 0;
@@ -760,3 +760,13 @@ int mtd_is_partition(struct mtd_info *mtd)
	return ispart;
	return ispart;
}
}
EXPORT_SYMBOL_GPL(mtd_is_partition);
EXPORT_SYMBOL_GPL(mtd_is_partition);

/* Returns the size of the entire flash chip */
uint64_t mtd_get_device_size(const struct mtd_info *mtd)
{
	if (!mtd_is_partition(mtd))
		return mtd->size;

	return PART(mtd)->master->size;
}
EXPORT_SYMBOL_GPL(mtd_get_device_size);
+27 −13
Original line number Original line Diff line number Diff line
@@ -27,20 +27,34 @@ config MTD_UBI_WL_THRESHOLD
	  life-cycle less than 10000, the threshold should be lessened (e.g.,
	  life-cycle less than 10000, the threshold should be lessened (e.g.,
	  to 128 or 256, although it does not have to be power of 2).
	  to 128 or 256, although it does not have to be power of 2).


config MTD_UBI_BEB_RESERVE
config MTD_UBI_BEB_LIMIT
	int "Percentage of reserved eraseblocks for bad eraseblocks handling"
	int "Maximum expected bad eraseblock count per 1024 eraseblocks"
	default 2
	default 20
	range 0 25
	range 0 768
	help
	help
	  If the MTD device admits of bad eraseblocks (e.g. NAND flash), UBI
	  This option specifies the maximum bad physical eraseblocks UBI
	  reserves some amount of physical eraseblocks to handle new bad
	  expects on the MTD device (per 1024 eraseblocks). If the underlying
	  eraseblocks. For example, if a flash physical eraseblock becomes bad,
	  flash does not admit of bad eraseblocks (e.g. NOR flash), this value
	  UBI uses these reserved physical eraseblocks to relocate the bad one.
	  is ignored.
	  This option specifies how many physical eraseblocks will be reserved

	  for bad eraseblock handling (percents of total number of good flash
	  NAND datasheets often specify the minimum and maximum NVM (Number of
	  eraseblocks). If the underlying flash does not admit of bad
	  Valid Blocks) for the flashes' endurance lifetime. The maximum
	  eraseblocks (e.g. NOR flash), this value is ignored and nothing is
	  expected bad eraseblocks per 1024 eraseblocks then can be calculated
	  reserved. Leave the default value if unsure.
	  as "1024 * (1 - MinNVB / MaxNVB)", which gives 20 for most NANDs
	  (MaxNVB is basically the total count of eraseblocks on the chip).

	  To put it differently, if this value is 20, UBI will try to reserve
	  about 1.9% of physical eraseblocks for bad blocks handling. And that
	  will be 1.9% of eraseblocks on the entire NAND chip, not just the MTD
	  partition UBI attaches. This means that if you have, say, a NAND
	  flash chip admits maximum 40 bad eraseblocks, and it is split on two
	  MTD partitions of the same size, UBI will reserve 40 eraseblocks when
	  attaching a partition.

	  This option can be overridden by the "mtd=" UBI module parameter or
	  by the "attach" ioctl.

	  Leave the default value if unsure.


config MTD_UBI_GLUEBI
config MTD_UBI_GLUEBI
	tristate "MTD devices emulation driver (gluebi)"
	tristate "MTD devices emulation driver (gluebi)"
+22 −24
Original line number Original line Diff line number Diff line
@@ -79,7 +79,7 @@
 *     NAND), it is probably a PEB which was being erased when power cut
 *     NAND), it is probably a PEB which was being erased when power cut
 *     happened, so this is corruption type 1. However, this is just a guess,
 *     happened, so this is corruption type 1. However, this is just a guess,
 *     which might be wrong.
 *     which might be wrong.
 *   o Otherwise this it corruption type 2.
 *   o Otherwise this is corruption type 2.
 */
 */


#include <linux/err.h>
#include <linux/err.h>
@@ -378,8 +378,8 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
			if (err == UBI_IO_BITFLIPS)
			if (err == UBI_IO_BITFLIPS)
				bitflips = 1;
				bitflips = 1;
			else {
			else {
				ubi_err("VID of PEB %d header is bad, but it "
				ubi_err("VID of PEB %d header is bad, but it was OK earlier, err %d",
					"was OK earlier, err %d", pnum, err);
					pnum, err);
				if (err > 0)
				if (err > 0)
					err = -EIO;
					err = -EIO;


@@ -790,11 +790,11 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
	if (ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->leb_size))
	if (ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->leb_size))
		goto out_unlock;
		goto out_unlock;


	ubi_err("PEB %d contains corrupted VID header, and the data does not "
	ubi_err("PEB %d contains corrupted VID header, and the data does not contain all 0xFF",
		"contain all 0xFF, this may be a non-UBI PEB or a severe VID "
		pnum);
		"header corruption which requires manual inspection", pnum);
	ubi_err("this may be a non-UBI PEB or a severe VID header corruption which requires manual inspection");
	ubi_dump_vid_hdr(vid_hdr);
	ubi_dump_vid_hdr(vid_hdr);
	dbg_msg("hexdump of PEB %d offset %d, length %d",
	pr_err("hexdump of PEB %d offset %d, length %d",
	       pnum, ubi->leb_start, ubi->leb_size);
	       pnum, ubi->leb_start, ubi->leb_size);
	ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
	ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
			       ubi->peb_buf, ubi->leb_size, 1);
			       ubi->peb_buf, ubi->leb_size, 1);
@@ -907,8 +907,8 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
			ubi->image_seq = image_seq;
			ubi->image_seq = image_seq;
		if (ubi->image_seq && image_seq &&
		if (ubi->image_seq && image_seq &&
		    ubi->image_seq != image_seq) {
		    ubi->image_seq != image_seq) {
			ubi_err("bad image sequence number %d in PEB %d, "
			ubi_err("bad image sequence number %d in PEB %d, expected %d",
				"expected %d", image_seq, pnum, ubi->image_seq);
				image_seq, pnum, ubi->image_seq);
			ubi_dump_ec_hdr(ech);
			ubi_dump_ec_hdr(ech);
			return -EINVAL;
			return -EINVAL;
		}
		}
@@ -975,7 +975,7 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
			return err;
			return err;
		goto adjust_mean_ec;
		goto adjust_mean_ec;
	case UBI_IO_FF:
	case UBI_IO_FF:
		if (ec_err)
		if (ec_err || bitflips)
			err = add_to_list(ai, pnum, UBI_UNKNOWN,
			err = add_to_list(ai, pnum, UBI_UNKNOWN,
					  UBI_UNKNOWN, ec, 1, &ai->erase);
					  UBI_UNKNOWN, ec, 1, &ai->erase);
		else
		else
@@ -997,8 +997,8 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
		/* Unsupported internal volume */
		/* Unsupported internal volume */
		switch (vidh->compat) {
		switch (vidh->compat) {
		case UBI_COMPAT_DELETE:
		case UBI_COMPAT_DELETE:
			ubi_msg("\"delete\" compatible internal volume %d:%d"
			ubi_msg("\"delete\" compatible internal volume %d:%d found, will remove it",
				" found, will remove it", vol_id, lnum);
				vol_id, lnum);
			err = add_to_list(ai, pnum, vol_id, lnum,
			err = add_to_list(ai, pnum, vol_id, lnum,
					  ec, 1, &ai->erase);
					  ec, 1, &ai->erase);
			if (err)
			if (err)
@@ -1006,15 +1006,14 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
			return 0;
			return 0;


		case UBI_COMPAT_RO:
		case UBI_COMPAT_RO:
			ubi_msg("read-only compatible internal volume %d:%d"
			ubi_msg("read-only compatible internal volume %d:%d found, switch to read-only mode",
				" found, switch to read-only mode",
				vol_id, lnum);
				vol_id, lnum);
			ubi->ro_mode = 1;
			ubi->ro_mode = 1;
			break;
			break;


		case UBI_COMPAT_PRESERVE:
		case UBI_COMPAT_PRESERVE:
			ubi_msg("\"preserve\" compatible internal volume %d:%d"
			ubi_msg("\"preserve\" compatible internal volume %d:%d found",
				" found", vol_id, lnum);
				vol_id, lnum);
			err = add_to_list(ai, pnum, vol_id, lnum,
			err = add_to_list(ai, pnum, vol_id, lnum,
					  ec, 0, &ai->alien);
					  ec, 0, &ai->alien);
			if (err)
			if (err)
@@ -1075,10 +1074,10 @@ static int late_analysis(struct ubi_device *ubi, struct ubi_attach_info *ai)
	if (ai->corr_peb_count) {
	if (ai->corr_peb_count) {
		ubi_err("%d PEBs are corrupted and preserved",
		ubi_err("%d PEBs are corrupted and preserved",
			ai->corr_peb_count);
			ai->corr_peb_count);
		printk(KERN_ERR "Corrupted PEBs are:");
		pr_err("Corrupted PEBs are:");
		list_for_each_entry(aeb, &ai->corr, u.list)
		list_for_each_entry(aeb, &ai->corr, u.list)
			printk(KERN_CONT " %d", aeb->pnum);
			pr_cont(" %d", aeb->pnum);
		printk(KERN_CONT "\n");
		pr_cont("\n");


		/*
		/*
		 * If too many PEBs are corrupted, we refuse attaching,
		 * If too many PEBs are corrupted, we refuse attaching,
@@ -1112,8 +1111,7 @@ static int late_analysis(struct ubi_device *ubi, struct ubi_attach_info *ai)
			get_random_bytes(&ubi->image_seq,
			get_random_bytes(&ubi->image_seq,
					 sizeof(ubi->image_seq));
					 sizeof(ubi->image_seq));
		} else {
		} else {
			ubi_err("MTD device is not UBI-formatted and possibly "
			ubi_err("MTD device is not UBI-formatted and possibly contains non-UBI data - refusing it");
				"contains non-UBI data - refusing it");
			return -EINVAL;
			return -EINVAL;
		}
		}


@@ -1172,7 +1170,7 @@ static struct ubi_attach_info *scan_all(struct ubi_device *ubi)
			goto out_vidh;
			goto out_vidh;
	}
	}


	dbg_msg("scanning is finished");
	ubi_msg("scanning is finished");


	/* Calculate mean erase counter */
	/* Calculate mean erase counter */
	if (ai->ec_count)
	if (ai->ec_count)
@@ -1244,7 +1242,7 @@ int ubi_attach(struct ubi_device *ubi)
	ubi->corr_peb_count = ai->corr_peb_count;
	ubi->corr_peb_count = ai->corr_peb_count;
	ubi->max_ec = ai->max_ec;
	ubi->max_ec = ai->max_ec;
	ubi->mean_ec = ai->mean_ec;
	ubi->mean_ec = ai->mean_ec;
	ubi_msg("max. sequence number:       %llu", ai->max_sqnum);
	dbg_gen("max. sequence number:       %llu", ai->max_sqnum);


	err = ubi_read_volume_table(ubi, ai);
	err = ubi_read_volume_table(ubi, ai);
	if (err)
	if (err)
+126 −78
Original line number Original line Diff line number Diff line
@@ -36,6 +36,7 @@
#include <linux/namei.h>
#include <linux/namei.h>
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/miscdevice.h>
#include <linux/miscdevice.h>
#include <linux/mtd/partitions.h>
#include <linux/log2.h>
#include <linux/log2.h>
#include <linux/kthread.h>
#include <linux/kthread.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
@@ -45,6 +46,12 @@
/* Maximum length of the 'mtd=' parameter */
/* Maximum length of the 'mtd=' parameter */
#define MTD_PARAM_LEN_MAX 64
#define MTD_PARAM_LEN_MAX 64


/* Maximum number of comma-separated items in the 'mtd=' parameter */
#define MTD_PARAM_MAX_COUNT 3

/* Maximum value for the number of bad PEBs per 1024 PEBs */
#define MAX_MTD_UBI_BEB_LIMIT 768

#ifdef CONFIG_MTD_UBI_MODULE
#ifdef CONFIG_MTD_UBI_MODULE
#define ubi_is_module() 1
#define ubi_is_module() 1
#else
#else
@@ -56,10 +63,12 @@
 * @name: MTD character device node path, MTD device name, or MTD device number
 * @name: MTD character device node path, MTD device name, or MTD device number
 *        string
 *        string
 * @vid_hdr_offs: VID header offset
 * @vid_hdr_offs: VID header offset
 * @max_beb_per1024: maximum expected number of bad PEBs per 1024 PEBs
 */
 */
struct mtd_dev_param {
struct mtd_dev_param {
	char name[MTD_PARAM_LEN_MAX];
	char name[MTD_PARAM_LEN_MAX];
	int vid_hdr_offs;
	int vid_hdr_offs;
	int max_beb_per1024;
};
};


/* Numbers of elements set in the @mtd_dev_param array */
/* Numbers of elements set in the @mtd_dev_param array */
@@ -564,9 +573,38 @@ void ubi_free_internal_volumes(struct ubi_device *ubi)
	}
	}
}
}


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;

	/*
	 * Here we are using size of the entire flash chip and
	 * not just the MTD partition size because the maximum
	 * number of bad eraseblocks is a percentage of the
	 * whole device and bad eraseblocks are not fairly
	 * distributed over the flash chip. So the worst case
	 * is that all the bad eraseblocks of the chip are in
	 * the MTD partition we are attaching (ubi->mtd).
	 */
	device_size = mtd_get_device_size(ubi->mtd);
	device_pebs = mtd_div_by_eb(device_size, ubi->mtd);
	limit = mult_frac(device_pebs, max_beb_per1024, 1024);

	/* Round it up */
	if (mult_frac(limit, 1024, max_beb_per1024) < device_pebs)
		limit += 1;

	return limit;
}

/**
/**
 * io_init - initialize I/O sub-system for a given UBI device.
 * io_init - initialize I/O sub-system for a given UBI device.
 * @ubi: UBI device description object
 * @ubi: UBI device description object
 * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs
 *
 *
 * If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are
 * If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are
 * assumed:
 * assumed:
@@ -579,8 +617,11 @@ void ubi_free_internal_volumes(struct ubi_device *ubi)
 * This function returns zero in case of success and a negative error code in
 * This function returns zero in case of success and a negative error code in
 * case of failure.
 * case of failure.
 */
 */
static int io_init(struct ubi_device *ubi)
static int io_init(struct ubi_device *ubi, int max_beb_per1024)
{
{
	dbg_gen("sizeof(struct ubi_ainf_peb) %zu", sizeof(struct ubi_ainf_peb));
	dbg_gen("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));

	if (ubi->mtd->numeraseregions != 0) {
	if (ubi->mtd->numeraseregions != 0) {
		/*
		/*
		 * Some flashes have several erase regions. Different regions
		 * Some flashes have several erase regions. Different regions
@@ -607,8 +648,10 @@ static int io_init(struct ubi_device *ubi)
	ubi->peb_count  = mtd_div_by_eb(ubi->mtd->size, ubi->mtd);
	ubi->peb_count  = mtd_div_by_eb(ubi->mtd->size, ubi->mtd);
	ubi->flash_size = ubi->mtd->size;
	ubi->flash_size = ubi->mtd->size;


	if (mtd_can_have_bb(ubi->mtd))
	if (mtd_can_have_bb(ubi->mtd)) {
		ubi->bad_allowed = 1;
		ubi->bad_allowed = 1;
		ubi->bad_peb_limit = get_bad_peb_limit(ubi, max_beb_per1024);
	}


	if (ubi->mtd->type == MTD_NORFLASH) {
	if (ubi->mtd->type == MTD_NORFLASH) {
		ubi_assert(ubi->mtd->writesize == 1);
		ubi_assert(ubi->mtd->writesize == 1);
@@ -650,11 +693,11 @@ static int io_init(struct ubi_device *ubi)
	ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size);
	ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size);
	ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size);
	ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size);


	dbg_msg("min_io_size      %d", ubi->min_io_size);
	dbg_gen("min_io_size      %d", ubi->min_io_size);
	dbg_msg("max_write_size   %d", ubi->max_write_size);
	dbg_gen("max_write_size   %d", ubi->max_write_size);
	dbg_msg("hdrs_min_io_size %d", ubi->hdrs_min_io_size);
	dbg_gen("hdrs_min_io_size %d", ubi->hdrs_min_io_size);
	dbg_msg("ec_hdr_alsize    %d", ubi->ec_hdr_alsize);
	dbg_gen("ec_hdr_alsize    %d", ubi->ec_hdr_alsize);
	dbg_msg("vid_hdr_alsize   %d", ubi->vid_hdr_alsize);
	dbg_gen("vid_hdr_alsize   %d", ubi->vid_hdr_alsize);


	if (ubi->vid_hdr_offset == 0)
	if (ubi->vid_hdr_offset == 0)
		/* Default offset */
		/* Default offset */
@@ -671,10 +714,10 @@ static int io_init(struct ubi_device *ubi)
	ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE;
	ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE;
	ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);
	ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);


	dbg_msg("vid_hdr_offset   %d", ubi->vid_hdr_offset);
	dbg_gen("vid_hdr_offset   %d", ubi->vid_hdr_offset);
	dbg_msg("vid_hdr_aloffset %d", ubi->vid_hdr_aloffset);
	dbg_gen("vid_hdr_aloffset %d", ubi->vid_hdr_aloffset);
	dbg_msg("vid_hdr_shift    %d", ubi->vid_hdr_shift);
	dbg_gen("vid_hdr_shift    %d", ubi->vid_hdr_shift);
	dbg_msg("leb_start        %d", ubi->leb_start);
	dbg_gen("leb_start        %d", ubi->leb_start);


	/* The shift must be aligned to 32-bit boundary */
	/* The shift must be aligned to 32-bit boundary */
	if (ubi->vid_hdr_shift % 4) {
	if (ubi->vid_hdr_shift % 4) {
@@ -700,7 +743,7 @@ static int io_init(struct ubi_device *ubi)
	ubi->max_erroneous = ubi->peb_count / 10;
	ubi->max_erroneous = ubi->peb_count / 10;
	if (ubi->max_erroneous < 16)
	if (ubi->max_erroneous < 16)
		ubi->max_erroneous = 16;
		ubi->max_erroneous = 16;
	dbg_msg("max_erroneous    %d", ubi->max_erroneous);
	dbg_gen("max_erroneous    %d", ubi->max_erroneous);


	/*
	/*
	 * It may happen that EC and VID headers are situated in one minimal
	 * It may happen that EC and VID headers are situated in one minimal
@@ -708,30 +751,18 @@ static int io_init(struct ubi_device *ubi)
	 * read-only mode.
	 * read-only mode.
	 */
	 */
	if (ubi->vid_hdr_offset + UBI_VID_HDR_SIZE <= ubi->hdrs_min_io_size) {
	if (ubi->vid_hdr_offset + UBI_VID_HDR_SIZE <= ubi->hdrs_min_io_size) {
		ubi_warn("EC and VID headers are in the same minimal I/O unit, "
		ubi_warn("EC and VID headers are in the same minimal I/O unit, switch to read-only mode");
			 "switch to read-only mode");
		ubi->ro_mode = 1;
		ubi->ro_mode = 1;
	}
	}


	ubi->leb_size = ubi->peb_size - ubi->leb_start;
	ubi->leb_size = ubi->peb_size - ubi->leb_start;


	if (!(ubi->mtd->flags & MTD_WRITEABLE)) {
	if (!(ubi->mtd->flags & MTD_WRITEABLE)) {
		ubi_msg("MTD device %d is write-protected, attach in "
		ubi_msg("MTD device %d is write-protected, attach in read-only mode",
			"read-only mode", ubi->mtd->index);
			ubi->mtd->index);
		ubi->ro_mode = 1;
		ubi->ro_mode = 1;
	}
	}


	ubi_msg("physical eraseblock size:   %d bytes (%d KiB)",
		ubi->peb_size, ubi->peb_size >> 10);
	ubi_msg("logical eraseblock size:    %d bytes", ubi->leb_size);
	ubi_msg("smallest flash I/O unit:    %d", ubi->min_io_size);
	if (ubi->hdrs_min_io_size != ubi->min_io_size)
		ubi_msg("sub-page size:              %d",
			ubi->hdrs_min_io_size);
	ubi_msg("VID header offset:          %d (aligned %d)",
		ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
	ubi_msg("data offset:                %d", ubi->leb_start);

	/*
	/*
	 * Note, ideally, we have to initialize @ubi->bad_peb_count here. But
	 * Note, ideally, we have to initialize @ubi->bad_peb_count here. But
	 * unfortunately, MTD does not provide this information. We should loop
	 * unfortunately, MTD does not provide this information. We should loop
@@ -759,6 +790,11 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
	struct ubi_volume *vol = ubi->volumes[vol_id];
	struct ubi_volume *vol = ubi->volumes[vol_id];
	int err, old_reserved_pebs = vol->reserved_pebs;
	int err, old_reserved_pebs = vol->reserved_pebs;


	if (ubi->ro_mode) {
		ubi_warn("skip auto-resize because of R/O mode");
		return 0;
	}

	/*
	/*
	 * Clear the auto-resize flag in the volume in-memory copy of the
	 * Clear the auto-resize flag in the volume in-memory copy of the
	 * volume table, and 'ubi_resize_volume()' will propagate this change
	 * volume table, and 'ubi_resize_volume()' will propagate this change
@@ -800,6 +836,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
 * @mtd: MTD device description object
 * @mtd: MTD device description object
 * @ubi_num: number to assign to the new UBI device
 * @ubi_num: number to assign to the new UBI device
 * @vid_hdr_offset: VID header offset
 * @vid_hdr_offset: VID header offset
 * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs
 *
 *
 * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number
 * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number
 * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in
 * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in
@@ -810,11 +847,18 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
 * Note, the invocations of this function has to be serialized by the
 * Note, the invocations of this function has to be serialized by the
 * @ubi_devices_mutex.
 * @ubi_devices_mutex.
 */
 */
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
		       int vid_hdr_offset, int max_beb_per1024)
{
{
	struct ubi_device *ubi;
	struct ubi_device *ubi;
	int i, err, ref = 0;
	int i, err, ref = 0;


	if (max_beb_per1024 < 0 || max_beb_per1024 > MAX_MTD_UBI_BEB_LIMIT)
		return -EINVAL;

	if (!max_beb_per1024)
		max_beb_per1024 = CONFIG_MTD_UBI_BEB_LIMIT;

	/*
	/*
	 * Check if we already have the same MTD device attached.
	 * Check if we already have the same MTD device attached.
	 *
	 *
@@ -839,8 +883,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
	 * no sense to attach emulated MTD devices, so we prohibit this.
	 * no sense to attach emulated MTD devices, so we prohibit this.
	 */
	 */
	if (mtd->type == MTD_UBIVOLUME) {
	if (mtd->type == MTD_UBIVOLUME) {
		ubi_err("refuse attaching mtd%d - it is already emulated on "
		ubi_err("refuse attaching mtd%d - it is already emulated on top of UBI",
			"top of UBI", mtd->index);
			mtd->index);
		return -EINVAL;
		return -EINVAL;
	}
	}


@@ -880,10 +924,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
	spin_lock_init(&ubi->volumes_lock);
	spin_lock_init(&ubi->volumes_lock);


	ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
	ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
	dbg_msg("sizeof(struct ubi_ainf_peb) %zu", sizeof(struct ubi_ainf_peb));
	dbg_msg("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));


	err = io_init(ubi);
	err = io_init(ubi, max_beb_per1024);
	if (err)
	if (err)
		goto out_free;
		goto out_free;


@@ -924,23 +966,24 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
		goto out_debugfs;
		goto out_debugfs;
	}
	}


	ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num);
	ubi_msg("attached mtd%d (name \"%s\", size %llu MiB) to ubi%d",
	ubi_msg("MTD device name:            \"%s\"", mtd->name);
		mtd->index, mtd->name, ubi->flash_size >> 20, ubi_num);
	ubi_msg("MTD device size:            %llu MiB", ubi->flash_size >> 20);
	ubi_msg("PEB size: %d bytes (%d KiB), LEB size: %d bytes",
	ubi_msg("number of good PEBs:        %d", ubi->good_peb_count);
		ubi->peb_size, ubi->peb_size >> 10, ubi->leb_size);
	ubi_msg("number of bad PEBs:         %d", ubi->bad_peb_count);
	ubi_msg("min./max. I/O unit sizes: %d/%d, sub-page size %d",
	ubi_msg("number of corrupted PEBs:   %d", ubi->corr_peb_count);
		ubi->min_io_size, ubi->max_write_size, ubi->hdrs_min_io_size);
	ubi_msg("max. allowed volumes:       %d", ubi->vtbl_slots);
	ubi_msg("VID header offset: %d (aligned %d), data offset: %d",
	ubi_msg("wear-leveling threshold:    %d", CONFIG_MTD_UBI_WL_THRESHOLD);
		ubi->vid_hdr_offset, ubi->vid_hdr_aloffset, ubi->leb_start);
	ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
	ubi_msg("good PEBs: %d, bad PEBs: %d, corrupted PEBs: %d",
	ubi_msg("number of user volumes:     %d",
		ubi->good_peb_count, ubi->bad_peb_count, ubi->corr_peb_count);
		ubi->vol_count - UBI_INT_VOL_COUNT);
	ubi_msg("user volume: %d, internal volumes: %d, max. volumes count: %d",
	ubi_msg("available PEBs:             %d", ubi->avail_pebs);
		ubi->vol_count - UBI_INT_VOL_COUNT, UBI_INT_VOL_COUNT,
	ubi_msg("total number of reserved PEBs: %d", ubi->rsvd_pebs);
		ubi->vtbl_slots);
	ubi_msg("number of PEBs reserved for bad PEB handling: %d",
	ubi_msg("max/mean erase counter: %d/%d, WL threshold: %d, image sequence number: %u",
		ubi->beb_rsvd_pebs);
		ubi->max_ec, ubi->mean_ec, CONFIG_MTD_UBI_WL_THRESHOLD,
	ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
		ubi->image_seq);
	ubi_msg("image sequence number:  %d", ubi->image_seq);
	ubi_msg("available PEBs: %d, total reserved PEBs: %d, PEBs reserved for bad PEB handling: %d",
		ubi->avail_pebs, ubi->rsvd_pebs, ubi->beb_rsvd_pebs);


	/*
	/*
	 * The below lock makes sure we do not race with 'ubi_thread()' which
	 * The below lock makes sure we do not race with 'ubi_thread()' which
@@ -1017,7 +1060,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)


	ubi_assert(ubi_num == ubi->ubi_num);
	ubi_assert(ubi_num == ubi->ubi_num);
	ubi_notify_all(ubi, UBI_VOLUME_REMOVED, NULL);
	ubi_notify_all(ubi, UBI_VOLUME_REMOVED, NULL);
	dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);
	ubi_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);


	/*
	/*
	 * Before freeing anything, we have to stop the background thread to
	 * Before freeing anything, we have to stop the background thread to
@@ -1172,7 +1215,7 @@ static int __init ubi_init(void)


		mutex_lock(&ubi_devices_mutex);
		mutex_lock(&ubi_devices_mutex);
		err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO,
		err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO,
					 p->vid_hdr_offs);
					 p->vid_hdr_offs, p->max_beb_per1024);
		mutex_unlock(&ubi_devices_mutex);
		mutex_unlock(&ubi_devices_mutex);
		if (err < 0) {
		if (err < 0) {
			ubi_err("cannot attach mtd%d", mtd->index);
			ubi_err("cannot attach mtd%d", mtd->index);
@@ -1218,7 +1261,7 @@ static int __init ubi_init(void)
	ubi_err("UBI error: cannot initialize UBI, error %d", err);
	ubi_err("UBI error: cannot initialize UBI, error %d", err);
	return err;
	return err;
}
}
module_init(ubi_init);
late_initcall(ubi_init);


static void __exit ubi_exit(void)
static void __exit ubi_exit(void)
{
{
@@ -1252,8 +1295,7 @@ static int __init bytes_str_to_int(const char *str)


	result = simple_strtoul(str, &endp, 0);
	result = simple_strtoul(str, &endp, 0);
	if (str == endp || result >= INT_MAX) {
	if (str == endp || result >= INT_MAX) {
		printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n",
		ubi_err("UBI error: incorrect bytes count: \"%s\"\n", str);
		       str);
		return -EINVAL;
		return -EINVAL;
	}
	}


@@ -1269,8 +1311,7 @@ static int __init bytes_str_to_int(const char *str)
	case '\0':
	case '\0':
		break;
		break;
	default:
	default:
		printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n",
		ubi_err("UBI error: incorrect bytes count: \"%s\"\n", str);
		       str);
		return -EINVAL;
		return -EINVAL;
	}
	}


@@ -1291,27 +1332,26 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
	struct mtd_dev_param *p;
	struct mtd_dev_param *p;
	char buf[MTD_PARAM_LEN_MAX];
	char buf[MTD_PARAM_LEN_MAX];
	char *pbuf = &buf[0];
	char *pbuf = &buf[0];
	char *tokens[2] = {NULL, NULL};
	char *tokens[MTD_PARAM_MAX_COUNT];


	if (!val)
	if (!val)
		return -EINVAL;
		return -EINVAL;


	if (mtd_devs == UBI_MAX_DEVICES) {
	if (mtd_devs == UBI_MAX_DEVICES) {
		printk(KERN_ERR "UBI error: too many parameters, max. is %d\n",
		ubi_err("UBI error: too many parameters, max. is %d\n",
			UBI_MAX_DEVICES);
			UBI_MAX_DEVICES);
		return -EINVAL;
		return -EINVAL;
	}
	}


	len = strnlen(val, MTD_PARAM_LEN_MAX);
	len = strnlen(val, MTD_PARAM_LEN_MAX);
	if (len == MTD_PARAM_LEN_MAX) {
	if (len == MTD_PARAM_LEN_MAX) {
		printk(KERN_ERR "UBI error: parameter \"%s\" is too long, "
		ubi_err("UBI error: parameter \"%s\" is too long, max. is %d\n",
		       "max. is %d\n", val, MTD_PARAM_LEN_MAX);
			val, MTD_PARAM_LEN_MAX);
		return -EINVAL;
		return -EINVAL;
	}
	}


	if (len == 0) {
	if (len == 0) {
		printk(KERN_WARNING "UBI warning: empty 'mtd=' parameter - "
		pr_warn("UBI warning: empty 'mtd=' parameter - ignored\n");
		       "ignored\n");
		return 0;
		return 0;
	}
	}


@@ -1321,12 +1361,11 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
	if (buf[len - 1] == '\n')
	if (buf[len - 1] == '\n')
		buf[len - 1] = '\0';
		buf[len - 1] = '\0';


	for (i = 0; i < 2; i++)
	for (i = 0; i < MTD_PARAM_MAX_COUNT; i++)
		tokens[i] = strsep(&pbuf, ",");
		tokens[i] = strsep(&pbuf, ",");


	if (pbuf) {
	if (pbuf) {
		printk(KERN_ERR "UBI error: too many arguments at \"%s\"\n",
		ubi_err("UBI error: too many arguments at \"%s\"\n", val);
		       val);
		return -EINVAL;
		return -EINVAL;
	}
	}


@@ -1339,23 +1378,32 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
	if (p->vid_hdr_offs < 0)
	if (p->vid_hdr_offs < 0)
		return p->vid_hdr_offs;
		return p->vid_hdr_offs;


	if (tokens[2]) {
		int err = kstrtoint(tokens[2], 10, &p->max_beb_per1024);

		if (err) {
			ubi_err("UBI error: bad value for max_beb_per1024 parameter: %s",
				tokens[2]);
			return -EINVAL;
		}
	}

	mtd_devs += 1;
	mtd_devs += 1;
	return 0;
	return 0;
}
}


module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000);
module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000);
MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: "
MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,max_beb_per1024]].\n"
		      "mtd=<name|num|path>[,<vid_hdr_offs>].\n"
		      "Multiple \"mtd\" parameters may be specified.\n"
		      "Multiple \"mtd\" parameters may be specified.\n"
		      "MTD devices may be specified by their number, name, or "
		      "MTD devices may be specified by their number, name, or path to the MTD character device node.\n"
		      "path to the MTD character device node.\n"
		      "Optional \"vid_hdr_offs\" parameter specifies UBI VID header position to be used by UBI. (default value if 0)\n"
		      "Optional \"vid_hdr_offs\" parameter specifies UBI VID "
		      "Optional \"max_beb_per1024\" parameter specifies the maximum expected bad eraseblock per 1024 eraseblocks. (default value ("
		      "header position to be used by UBI.\n"
		      __stringify(CONFIG_MTD_UBI_BEB_LIMIT) ") if 0)\n"
		      "Example 1: mtd=/dev/mtd0 - attach MTD device "
		      "\n"
		      "/dev/mtd0.\n"
		      "Example 1: mtd=/dev/mtd0 - attach MTD device /dev/mtd0.\n"
		      "Example 2: mtd=content,1984 mtd=4 - attach MTD device "
		      "Example 2: mtd=content,1984 mtd=4 - attach MTD device with name \"content\" using VID header offset 1984, and MTD device number 4 with default VID header offset.\n"
		      "with name \"content\" using VID header offset 1984, and "
		      "Example 3: mtd=/dev/mtd1,0,25 - attach MTD device /dev/mtd1 using default VID header offset and reserve 25*nand_size_in_blocks/1024 erase blocks for bad block handling.\n"
		      "MTD device number 4 with default VID header offset.");
		      "\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device).");


MODULE_VERSION(__stringify(UBI_VERSION));
MODULE_VERSION(__stringify(UBI_VERSION));
MODULE_DESCRIPTION("UBI - Unsorted Block Images");
MODULE_DESCRIPTION("UBI - Unsorted Block Images");
Loading