Commit d6be791c authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linux-next' of git://git.infradead.org/ubi-2.6

* 'linux-next' of git://git.infradead.org/ubi-2.6:
  UBI: fix compilation warnings
  UBI: fix NOR flash recovery
  UBI: nicify image sequence number handling
  UBI: add image sequence number to EC header
  UBI: remove bogus debugging checks
  UBI: add empty eraseblocks verification
parents 44c695b1 83c2099f
...@@ -657,6 +657,11 @@ static int io_init(struct ubi_device *ubi) ...@@ -657,6 +657,11 @@ static int io_init(struct ubi_device *ubi)
if (ubi->mtd->block_isbad && ubi->mtd->block_markbad) if (ubi->mtd->block_isbad && ubi->mtd->block_markbad)
ubi->bad_allowed = 1; ubi->bad_allowed = 1;
if (ubi->mtd->type == MTD_NORFLASH) {
ubi_assert(ubi->mtd->writesize == 1);
ubi->nor_flash = 1;
}
ubi->min_io_size = ubi->mtd->writesize; ubi->min_io_size = ubi->mtd->writesize;
ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
...@@ -996,6 +1001,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) ...@@ -996,6 +1001,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
ubi_msg("number of PEBs reserved for bad PEB handling: %d", ubi_msg("number of PEBs reserved for bad PEB handling: %d",
ubi->beb_rsvd_pebs); ubi->beb_rsvd_pebs);
ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
ubi_msg("image sequence number: %d", ubi->image_seq);
/* /*
* 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
......
...@@ -44,6 +44,8 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) ...@@ -44,6 +44,8 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
be32_to_cpu(ec_hdr->vid_hdr_offset)); be32_to_cpu(ec_hdr->vid_hdr_offset));
printk(KERN_DEBUG "\tdata_offset %d\n", printk(KERN_DEBUG "\tdata_offset %d\n",
be32_to_cpu(ec_hdr->data_offset)); be32_to_cpu(ec_hdr->data_offset));
printk(KERN_DEBUG "\timage_seq %d\n",
be32_to_cpu(ec_hdr->image_seq));
printk(KERN_DEBUG "\thdr_crc %#08x\n", printk(KERN_DEBUG "\thdr_crc %#08x\n",
be32_to_cpu(ec_hdr->hdr_crc)); be32_to_cpu(ec_hdr->hdr_crc));
printk(KERN_DEBUG "erase counter header hexdump:\n"); printk(KERN_DEBUG "erase counter header hexdump:\n");
......
...@@ -93,6 +93,12 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); ...@@ -93,6 +93,12 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
#define UBI_IO_DEBUG 0 #define UBI_IO_DEBUG 0
#endif #endif
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
#else
#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
#endif
#ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT
#define DBG_DISABLE_BGT 1 #define DBG_DISABLE_BGT 1
#else #else
...@@ -167,6 +173,7 @@ static inline int ubi_dbg_is_erase_failure(void) ...@@ -167,6 +173,7 @@ static inline int ubi_dbg_is_erase_failure(void)
#define ubi_dbg_is_bitflip() 0 #define ubi_dbg_is_bitflip() 0
#define ubi_dbg_is_write_failure() 0 #define ubi_dbg_is_write_failure() 0
#define ubi_dbg_is_erase_failure() 0 #define ubi_dbg_is_erase_failure() 0
#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
#endif /* !CONFIG_MTD_UBI_DEBUG */ #endif /* !CONFIG_MTD_UBI_DEBUG */
#endif /* !__UBI_DEBUG_H__ */ #endif /* !__UBI_DEBUG_H__ */
...@@ -98,17 +98,12 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, ...@@ -98,17 +98,12 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum); static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum);
static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
const struct ubi_vid_hdr *vid_hdr); const struct ubi_vid_hdr *vid_hdr);
static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
int len);
static int paranoid_check_empty(struct ubi_device *ubi, int pnum);
#else #else
#define paranoid_check_not_bad(ubi, pnum) 0 #define paranoid_check_not_bad(ubi, pnum) 0
#define paranoid_check_peb_ec_hdr(ubi, pnum) 0 #define paranoid_check_peb_ec_hdr(ubi, pnum) 0
#define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0 #define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0
#define paranoid_check_peb_vid_hdr(ubi, pnum) 0 #define paranoid_check_peb_vid_hdr(ubi, pnum) 0
#define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0 #define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0
#define paranoid_check_all_ff(ubi, pnum, offset, len) 0
#define paranoid_check_empty(ubi, pnum) 0
#endif #endif
/** /**
...@@ -244,7 +239,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, ...@@ -244,7 +239,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
return err > 0 ? -EINVAL : err; return err > 0 ? -EINVAL : err;
/* The area we are writing to has to contain all 0xFF bytes */ /* The area we are writing to has to contain all 0xFF bytes */
err = paranoid_check_all_ff(ubi, pnum, offset, len); err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
if (err) if (err)
return err > 0 ? -EINVAL : err; return err > 0 ? -EINVAL : err;
...@@ -271,8 +266,8 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, ...@@ -271,8 +266,8 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
addr = (loff_t)pnum * ubi->peb_size + offset; addr = (loff_t)pnum * ubi->peb_size + offset;
err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf); err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf);
if (err) { if (err) {
ubi_err("error %d while writing %d bytes to PEB %d:%d, written" ubi_err("error %d while writing %d bytes to PEB %d:%d, written "
" %zd bytes", err, len, pnum, offset, written); "%zd bytes", err, len, pnum, offset, written);
ubi_dbg_dump_stack(); ubi_dbg_dump_stack();
} else } else
ubi_assert(written == len); ubi_assert(written == len);
...@@ -350,7 +345,7 @@ static int do_sync_erase(struct ubi_device *ubi, int pnum) ...@@ -350,7 +345,7 @@ static int do_sync_erase(struct ubi_device *ubi, int pnum)
return -EIO; return -EIO;
} }
err = paranoid_check_all_ff(ubi, pnum, 0, ubi->peb_size); err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size);
if (err) if (err)
return err > 0 ? -EINVAL : err; return err > 0 ? -EINVAL : err;
...@@ -458,6 +453,54 @@ static int torture_peb(struct ubi_device *ubi, int pnum) ...@@ -458,6 +453,54 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
return err; return err;
} }
/**
* nor_erase_prepare - prepare a NOR flash PEB for erasure.
* @ubi: UBI device description object
* @pnum: physical eraseblock number to prepare
*
* NOR flash, or at least some of them, have peculiar embedded PEB erasure
* algorithm: the PEB is first filled with zeroes, then it is erased. And
* filling with zeroes starts from the end of the PEB. This was observed with
* Spansion S29GL512N NOR flash.
*
* This means that in case of a power cut we may end up with intact data at the
* beginning of the PEB, and all zeroes at the end of PEB. In other words, the
* EC and VID headers are OK, but a large chunk of data at the end of PEB is
* zeroed. This makes UBI mistakenly treat this PEB as used and associate it
* with an LEB, which leads to subsequent failures (e.g., UBIFS fails).
*
* This function is called before erasing NOR PEBs and it zeroes out EC and VID
* magic numbers in order to invalidate them and prevent the failures. Returns
* zero in case of success and a negative error code in case of failure.
*/
static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
{
int err;
size_t written;
loff_t addr;
uint32_t data = 0;
addr = (loff_t)pnum * ubi->peb_size;
err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
if (err) {
ubi_err("error %d while writing 4 bytes to PEB %d:%d, written "
"%zd bytes", err, pnum, 0, written);
ubi_dbg_dump_stack();
return err;
}
addr += ubi->vid_hdr_aloffset;
err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
if (err) {
ubi_err("error %d while writing 4 bytes to PEB %d:%d, written "
"%zd bytes", err, pnum, ubi->vid_hdr_aloffset, written);
ubi_dbg_dump_stack();
return err;
}
return 0;
}
/** /**
* ubi_io_sync_erase - synchronously erase a physical eraseblock. * ubi_io_sync_erase - synchronously erase a physical eraseblock.
* @ubi: UBI device description object * @ubi: UBI device description object
...@@ -489,6 +532,12 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture) ...@@ -489,6 +532,12 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture)
return -EROFS; return -EROFS;
} }
if (ubi->nor_flash) {
err = nor_erase_prepare(ubi, pnum);
if (err)
return err;
}
if (torture) { if (torture) {
ret = torture_peb(ubi, pnum); ret = torture_peb(ubi, pnum);
if (ret < 0) if (ret < 0)
...@@ -672,11 +721,6 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, ...@@ -672,11 +721,6 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
if (read_err != -EBADMSG && if (read_err != -EBADMSG &&
check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
/* The physical eraseblock is supposedly empty */ /* The physical eraseblock is supposedly empty */
err = paranoid_check_all_ff(ubi, pnum, 0,
ubi->peb_size);
if (err)
return err > 0 ? UBI_IO_BAD_EC_HDR : err;
if (verbose) if (verbose)
ubi_warn("no EC header found at PEB %d, " ubi_warn("no EC header found at PEB %d, "
"only 0xFF bytes", pnum); "only 0xFF bytes", pnum);
...@@ -752,6 +796,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, ...@@ -752,6 +796,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
ec_hdr->version = UBI_VERSION; ec_hdr->version = UBI_VERSION;
ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset); ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset);
ec_hdr->data_offset = cpu_to_be32(ubi->leb_start); ec_hdr->data_offset = cpu_to_be32(ubi->leb_start);
ec_hdr->image_seq = cpu_to_be32(ubi->image_seq);
crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
ec_hdr->hdr_crc = cpu_to_be32(crc); ec_hdr->hdr_crc = cpu_to_be32(crc);
...@@ -947,15 +992,6 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, ...@@ -947,15 +992,6 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
if (read_err != -EBADMSG && if (read_err != -EBADMSG &&
check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
/* The physical eraseblock is supposedly free */ /* The physical eraseblock is supposedly free */
/*
* The below is just a paranoid check, it has to be
* compiled out if paranoid checks are disabled.
*/
err = paranoid_check_empty(ubi, pnum);
if (err)
return err > 0 ? UBI_IO_BAD_VID_HDR : err;
if (verbose) if (verbose)
ubi_warn("no VID header found at PEB %d, " ubi_warn("no VID header found at PEB %d, "
"only 0xFF bytes", pnum); "only 0xFF bytes", pnum);
...@@ -1229,7 +1265,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) ...@@ -1229,7 +1265,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
} }
/** /**
* paranoid_check_all_ff - check that a region of flash is empty. * ubi_dbg_check_all_ff - check that a region of flash is empty.
* @ubi: UBI device description object * @ubi: UBI device description object
* @pnum: the physical eraseblock number to check * @pnum: the physical eraseblock number to check
* @offset: the starting offset within the physical eraseblock to check * @offset: the starting offset within the physical eraseblock to check
...@@ -1239,8 +1275,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) ...@@ -1239,8 +1275,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
* @offset of the physical eraseblock @pnum, %1 if not, and a negative error * @offset of the physical eraseblock @pnum, %1 if not, and a negative error
* code if an error occurred. * code if an error occurred.
*/ */
static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
int len)
{ {
size_t read; size_t read;
int err; int err;
...@@ -1276,74 +1311,4 @@ static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, ...@@ -1276,74 +1311,4 @@ static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
return err; return err;
} }
/**
* paranoid_check_empty - whether a PEB is empty.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
*
* This function makes sure PEB @pnum is empty, which means it contains only
* %0xFF data bytes. Returns zero if the PEB is empty, %1 if not, and a
* negative error code in case of failure.
*
* Empty PEBs have the EC header, and do not have the VID header. The caller of
* this function should have already made sure the PEB does not have the VID
* header. However, this function re-checks that, because it is possible that
* the header and data has already been written to the PEB.
*
* Let's consider a possible scenario. Suppose there are 2 tasks - A and B.
* Task A is in 'wear_leveling_worker()'. It is reading VID header of PEB X to
* find which LEB it corresponds to. PEB X is currently unmapped, and has no
* VID header. Task B is trying to write to PEB X.
*
* Task A: in 'ubi_io_read_vid_hdr()': reads the VID header from PEB X. The
* read data contain all 0xFF bytes;
* Task B: writes VID header and some data to PEB X;
* Task A: assumes PEB X is empty, calls 'paranoid_check_empty()'. And if we
* do not re-read the VID header, and do not cancel the checking if it
* is there, we fail.
*/
static int paranoid_check_empty(struct ubi_device *ubi, int pnum)
{
int err, offs = ubi->vid_hdr_aloffset, len = ubi->vid_hdr_alsize;
size_t read;
uint32_t magic;
const struct ubi_vid_hdr *vid_hdr;
mutex_lock(&ubi->dbg_buf_mutex);
err = ubi->mtd->read(ubi->mtd, offs, len, &read, ubi->dbg_peb_buf);
if (err && err != -EUCLEAN) {
ubi_err("error %d while reading %d bytes from PEB %d:%d, "
"read %zd bytes", err, len, pnum, offs, read);
goto error;
}
vid_hdr = ubi->dbg_peb_buf;
magic = be32_to_cpu(vid_hdr->magic);
if (magic == UBI_VID_HDR_MAGIC)
/* The PEB contains VID header, so it is not empty */
goto out;
err = check_pattern(ubi->dbg_peb_buf, 0xFF, len);
if (err == 0) {
ubi_err("flash region at PEB %d:%d, length %d does not "
"contain all 0xFF bytes", pnum, offs, len);
goto fail;
}
out:
mutex_unlock(&ubi->dbg_buf_mutex);
return 0;
fail:
ubi_err("paranoid check failed for PEB %d", pnum);
ubi_msg("hex dump of the %d-%d region", offs, offs + len);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
ubi->dbg_peb_buf, len, 1);
err = 1;
error:
ubi_dbg_dump_stack();
mutex_unlock(&ubi->dbg_buf_mutex);
return err;
}
#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
...@@ -757,6 +757,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -757,6 +757,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
si->is_empty = 0; si->is_empty = 0;
if (!ec_corr) { if (!ec_corr) {
int image_seq;
/* Make sure UBI version is OK */ /* Make sure UBI version is OK */
if (ech->version != UBI_VERSION) { if (ech->version != UBI_VERSION) {
ubi_err("this UBI version is %d, image version is %d", ubi_err("this UBI version is %d, image version is %d",
...@@ -778,6 +780,18 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -778,6 +780,18 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
ubi_dbg_dump_ec_hdr(ech); ubi_dbg_dump_ec_hdr(ech);
return -EINVAL; return -EINVAL;
} }
image_seq = be32_to_cpu(ech->ec);
if (!si->image_seq_set) {
ubi->image_seq = image_seq;
si->image_seq_set = 1;
} else if (ubi->image_seq != image_seq) {
ubi_err("bad image sequence number %d in PEB %d, "
"expected %d", image_seq, pnum, ubi->image_seq);
ubi_dbg_dump_ec_hdr(ech);
return -EINVAL;
}
} }
/* OK, we've done with the EC header, let's look at the VID header */ /* OK, we've done with the EC header, let's look at the VID header */
......
...@@ -102,6 +102,7 @@ struct ubi_scan_volume { ...@@ -102,6 +102,7 @@ struct ubi_scan_volume {
* @mean_ec: mean erase counter value * @mean_ec: mean erase counter value
* @ec_sum: a temporary variable used when calculating @mean_ec * @ec_sum: a temporary variable used when calculating @mean_ec
* @ec_count: a temporary variable used when calculating @mean_ec * @ec_count: a temporary variable used when calculating @mean_ec
* @image_seq_set: indicates @ubi->image_seq is known
* *
* This data structure contains the result of scanning and may be used by other * This data structure contains the result of scanning and may be used by other
* UBI sub-systems to build final UBI data structures, further error-recovery * UBI sub-systems to build final UBI data structures, further error-recovery
...@@ -124,6 +125,7 @@ struct ubi_scan_info { ...@@ -124,6 +125,7 @@ struct ubi_scan_info {
int mean_ec; int mean_ec;
uint64_t ec_sum; uint64_t ec_sum;
int ec_count; int ec_count;
int image_seq_set;
}; };
struct ubi_device; struct ubi_device;
......
...@@ -129,6 +129,7 @@ enum { ...@@ -129,6 +129,7 @@ enum {
* @ec: the erase counter * @ec: the erase counter
* @vid_hdr_offset: where the VID header starts * @vid_hdr_offset: where the VID header starts
* @data_offset: where the user data start * @data_offset: where the user data start
* @image_seq: image sequence number
* @padding2: reserved for future, zeroes * @padding2: reserved for future, zeroes
* @hdr_crc: erase counter header CRC checksum * @hdr_crc: erase counter header CRC checksum
* *
...@@ -144,6 +145,14 @@ enum { ...@@ -144,6 +145,14 @@ enum {
* volume identifier header and user data, relative to the beginning of the * volume identifier header and user data, relative to the beginning of the
* physical eraseblock. These values have to be the same for all physical * physical eraseblock. These values have to be the same for all physical
* eraseblocks. * eraseblocks.
*
* The @image_seq field is used to validate a UBI image that has been prepared
* for a UBI device. The @image_seq value can be any value, but it must be the
* same on all eraseblocks. UBI will ensure that all new erase counter headers
* also contain this value, and will check the value when scanning at start-up.
* One way to make use of @image_seq is to increase its value by one every time
* an image is flashed over an existing image, then, if the flashing does not
* complete, UBI will detect the error when scanning.
*/ */
struct ubi_ec_hdr { struct ubi_ec_hdr {
__be32 magic; __be32 magic;
...@@ -152,7 +161,8 @@ struct ubi_ec_hdr { ...@@ -152,7 +161,8 @@ struct ubi_ec_hdr {
__be64 ec; /* Warning: the current limit is 31-bit anyway! */ __be64 ec; /* Warning: the current limit is 31-bit anyway! */
__be32 vid_hdr_offset; __be32 vid_hdr_offset;
__be32 data_offset; __be32 data_offset;
__u8 padding2[36]; __be32 image_seq;
__u8 padding2[32];
__be32 hdr_crc; __be32 hdr_crc;
} __attribute__ ((packed)); } __attribute__ ((packed));
......
...@@ -301,6 +301,7 @@ struct ubi_wl_entry; ...@@ -301,6 +301,7 @@ struct ubi_wl_entry;
* @vol->readers, @vol->writers, @vol->exclusive, * @vol->readers, @vol->writers, @vol->exclusive,
* @vol->ref_count, @vol->mapping and @vol->eba_tbl. * @vol->ref_count, @vol->mapping and @vol->eba_tbl.
* @ref_count: count of references on the UBI device * @ref_count: count of references on the UBI device
* @image_seq: image sequence number recorded on EC headers
* *
* @rsvd_pebs: count of reserved physical eraseblocks * @rsvd_pebs: count of reserved physical eraseblocks
* @avail_pebs: count of available physical eraseblocks * @avail_pebs: count of available physical eraseblocks
...@@ -372,6 +373,7 @@ struct ubi_wl_entry; ...@@ -372,6 +373,7 @@ struct ubi_wl_entry;
* @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset
* @bad_allowed: whether the MTD device admits of bad physical eraseblocks or * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or
* not * not
* @nor_flash: non-zero if working on top of NOR flash
* @mtd: MTD device descriptor * @mtd: MTD device descriptor
* *
* @peb_buf1: a buffer of PEB size used for different purposes * @peb_buf1: a buffer of PEB size used for different purposes
...@@ -390,6 +392,7 @@ struct ubi_device { ...@@ -390,6 +392,7 @@ struct ubi_device {
struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT]; struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT];
spinlock_t volumes_lock; spinlock_t volumes_lock;
int ref_count; int ref_count;
int image_seq;
int rsvd_pebs; int rsvd_pebs;
int avail_pebs; int avail_pebs;
...@@ -452,7 +455,8 @@ struct ubi_device { ...@@ -452,7 +455,8 @@ struct ubi_device {
int vid_hdr_offset; int vid_hdr_offset;
int vid_hdr_aloffset; int vid_hdr_aloffset;
int vid_hdr_shift; int vid_hdr_shift;
int bad_allowed; unsigned int bad_allowed:1;
unsigned int nor_flash:1;
struct mtd_info *mtd; struct mtd_info *mtd;
void *peb_buf1; void *peb_buf1;
......
...@@ -459,6 +459,14 @@ int ubi_wl_get_peb(struct ubi_device *ubi, int dtype) ...@@ -459,6 +459,14 @@ int ubi_wl_get_peb(struct ubi_device *ubi, int dtype)
dbg_wl("PEB %d EC %d", e->pnum, e->ec); dbg_wl("PEB %d EC %d", e->pnum, e->ec);
prot_queue_add(ubi, e); prot_queue_add(ubi, e);
spin_unlock(&ubi->wl_lock); spin_unlock(&ubi->wl_lock);
err = ubi_dbg_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
ubi->peb_size - ubi->vid_hdr_aloffset);
if (err) {
ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum);
return err > 0 ? -EINVAL : err;
}
return e->pnum; return e->pnum;
} }
......
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