|
@@ -41,6 +41,8 @@
|
|
#include <crypto/algapi.h>
|
|
#include <crypto/algapi.h>
|
|
#include <crypto/engine.h>
|
|
#include <crypto/engine.h>
|
|
|
|
|
|
|
|
+#include "omap-crypto.h"
|
|
|
|
+
|
|
#define DST_MAXBURST 2
|
|
#define DST_MAXBURST 2
|
|
|
|
|
|
#define DES_BLOCK_WORDS (DES_BLOCK_SIZE >> 2)
|
|
#define DES_BLOCK_WORDS (DES_BLOCK_SIZE >> 2)
|
|
@@ -80,6 +82,9 @@
|
|
|
|
|
|
#define DEFAULT_AUTOSUSPEND_DELAY 1000
|
|
#define DEFAULT_AUTOSUSPEND_DELAY 1000
|
|
|
|
|
|
|
|
+#define FLAGS_IN_DATA_ST_SHIFT 8
|
|
|
|
+#define FLAGS_OUT_DATA_ST_SHIFT 10
|
|
|
|
+
|
|
struct omap_des_ctx {
|
|
struct omap_des_ctx {
|
|
struct omap_des_dev *dd;
|
|
struct omap_des_dev *dd;
|
|
|
|
|
|
@@ -153,7 +158,6 @@ struct omap_des_dev {
|
|
struct scatterlist in_sgl;
|
|
struct scatterlist in_sgl;
|
|
struct scatterlist out_sgl;
|
|
struct scatterlist out_sgl;
|
|
struct scatterlist *orig_out;
|
|
struct scatterlist *orig_out;
|
|
- int sgs_copied;
|
|
|
|
|
|
|
|
struct scatter_walk in_walk;
|
|
struct scatter_walk in_walk;
|
|
struct scatter_walk out_walk;
|
|
struct scatter_walk out_walk;
|
|
@@ -372,20 +376,6 @@ static void omap_des_dma_cleanup(struct omap_des_dev *dd)
|
|
dma_release_channel(dd->dma_lch_in);
|
|
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_des_crypt_dma(struct crypto_tfm *tfm,
|
|
static int omap_des_crypt_dma(struct crypto_tfm *tfm,
|
|
struct scatterlist *in_sg, struct scatterlist *out_sg,
|
|
struct scatterlist *in_sg, struct scatterlist *out_sg,
|
|
int in_sg_len, int out_sg_len)
|
|
int in_sg_len, int out_sg_len)
|
|
@@ -526,55 +516,6 @@ static int omap_des_crypt_dma_stop(struct omap_des_dev *dd)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int omap_des_copy_needed(struct scatterlist *sg)
|
|
|
|
-{
|
|
|
|
- while (sg) {
|
|
|
|
- if (!IS_ALIGNED(sg->offset, 4))
|
|
|
|
- return -1;
|
|
|
|
- if (!IS_ALIGNED(sg->length, DES_BLOCK_SIZE))
|
|
|
|
- return -1;
|
|
|
|
- sg = sg_next(sg);
|
|
|
|
- }
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int omap_des_copy_sgs(struct omap_des_dev *dd)
|
|
|
|
-{
|
|
|
|
- void *buf_in, *buf_out;
|
|
|
|
- int pages;
|
|
|
|
-
|
|
|
|
- pages = dd->total >> PAGE_SHIFT;
|
|
|
|
-
|
|
|
|
- if (dd->total & (PAGE_SIZE-1))
|
|
|
|
- pages++;
|
|
|
|
-
|
|
|
|
- BUG_ON(!pages);
|
|
|
|
-
|
|
|
|
- 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, dd->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, dd->total);
|
|
|
|
- dd->out_sg = &dd->out_sgl;
|
|
|
|
- dd->out_sg_len = 1;
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static int omap_des_handle_queue(struct omap_des_dev *dd,
|
|
static int omap_des_handle_queue(struct omap_des_dev *dd,
|
|
struct ablkcipher_request *req)
|
|
struct ablkcipher_request *req)
|
|
{
|
|
{
|
|
@@ -591,6 +532,8 @@ static int omap_des_prepare_req(struct crypto_engine *engine,
|
|
crypto_ablkcipher_reqtfm(req));
|
|
crypto_ablkcipher_reqtfm(req));
|
|
struct omap_des_dev *dd = omap_des_find_dev(ctx);
|
|
struct omap_des_dev *dd = omap_des_find_dev(ctx);
|
|
struct omap_des_reqctx *rctx;
|
|
struct omap_des_reqctx *rctx;
|
|
|
|
+ int ret;
|
|
|
|
+ u16 flags;
|
|
|
|
|
|
if (!dd)
|
|
if (!dd)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
@@ -601,6 +544,23 @@ static int omap_des_prepare_req(struct crypto_engine *engine,
|
|
dd->total_save = req->nbytes;
|
|
dd->total_save = req->nbytes;
|
|
dd->in_sg = req->src;
|
|
dd->in_sg = req->src;
|
|
dd->out_sg = req->dst;
|
|
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, DES_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, DES_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);
|
|
dd->in_sg_len = sg_nents_for_len(dd->in_sg, dd->total);
|
|
if (dd->in_sg_len < 0)
|
|
if (dd->in_sg_len < 0)
|
|
@@ -610,15 +570,6 @@ static int omap_des_prepare_req(struct crypto_engine *engine,
|
|
if (dd->out_sg_len < 0)
|
|
if (dd->out_sg_len < 0)
|
|
return dd->out_sg_len;
|
|
return dd->out_sg_len;
|
|
|
|
|
|
- if (omap_des_copy_needed(dd->in_sg) ||
|
|
|
|
- omap_des_copy_needed(dd->out_sg)) {
|
|
|
|
- if (omap_des_copy_sgs(dd))
|
|
|
|
- pr_err("Failed to copy SGs for unaligned cases\n");
|
|
|
|
- dd->sgs_copied = 1;
|
|
|
|
- } else {
|
|
|
|
- dd->sgs_copied = 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
rctx = ablkcipher_request_ctx(req);
|
|
rctx = ablkcipher_request_ctx(req);
|
|
ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
|
|
ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
|
|
rctx->mode &= FLAGS_MODE_MASK;
|
|
rctx->mode &= FLAGS_MODE_MASK;
|
|
@@ -646,8 +597,6 @@ static int omap_des_crypt_req(struct crypto_engine *engine,
|
|
static void omap_des_done_task(unsigned long data)
|
|
static void omap_des_done_task(unsigned long data)
|
|
{
|
|
{
|
|
struct omap_des_dev *dd = (struct omap_des_dev *)data;
|
|
struct omap_des_dev *dd = (struct omap_des_dev *)data;
|
|
- void *buf_in, *buf_out;
|
|
|
|
- int pages;
|
|
|
|
|
|
|
|
pr_debug("enter done_task\n");
|
|
pr_debug("enter done_task\n");
|
|
|
|
|
|
@@ -660,16 +609,11 @@ static void omap_des_done_task(unsigned long data)
|
|
omap_des_crypt_dma_stop(dd);
|
|
omap_des_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);
|
|
|
|
-
|
|
|
|
- pages = get_order(dd->total_save);
|
|
|
|
- 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_des_finish_req(dd, 0);
|
|
omap_des_finish_req(dd, 0);
|
|
|
|
|