]> git.sur5r.net Git - u-boot/blobdiff - drivers/mtd/ubi/upd.c
Merge branch 'zynq' of git://www.denx.de/git/u-boot-microblaze
[u-boot] / drivers / mtd / ubi / upd.c
index e597f82b874dcf3926feb7b44a46a550d8d46bce..220c120515ac508f58eb9e1459cb8aed4d3eeb0e 100644 (file)
  * transaction with a roll-back capability.
  */
 
-#ifdef UBI_LINUX
-#include <linux/err.h>
-#include <asm/uaccess.h>
-#include <asm/div64.h>
+#define __UBOOT__
+#ifndef __UBOOT__
+#include <linux/uaccess.h>
+#else
+#include <div64.h>
+#include <ubi_uboot.h>
 #endif
+#include <linux/err.h>
+#include <linux/math64.h>
 
-#include <ubi_uboot.h>
 #include "ubi.h"
 
 /**
@@ -48,22 +51,21 @@ static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol)
        int err;
        struct ubi_vtbl_record vtbl_rec;
 
-       dbg_msg("set update marker for volume %d", vol->vol_id);
+       dbg_gen("set update marker for volume %d", vol->vol_id);
 
        if (vol->upd_marker) {
                ubi_assert(ubi->vtbl[vol->vol_id].upd_marker);
-               dbg_msg("already set");
+               dbg_gen("already set");
                return 0;
        }
 
-       memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id],
-              sizeof(struct ubi_vtbl_record));
+       vtbl_rec = ubi->vtbl[vol->vol_id];
        vtbl_rec.upd_marker = 1;
 
-       mutex_lock(&ubi->volumes_mutex);
+       mutex_lock(&ubi->device_mutex);
        err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
-       mutex_unlock(&ubi->volumes_mutex);
        vol->upd_marker = 1;
+       mutex_unlock(&ubi->device_mutex);
        return err;
 }
 
@@ -81,31 +83,29 @@ static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol,
                               long long bytes)
 {
        int err;
-       uint64_t tmp;
        struct ubi_vtbl_record vtbl_rec;
 
-       dbg_msg("clear update marker for volume %d", vol->vol_id);
+       dbg_gen("clear update marker for volume %d", vol->vol_id);
 
-       memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id],
-              sizeof(struct ubi_vtbl_record));
+       vtbl_rec = ubi->vtbl[vol->vol_id];
        ubi_assert(vol->upd_marker && vtbl_rec.upd_marker);
        vtbl_rec.upd_marker = 0;
 
        if (vol->vol_type == UBI_STATIC_VOLUME) {
                vol->corrupted = 0;
-               vol->used_bytes = tmp = bytes;
-               vol->last_eb_bytes = do_div(tmp, vol->usable_leb_size);
-               vol->used_ebs = tmp;
+               vol->used_bytes = bytes;
+               vol->used_ebs = div_u64_rem(bytes, vol->usable_leb_size,
+                                           &vol->last_eb_bytes);
                if (vol->last_eb_bytes)
                        vol->used_ebs += 1;
                else
                        vol->last_eb_bytes = vol->usable_leb_size;
        }
 
-       mutex_lock(&ubi->volumes_mutex);
+       mutex_lock(&ubi->device_mutex);
        err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
-       mutex_unlock(&ubi->volumes_mutex);
        vol->upd_marker = 0;
+       mutex_unlock(&ubi->device_mutex);
        return err;
 }
 
@@ -123,9 +123,8 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
                     long long bytes)
 {
        int i, err;
-       uint64_t tmp;
 
-       dbg_msg("start update of volume %d, %llu bytes", vol->vol_id, bytes);
+       dbg_gen("start update of volume %d, %llu bytes", vol->vol_id, bytes);
        ubi_assert(!vol->updating && !vol->changing_leb);
        vol->updating = 1;
 
@@ -141,21 +140,23 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
        }
 
        if (bytes == 0) {
+               err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
+               if (err)
+                       return err;
+
                err = clear_update_marker(ubi, vol, 0);
                if (err)
                        return err;
-               err = ubi_wl_flush(ubi);
-               if (!err)
-                       vol->updating = 0;
+               vol->updating = 0;
+               return 0;
        }
 
        vol->upd_buf = vmalloc(ubi->leb_size);
        if (!vol->upd_buf)
                return -ENOMEM;
 
-       tmp = bytes;
-       vol->upd_ebs = !!do_div(tmp, vol->usable_leb_size);
-       vol->upd_ebs += tmp;
+       vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1,
+                              vol->usable_leb_size);
        vol->upd_bytes = bytes;
        vol->upd_received = 0;
        return 0;
@@ -175,17 +176,15 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
 {
        ubi_assert(!vol->updating && !vol->changing_leb);
 
-       dbg_msg("start changing LEB %d:%d, %u bytes",
+       dbg_gen("start changing LEB %d:%d, %u bytes",
                vol->vol_id, req->lnum, req->bytes);
        if (req->bytes == 0)
-               return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0,
-                                                req->dtype);
+               return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0);
 
        vol->upd_bytes = req->bytes;
        vol->upd_received = 0;
        vol->changing_leb = 1;
        vol->ch_lnum = req->lnum;
-       vol->ch_dtype = req->dtype;
 
        vol->upd_buf = vmalloc(req->bytes);
        if (!vol->upd_buf)
@@ -234,11 +233,11 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
                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);
+                       dbg_gen("all %d bytes contain 0xFF - skip", len);
                        return 0;
                }
 
-               err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len, UBI_UNKNOWN);
+               err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len);
        } else {
                /*
                 * When writing static volume, and this is the last logical
@@ -250,8 +249,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
                 * contain zeros, not random trash.
                 */
                memset(buf + len, 0, vol->usable_leb_size - len);
