crypto: caam - Set last bit on src SG list
[firefly-linux-kernel-4.4.55.git] / drivers / crypto / picoxcell_crypto.c
index eb2a0ca49eda4f65715586f22c8f866f67f66f82..c2fd860745adffcfa5fb55edf92bccf70011e3bc 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/scatterlist.h>
 #include <linux/sched.h>
+#include <linux/sizes.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
 
@@ -261,18 +262,9 @@ static unsigned spacc_load_ctx(struct spacc_generic_ctx *ctx,
 }
 
 /* Count the number of scatterlist entries in a scatterlist. */
-static int sg_count(struct scatterlist *sg_list, int nbytes)
+static inline int sg_count(struct scatterlist *sg_list, int nbytes)
 {
-       struct scatterlist *sg = sg_list;
-       int sg_nents = 0;
-
-       while (nbytes > 0) {
-               ++sg_nents;
-               nbytes -= sg->length;
-               sg = sg_next(sg);
-       }
-
-       return sg_nents;
+       return sg_nents_for_len(sg_list, nbytes);
 }
 
 static inline void ddt_set(struct spacc_ddt *ddt, dma_addr_t phys, size_t len)
@@ -326,6 +318,7 @@ static int spacc_aead_make_ddts(struct spacc_req *req, u8 *giv)
        struct spacc_ddt *src_ddt, *dst_ddt;
        unsigned ivsize = crypto_aead_ivsize(crypto_aead_reqtfm(areq));
        unsigned nents = sg_count(areq->src, areq->cryptlen);
+       unsigned total;
        dma_addr_t iv_addr;
        struct scatterlist *cur;
        int i, dst_ents, src_ents, assoc_ents;
@@ -369,11 +362,18 @@ static int spacc_aead_make_ddts(struct spacc_req *req, u8 *giv)
         * Map the associated data. For decryption we don't copy the
         * associated data.
         */
+       total = areq->assoclen;
        for_each_sg(areq->assoc, cur, assoc_ents, i) {
-               ddt_set(src_ddt++, sg_dma_address(cur), sg_dma_len(cur));
+               unsigned len = sg_dma_len(cur);
+
+               if (len > total)
+                       len = total;
+
+               total -= len;
+
+               ddt_set(src_ddt++, sg_dma_address(cur), len);
                if (req->is_encrypt)
-                       ddt_set(dst_ddt++, sg_dma_address(cur),
-                               sg_dma_len(cur));
+                       ddt_set(dst_ddt++, sg_dma_address(cur), len);
        }
        ddt_set(src_ddt++, iv_addr, ivsize);