These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / crypto / omap-aes.c
index 9a28b7e..eba2314 100644 (file)
 #define AES_REG_IV(dd, x)              ((dd)->pdata->iv_ofs + ((x) * 0x04))
 
 #define AES_REG_CTRL(dd)               ((dd)->pdata->ctrl_ofs)
-#define AES_REG_CTRL_CTR_WIDTH_MASK    (3 << 7)
-#define AES_REG_CTRL_CTR_WIDTH_32              (0 << 7)
-#define AES_REG_CTRL_CTR_WIDTH_64              (1 << 7)
-#define AES_REG_CTRL_CTR_WIDTH_96              (2 << 7)
-#define AES_REG_CTRL_CTR_WIDTH_128             (3 << 7)
-#define AES_REG_CTRL_CTR               (1 << 6)
-#define AES_REG_CTRL_CBC               (1 << 5)
-#define AES_REG_CTRL_KEY_SIZE          (3 << 3)
-#define AES_REG_CTRL_DIRECTION         (1 << 2)
-#define AES_REG_CTRL_INPUT_READY       (1 << 1)
-#define AES_REG_CTRL_OUTPUT_READY      (1 << 0)
+#define AES_REG_CTRL_CTR_WIDTH_MASK    GENMASK(8, 7)
+#define AES_REG_CTRL_CTR_WIDTH_32      0
+#define AES_REG_CTRL_CTR_WIDTH_64      BIT(7)
+#define AES_REG_CTRL_CTR_WIDTH_96      BIT(8)
+#define AES_REG_CTRL_CTR_WIDTH_128     GENMASK(8, 7)
+#define AES_REG_CTRL_CTR               BIT(6)
+#define AES_REG_CTRL_CBC               BIT(5)
+#define AES_REG_CTRL_KEY_SIZE          GENMASK(4, 3)
+#define AES_REG_CTRL_DIRECTION         BIT(2)
+#define AES_REG_CTRL_INPUT_READY       BIT(1)
+#define AES_REG_CTRL_OUTPUT_READY      BIT(0)
+#define AES_REG_CTRL_MASK              GENMASK(24, 2)
 
 #define AES_REG_DATA_N(dd, x)          ((dd)->pdata->data_ofs + ((x) * 0x04))
 
 #define AES_REG_REV(dd)                        ((dd)->pdata->rev_ofs)
 
 #define AES_REG_MASK(dd)               ((dd)->pdata->mask_ofs)
-#define AES_REG_MASK_SIDLE             (1 << 6)
-#define AES_REG_MASK_START             (1 << 5)
-#define AES_REG_MASK_DMA_OUT_EN                (1 << 3)
-#define AES_REG_MASK_DMA_IN_EN         (1 << 2)
-#define AES_REG_MASK_SOFTRESET         (1 << 1)
-#define AES_REG_AUTOIDLE               (1 << 0)
+#define AES_REG_MASK_SIDLE             BIT(6)
+#define AES_REG_MASK_START             BIT(5)
+#define AES_REG_MASK_DMA_OUT_EN                BIT(3)
+#define AES_REG_MASK_DMA_IN_EN         BIT(2)
+#define AES_REG_MASK_SOFTRESET         BIT(1)
+#define AES_REG_AUTOIDLE               BIT(0)
 
 #define AES_REG_LENGTH_N(x)            (0x54 + ((x) * 0x04))
 
@@ -254,7 +255,7 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
 {
        unsigned int key32;
        int i, err;
-       u32 val, mask = 0;
+       u32 val;
 
        err = omap_aes_hw_init(dd);
        if (err)
@@ -274,17 +275,13 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
        val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
        if (dd->flags & FLAGS_CBC)
                val |= AES_REG_CTRL_CBC;
-       if (dd->flags & FLAGS_CTR) {
+       if (dd->flags & FLAGS_CTR)
                val |= AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_128;
-               mask = AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_MASK;
-       }
+
        if (dd->flags & FLAGS_ENCRYPT)
                val |= AES_REG_CTRL_DIRECTION;
 
-       mask |= AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
-                       AES_REG_CTRL_KEY_SIZE;
-
-       omap_aes_write_mask(dd, AES_REG_CTRL(dd), val, mask);
+       omap_aes_write_mask(dd, AES_REG_CTRL(dd), val, AES_REG_CTRL_MASK);
 
        return 0;
 }
