summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2008-05-23 11:58:55 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2008-05-23 11:58:55 +1000
commit732673cfd876834719731a5e028d6db92d3686e3 (patch)
treef9fd5642d373a953747c41a1cb1be0f479eaee3b
parent83e00eaf1bfe671040bc31d299ce82d3d4002e39 (diff)
parent609154bceedf1c5f90ef8ae8a4d4844219c45b9f (diff)
Merge commit 'ubi/master'
-rw-r--r--drivers/mtd/ubi/build.c8
-rw-r--r--drivers/mtd/ubi/cdev.c6
-rw-r--r--drivers/mtd/ubi/eba.c2
-rw-r--r--drivers/mtd/ubi/kapi.c6
-rw-r--r--drivers/mtd/ubi/misc.c2
-rw-r--r--drivers/mtd/ubi/upd.c6
-rw-r--r--drivers/mtd/ubi/vmt.c2
-rw-r--r--drivers/mtd/ubi/vtbl.c55
-rw-r--r--drivers/mtd/ubi/wl.c3
9 files changed, 52 insertions, 38 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 961416ac0616..ff4425de1527 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -530,7 +530,11 @@ static int io_init(struct ubi_device *ubi)
ubi->min_io_size = ubi->mtd->writesize;
ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
- /* Make sure minimal I/O unit is power of 2 */
+ /*
+ * Make sure minimal I/O unit is power of 2. Note, there is no
+ * fundamental reason for this assumption. It is just an optimization
+ * which allows us to avoid costly division operations.
+ */
if (!is_power_of_2(ubi->min_io_size)) {
ubi_err("min. I/O unit (%d) is not power of 2",
ubi->min_io_size);
@@ -581,7 +585,7 @@ static int io_init(struct ubi_device *ubi)
if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE ||
ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE ||
ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE ||
- ubi->leb_start % ubi->min_io_size) {
+ ubi->leb_start & (ubi->min_io_size - 1)) {
ubi_err("bad VID header (%d) or data offsets (%d)",
ubi->vid_hdr_offset, ubi->leb_start);
return -EINVAL;
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 9d6aae5449b6..34175ec53b73 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -290,7 +290,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
off = do_div(tmp, vol->usable_leb_size);
lnum = tmp;
- if (off % ubi->min_io_size) {
+ if (off & (ubi->min_io_size - 1)) {
dbg_err("unaligned position");
return -EINVAL;
}
@@ -299,7 +299,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
count_save = count = vol->used_bytes - *offp;
/* We can write only in fractions of the minimum I/O unit */
- if (count % ubi->min_io_size) {
+ if (count & (ubi->min_io_size - 1)) {
dbg_err("unaligned write length");
return -EINVAL;
}
@@ -559,7 +559,7 @@ static int verify_mkvol_req(const struct ubi_device *ubi,
if (req->alignment > ubi->leb_size)
goto bad;
- n = req->alignment % ubi->min_io_size;
+ n = req->alignment & (ubi->min_io_size - 1);
if (req->alignment != 1 && n)
goto bad;
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 7ce91ca742b1..37d778447943 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -752,7 +752,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
/* If this is the last LEB @len may be unaligned */
len = ALIGN(data_size, ubi->min_io_size);
else
- ubi_assert(len % ubi->min_io_size == 0);
+ ubi_assert(!(len & (ubi->min_io_size - 1)));
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
if (!vid_hdr)
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index a70d58823f8d..51508832566d 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -397,8 +397,8 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
return -EROFS;
if (lnum < 0 || lnum >= vol->reserved_pebs || offset < 0 || len < 0 ||
- offset + len > vol->usable_leb_size || offset % ubi->min_io_size ||
- len % ubi->min_io_size)
+ offset + len > vol->usable_leb_size ||
+ offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1))
return -EINVAL;
if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
@@ -447,7 +447,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
return -EROFS;
if (lnum < 0 || lnum >= vol->reserved_pebs || len < 0 ||
- len > vol->usable_leb_size || len % ubi->min_io_size)
+ len > vol->usable_leb_size || len & (ubi->min_io_size - 1))
return -EINVAL;
if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c
index 93e052812012..22ad31402945 100644
--- a/drivers/mtd/ubi/misc.c
+++ b/drivers/mtd/ubi/misc.c
@@ -37,7 +37,7 @@ int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
{
int i;
- ubi_assert(length % ubi->min_io_size == 0);
+ ubi_assert(!(length & (ubi->min_io_size - 1)));
for (i = length - 1; i >= 0; i--)
if (((const uint8_t *)buf)[i] != 0xFF)
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
index ddaa1a56cc69..6fa1ab3f2a70 100644
--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -237,10 +237,10 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
int err;
if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
- len = ALIGN(len, ubi->min_io_size);
- memset(buf + len, 0xFF, len - len);
+ int l = ALIGN(len, ubi->min_io_size);
- len = ubi_calc_data_len(ubi, buf, len);
+ memset(buf + len, 0xFF, l - len);
+ len = ubi_calc_data_len(ubi, buf, l);
if (len == 0) {
dbg_msg("all %d bytes contain 0xFF - skip", len);
return 0;
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 5be58d85c639..7402025ded94 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -727,7 +727,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id)
goto fail;
}
- n = vol->alignment % ubi->min_io_size;
+ n = vol->alignment & (ubi->min_io_size - 1);
if (vol->alignment != 1 && n) {
ubi_err("alignment is not multiple of min I/O unit");
goto fail;
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index af36b12be278..d9af11a8682b 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -127,7 +127,7 @@ static int vtbl_check(const struct ubi_device *ubi,
const struct ubi_vtbl_record *vtbl)
{
int i, n, reserved_pebs, alignment, data_pad, vol_type, name_len;
- int upd_marker;
+ int upd_marker, err;
uint32_t crc;
const char *name;
@@ -153,7 +153,7 @@ static int vtbl_check(const struct ubi_device *ubi,
if (reserved_pebs == 0) {
if (memcmp(&vtbl[i], &empty_vtbl_record,
UBI_VTBL_RECORD_SIZE)) {
- dbg_err("bad empty record");
+ err = 2;
goto bad;
}
continue;
@@ -161,56 +161,57 @@ static int vtbl_check(const struct ubi_device *ubi,
if (reserved_pebs < 0 || alignment < 0 || data_pad < 0 ||
name_len < 0) {
- dbg_err("negative values");
+ err = 3;
goto bad;
}
if (alignment > ubi->leb_size || alignment == 0) {
- dbg_err("bad alignment");
+ err = 4;
goto bad;
}
- n = alignment % ubi->min_io_size;
+ n = alignment & (ubi->min_io_size - 1);
if (alignment != 1 && n) {
- dbg_err("alignment is not multiple of min I/O unit");
+ err = 5;
goto bad;
}
n = ubi->leb_size % alignment;
if (data_pad != n) {
dbg_err("bad data_pad, has to be %d", n);
+ err = 6;
goto bad;
}
if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) {
- dbg_err("bad vol_type");
+ err = 7;
goto bad;
}
if (upd_marker != 0 && upd_marker != 1) {
- dbg_err("bad upd_marker");
+ err = 8;
goto bad;
}
if (reserved_pebs > ubi->good_peb_count) {
dbg_err("too large reserved_pebs, good PEBs %d",
ubi->good_peb_count);
+ err = 9;
goto bad;
}
if (name_len > UBI_VOL_NAME_MAX) {
- dbg_err("too long volume name, max %d",
- UBI_VOL_NAME_MAX);
+ err = 10;
goto bad;
}
if (name[0] == '\0') {
- dbg_err("NULL volume name");
+ err = 11;
goto bad;
}
if (name_len != strnlen(name, name_len + 1)) {
- dbg_err("bad name_len");
+ err = 12;
goto bad;
}
}
@@ -235,7 +236,7 @@ static int vtbl_check(const struct ubi_device *ubi,
return 0;
bad:
- ubi_err("volume table check failed, record %d", i);
+ ubi_err("volume table check failed: record %d, error %d", i, err);
ubi_dbg_dump_vtbl_record(&vtbl[i], i);
return -EINVAL;
}
@@ -384,7 +385,16 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
ubi->vtbl_size);
if (err == UBI_IO_BITFLIPS || err == -EBADMSG)
- /* Scrub the PEB later */
+ /*
+ * Scrub the PEB later. Note, -EBADMSG indicates an
+ * uncorrectable ECC error, but we have our own CRC and
+ * the data will be checked later. If the data is OK,
+ * the PEB will be scrubbed (because we set
+ * seb->scrub). If the data is not OK, the contents of
+ * the PEB will be recovered from the second copy, and
+ * seb->scrub will be cleared in
+ * 'ubi_scan_add_used()'.
+ */
seb->scrub = 1;
else if (err)
goto out_free;
@@ -620,30 +630,32 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
static int check_sv(const struct ubi_volume *vol,
const struct ubi_scan_volume *sv)
{
+ int err;
+
if (sv->highest_lnum >= vol->reserved_pebs) {
- dbg_err("bad highest_lnum");
+ err = 1;
goto bad;
}
if (sv->leb_count > vol->reserved_pebs) {
- dbg_err("bad leb_count");
+ err = 2;
goto bad;
}
if (sv->vol_type != vol->vol_type) {
- dbg_err("bad vol_type");
+ err = 3;
goto bad;
}
if (sv->used_ebs > vol->reserved_pebs) {
- dbg_err("bad used_ebs");
+ err = 4;
goto bad;
}
if (sv->data_pad != vol->data_pad) {
- dbg_err("bad data_pad");
+ err = 5;
goto bad;
}
return 0;
bad:
- ubi_err("bad scanning information");
+ ubi_err("bad scanning information, error %d", err);
ubi_dbg_dump_sv(sv);
ubi_dbg_dump_vol_info(vol);
return -EINVAL;
@@ -672,14 +684,13 @@ static int check_scanning_info(const struct ubi_device *ubi,
return -EINVAL;
}
- if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT&&
+ if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&
si->highest_vol_id < UBI_INTERNAL_VOL_START) {
ubi_err("too large volume ID %d found by scanning",
si->highest_vol_id);
return -EINVAL;
}
-
for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
cond_resched();
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index a471a491f0ab..cc8fe2934d2b 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1368,7 +1368,7 @@ int ubi_thread(void *u)
int err;
if (kthread_should_stop())
- goto out;
+ break;
if (try_to_freeze())
continue;
@@ -1403,7 +1403,6 @@ int ubi_thread(void *u)
cond_resched();
}
-out:
dbg_wl("background thread \"%s\" is killed", ubi->bgt_name);
return 0;
}