-               err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len,
-                                          UBI_UNKNOWN, used_ebs);
+               err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, used_ebs);
        }
 
        return err;
@@ -259,6 +257,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
 
 /**
  * ubi_more_update_data - write more update data.
+ * @ubi: UBI device description object
  * @vol: volume description object
  * @buf: write data (user-space memory buffer)
  * @count: how much bytes to write
@@ -272,19 +271,20 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
 int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
                         const void __user *buf, int count)
 {
-       uint64_t tmp;
+#ifndef __UBOOT__
        int lnum, offs, err = 0, len, to_write = count;
+#else
+       int lnum, err = 0, len, to_write = count;
+       u32 offs;
+#endif
 
-       dbg_msg("write %d of %lld bytes, %lld already passed",
+       dbg_gen("write %d of %lld bytes, %lld already passed",
                count, vol->upd_bytes, vol->upd_received);
 
        if (ubi->ro_mode)
                return -EROFS;
 
-       tmp = vol->upd_received;
-       offs = do_div(tmp, vol->usable_leb_size);
-       lnum = tmp;
-
+       lnum = div_u64_rem(vol->upd_received,  vol->usable_leb_size, &offs);
        if (vol->upd_received + count > vol->upd_bytes)
                to_write = count = vol->upd_bytes - vol->upd_received;
 
@@ -359,16 +359,16 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
 
        ubi_assert(vol->upd_received <= vol->upd_bytes);
        if (vol->upd_received == vol->upd_bytes) {
+               err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
+               if (err)
+                       return err;
                /* The update is finished, clear the update marker */
                err = clear_update_marker(ubi, vol, vol->upd_bytes);
                if (err)
                        return err;
-               err = ubi_wl_flush(ubi);
-               if (err == 0) {
-                       vol->updating = 0;
-                       err = to_write;
-                       vfree(vol->upd_buf);
-               }
+               vol->updating = 0;
+               err = to_write;
+               vfree(vol->upd_buf);
        }
 
        return err;
@@ -376,6 +376,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
 
 /**
  * ubi_more_leb_change_data - accept more data for atomic LEB change.
+ * @ubi: UBI device description object
  * @vol: volume description object
  * @buf: write data (user-space memory buffer)
  * @count: how much bytes to write
@@ -392,7 +393,7 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
 {
        int err;
 
-       dbg_msg("write %d of %lld bytes, %lld already passed",
+       dbg_gen("write %d of %lld bytes, %lld already passed",
                count, vol->upd_bytes, vol->upd_received);
 
        if (ubi->ro_mode)
@@ -410,10 +411,11 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
        if (vol->upd_received == vol->upd_bytes) {
                int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size);
 
-               memset(vol->upd_buf + vol->upd_bytes, 0xFF, len - vol->upd_bytes);
+               memset(vol->upd_buf + vol->upd_bytes, 0xFF,
+                      len - vol->upd_bytes);
                len = ubi_calc_data_len(ubi, vol->upd_buf, len);
                err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,
-                                               vol->upd_buf, len, UBI_UNKNOWN);
+                                               vol->upd_buf, len);
                if (err)
                        return err;
        }