summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/eba.c
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2015-01-10 22:52:13 +0100
committerRichard Weinberger <richard@nod.at>2015-01-28 16:04:26 +0100
commit9ff08979e17423f0f691c1d76f35dfec72a5e459 (patch)
treebba6c2556e642bfae792983766d3f07652f9714c /drivers/mtd/ubi/eba.c
parent892abde56c1c5a62d49d8b70c73e5d388e74345d (diff)
downloadlinux-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.c55
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