crypto: mv_cesa - Fix situations where the src sglist spans more data than the reques...
authorUri Simchoni <uri@jdland.co.il>
Thu, 8 Apr 2010 16:27:02 +0000 (19:27 +0300)
committerHerbert Xu <herbert@gondor.apana.org.au>
Tue, 13 Apr 2010 08:50:47 +0000 (16:50 +0800)
Fix for situations where the source scatterlist spans more data than the
request nbytes

Signed-off-by: Uri Simchoni <uri@jdland.co.il>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/mv_cesa.c

index 018a95ce0c9b0d6e6a13bff1522630799bc445b3..096f9ff6578a0457da0cf045d5617b07f30f8c51 100644 (file)
@@ -143,27 +143,45 @@ static int mv_setkey_aes(struct crypto_ablkcipher *cipher, const u8 *key,
        return 0;
 }
 
-static void setup_data_in(struct ablkcipher_request *req)
+static void copy_src_to_buf(struct req_progress *p, char *dbuf, int len)
 {
        int ret;
-       void *buf;
-
-       if (!cpg->p.sg_src_left) {
-               ret = sg_miter_next(&cpg->p.src_sg_it);
-               BUG_ON(!ret);
-               cpg->p.sg_src_left = cpg->p.src_sg_it.length;
-               cpg->p.src_start = 0;
-       }
+       void *sbuf;
+       int copied = 0;
 
-       cpg->p.crypt_len = min(cpg->p.sg_src_left, cpg->max_req_size);
-
-       buf = cpg->p.src_sg_it.addr;
-       buf += cpg->p.src_start;
+       while (1) {
+               if (!p->sg_src_left) {
+                       ret = sg_miter_next(&p->src_sg_it);
+                       BUG_ON(!ret);
+                       p->sg_src_left = p->src_sg_it.length;
+                       p->src_start = 0;
+               }
 
-       memcpy(cpg->sram + SRAM_DATA_IN_START, buf, cpg->p.crypt_len);
+               sbuf = p->src_sg_it.addr + p->src_start;
+
+               if (p->sg_src_left <= len - copied) {
+                       memcpy(dbuf + copied, sbuf, p->sg_src_left);
+                       copied += p->sg_src_left;
+                       p->sg_src_left = 0;
+                       if (copied >= len)
+                               break;
+               } else {
+                       int copy_len = len - copied;
+                       memcpy(dbuf + copied, sbuf, copy_len);
+                       p->src_start += copy_len;
+                       p->sg_src_left -= copy_len;
+                       break;
+               }
+       }
+}
 
-       cpg->p.sg_src_left -= cpg->p.crypt_len;
-       cpg->p.src_start += cpg->p.crypt_len;
+static void setup_data_in(struct ablkcipher_request *req)
+{
+       struct req_progress *p = &cpg->p;
+       p->crypt_len =
+           min((int)req->nbytes - p->total_req_bytes, cpg->max_req_size);
+       copy_src_to_buf(p, cpg->sram + SRAM_DATA_IN_START,
+                       p->crypt_len);
 }
 
 static void mv_process_current_q(int first_block)
@@ -289,12 +307,16 @@ static void dequeue_complete_req(void)
 static int count_sgs(struct scatterlist *sl, unsigned int total_bytes)
 {
        int i = 0;
-
-       do {
-               total_bytes -= sl[i].length;
-               i++;
-
-       } while (total_bytes > 0);
+       size_t cur_len;
+
+       while (1) {
+               cur_len = sl[i].length;
+               ++i;
+               if (total_bytes > cur_len)
+                       total_bytes -= cur_len;
+               else
+                       break;
+       }
 
        return i;
 }