aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/upd.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-07 13:20:31 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-07 13:20:31 -0500
commita8e98d6d51a3eb7bb061b1625193a129c8bd094f (patch)
tree0fa58b6e11e37023b024e55b8f0e7e01438706d4 /drivers/mtd/ubi/upd.c
parentf0f1b3364ae7f48084bdf2837fb979ff59622523 (diff)
parentf9f7dd222364a6428d2ad99a515935dd1dd89d18 (diff)
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (120 commits) [MTD] Fix mtdoops.c compilation [MTD] [NOR] fix startup lock when using multiple nor flash chips [MTD] [DOC200x] eccbuf is statically defined and always evaluate to true [MTD] Fix maps/physmap.c compilation with CONFIG_PM [MTD] onenand: Add panic_write function to the onenand driver [MTD] mtdoops: Use the panic_write function when present [MTD] Add mtd panic_write function pointer [MTD] [NAND] Freescale enhanced Local Bus Controller FCM NAND support. [MTD] physmap.c: Add support for multiple resources [MTD] [NAND] Fix misparenthesization introduced by commit 78b65179... [MTD] [NAND] Fix Blackfin NFC ECC calculating bug with page size 512 bytes [MTD] [NAND] Remove wrong operation in PM function of the BF54x NFC driver [MTD] [NAND] Remove unused variable in plat_nand_remove [MTD] Unlocking all Intel flash that is locked on power up. [MTD] [NAND] at91_nand: Make mtdparts option can override board info [MTD] mtdoops: Various minor cleanups [MTD] mtdoops: Ensure sequential write to the buffer [MTD] mtdoops: Perform write operations in a workqueue [MTD] mtdoops: Add further error return code checking [MTD] [NOR] Test devtype, not definition in flash_probe(), drivers/mtd/devices/lart.c ...
Diffstat (limited to 'drivers/mtd/ubi/upd.c')
-rw-r--r--drivers/mtd/ubi/upd.c185
1 files changed, 137 insertions, 48 deletions
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
index 0efc586a8328..ddaa1a56cc69 100644
--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -22,7 +22,8 @@
22 */ 22 */
23 23
24/* 24/*
25 * This file contains implementation of the volume update functionality. 25 * This file contains implementation of the volume update and atomic LEB change
26 * functionality.
26 * 27 *
27 * The update operation is based on the per-volume update marker which is 28 * The update operation is based on the per-volume update marker which is
28 * stored in the volume table. The update marker is set before the update 29 * stored in the volume table. The update marker is set before the update
@@ -45,29 +46,31 @@
45/** 46/**
46 * set_update_marker - set update marker. 47 * set_update_marker - set update marker.
47 * @ubi: UBI device description object 48 * @ubi: UBI device description object
48 * @vol_id: volume ID 49 * @vol: volume description object
49 * 50 *
50 * This function sets the update marker flag for volume @vol_id. Returns zero 51 * This function sets the update marker flag for volume @vol. Returns zero
51 * in case of success and a negative error code in case of failure. 52 * in case of success and a negative error code in case of failure.
52 */ 53 */
53static int set_update_marker(struct ubi_device *ubi, int vol_id) 54static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol)
54{ 55{
55 int err; 56 int err;
56 struct ubi_vtbl_record vtbl_rec; 57 struct ubi_vtbl_record vtbl_rec;
57 struct ubi_volume *vol = ubi->volumes[vol_id];
58 58
59 dbg_msg("set update marker for volume %d", vol_id); 59 dbg_msg("set update marker for volume %d", vol->vol_id);
60 60
61 if (vol->upd_marker) { 61 if (vol->upd_marker) {
62 ubi_assert(ubi->vtbl[vol_id].upd_marker); 62 ubi_assert(ubi->vtbl[vol->vol_id].upd_marker);
63 dbg_msg("already set"); 63 dbg_msg("already set");
64 return 0; 64 return 0;
65 } 65 }
66 66
67 memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record)); 67 memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id],
68 sizeof(struct ubi_vtbl_record));
68 vtbl_rec.upd_marker = 1; 69 vtbl_rec.upd_marker = 1;
69 70
70 err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); 71 mutex_lock(&ubi->volumes_mutex);
72 err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
73 mutex_unlock(&ubi->volumes_mutex);
71 vol->upd_marker = 1; 74 vol->upd_marker = 1;
72 return err; 75 return err;
73} 76}
@@ -75,23 +78,24 @@ static int set_update_marker(struct ubi_device *ubi, int vol_id)
75/** 78/**
76 * clear_update_marker - clear update marker. 79 * clear_update_marker - clear update marker.
77 * @ubi: UBI device description object 80 * @ubi: UBI device description object
78 * @vol_id: volume ID 81 * @vol: volume description object
79 * @bytes: new data size in bytes 82 * @bytes: new data size in bytes
80 * 83 *
81 * This function clears the update marker for volume @vol_id, sets new volume 84 * This function clears the update marker for volume @vol, sets new volume
82 * data size and clears the "corrupted" flag (static volumes only). Returns 85 * data size and clears the "corrupted" flag (static volumes only). Returns
83 * zero in case of success and a negative error code in case of failure. 86 * zero in case of success and a negative error code in case of failure.
84 */ 87 */
85static int clear_update_marker(struct ubi_device *ubi, int vol_id, long long bytes) 88static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol,
89 long long bytes)
86{ 90{
87 int err; 91 int err;
88 uint64_t tmp; 92 uint64_t tmp;
89 struct ubi_vtbl_record vtbl_rec; 93 struct ubi_vtbl_record vtbl_rec;
90 struct ubi_volume *vol = ubi->volumes[vol_id];
91 94
92 dbg_msg("clear update marker for volume %d", vol_id); 95 dbg_msg("clear update marker for volume %d", vol->vol_id);
93 96
94 memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record)); 97 memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id],
98 sizeof(struct ubi_vtbl_record));
95 ubi_assert(vol->upd_marker && vtbl_rec.upd_marker); 99 ubi_assert(vol->upd_marker && vtbl_rec.upd_marker);
96 vtbl_rec.upd_marker = 0; 100 vtbl_rec.upd_marker = 0;
97 101
@@ -106,7 +110,9 @@ static int clear_update_marker(struct ubi_device *ubi, int vol_id, long long byt
106 vol->last_eb_bytes = vol->usable_leb_size; 110 vol->last_eb_bytes = vol->usable_leb_size;
107 } 111 }
108 112
109 err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); 113 mutex_lock(&ubi->volumes_mutex);
114 err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
115 mutex_unlock(&ubi->volumes_mutex);
110 vol->upd_marker = 0; 116 vol->upd_marker = 0;
111 return err; 117 return err;
112} 118}
@@ -114,35 +120,36 @@ static int clear_update_marker(struct ubi_device *ubi, int vol_id, long long byt
114/** 120/**
115 * ubi_start_update - start volume update. 121 * ubi_start_update - start volume update.
116 * @ubi: UBI device description object 122 * @ubi: UBI device description object
117 * @vol_id: volume ID 123 * @vol: volume description object
118 * @bytes: update bytes 124 * @bytes: update bytes
119 * 125 *
120 * This function starts volume update operation. If @bytes is zero, the volume 126 * This function starts volume update operation. If @bytes is zero, the volume
121 * is just wiped out. Returns zero in case of success and a negative error code 127 * is just wiped out. Returns zero in case of success and a negative error code
122 * in case of failure. 128 * in case of failure.
123 */ 129 */
124int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes) 130int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
131 long long bytes)
125{ 132{
126 int i, err; 133 int i, err;
127 uint64_t tmp; 134 uint64_t tmp;
128 struct ubi_volume *vol = ubi->volumes[vol_id];
129 135
130 dbg_msg("start update of volume %d, %llu bytes", vol_id, bytes); 136 dbg_msg("start update of volume %d, %llu bytes", vol->vol_id, bytes);
137 ubi_assert(!vol->updating && !vol->changing_leb);
131 vol->updating = 1; 138 vol->updating = 1;
132 139
133 err = set_update_marker(ubi, vol_id); 140 err = set_update_marker(ubi, vol);
134 if (err) 141 if (err)
135 return err; 142 return err;
136 143
137 /* Before updating - wipe out the volume */ 144 /* Before updating - wipe out the volume */
138 for (i = 0; i < vol->reserved_pebs; i++) { 145 for (i = 0; i < vol->reserved_pebs; i++) {
139 err = ubi_eba_unmap_leb(ubi, vol_id, i); 146 err = ubi_eba_unmap_leb(ubi, vol, i);
140 if (err) 147 if (err)
141 return err; 148 return err;
142 } 149 }
143 150
144 if (bytes == 0) { 151 if (bytes == 0) {
145 err = clear_update_marker(ubi, vol_id, 0); 152 err = clear_update_marker(ubi, vol, 0);
146 if (err) 153 if (err)
147 return err; 154 return err;
148 err = ubi_wl_flush(ubi); 155 err = ubi_wl_flush(ubi);
@@ -163,9 +170,42 @@ int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes)
163} 170}
164 171
165/** 172/**
173 * ubi_start_leb_change - start atomic LEB change.
174 * @ubi: UBI device description object
175 * @vol: volume description object
176 * @req: operation request
177 *
178 * This function starts atomic LEB change operation. Returns zero in case of
179 * success and a negative error code in case of failure.
180 */
181int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
182 const struct ubi_leb_change_req *req)
183{
184 ubi_assert(!vol->updating && !vol->changing_leb);
185
186 dbg_msg("start changing LEB %d:%d, %u bytes",
187 vol->vol_id, req->lnum, req->bytes);
188 if (req->bytes == 0)
189 return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0,
190 req->dtype);
191
192 vol->upd_bytes = req->bytes;
193 vol->upd_received = 0;
194 vol->changing_leb = 1;
195 vol->ch_lnum = req->lnum;
196 vol->ch_dtype = req->dtype;
197
198 vol->upd_buf = vmalloc(req->bytes);
199 if (!vol->upd_buf)
200 return -ENOMEM;
201
202 return 0;
203}
204
205/**
166 * write_leb - write update data. 206 * write_leb - write update data.
167 * @ubi: UBI device description object 207 * @ubi: UBI device description object
168 * @vol_id: volume ID 208 * @vol: volume description object
169 * @lnum: logical eraseblock number 209 * @lnum: logical eraseblock number
170 * @buf: data to write 210 * @buf: data to write
171 * @len: data size 211 * @len: data size
@@ -191,26 +231,22 @@ int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes)
191 * This function returns zero in case of success and a negative error code in 231 * This function returns zero in case of success and a negative error code in
192 * case of failure. 232 * case of failure.
193 */ 233 */
194static int write_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf, 234static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
195 int len, int used_ebs) 235 void *buf, int len, int used_ebs)
196{ 236{
197 int err, l; 237 int err;
198 struct ubi_volume *vol = ubi->volumes[vol_id];
199 238
200 if (vol->vol_type == UBI_DYNAMIC_VOLUME) { 239 if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
201 l = ALIGN(len, ubi->min_io_size); 240 len = ALIGN(len, ubi->min_io_size);
202 memset(buf + len, 0xFF, l - len); 241 memset(buf + len, 0xFF, len - len);
203 242
204 l = ubi_calc_data_len(ubi, buf, l); 243 len = ubi_calc_data_len(ubi, buf, len);
205 if (l == 0) { 244 if (len == 0) {
206 dbg_msg("all %d bytes contain 0xFF - skip", len); 245 dbg_msg("all %d bytes contain 0xFF - skip", len);
207 return 0; 246 return 0;
208 } 247 }
209 if (len != l)
210 dbg_msg("skip last %d bytes (0xFF)", len - l);
211 248
212 err = ubi_eba_write_leb(ubi, vol_id, lnum, buf, 0, l, 249 err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len, UBI_UNKNOWN);
213 UBI_UNKNOWN);
214 } else { 250 } else {
215 /* 251 /*
216 * When writing static volume, and this is the last logical 252 * When writing static volume, and this is the last logical
@@ -222,7 +258,7 @@ static int write_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf,
222 * contain zeros, not random trash. 258 * contain zeros, not random trash.
223 */ 259 */
224 memset(buf + len, 0, vol->usable_leb_size - len); 260 memset(buf + len, 0, vol->usable_leb_size - len);
225 err = ubi_eba_write_leb_st(ubi, vol_id, lnum, buf, len, 261 err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len,
226 UBI_UNKNOWN, used_ebs); 262 UBI_UNKNOWN, used_ebs);
227 } 263 }
228 264
@@ -236,16 +272,15 @@ static int write_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf,
236 * @count: how much bytes to write 272 * @count: how much bytes to write
237 * 273 *
238 * This function writes more data to the volume which is being updated. It may 274 * This function writes more data to the volume which is being updated. It may
239 * be called arbitrary number of times until all of the update data arrive. 275 * be called arbitrary number of times until all the update data arriveis. This
240 * This function returns %0 in case of success, number of bytes written during 276 * function returns %0 in case of success, number of bytes written during the
241 * the last call if the whole volume update was successfully finished, and a 277 * last call if the whole volume update has been successfully finished, and a
242 * negative error code in case of failure. 278 * negative error code in case of failure.
243 */ 279 */
244int ubi_more_update_data(struct ubi_device *ubi, int vol_id, 280int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
245 const void __user *buf, int count) 281 const void __user *buf, int count)
246{ 282{
247 uint64_t tmp; 283 uint64_t tmp;
248 struct ubi_volume *vol = ubi->volumes[vol_id];
249 int lnum, offs, err = 0, len, to_write = count; 284 int lnum, offs, err = 0, len, to_write = count;
250 285
251 dbg_msg("write %d of %lld bytes, %lld already passed", 286 dbg_msg("write %d of %lld bytes, %lld already passed",
@@ -290,8 +325,8 @@ int ubi_more_update_data(struct ubi_device *ubi, int vol_id,
290 * is the last chunk, it's time to flush the buffer. 325 * is the last chunk, it's time to flush the buffer.
291 */ 326 */
292 ubi_assert(flush_len <= vol->usable_leb_size); 327 ubi_assert(flush_len <= vol->usable_leb_size);
293 err = write_leb(ubi, vol_id, lnum, vol->upd_buf, 328 err = write_leb(ubi, vol, lnum, vol->upd_buf, flush_len,
294 flush_len, vol->upd_ebs); 329 vol->upd_ebs);
295 if (err) 330 if (err)
296 return err; 331 return err;
297 } 332 }
@@ -318,8 +353,8 @@ int ubi_more_update_data(struct ubi_device *ubi, int vol_id,
318 353
319 if (len == vol->usable_leb_size || 354 if (len == vol->usable_leb_size ||
320 vol->upd_received + len == vol->upd_bytes) { 355 vol->upd_received + len == vol->upd_bytes) {
321 err = write_leb(ubi, vol_id, lnum, vol->upd_buf, len, 356 err = write_leb(ubi, vol, lnum, vol->upd_buf,
322 vol->upd_ebs); 357 len, vol->upd_ebs);
323 if (err) 358 if (err)
324 break; 359 break;
325 } 360 }
@@ -333,16 +368,70 @@ int ubi_more_update_data(struct ubi_device *ubi, int vol_id,
333 ubi_assert(vol->upd_received <= vol->upd_bytes); 368 ubi_assert(vol->upd_received <= vol->upd_bytes);
334 if (vol->upd_received == vol->upd_bytes) { 369 if (vol->upd_received == vol->upd_bytes) {
335 /* The update is finished, clear the update marker */ 370 /* The update is finished, clear the update marker */
336 err = clear_update_marker(ubi, vol_id, vol->upd_bytes); 371 err = clear_update_marker(ubi, vol, vol->upd_bytes);
337 if (err) 372 if (err)
338 return err; 373 return err;
339 err = ubi_wl_flush(ubi); 374 err = ubi_wl_flush(ubi);
340 if (err == 0) { 375 if (err == 0) {
376 vol->updating = 0;
341 err = to_write; 377 err = to_write;
342 vfree(vol->upd_buf); 378 vfree(vol->upd_buf);
343 vol->updating = 0;
344 } 379 }
345 } 380 }
346 381
347 return err; 382 return err;
348} 383}
384
385/**
386 * ubi_more_leb_change_data - accept more data for atomic LEB change.
387 * @vol: volume description object
388 * @buf: write data (user-space memory buffer)
389 * @count: how much bytes to write
390 *
391 * This function accepts more data to the volume which is being under the
392 * "atomic LEB change" operation. It may be called arbitrary number of times
393 * until all data arrives. This function returns %0 in case of success, number
394 * of bytes written during the last call if the whole "atomic LEB change"
395 * operation has been successfully finished, and a negative error code in case
396 * of failure.
397 */
398int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
399 const void __user *buf, int count)
400{
401 int err;
402
403 dbg_msg("write %d of %lld bytes, %lld already passed",
404 count, vol->upd_bytes, vol->upd_received);
405
406 if (ubi->ro_mode)
407 return -EROFS;
408
409 if (vol->upd_received + count > vol->upd_bytes)
410 count = vol->upd_bytes - vol->upd_received;
411
412 err = copy_from_user(vol->upd_buf + vol->upd_received, buf, count);
413 if (err)
414 return -EFAULT;
415
416 vol->upd_received += count;
417
418 if (vol->upd_received == vol->upd_bytes) {
419 int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size);
420
421 memset(vol->upd_buf + vol->upd_bytes, 0xFF, len - vol->upd_bytes);
422 len = ubi_calc_data_len(ubi, vol->upd_buf, len);
423 err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,
424 vol->upd_buf, len, UBI_UNKNOWN);
425 if (err)
426 return err;
427 }
428
429 ubi_assert(vol->upd_received <= vol->upd_bytes);
430 if (vol->upd_received == vol->upd_bytes) {
431 vol->changing_leb = 0;
432 err = count;
433 vfree(vol->upd_buf);
434 }
435
436 return err;
437}