aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2015-01-10 16:52:13 -0500
committerRichard Weinberger <richard@nod.at>2015-01-28 10:04:26 -0500
commit9ff08979e17423f0f691c1d76f35dfec72a5e459 (patch)
treebba6c2556e642bfae792983766d3f07652f9714c
parent892abde56c1c5a62d49d8b70c73e5d388e74345d (diff)
UBI: Add initial support for scatter gather
Adds a new set of functions to deal with scatter gather. ubi_eba_read_leb_sg() will read from a LEB into a scatter gather list. The new data structure struct ubi_sgl will be used within UBI to hold the scatter gather list itself and metadata to have a cursor within the list. Signed-off-by: Richard Weinberger <richard@nod.at> Tested-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> Reviewed-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
-rw-r--r--drivers/mtd/ubi/eba.c55
-rw-r--r--drivers/mtd/ubi/kapi.c95
-rw-r--r--drivers/mtd/ubi/ubi.h3
-rw-r--r--include/linux/mtd/ubi.h48
4 files changed, 186 insertions, 15 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index a40020cf0923..f1db73da7975 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -480,6 +480,61 @@ out_unlock:
480} 480}
481 481
482/** 482/**
483 * ubi_eba_read_leb_sg - read data into a scatter gather list.
484 * @ubi: UBI device description object
485 * @vol: volume description object
486 * @lnum: logical eraseblock number
487 * @sgl: UBI scatter gather list to store the read data
488 * @offset: offset from where to read
489 * @len: how many bytes to read
490 * @check: data CRC check flag
491 *
492 * This function works exactly like ubi_eba_read_leb(). But instead of
493 * storing the read data into a buffer it writes to an UBI scatter gather
494 * list.
495 */
496int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol,
497 struct ubi_sgl *sgl, int lnum, int offset, int len,
498 int check)
499{
500 int to_read;
501 int ret;
502 struct scatterlist *sg;
503
504 for (;;) {
505 ubi_assert(sgl->list_pos < UBI_MAX_SG_COUNT);
506 sg = &sgl->sg[sgl->list_pos];
507 if (len < sg->length - sgl->page_pos)
508 to_read = len;
509 else
510 to_read = sg->length - sgl->page_pos;
511
512 ret = ubi_eba_read_leb(ubi, vol, lnum,
513 sg_virt(sg) + sgl->page_pos, offset,
514 to_read, check);
515 if (ret < 0)
516 return ret;
517
518 offset += to_read;
519 len -= to_read;
520 if (!len) {
521 sgl->page_pos += to_read;
522 if (sgl->page_pos == sg->length) {
523 sgl->list_pos++;
524 sgl->page_pos = 0;
525 }
526
527 break;
528 }
529
530 sgl->list_pos++;
531 sgl->page_pos = 0;
532 }
533
534 return ret;
535}
536
537/**
483 * recover_peb - recover from write failure. 538 * recover_peb - recover from write failure.
484 * @ubi: UBI device description object 539 * @ubi: UBI device description object
485 * @pnum: the physical eraseblock to recover 540 * @pnum: the physical eraseblock to recover
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index 589c423fac2d..478e00cf2d9e 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -366,6 +366,43 @@ void ubi_close_volume(struct ubi_volume_desc *desc)
366EXPORT_SYMBOL_GPL(ubi_close_volume); 366EXPORT_SYMBOL_GPL(ubi_close_volume);
367 367
368/** 368/**
369 * leb_read_sanity_check - does sanity checks on read requests.
370 * @desc: volume descriptor
371 * @lnum: logical eraseblock number to read from
372 * @offset: offset within the logical eraseblock to read from
373 * @len: how many bytes to read
374 *
375 * This function is used by ubi_leb_read() and ubi_leb_read_sg()
376 * to perform sanity checks.
377 */
378static int leb_read_sanity_check(struct ubi_volume_desc *desc, int lnum,
379 int offset, int len)
380{
381 struct ubi_volume *vol = desc->vol;
382 struct ubi_device *ubi = vol->ubi;
383 int vol_id = vol->vol_id;
384
385 if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 ||
386 lnum >= vol->used_ebs || offset < 0 || len < 0 ||
387 offset + len > vol->usable_leb_size)
388 return -EINVAL;
389
390 if (vol->vol_type == UBI_STATIC_VOLUME) {
391 if (vol->used_ebs == 0)
392 /* Empty static UBI volume */
393 return 0;
394 if (lnum == vol->used_ebs - 1 &&
395 offset + len > vol->last_eb_bytes)
396 return -EINVAL;
397 }
398
399 if (vol->upd_marker)
400 return -EBADF;
401
402 return 0;
403}
404
405/**
369 * ubi_leb_read - read data. 406 * ubi_leb_read - read data.
370 * @desc: volume descriptor 407 * @desc: volume descriptor
371 * @lnum: logical eraseblock number to read from 408 * @lnum: logical eraseblock number to read from
@@ -401,22 +438,10 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
401 438
402 dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset); 439 dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
403 440
404 if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 || 441 err = leb_read_sanity_check(desc, lnum, offset, len);
405 lnum >= vol->used_ebs || offset < 0 || len < 0 || 442 if (err < 0)
406 offset + len > vol->usable_leb_size) 443 return err;
407 return -EINVAL;
408
409 if (vol->vol_type == UBI_STATIC_VOLUME) {
410 if (vol->used_ebs == 0)
411 /* Empty static UBI volume */
412 return 0;
413 if (lnum == vol->used_ebs - 1 &&
414 offset + len > vol->last_eb_bytes)
415 return -EINVAL;
416 }
417 444
418 if (vol->upd_marker)
419 return -EBADF;
420 if (len == 0) 445 if (len == 0)
421 return 0; 446 return 0;
422 447
@@ -430,6 +455,46 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
430} 455}
431EXPORT_SYMBOL_GPL(ubi_leb_read); 456EXPORT_SYMBOL_GPL(ubi_leb_read);
432 457
458
459/**
460 * ubi_leb_read_sg - read data into a scatter gather list.
461 * @desc: volume descriptor
462 * @lnum: logical eraseblock number to read from
463 * @buf: buffer where to store the read data
464 * @offset: offset within the logical eraseblock to read from
465 * @len: how many bytes to read
466 * @check: whether UBI has to check the read data's CRC or not.
467 *
468 * This function works exactly like ubi_leb_read_sg(). But instead of
469 * storing the read data into a buffer it writes to an UBI scatter gather
470 * list.
471 */
472int ubi_leb_read_sg(struct ubi_volume_desc *desc, int lnum, struct ubi_sgl *sgl,
473 int offset, int len, int check)
474{
475 struct ubi_volume *vol = desc->vol;
476 struct ubi_device *ubi = vol->ubi;
477 int err, vol_id = vol->vol_id;
478
479 dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
480
481 err = leb_read_sanity_check(desc, lnum, offset, len);
482 if (err < 0)
483 return err;
484
485 if (len == 0)
486 return 0;
487
488 err = ubi_eba_read_leb_sg(ubi, vol, sgl, lnum, offset, len, check);
489 if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) {
490 ubi_warn(ubi, "mark volume %d as corrupted", vol_id);
491 vol->corrupted = 1;
492 }
493
494 return err;
495}
496EXPORT_SYMBOL_GPL(ubi_leb_read_sg);
497
433/** 498/**
434 * ubi_leb_write - write data. 499 * ubi_leb_write - write data.
435 * @desc: volume descriptor 500 * @desc: volume descriptor
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 20cabc060b61..d94b81fa2306 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -795,6 +795,9 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
795 int lnum); 795 int lnum);
796int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, 796int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
797 void *buf, int offset, int len, int check); 797 void *buf, int offset, int len, int check);
798int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol,
799 struct ubi_sgl *sgl, int lnum, int offset, int len,
800 int check);
798int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, 801int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
799 const void *buf, int offset, int len); 802 const void *buf, int offset, int len);
800int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, 803int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h
index 8fa2753316e8..1e271cb559cd 100644
--- a/include/linux/mtd/ubi.h
+++ b/include/linux/mtd/ubi.h
@@ -23,12 +23,19 @@
23 23
24#include <linux/ioctl.h> 24#include <linux/ioctl.h>
25#include <linux/types.h> 25#include <linux/types.h>
26#include <linux/scatterlist.h>
26#include <mtd/ubi-user.h> 27#include <mtd/ubi-user.h>
27 28
28/* All voumes/LEBs */ 29/* All voumes/LEBs */
29#define UBI_ALL -1 30#define UBI_ALL -1
30 31
31/* 32/*
33 * Maximum number of scatter gather list entries,
34 * we use only 64 to have a lower memory foot print.
35 */
36#define UBI_MAX_SG_COUNT 64
37
38/*
32 * enum ubi_open_mode - UBI volume open mode constants. 39 * enum ubi_open_mode - UBI volume open mode constants.
33 * 40 *
34 * UBI_READONLY: read-only mode 41 * UBI_READONLY: read-only mode
@@ -119,6 +126,35 @@ struct ubi_volume_info {
119}; 126};
120 127
121/** 128/**
129 * struct ubi_sgl - UBI scatter gather list data structure.
130 * @list_pos: current position in @sg[]
131 * @page_pos: current position in @sg[@list_pos]
132 * @sg: the scatter gather list itself
133 *
134 * ubi_sgl is a wrapper around a scatter list which keeps track of the
135 * current position in the list and the current list item such that
136 * it can be used across multiple ubi_leb_read_sg() calls.
137 */
138struct ubi_sgl {
139 int list_pos;
140 int page_pos;
141 struct scatterlist sg[UBI_MAX_SG_COUNT];
142};
143
144/**
145 * ubi_sgl_init - initialize an UBI scatter gather list data structure.
146 * @usgl: the UBI scatter gather struct itself
147 *
148 * Please note that you still have to use sg_init_table() or any adequate
149 * function to initialize the unterlaying struct scatterlist.
150 */
151static inline void ubi_sgl_init(struct ubi_sgl *usgl)
152{
153 usgl->list_pos = 0;
154 usgl->page_pos = 0;
155}
156
157/**
122 * struct ubi_device_info - UBI device description data structure. 158 * struct ubi_device_info - UBI device description data structure.
123 * @ubi_num: ubi device number 159 * @ubi_num: ubi device number
124 * @leb_size: logical eraseblock size on this UBI device 160 * @leb_size: logical eraseblock size on this UBI device
@@ -213,6 +249,8 @@ int ubi_unregister_volume_notifier(struct notifier_block *nb);
213void ubi_close_volume(struct ubi_volume_desc *desc); 249void ubi_close_volume(struct ubi_volume_desc *desc);
214int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, 250int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
215 int len, int check); 251 int len, int check);
252int ubi_leb_read_sg(struct ubi_volume_desc *desc, int lnum, struct ubi_sgl *sgl,
253 int offset, int len, int check);
216int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, 254int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
217 int offset, int len); 255 int offset, int len);
218int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, 256int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
@@ -233,4 +271,14 @@ static inline int ubi_read(struct ubi_volume_desc *desc, int lnum, char *buf,
233{ 271{
234 return ubi_leb_read(desc, lnum, buf, offset, len, 0); 272 return ubi_leb_read(desc, lnum, buf, offset, len, 0);
235} 273}
274
275/*
276 * This function is the same as the 'ubi_leb_read_sg()' function, but it does
277 * not provide the checking capability.
278 */
279static inline int ubi_read_sg(struct ubi_volume_desc *desc, int lnum,
280 struct ubi_sgl *sgl, int offset, int len)
281{
282 return ubi_leb_read_sg(desc, lnum, sgl, offset, len, 0);
283}
236#endif /* !__LINUX_UBI_H__ */ 284#endif /* !__LINUX_UBI_H__ */