@@ -558,6 +555,9 @@ static int omap_aes_check_aligned(struct scatterlist *sg, int total)
 {
        int len = 0;
 
+       if (!IS_ALIGNED(total, AES_BLOCK_SIZE))
+               return -EINVAL;
+
        while (sg) {
                if (!IS_ALIGNED(sg->offset, 4))
                        return -1;
@@ -577,9 +577,10 @@ static int omap_aes_check_aligned(struct scatterlist *sg, int total)
 static int omap_aes_copy_sgs(struct omap_aes_dev *dd)
 {
        void *buf_in, *buf_out;
-       int pages;
+       int pages, total;
 
-       pages = get_order(dd->total);
+       total = ALIGN(dd->total, AES_BLOCK_SIZE);
+       pages = get_order(total);
 
        buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
        buf_out = (void *)__get_free_pages(GFP_ATOMIC, pages);
@@ -594,11 +595,11 @@ static int omap_aes_copy_sgs(struct omap_aes_dev *dd)
        sg_copy_buf(buf_in, dd->in_sg, 0, dd->total, 0);
 
        sg_init_table(&dd->in_sgl, 1);
-       sg_set_buf(&dd->in_sgl, buf_in, dd->total);
+       sg_set_buf(&dd->in_sgl, buf_in, total);
        dd->in_sg = &dd->in_sgl;
 
        sg_init_table(&dd->out_sgl, 1);
-       sg_set_buf(&dd->out_sgl, buf_out, dd->total);
+       sg_set_buf(&dd->out_sgl, buf_out, total);
        dd->out_sg = &dd->out_sgl;
 
        return 0;
@@ -611,7 +612,7 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
        struct omap_aes_ctx *ctx;
        struct omap_aes_reqctx *rctx;
        unsigned long flags;
-       int err, ret = 0;
+       int err, ret = 0, len;
 
        spin_lock_irqsave(&dd->lock, flags);
        if (req)
@@ -650,8 +651,9 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
                dd->sgs_copied = 0;
        }
 
-       dd->in_sg_len = scatterwalk_bytes_sglen(dd->in_sg, dd->total);
-       dd->out_sg_len = scatterwalk_bytes_sglen(dd->out_sg, dd->total);
+       len = ALIGN(dd->total, AES_BLOCK_SIZE);
+       dd->in_sg_len = scatterwalk_bytes_sglen(dd->in_sg, len);
+       dd->out_sg_len = scatterwalk_bytes_sglen(dd->out_sg, len);
        BUG_ON(dd->in_sg_len < 0 || dd->out_sg_len < 0);
 
        rctx = ablkcipher_request_ctx(req);
@@ -678,7 +680,7 @@ static void omap_aes_done_task(unsigned long data)
 {
        struct omap_aes_dev *dd = (struct omap_aes_dev *)data;
        void *buf_in, *buf_out;
-       int pages;
+       int pages, len;
 
        pr_debug("enter done_task\n");
 
@@ -697,7 +699,8 @@ static void omap_aes_done_task(unsigned long data)
 
                sg_copy_buf(buf_out, dd->orig_out, 0, dd->total_save, 1);
 
-               pages = get_order(dd->total_save);
+               len = ALIGN(dd->total_save, AES_BLOCK_SIZE);
+               pages = get_order(len);
                free_pages((unsigned long)buf_in, pages);
                free_pages((unsigned long)buf_out, pages);
        }
@@ -726,11 +729,6 @@ static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
                  !!(mode & FLAGS_ENCRYPT),
                  !!(mode & FLAGS_CBC));
 
-       if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) {
-               pr_err("request size is not exact amount of AES blocks\n");
-               return -EINVAL;
-       }
-
        dd = omap_aes_find_dev(ctx);
        if (!dd)
                return -ENODEV;
@@ -833,7 +831,7 @@ static struct crypto_alg algs_ecb_cbc[] = {
 {
        .cra_name               = "ecb(aes)",
        .cra_driver_name        = "ecb-aes-omap",
-       .cra_priority           = 100,
+       .cra_priority           = 300,
        .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER |
                                  CRYPTO_ALG_KERN_DRIVER_ONLY |
                                  CRYPTO_ALG_ASYNC,
@@ -855,7 +853,7 @@ static struct crypto_alg algs_ecb_cbc[] = {
 {
        .cra_name               = "cbc(aes)",
        .cra_driver_name        = "cbc-aes-omap",
-       .cra_priority           = 100,
+       .cra_priority           = 300,
        .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER |
                                  CRYPTO_ALG_KERN_DRIVER_ONLY |
                                  CRYPTO_ALG_ASYNC,
@@ -881,7 +879,7 @@ static struct crypto_alg algs_ctr[] = {
 {
        .cra_name               = "ctr(aes)",
        .cra_driver_name        = "ctr-aes-omap",
-       .cra_priority           = 100,
+       .cra_priority           = 300,
        .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER |
                                  CRYPTO_ALG_KERN_DRIVER_ONLY |
                                  CRYPTO_ALG_ASYNC,
@@ -1046,9 +1044,7 @@ static irqreturn_t omap_aes_irq(int irq, void *dev_id)
                        }
                }
 
-               dd->total -= AES_BLOCK_SIZE;
-
-               BUG_ON(dd->total < 0);
+               dd->total -= min_t(size_t, AES_BLOCK_SIZE, dd->total);
 
                /* Clear IRQ status */
                status &= ~AES_REG_IRQ_DATA_OUT;