summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/eba.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/eba.c')
-rw-r--r--drivers/mtd/ubi/eba.c81
1 files changed, 47 insertions, 34 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 884c91ffe7ba..ddf4e63eed76 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -513,6 +513,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
void *buf, int offset, int len, int check)
{
int err, pnum, scrub = 0, vol_id = vol->vol_id;
+ struct ubi_vid_io_buf *vidb;
struct ubi_vid_hdr *vid_hdr;
uint32_t uninitialized_var(crc);
@@ -543,13 +544,15 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
retry:
if (check) {
- vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
- if (!vid_hdr) {
+ vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
+ if (!vidb) {
err = -ENOMEM;
goto out_unlock;
}
- err = ubi_io_read_vid_hdr(ubi, pnum, vid_hdr, 1);
+ vid_hdr = ubi_get_vid_hdr(vidb);
+
+ err = ubi_io_read_vid_hdr(ubi, pnum, vidb, 1);
if (err && err != UBI_IO_BITFLIPS) {
if (err > 0) {
/*
@@ -595,7 +598,7 @@ retry:
ubi_assert(len == be32_to_cpu(vid_hdr->data_size));
crc = be32_to_cpu(vid_hdr->data_crc);
- ubi_free_vid_hdr(ubi, vid_hdr);
+ ubi_free_vid_buf(vidb);
}
err = ubi_io_read_data(ubi, buf, pnum, offset, len);
@@ -632,7 +635,7 @@ retry:
return err;
out_free:
- ubi_free_vid_hdr(ubi, vid_hdr);
+ ubi_free_vid_buf(vidb);
out_unlock:
leb_read_unlock(ubi, vol_id, lnum);
return err;
@@ -701,7 +704,7 @@ int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol,
* @buf: data which was not written because of the write failure
* @offset: offset of the failed write
* @len: how many bytes should have been written
- * @vid: VID header
+ * @vidb: VID buffer
* @retry: whether the caller should retry in case of failure
*
* This function is called in case of a write failure and moves all good data
@@ -713,9 +716,10 @@ int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol,
*/
static int try_recover_peb(struct ubi_volume *vol, int pnum, int lnum,
const void *buf, int offset, int len,
- struct ubi_vid_hdr *vid_hdr, bool *retry)
+ struct ubi_vid_io_buf *vidb, bool *retry)
{
struct ubi_device *ubi = vol->ubi;
+ struct ubi_vid_hdr *vid_hdr;
int new_pnum, err, vol_id = vol->vol_id, data_size;
uint32_t crc;
@@ -730,7 +734,7 @@ static int try_recover_peb(struct ubi_volume *vol, int pnum, int lnum,
ubi_msg(ubi, "recover PEB %d, move data to PEB %d",
pnum, new_pnum);
- err = ubi_io_read_vid_hdr(ubi, pnum, vid_hdr, 1);
+ err = ubi_io_read_vid_hdr(ubi, pnum, vidb, 1);
if (err && err != UBI_IO_BITFLIPS) {
if (err > 0)
err = -EIO;
@@ -759,7 +763,7 @@ static int try_recover_peb(struct ubi_volume *vol, int pnum, int lnum,
vid_hdr->copy_flag = 1;
vid_hdr->data_size = cpu_to_be32(data_size);
vid_hdr->data_crc = cpu_to_be32(crc);
- err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
+ err = ubi_io_write_vid_hdr(ubi, new_pnum, vidb);
if (err)
goto out_unlock;
@@ -810,24 +814,24 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
{
int err, idx = vol_id2idx(ubi, vol_id), tries;
struct ubi_volume *vol = ubi->volumes[idx];
- struct ubi_vid_hdr *vid_hdr;
+ struct ubi_vid_io_buf *vidb;
- vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
- if (!vid_hdr)
+ vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
+ if (!vidb)
return -ENOMEM;
for (tries = 0; tries <= UBI_IO_RETRIES; tries++) {
bool retry;
- err = try_recover_peb(vol, pnum, lnum, buf, offset, len,
- vid_hdr, &retry);
+ err = try_recover_peb(vol, pnum, lnum, buf, offset, len, vidb,
+ &retry);
if (!err || !retry)
break;
ubi_msg(ubi, "try again");
}
- ubi_free_vid_hdr(ubi, vid_hdr);
+ ubi_free_vid_buf(vidb);
return err;
}
@@ -836,7 +840,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
* try_write_vid_and_data - try to write VID header and data to a new PEB.
* @vol: volume description object
* @lnum: logical eraseblock number
- * @vid_hdr: VID header to write
+ * @vidb: the VID buffer to write
* @buf: buffer containing the data
* @offset: where to start writing data
* @len: how many bytes should be written
@@ -848,7 +852,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
* flash media, but may be some garbage.
*/
static int try_write_vid_and_data(struct ubi_volume *vol, int lnum,
- struct ubi_vid_hdr *vid_hdr, const void *buf,
+ struct ubi_vid_io_buf *vidb, const void *buf,
int offset, int len)
{
struct ubi_device *ubi = vol->ubi;
@@ -865,7 +869,7 @@ static int try_write_vid_and_data(struct ubi_volume *vol, int lnum,
dbg_eba("write VID hdr and %d bytes at offset %d of LEB %d:%d, PEB %d",
len, offset, vol_id, lnum, pnum);
- err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr);
+ err = ubi_io_write_vid_hdr(ubi, pnum, vidb);
if (err) {
ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d",
vol_id, lnum, pnum);
@@ -914,6 +918,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
const void *buf, int offset, int len)
{
int err, pnum, tries, vol_id = vol->vol_id;
+ struct ubi_vid_io_buf *vidb;
struct ubi_vid_hdr *vid_hdr;
if (ubi->ro_mode)
@@ -943,12 +948,14 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
* The logical eraseblock is not mapped. We have to get a free physical
* eraseblock and write the volume identifier header there first.
*/
- vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
- if (!vid_hdr) {
+ vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
+ if (!vidb) {
leb_write_unlock(ubi, vol_id, lnum);
return -ENOMEM;
}
+ vid_hdr = ubi_get_vid_hdr(vidb);
+
vid_hdr->vol_type = UBI_VID_DYNAMIC;
vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
vid_hdr->vol_id = cpu_to_be32(vol_id);
@@ -957,8 +964,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
vid_hdr->data_pad = cpu_to_be32(vol->data_pad);
for (tries = 0; tries <= UBI_IO_RETRIES; tries++) {
- err = try_write_vid_and_data(vol, lnum, vid_hdr, buf, offset,
- len);
+ err = try_write_vid_and_data(vol, lnum, vidb, buf, offset, len);
if (err != -EIO || !ubi->bad_allowed)
break;
@@ -972,7 +978,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
ubi_msg(ubi, "try another PEB");
}
- ubi_free_vid_hdr(ubi, vid_hdr);
+ ubi_free_vid_buf(vidb);
out:
if (err)
@@ -1009,6 +1015,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
int lnum, const void *buf, int len, int used_ebs)
{
int err, tries, data_size = len, vol_id = vol->vol_id;
+ struct ubi_vid_io_buf *vidb;
struct ubi_vid_hdr *vid_hdr;
uint32_t crc;
@@ -1021,10 +1028,12 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
else
ubi_assert(!(len & (ubi->min_io_size - 1)));
- vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
- if (!vid_hdr)
+ vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
+ if (!vidb)
return -ENOMEM;
+ vid_hdr = ubi_get_vid_hdr(vidb);
+
err = leb_write_lock(ubi, vol_id, lnum);
if (err)
goto out;
@@ -1044,7 +1053,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
ubi_assert(vol->eba_tbl->entries[lnum].pnum < 0);
for (tries = 0; tries <= UBI_IO_RETRIES; tries++) {
- err = try_write_vid_and_data(vol, lnum, vid_hdr, buf, 0, len);
+ err = try_write_vid_and_data(vol, lnum, vidb, buf, 0, len);
if (err != -EIO || !ubi->bad_allowed)
break;
@@ -1058,7 +1067,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
leb_write_unlock(ubi, vol_id, lnum);
out:
- ubi_free_vid_hdr(ubi, vid_hdr);
+ ubi_free_vid_buf(vidb);
return err;
}
@@ -1084,6 +1093,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
int lnum, const void *buf, int len)
{
int err, tries, vol_id = vol->vol_id;
+ struct ubi_vid_io_buf *vidb;
struct ubi_vid_hdr *vid_hdr;
uint32_t crc;
@@ -1101,10 +1111,12 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0);
}
- vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
- if (!vid_hdr)
+ vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
+ if (!vidb)
return -ENOMEM;
+ vid_hdr = ubi_get_vid_hdr(vidb);
+
mutex_lock(&ubi->alc_mutex);
err = leb_write_lock(ubi, vol_id, lnum);
if (err)
@@ -1125,7 +1137,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
dbg_eba("change LEB %d:%d", vol_id, lnum);
for (tries = 0; tries <= UBI_IO_RETRIES; tries++) {
- err = try_write_vid_and_data(vol, lnum, vid_hdr, buf, 0, len);
+ err = try_write_vid_and_data(vol, lnum, vidb, buf, 0, len);
if (err != -EIO || !ubi->bad_allowed)
break;
@@ -1145,7 +1157,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
out_mutex:
mutex_unlock(&ubi->alc_mutex);
- ubi_free_vid_hdr(ubi, vid_hdr);
+ ubi_free_vid_buf(vidb);
return err;
}
@@ -1191,9 +1203,10 @@ static int is_error_sane(int err)
* o a negative error code in case of failure.
*/
int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
- struct ubi_vid_hdr *vid_hdr)
+ struct ubi_vid_io_buf *vidb)
{
int err, vol_id, lnum, data_size, aldata_size, idx;
+ struct ubi_vid_hdr *vid_hdr = ubi_get_vid_hdr(vidb);
struct ubi_volume *vol;
uint32_t crc;
@@ -1305,7 +1318,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
}
vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
- err = ubi_io_write_vid_hdr(ubi, to, vid_hdr);
+ err = ubi_io_write_vid_hdr(ubi, to, vidb);
if (err) {
if (err == -EIO)
err = MOVE_TARGET_WR_ERR;
@@ -1315,7 +1328,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
cond_resched();
/* Read the VID header back and check if it was written correctly */
- err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1);
+ err = ubi_io_read_vid_hdr(ubi, to, vidb, 1);
if (err) {
if (err != UBI_IO_BITFLIPS) {
ubi_warn(ubi, "error %d while reading VID header back from PEB %d",