summaryrefslogtreecommitdiff
path: root/drivers/crypto/omap-des.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/crypto/omap-des.c')
-rw-r--r--drivers/crypto/omap-des.c138
1 files changed, 50 insertions, 88 deletions
diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c
index a6f65532fd16..0bcab00e0ff5 100644
--- a/drivers/crypto/omap-des.c
+++ b/drivers/crypto/omap-des.c
@@ -41,6 +41,8 @@
#include <crypto/algapi.h>
#include <crypto/engine.h>
+#include "omap-crypto.h"
+
#define DST_MAXBURST 2
#define DES_BLOCK_WORDS (DES_BLOCK_SIZE >> 2)
@@ -78,6 +80,11 @@
#define FLAGS_INIT BIT(4)
#define FLAGS_BUSY BIT(6)
+#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_dev *dd;
@@ -151,7 +158,6 @@ struct omap_des_dev {
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;
@@ -370,20 +376,6 @@ static void omap_des_dma_cleanup(struct omap_des_dev *dd)
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,
struct scatterlist *in_sg, struct scatterlist *out_sg,
int in_sg_len, int out_sg_len)
@@ -506,8 +498,10 @@ static void omap_des_finish_req(struct omap_des_dev *dd, int err)
pr_debug("err: %d\n", err);
- pm_runtime_put(dd->dev);
crypto_finalize_cipher_request(dd->engine, req, err);
+
+ pm_runtime_mark_last_busy(dd->dev);
+ pm_runtime_put_autosuspend(dd->dev);
}
static int omap_des_crypt_dma_stop(struct omap_des_dev *dd)
@@ -522,55 +516,6 @@ static int omap_des_crypt_dma_stop(struct omap_des_dev *dd)
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,
struct ablkcipher_request *req)
{
@@ -587,6 +532,8 @@ static int omap_des_prepare_req(struct crypto_engine *engine,
crypto_ablkcipher_reqtfm(req));
struct omap_des_dev *dd = omap_des_find_dev(ctx);
struct omap_des_reqctx *rctx;
+ int ret;
+ u16 flags;
if (!dd)
return -ENODEV;
@@ -597,6 +544,23 @@ static int omap_des_prepare_req(struct crypto_engine *engine,
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, 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);
if (dd->in_sg_len < 0)
@@ -606,15 +570,6 @@ static int omap_des_prepare_req(struct crypto_engine *engine,
if (dd->out_sg_len < 0)
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);
ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
rctx->mode &= FLAGS_MODE_MASK;
@@ -642,8 +597,6 @@ static int omap_des_crypt_req(struct crypto_engine *engine,
static void omap_des_done_task(unsigned long data)
{
struct omap_des_dev *dd = (struct omap_des_dev *)data;
- void *buf_in, *buf_out;
- int pages;
pr_debug("enter done_task\n");
@@ -656,16 +609,11 @@ static void omap_des_done_task(unsigned long data)
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);
@@ -699,16 +647,28 @@ static int omap_des_crypt(struct ablkcipher_request *req, unsigned long mode)
/* ********************** ALG API ************************************ */
-static int omap_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+static int omap_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
unsigned int keylen)
{
- struct omap_des_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ struct omap_des_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+ struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
if (keylen != DES_KEY_SIZE && keylen != (3*DES_KEY_SIZE))
return -EINVAL;
pr_debug("enter, keylen: %d\n", keylen);
+ /* Do we need to test against weak key? */
+ if (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY) {
+ u32 tmp[DES_EXPKEY_WORDS];
+ int ret = des_ekey(tmp, key);
+
+ if (!ret) {
+ tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
+ return -EINVAL;
+ }
+ }
+
memcpy(ctx->key, key, keylen);
ctx->keylen = keylen;
@@ -1032,8 +992,10 @@ static int omap_des_probe(struct platform_device *pdev)
}
dd->phys_base = res->start;
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_autosuspend_delay(dev, DEFAULT_AUTOSUSPEND_DELAY);
+
pm_runtime_enable(dev);
- pm_runtime_irq_safe(dev);
err = pm_runtime_get_sync(dev);
if (err < 0) {
pm_runtime_put_noidle(dev);