crypto: cryptd - Convert to new AEAD interface
[linux-2.6-block.git] / crypto / scatterwalk.c
index 3bd749c7bb7062d33ee694e4131d13ce7c051c31..2ef9cbbc5dbf326904bac71359e559402b1cd35b 100644 (file)
@@ -104,22 +104,18 @@ void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
                              unsigned int start, unsigned int nbytes, int out)
 {
        struct scatter_walk walk;
-       unsigned int offset = 0;
+       struct scatterlist tmp[2];
 
        if (!nbytes)
                return;
 
-       for (;;) {
-               scatterwalk_start(&walk, sg);
-
-               if (start < offset + sg->length)
-                       break;
+       sg = scatterwalk_ffwd(tmp, sg, start);
 
-               offset += sg->length;
-               sg = sg_next(sg);
-       }
+       if (sg_page(sg) == virt_to_page(buf) &&
+           sg->offset == offset_in_page(buf))
+               return;
 
-       scatterwalk_advance(&walk, start - offset);
+       scatterwalk_start(&walk, sg);
        scatterwalk_copychunks(buf, &walk, nbytes, out);
        scatterwalk_done(&walk, out, 0);
 }
@@ -146,3 +142,26 @@ int scatterwalk_bytes_sglen(struct scatterlist *sg, int num_bytes)
        return n;
 }
 EXPORT_SYMBOL_GPL(scatterwalk_bytes_sglen);
+
+struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2],
+                                    struct scatterlist *src,
+                                    unsigned int len)
+{
+       for (;;) {
+               if (!len)
+                       return src;
+
+               if (src->length > len)
+                       break;
+
+               len -= src->length;
+               src = sg_next(src);
+       }
+
+       sg_init_table(dst, 2);
+       sg_set_page(dst, sg_page(src), src->length - len, src->offset + len);
+       scatterwalk_crypto_chain(dst, sg_next(src), 0, 2);
+
+       return dst;
+}
+EXPORT_SYMBOL_GPL(scatterwalk_ffwd);