diff options
author | Richard Weinberger <richard@nod.at> | 2015-01-10 22:52:13 +0100 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2015-01-28 16:04:26 +0100 |
commit | 9ff08979e17423f0f691c1d76f35dfec72a5e459 (patch) | |
tree | bba6c2556e642bfae792983766d3f07652f9714c /drivers/mtd/ubi/eba.c | |
parent | 892abde56c1c5a62d49d8b70c73e5d388e74345d (diff) | |
download | linux-9ff08979e17423f0f691c1d76f35dfec72a5e459.tar.bz2 |
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>
Diffstat (limited to 'drivers/mtd/ubi/eba.c')
-rw-r--r-- | drivers/mtd/ubi/eba.c | 55 |
1 files changed, 55 insertions, 0 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: } /** + * ubi_eba_read_leb_sg - read data into a scatter gather list. + * @ubi: UBI device description object + * @vol: volume description object + * @lnum: logical eraseblock number + * @sgl: UBI scatter gather list to store the read data + * @offset: offset from where to read + * @len: how many bytes to read + * @check: data CRC check flag + * + * This function works exactly like ubi_eba_read_leb(). But instead of + * storing the read data into a buffer it writes to an UBI scatter gather + * list. + */ +int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol, + struct ubi_sgl *sgl, int lnum, int offset, int len, + int check) +{ + int to_read; + int ret; + struct scatterlist *sg; + + for (;;) { + ubi_assert(sgl->list_pos < UBI_MAX_SG_COUNT); + sg = &sgl->sg[sgl->list_pos]; + if (len < sg->length - sgl->page_pos) + to_read = len; + else + to_read = sg->length - sgl->page_pos; + + ret = ubi_eba_read_leb(ubi, vol, lnum, + sg_virt(sg) + sgl->page_pos, offset, + to_read, check); + if (ret < 0) + return ret; + + offset += to_read; + len -= to_read; + if (!len) { + sgl->page_pos += to_read; + if (sgl->page_pos == sg->length) { + sgl->list_pos++; + sgl->page_pos = 0; + } + + break; + } + + sgl->list_pos++; + sgl->page_pos = 0; + } + + return ret; +} + +/** * recover_peb - recover from write failure. * @ubi: UBI device description object * @pnum: the physical eraseblock to recover |