#include <crypto/engine.h>
#include <crypto/internal/skcipher.h>
+#include "omap-crypto.h"
+
#define DST_MAXBURST 4
#define DMA_MIN (DST_MAXBURST * sizeof(u32))
#define FLAGS_FAST BIT(5)
#define FLAGS_BUSY BIT(6)
+#define FLAGS_IN_DATA_ST_SHIFT 8
+#define FLAGS_OUT_DATA_ST_SHIFT 10
+
#define AES_BLOCK_WORDS (AES_BLOCK_SIZE >> 2)
struct omap_aes_ctx {
struct scatterlist in_sgl;
struct scatterlist out_sgl;
struct scatterlist *orig_out;
- int sgs_copied;
struct scatter_walk in_walk;
struct scatter_walk out_walk;
dma_release_channel(dd->dma_lch_in);
}
-static void sg_copy_buf(void *buf, struct scatterlist *sg,
- unsigned int start, unsigned int nbytes, int out)
-{
- struct scatter_walk walk;
-
- if (!nbytes)
- return;
-
- scatterwalk_start(&walk, sg);
- scatterwalk_advance(&walk, start);
- scatterwalk_copychunks(buf, &walk, nbytes, out);
- scatterwalk_done(&walk, out, 0);
-}
-
static int omap_aes_crypt_dma(struct omap_aes_dev *dd,
struct scatterlist *in_sg,
struct scatterlist *out_sg,
return 0;
}
-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;
- if (!IS_ALIGNED(sg->length, AES_BLOCK_SIZE))
- return -1;
-
- len += sg->length;
- sg = sg_next(sg);
- }
-
- if (len != total)
- return -1;
-
- return 0;
-}
-
-static int omap_aes_copy_sgs(struct omap_aes_dev *dd)
-{
- void *buf_in, *buf_out;
- int pages, 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);
-
- if (!buf_in || !buf_out) {
- pr_err("Couldn't allocated pages for unaligned cases.\n");
- return -1;
- }
-
- dd->orig_out = dd->out_sg;
-
- 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, total);
- dd->in_sg = &dd->in_sgl;
- dd->in_sg_len = 1;
-
- sg_init_table(&dd->out_sgl, 1);
- sg_set_buf(&dd->out_sgl, buf_out, total);
- dd->out_sg = &dd->out_sgl;
- dd->out_sg_len = 1;
-
- return 0;
-}
-
static int omap_aes_handle_queue(struct omap_aes_dev *dd,
struct ablkcipher_request *req)
{
crypto_ablkcipher_reqtfm(req));
struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req);
struct omap_aes_dev *dd = rctx->dd;
+ int ret;
+ u16 flags;
if (!dd)
return -ENODEV;
dd->total_save = req->nbytes;
dd->in_sg = req->src;
dd->out_sg = req->dst;
+ dd->orig_out = req->dst;
+
+ flags = OMAP_CRYPTO_COPY_DATA;
+ if (req->src == req->dst)
+ flags |= OMAP_CRYPTO_FORCE_COPY;
+
+ ret = omap_crypto_align_sg(&dd->in_sg, dd->total, AES_BLOCK_SIZE,
+ &dd->in_sgl, flags,
+ FLAGS_IN_DATA_ST_SHIFT, &dd->flags);
+ if (ret)
+ return ret;
+
+ ret = omap_crypto_align_sg(&dd->out_sg, dd->total, AES_BLOCK_SIZE,
+ &dd->out_sgl, 0,
+ FLAGS_OUT_DATA_ST_SHIFT, &dd->flags);
+ if (ret)
+ return ret;
dd->in_sg_len = sg_nents_for_len(dd->in_sg, dd->total);
if (dd->in_sg_len < 0)
if (dd->out_sg_len < 0)
return dd->out_sg_len;
- if (omap_aes_check_aligned(dd->in_sg, dd->total) ||
- omap_aes_check_aligned(dd->out_sg, dd->total)) {
- if (omap_aes_copy_sgs(dd))
- pr_err("Failed to copy SGs for unaligned cases\n");
- dd->sgs_copied = 1;
- } else {
- dd->sgs_copied = 0;
- }
-
rctx->mode &= FLAGS_MODE_MASK;
dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode;
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, len;
pr_debug("enter done_task\n");
omap_aes_crypt_dma_stop(dd);
}
- if (dd->sgs_copied) {
- buf_in = sg_virt(&dd->in_sgl);
- buf_out = sg_virt(&dd->out_sgl);
+ omap_crypto_cleanup(&dd->in_sgl, NULL, 0, dd->total_save,
+ FLAGS_IN_DATA_ST_SHIFT, dd->flags);
- sg_copy_buf(buf_out, dd->orig_out, 0, dd->total_save, 1);
-
- 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);
- }
+ omap_crypto_cleanup(&dd->out_sgl, dd->orig_out, 0, dd->total_save,
+ FLAGS_OUT_DATA_ST_SHIFT, dd->flags);
omap_aes_finish_req(dd, 0);