summaryrefslogtreecommitdiff
path: root/drivers/crypto/omap-sham.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/crypto/omap-sham.c')
-rw-r--r--drivers/crypto/omap-sham.c582
1 files changed, 252 insertions, 330 deletions
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 82691a057d2a..ff8aac02994a 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -13,32 +13,31 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
+#include <crypto/engine.h>
+#include <crypto/hmac.h>
+#include <crypto/internal/hash.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/sha1.h>
+#include <crypto/sha2.h>
#include <linux/err.h>
#include <linux/device.h>
-#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
#include <linux/init.h>
-#include <linux/errno.h>
#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/irq.h>
#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/scatterlist.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmaengine.h>
-#include <linux/pm_runtime.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
-#include <linux/delay.h>
-#include <linux/crypto.h>
-#include <crypto/scatterwalk.h>
-#include <crypto/algapi.h>
-#include <crypto/sha.h>
-#include <crypto/hash.h>
-#include <crypto/hmac.h>
-#include <crypto/internal/hash.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
#define MD5_DIGEST_SIZE 16
@@ -100,11 +99,9 @@
#define DEFAULT_AUTOSUSPEND_DELAY 1000
/* mostly device flags */
-#define FLAGS_BUSY 0
#define FLAGS_FINAL 1
#define FLAGS_DMA_ACTIVE 2
#define FLAGS_OUTPUT_READY 3
-#define FLAGS_INIT 4
#define FLAGS_CPU 5
#define FLAGS_DMA_READY 6
#define FLAGS_AUTO_XOR 7
@@ -144,7 +141,7 @@ struct omap_sham_dev;
struct omap_sham_reqctx {
struct omap_sham_dev *dd;
unsigned long flags;
- unsigned long op;
+ u8 op;
u8 digest[SHA512_DIGEST_SIZE] OMAP_ALIGNED;
size_t digcnt;
@@ -179,7 +176,7 @@ struct omap_sham_ctx {
#define OMAP_SHAM_QUEUE_LENGTH 10
struct omap_sham_algs_info {
- struct ahash_alg *algs_list;
+ struct ahash_engine_alg *algs_list;
unsigned int size;
unsigned int registered;
};
@@ -219,10 +216,9 @@ struct omap_sham_dev {
struct device *dev;
void __iomem *io_base;
int irq;
- spinlock_t lock;
int err;
struct dma_chan *dma_lch;
- struct tasklet_struct done_task;
+ struct work_struct done_task;
u8 polling_mode;
u8 xmit_buf[BUFLEN] OMAP_ALIGNED;
@@ -230,6 +226,7 @@ struct omap_sham_dev {
int fallback_sz;
struct crypto_queue queue;
struct ahash_request *req;
+ struct crypto_engine *engine;
const struct omap_sham_pdata *pdata;
};
@@ -245,6 +242,9 @@ static struct omap_sham_drv sham = {
.lock = __SPIN_LOCK_UNLOCKED(sham.lock),
};
+static int omap_sham_enqueue(struct ahash_request *req, unsigned int op);
+static void omap_sham_finish_req(struct ahash_request *req, int err);
+
static inline u32 omap_sham_read(struct omap_sham_dev *dd, u32 offset)
{
return __raw_readl(dd->io_base + offset);
@@ -357,28 +357,10 @@ static void omap_sham_copy_ready_hash(struct ahash_request *req)
if (big_endian)
for (i = 0; i < d; i++)
- hash[i] = be32_to_cpu(in[i]);
+ put_unaligned(be32_to_cpup((__be32 *)in + i), &hash[i]);
else
for (i = 0; i < d; i++)
- hash[i] = le32_to_cpu(in[i]);
-}
-
-static int omap_sham_hw_init(struct omap_sham_dev *dd)
-{
- int err;
-
- err = pm_runtime_get_sync(dd->dev);
- if (err < 0) {
- dev_err(dd->dev, "failed to get sync: %d\n", err);
- return err;
- }
-
- if (!test_bit(FLAGS_INIT, &dd->flags)) {
- set_bit(FLAGS_INIT, &dd->flags);
- dd->err = 0;
- }
-
- return 0;
+ put_unaligned(le32_to_cpup((__le32 *)in + i), &hash[i]);
}
static void omap_sham_write_ctrl_omap2(struct omap_sham_dev *dd, size_t length,
@@ -456,6 +438,9 @@ static void omap_sham_write_ctrl_omap4(struct omap_sham_dev *dd, size_t length,
struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
u32 val, mask;
+ if (likely(ctx->digcnt))
+ omap_sham_write(dd, SHA_REG_DIGCNT(dd), ctx->digcnt);
+
/*
* Setting ALGO_CONST only for the first iteration and
* CLOSE_HASH only for the last one. Note that flags mode bits
@@ -522,7 +507,7 @@ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, size_t length,
int mlen;
struct sg_mapping_iter mi;
- dev_dbg(dd->dev, "xmit_cpu: digcnt: %d, length: %d, final: %d\n",
+ dev_dbg(dd->dev, "xmit_cpu: digcnt: %zd, length: %zd, final: %d\n",
ctx->digcnt, length, final);
dd->pdata->write_ctrl(dd, length, final, 0);
@@ -577,7 +562,7 @@ static void omap_sham_dma_callback(void *param)
struct omap_sham_dev *dd = param;
set_bit(FLAGS_DMA_READY, &dd->flags);
- tasklet_schedule(&dd->done_task);
+ queue_work(system_bh_wq, &dd->done_task);
}
static int omap_sham_xmit_dma(struct omap_sham_dev *dd, size_t length,
@@ -588,7 +573,7 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, size_t length,
struct dma_slave_config cfg;
int ret;
- dev_dbg(dd->dev, "xmit_dma: digcnt: %d, length: %d, final: %d\n",
+ dev_dbg(dd->dev, "xmit_dma: digcnt: %zd, length: %zd, final: %d\n",
ctx->digcnt, length, final);
if (!dma_map_sg(dd->dev, ctx->sg, ctx->sg_len, DMA_TO_DEVICE)) {
@@ -854,13 +839,16 @@ static int omap_sham_align_sgs(struct scatterlist *sg,
return 0;
}
-static int omap_sham_prepare_request(struct ahash_request *req, bool update)
+static int omap_sham_prepare_request(struct crypto_engine *engine, void *areq)
{
+ struct ahash_request *req = container_of(areq, struct ahash_request,
+ base);
struct omap_sham_reqctx *rctx = ahash_request_ctx(req);
int bs;
int ret;
unsigned int nbytes;
bool final = rctx->flags & BIT(FLAGS_FINUP);
+ bool update = rctx->op == OP_UPDATE;
int hash_later;
bs = get_block_size(rctx);
@@ -871,7 +859,7 @@ static int omap_sham_prepare_request(struct ahash_request *req, bool update)
nbytes += req->nbytes - rctx->offset;
dev_dbg(rctx->dd->dev,
- "%s: nbytes=%d, bs=%d, total=%d, offset=%d, bufcnt=%d\n",
+ "%s: nbytes=%d, bs=%d, total=%d, offset=%d, bufcnt=%zd\n",
__func__, nbytes, bs, rctx->total, rctx->offset,
rctx->bufcnt);
@@ -932,7 +920,7 @@ static int omap_sham_update_dma_stop(struct omap_sham_dev *dd)
return 0;
}
-struct omap_sham_dev *omap_sham_find_dev(struct omap_sham_reqctx *ctx)
+static struct omap_sham_dev *omap_sham_find_dev(struct omap_sham_reqctx *ctx)
{
struct omap_sham_dev *dd;
@@ -1021,9 +1009,9 @@ static int omap_sham_update_req(struct omap_sham_dev *dd)
struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
int err;
bool final = (ctx->flags & BIT(FLAGS_FINUP)) &&
- !(dd->flags & BIT(FLAGS_HUGE));
+ !(dd->flags & BIT(FLAGS_HUGE));
- dev_dbg(dd->dev, "update_req: total: %u, digcnt: %d, final: %d",
+ dev_dbg(dd->dev, "update_req: total: %u, digcnt: %zd, final: %d",
ctx->total, ctx->digcnt, final);
if (ctx->total < get_block_size(ctx) ||
@@ -1036,7 +1024,7 @@ static int omap_sham_update_req(struct omap_sham_dev *dd)
err = omap_sham_xmit_dma(dd, ctx->total, final);
/* wait for dma completion before can take more data */
- dev_dbg(dd->dev, "update: err: %d, digcnt: %d\n", err, ctx->digcnt);
+ dev_dbg(dd->dev, "update: err: %d, digcnt: %zd\n", err, ctx->digcnt);
return err;
}
@@ -1069,6 +1057,46 @@ static int omap_sham_final_req(struct omap_sham_dev *dd)
return err;
}
+static int omap_sham_hash_one_req(struct crypto_engine *engine, void *areq)
+{
+ struct ahash_request *req = container_of(areq, struct ahash_request,
+ base);
+ struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
+ struct omap_sham_dev *dd = ctx->dd;
+ int err;
+ bool final = (ctx->flags & BIT(FLAGS_FINUP)) &&
+ !(dd->flags & BIT(FLAGS_HUGE));
+
+ dev_dbg(dd->dev, "hash-one: op: %u, total: %u, digcnt: %zd, final: %d",
+ ctx->op, ctx->total, ctx->digcnt, final);
+
+ err = omap_sham_prepare_request(engine, areq);
+ if (err)
+ return err;
+
+ err = pm_runtime_resume_and_get(dd->dev);
+ if (err < 0) {
+ dev_err(dd->dev, "failed to get sync: %d\n", err);
+ return err;
+ }
+
+ dd->err = 0;
+ dd->req = req;
+
+ if (ctx->digcnt)
+ dd->pdata->copy_hash(req, 0);
+
+ if (ctx->op == OP_UPDATE)
+ err = omap_sham_update_req(dd);
+ else if (ctx->op == OP_FINAL)
+ err = omap_sham_final_req(dd);
+
+ if (err != -EINPROGRESS)
+ omap_sham_finish_req(req, err);
+
+ return 0;
+}
+
static int omap_sham_finish_hmac(struct ahash_request *req)
{
struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
@@ -1097,7 +1125,7 @@ static int omap_sham_finish(struct ahash_request *req)
err = omap_sham_finish_hmac(req);
}
- dev_dbg(dd->dev, "digcnt: %d, bufcnt: %d\n", ctx->digcnt, ctx->bufcnt);
+ dev_dbg(dd->dev, "digcnt: %zd, bufcnt: %zd\n", ctx->digcnt, ctx->bufcnt);
return err;
}
@@ -1116,25 +1144,20 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
ctx->sg = NULL;
- dd->flags &= ~(BIT(FLAGS_SGS_ALLOCED) | BIT(FLAGS_SGS_COPIED));
+ dd->flags &= ~(BIT(FLAGS_SGS_ALLOCED) | BIT(FLAGS_SGS_COPIED) |
+ BIT(FLAGS_CPU) | BIT(FLAGS_DMA_READY) |
+ BIT(FLAGS_OUTPUT_READY));
+
+ if (!err)
+ dd->pdata->copy_hash(req, 1);
if (dd->flags & BIT(FLAGS_HUGE)) {
- dd->flags &= ~(BIT(FLAGS_CPU) | BIT(FLAGS_DMA_READY) |
- BIT(FLAGS_OUTPUT_READY) | BIT(FLAGS_HUGE));
- omap_sham_prepare_request(req, ctx->op == OP_UPDATE);
- if (ctx->op == OP_UPDATE || (dd->flags & BIT(FLAGS_HUGE))) {
- err = omap_sham_update_req(dd);
- if (err != -EINPROGRESS &&
- (ctx->flags & BIT(FLAGS_FINUP)))
- err = omap_sham_final_req(dd);
- } else if (ctx->op == OP_FINAL) {
- omap_sham_final_req(dd);
- }
+ /* Re-enqueue the request */
+ omap_sham_enqueue(req, ctx->op);
return;
}
if (!err) {
- dd->pdata->copy_hash(req, 1);
if (test_bit(FLAGS_FINAL, &dd->flags))
err = omap_sham_finish(req);
} else {
@@ -1142,89 +1165,20 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
}
/* atomic operation is not needed here */
- dd->flags &= ~(BIT(FLAGS_BUSY) | BIT(FLAGS_FINAL) | BIT(FLAGS_CPU) |
+ dd->flags &= ~(BIT(FLAGS_FINAL) | BIT(FLAGS_CPU) |
BIT(FLAGS_DMA_READY) | BIT(FLAGS_OUTPUT_READY));
- pm_runtime_mark_last_busy(dd->dev);
pm_runtime_put_autosuspend(dd->dev);
ctx->offset = 0;
- if (req->base.complete)
- req->base.complete(&req->base, err);
+ crypto_finalize_hash_request(dd->engine, req, err);
}
static int omap_sham_handle_queue(struct omap_sham_dev *dd,
struct ahash_request *req)
{
- struct crypto_async_request *async_req, *backlog;
- struct omap_sham_reqctx *ctx;
- unsigned long flags;
- int err = 0, ret = 0;
-
-retry:
- spin_lock_irqsave(&dd->lock, flags);
- if (req)
- ret = ahash_enqueue_request(&dd->queue, req);
- if (test_bit(FLAGS_BUSY, &dd->flags)) {
- spin_unlock_irqrestore(&dd->lock, flags);
- return ret;
- }
- backlog = crypto_get_backlog(&dd->queue);
- async_req = crypto_dequeue_request(&dd->queue);
- if (async_req)
- set_bit(FLAGS_BUSY, &dd->flags);
- spin_unlock_irqrestore(&dd->lock, flags);
-
- if (!async_req)
- return ret;
-
- if (backlog)
- backlog->complete(backlog, -EINPROGRESS);
-
- req = ahash_request_cast(async_req);
- dd->req = req;
- ctx = ahash_request_ctx(req);
-
- err = omap_sham_prepare_request(req, ctx->op == OP_UPDATE);
- if (err || !ctx->total)
- goto err1;
-
- dev_dbg(dd->dev, "handling new req, op: %lu, nbytes: %d\n",
- ctx->op, req->nbytes);
-
- err = omap_sham_hw_init(dd);
- if (err)
- goto err1;
-
- if (ctx->digcnt)
- /* request has changed - restore hash */
- dd->pdata->copy_hash(req, 0);
-
- if (ctx->op == OP_UPDATE || (dd->flags & BIT(FLAGS_HUGE))) {
- err = omap_sham_update_req(dd);
- if (err != -EINPROGRESS && (ctx->flags & BIT(FLAGS_FINUP)))
- /* no final() after finup() */
- err = omap_sham_final_req(dd);
- } else if (ctx->op == OP_FINAL) {
- err = omap_sham_final_req(dd);
- }
-err1:
- dev_dbg(dd->dev, "exit, err: %d\n", err);
-
- if (err != -EINPROGRESS) {
- /* done_task will not finish it, so do it here */
- omap_sham_finish_req(req, err);
- req = NULL;
-
- /*
- * Execute next request immediately if there is anything
- * in queue.
- */
- goto retry;
- }
-
- return ret;
+ return crypto_transfer_hash_request_to_engine(dd->engine, req);
}
static int omap_sham_enqueue(struct ahash_request *req, unsigned int op)
@@ -1464,15 +1418,15 @@ static int omap_sham_import(struct ahash_request *req, const void *in)
return 0;
}
-static struct ahash_alg algs_sha1_md5[] = {
+static struct ahash_engine_alg algs_sha1_md5[] = {
{
- .init = omap_sham_init,
- .update = omap_sham_update,
- .final = omap_sham_final,
- .finup = omap_sham_finup,
- .digest = omap_sham_digest,
- .halg.digestsize = SHA1_DIGEST_SIZE,
- .halg.base = {
+ .base.init = omap_sham_init,
+ .base.update = omap_sham_update,
+ .base.final = omap_sham_final,
+ .base.finup = omap_sham_finup,
+ .base.digest = omap_sham_digest,
+ .base.halg.digestsize = SHA1_DIGEST_SIZE,
+ .base.halg.base = {
.cra_name = "sha1",
.cra_driver_name = "omap-sha1",
.cra_priority = 400,
@@ -1481,20 +1435,20 @@ static struct ahash_alg algs_sha1_md5[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_init,
.cra_exit = omap_sham_cra_exit,
- }
+ },
+ .op.do_one_request = omap_sham_hash_one_req,
},
{
- .init = omap_sham_init,
- .update = omap_sham_update,
- .final = omap_sham_final,
- .finup = omap_sham_finup,
- .digest = omap_sham_digest,
- .halg.digestsize = MD5_DIGEST_SIZE,
- .halg.base = {
+ .base.init = omap_sham_init,
+ .base.update = omap_sham_update,
+ .base.final = omap_sham_final,
+ .base.finup = omap_sham_finup,
+ .base.digest = omap_sham_digest,
+ .base.halg.digestsize = MD5_DIGEST_SIZE,
+ .base.halg.base = {
.cra_name = "md5",
.cra_driver_name = "omap-md5",
.cra_priority = 400,
@@ -1503,21 +1457,21 @@ static struct ahash_alg algs_sha1_md5[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_init,
.cra_exit = omap_sham_cra_exit,
- }
+ },
+ .op.do_one_request = omap_sham_hash_one_req,
},
{
- .init = omap_sham_init,
- .update = omap_sham_update,
- .final = omap_sham_final,
- .finup = omap_sham_finup,
- .digest = omap_sham_digest,
- .setkey = omap_sham_setkey,
- .halg.digestsize = SHA1_DIGEST_SIZE,
- .halg.base = {
+ .base.init = omap_sham_init,
+ .base.update = omap_sham_update,
+ .base.final = omap_sham_final,
+ .base.finup = omap_sham_finup,
+ .base.digest = omap_sham_digest,
+ .base.setkey = omap_sham_setkey,
+ .base.halg.digestsize = SHA1_DIGEST_SIZE,
+ .base.halg.base = {
.cra_name = "hmac(sha1)",
.cra_driver_name = "omap-hmac-sha1",
.cra_priority = 400,
@@ -1527,21 +1481,21 @@ static struct ahash_alg algs_sha1_md5[] = {
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx) +
sizeof(struct omap_sham_hmac_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_sha1_init,
.cra_exit = omap_sham_cra_exit,
- }
+ },
+ .op.do_one_request = omap_sham_hash_one_req,
},
{
- .init = omap_sham_init,
- .update = omap_sham_update,
- .final = omap_sham_final,
- .finup = omap_sham_finup,
- .digest = omap_sham_digest,
- .setkey = omap_sham_setkey,
- .halg.digestsize = MD5_DIGEST_SIZE,
- .halg.base = {
+ .base.init = omap_sham_init,
+ .base.update = omap_sham_update,
+ .base.final = omap_sham_final,
+ .base.finup = omap_sham_finup,
+ .base.digest = omap_sham_digest,
+ .base.setkey = omap_sham_setkey,
+ .base.halg.digestsize = MD5_DIGEST_SIZE,
+ .base.halg.base = {
.cra_name = "hmac(md5)",
.cra_driver_name = "omap-hmac-md5",
.cra_priority = 400,
@@ -1551,24 +1505,24 @@ static struct ahash_alg algs_sha1_md5[] = {
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx) +
sizeof(struct omap_sham_hmac_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_md5_init,
.cra_exit = omap_sham_cra_exit,
- }
+ },
+ .op.do_one_request = omap_sham_hash_one_req,
}
};
/* OMAP4 has some algs in addition to what OMAP2 has */
-static struct ahash_alg algs_sha224_sha256[] = {
-{
- .init = omap_sham_init,
- .update = omap_sham_update,
- .final = omap_sham_final,
- .finup = omap_sham_finup,
- .digest = omap_sham_digest,
- .halg.digestsize = SHA224_DIGEST_SIZE,
- .halg.base = {
+static struct ahash_engine_alg algs_sha224_sha256[] = {
+{
+ .base.init = omap_sham_init,
+ .base.update = omap_sham_update,
+ .base.final = omap_sham_final,
+ .base.finup = omap_sham_finup,
+ .base.digest = omap_sham_digest,
+ .base.halg.digestsize = SHA224_DIGEST_SIZE,
+ .base.halg.base = {
.cra_name = "sha224",
.cra_driver_name = "omap-sha224",
.cra_priority = 400,
@@ -1577,20 +1531,20 @@ static struct ahash_alg algs_sha224_sha256[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_init,
.cra_exit = omap_sham_cra_exit,
- }
+ },
+ .op.do_one_request = omap_sham_hash_one_req,
},
{
- .init = omap_sham_init,
- .update = omap_sham_update,
- .final = omap_sham_final,
- .finup = omap_sham_finup,
- .digest = omap_sham_digest,
- .halg.digestsize = SHA256_DIGEST_SIZE,
- .halg.base = {
+ .base.init = omap_sham_init,
+ .base.update = omap_sham_update,
+ .base.final = omap_sham_final,
+ .base.finup = omap_sham_finup,
+ .base.digest = omap_sham_digest,
+ .base.halg.digestsize = SHA256_DIGEST_SIZE,
+ .base.halg.base = {
.cra_name = "sha256",
.cra_driver_name = "omap-sha256",
.cra_priority = 400,
@@ -1599,21 +1553,21 @@ static struct ahash_alg algs_sha224_sha256[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_init,
.cra_exit = omap_sham_cra_exit,
- }
+ },
+ .op.do_one_request = omap_sham_hash_one_req,
},
{
- .init = omap_sham_init,
- .update = omap_sham_update,
- .final = omap_sham_final,
- .finup = omap_sham_finup,
- .digest = omap_sham_digest,
- .setkey = omap_sham_setkey,
- .halg.digestsize = SHA224_DIGEST_SIZE,
- .halg.base = {
+ .base.init = omap_sham_init,
+ .base.update = omap_sham_update,
+ .base.final = omap_sham_final,
+ .base.finup = omap_sham_finup,
+ .base.digest = omap_sham_digest,
+ .base.setkey = omap_sham_setkey,
+ .base.halg.digestsize = SHA224_DIGEST_SIZE,
+ .base.halg.base = {
.cra_name = "hmac(sha224)",
.cra_driver_name = "omap-hmac-sha224",
.cra_priority = 400,
@@ -1623,21 +1577,21 @@ static struct ahash_alg algs_sha224_sha256[] = {
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx) +
sizeof(struct omap_sham_hmac_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_sha224_init,
.cra_exit = omap_sham_cra_exit,
- }
+ },
+ .op.do_one_request = omap_sham_hash_one_req,
},
{
- .init = omap_sham_init,
- .update = omap_sham_update,
- .final = omap_sham_final,
- .finup = omap_sham_finup,
- .digest = omap_sham_digest,
- .setkey = omap_sham_setkey,
- .halg.digestsize = SHA256_DIGEST_SIZE,
- .halg.base = {
+ .base.init = omap_sham_init,
+ .base.update = omap_sham_update,
+ .base.final = omap_sham_final,
+ .base.finup = omap_sham_finup,
+ .base.digest = omap_sham_digest,
+ .base.setkey = omap_sham_setkey,
+ .base.halg.digestsize = SHA256_DIGEST_SIZE,
+ .base.halg.base = {
.cra_name = "hmac(sha256)",
.cra_driver_name = "omap-hmac-sha256",
.cra_priority = 400,
@@ -1647,23 +1601,23 @@ static struct ahash_alg algs_sha224_sha256[] = {
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx) +
sizeof(struct omap_sham_hmac_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_sha256_init,
.cra_exit = omap_sham_cra_exit,
- }
+ },
+ .op.do_one_request = omap_sham_hash_one_req,
},
};
-static struct ahash_alg algs_sha384_sha512[] = {
+static struct ahash_engine_alg algs_sha384_sha512[] = {
{
- .init = omap_sham_init,
- .update = omap_sham_update,
- .final = omap_sham_final,
- .finup = omap_sham_finup,
- .digest = omap_sham_digest,
- .halg.digestsize = SHA384_DIGEST_SIZE,
- .halg.base = {
+ .base.init = omap_sham_init,
+ .base.update = omap_sham_update,
+ .base.final = omap_sham_final,
+ .base.finup = omap_sham_finup,
+ .base.digest = omap_sham_digest,
+ .base.halg.digestsize = SHA384_DIGEST_SIZE,
+ .base.halg.base = {
.cra_name = "sha384",
.cra_driver_name = "omap-sha384",
.cra_priority = 400,
@@ -1672,20 +1626,20 @@ static struct ahash_alg algs_sha384_sha512[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_init,
.cra_exit = omap_sham_cra_exit,
- }
+ },
+ .op.do_one_request = omap_sham_hash_one_req,
},
{
- .init = omap_sham_init,
- .update = omap_sham_update,
- .final = omap_sham_final,
- .finup = omap_sham_finup,
- .digest = omap_sham_digest,
- .halg.digestsize = SHA512_DIGEST_SIZE,
- .halg.base = {
+ .base.init = omap_sham_init,
+ .base.update = omap_sham_update,
+ .base.final = omap_sham_final,
+ .base.finup = omap_sham_finup,
+ .base.digest = omap_sham_digest,
+ .base.halg.digestsize = SHA512_DIGEST_SIZE,
+ .base.halg.base = {
.cra_name = "sha512",
.cra_driver_name = "omap-sha512",
.cra_priority = 400,
@@ -1694,21 +1648,21 @@ static struct ahash_alg algs_sha384_sha512[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_init,
.cra_exit = omap_sham_cra_exit,
- }
+ },
+ .op.do_one_request = omap_sham_hash_one_req,
},
{
- .init = omap_sham_init,
- .update = omap_sham_update,
- .final = omap_sham_final,
- .finup = omap_sham_finup,
- .digest = omap_sham_digest,
- .setkey = omap_sham_setkey,
- .halg.digestsize = SHA384_DIGEST_SIZE,
- .halg.base = {
+ .base.init = omap_sham_init,
+ .base.update = omap_sham_update,
+ .base.final = omap_sham_final,
+ .base.finup = omap_sham_finup,
+ .base.digest = omap_sham_digest,
+ .base.setkey = omap_sham_setkey,
+ .base.halg.digestsize = SHA384_DIGEST_SIZE,
+ .base.halg.base = {
.cra_name = "hmac(sha384)",
.cra_driver_name = "omap-hmac-sha384",
.cra_priority = 400,
@@ -1718,21 +1672,21 @@ static struct ahash_alg algs_sha384_sha512[] = {
.cra_blocksize = SHA384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx) +
sizeof(struct omap_sham_hmac_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_sha384_init,
.cra_exit = omap_sham_cra_exit,
- }
+ },
+ .op.do_one_request = omap_sham_hash_one_req,
},
{
- .init = omap_sham_init,
- .update = omap_sham_update,
- .final = omap_sham_final,
- .finup = omap_sham_finup,
- .digest = omap_sham_digest,
- .setkey = omap_sham_setkey,
- .halg.digestsize = SHA512_DIGEST_SIZE,
- .halg.base = {
+ .base.init = omap_sham_init,
+ .base.update = omap_sham_update,
+ .base.final = omap_sham_final,
+ .base.finup = omap_sham_finup,
+ .base.digest = omap_sham_digest,
+ .base.setkey = omap_sham_setkey,
+ .base.halg.digestsize = SHA512_DIGEST_SIZE,
+ .base.halg.base = {
.cra_name = "hmac(sha512)",
.cra_driver_name = "omap-hmac-sha512",
.cra_priority = 400,
@@ -1742,31 +1696,26 @@ static struct ahash_alg algs_sha384_sha512[] = {
.cra_blocksize = SHA512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx) +
sizeof(struct omap_sham_hmac_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_sha512_init,
.cra_exit = omap_sham_cra_exit,
- }
+ },
+ .op.do_one_request = omap_sham_hash_one_req,
},
};
-static void omap_sham_done_task(unsigned long data)
+static void omap_sham_done_task(struct work_struct *t)
{
- struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
+ struct omap_sham_dev *dd = from_work(dd, t, done_task);
int err = 0;
dev_dbg(dd->dev, "%s: flags=%lx\n", __func__, dd->flags);
- if (!test_bit(FLAGS_BUSY, &dd->flags)) {
- omap_sham_handle_queue(dd, NULL);
- return;
- }
-
if (test_bit(FLAGS_CPU, &dd->flags)) {
if (test_and_clear_bit(FLAGS_OUTPUT_READY, &dd->flags))
goto finish;
} else if (test_bit(FLAGS_DMA_READY, &dd->flags)) {
- if (test_and_clear_bit(FLAGS_DMA_ACTIVE, &dd->flags)) {
+ if (test_bit(FLAGS_DMA_ACTIVE, &dd->flags)) {
omap_sham_update_dma_stop(dd);
if (dd->err) {
err = dd->err;
@@ -1786,20 +1735,12 @@ finish:
dev_dbg(dd->dev, "update done: err: %d\n", err);
/* finish curent request */
omap_sham_finish_req(dd->req, err);
-
- /* If we are not busy, process next req */
- if (!test_bit(FLAGS_BUSY, &dd->flags))
- omap_sham_handle_queue(dd, NULL);
}
static irqreturn_t omap_sham_irq_common(struct omap_sham_dev *dd)
{
- if (!test_bit(FLAGS_BUSY, &dd->flags)) {
- dev_warn(dd->dev, "Interrupt when no active requests.\n");
- } else {
- set_bit(FLAGS_OUTPUT_READY, &dd->flags);
- tasklet_schedule(&dd->done_task);
- }
+ set_bit(FLAGS_OUTPUT_READY, &dd->flags);
+ queue_work(system_bh_wq, &dd->done_task);
return IRQ_HANDLED;
}
@@ -2072,7 +2013,6 @@ static ssize_t queue_len_store(struct device *dev,
struct omap_sham_dev *dd = dev_get_drvdata(dev);
ssize_t status;
long value;
- unsigned long flags;
status = kstrtol(buf, 0, &value);
if (status)
@@ -2086,9 +2026,7 @@ static ssize_t queue_len_store(struct device *dev,
* than current size, it will just not accept new entries until
* it has shrank enough.
*/
- spin_lock_irqsave(&dd->lock, flags);
dd->queue.max_qlen = value;
- spin_unlock_irqrestore(&dd->lock, flags);
return size;
}
@@ -2101,10 +2039,7 @@ static struct attribute *omap_sham_attrs[] = {
&dev_attr_fallback.attr,
NULL,
};
-
-static struct attribute_group omap_sham_attr_group = {
- .attrs = omap_sham_attrs,
-};
+ATTRIBUTE_GROUPS(omap_sham);
static int omap_sham_probe(struct platform_device *pdev)
{
@@ -2125,8 +2060,7 @@ static int omap_sham_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dd);
INIT_LIST_HEAD(&dd->list);
- spin_lock_init(&dd->lock);
- tasklet_init(&dd->done_task, omap_sham_done_task, (unsigned long)dd);
+ INIT_WORK(&dd->done_task, omap_sham_done_task);
crypto_init_queue(&dd->queue, OMAP_SHAM_QUEUE_LENGTH);
err = (dev->of_node) ? omap_sham_get_res_of(dd, dev, &res) :
@@ -2171,9 +2105,8 @@ static int omap_sham_probe(struct platform_device *pdev)
dd->fallback_sz = OMAP_SHA_DMA_THRESHOLD;
pm_runtime_enable(dev);
- pm_runtime_irq_safe(dev);
- err = pm_runtime_get_sync(dev);
+ err = pm_runtime_resume_and_get(dev);
if (err < 0) {
dev_err(dev, "failed to get sync: %d\n", err);
goto err_pm;
@@ -2186,23 +2119,35 @@ static int omap_sham_probe(struct platform_device *pdev)
(rev & dd->pdata->major_mask) >> dd->pdata->major_shift,
(rev & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
- spin_lock(&sham.lock);
+ spin_lock_bh(&sham.lock);
list_add_tail(&dd->list, &sham.dev_list);
- spin_unlock(&sham.lock);
+ spin_unlock_bh(&sham.lock);
+
+ dd->engine = crypto_engine_alloc_init(dev, 1);
+ if (!dd->engine) {
+ err = -ENOMEM;
+ goto err_engine;
+ }
+
+ err = crypto_engine_start(dd->engine);
+ if (err)
+ goto err_engine_start;
for (i = 0; i < dd->pdata->algs_info_size; i++) {
if (dd->pdata->algs_info[i].registered)
break;
for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
+ struct ahash_engine_alg *ealg;
struct ahash_alg *alg;
- alg = &dd->pdata->algs_info[i].algs_list[j];
+ ealg = &dd->pdata->algs_info[i].algs_list[j];
+ alg = &ealg->base;
alg->export = omap_sham_export;
alg->import = omap_sham_import;
alg->halg.statesize = sizeof(struct omap_sham_reqctx) +
BUFLEN;
- err = crypto_register_ahash(alg);
+ err = crypto_engine_register_ahash(ealg);
if (err)
goto err_algs;
@@ -2210,20 +2155,21 @@ static int omap_sham_probe(struct platform_device *pdev)
}
}
- err = sysfs_create_group(&dev->kobj, &omap_sham_attr_group);
- if (err) {
- dev_err(dev, "could not create sysfs device attrs\n");
- goto err_algs;
- }
-
return 0;
err_algs:
for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
- crypto_unregister_ahash(
+ crypto_engine_unregister_ahash(
&dd->pdata->algs_info[i].algs_list[j]);
+err_engine_start:
+ crypto_engine_exit(dd->engine);
+err_engine:
+ spin_lock_bh(&sham.lock);
+ list_del(&dd->list);
+ spin_unlock_bh(&sham.lock);
err_pm:
+ pm_runtime_dont_use_autosuspend(dev);
pm_runtime_disable(dev);
if (!dd->polling_mode)
dma_release_channel(dd->dma_lch);
@@ -2233,61 +2179,37 @@ data_err:
return err;
}
-static int omap_sham_remove(struct platform_device *pdev)
+static void omap_sham_remove(struct platform_device *pdev)
{
struct omap_sham_dev *dd;
int i, j;
dd = platform_get_drvdata(pdev);
- if (!dd)
- return -ENODEV;
- spin_lock(&sham.lock);
+
+ spin_lock_bh(&sham.lock);
list_del(&dd->list);
- spin_unlock(&sham.lock);
+ spin_unlock_bh(&sham.lock);
for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) {
- crypto_unregister_ahash(
+ crypto_engine_unregister_ahash(
&dd->pdata->algs_info[i].algs_list[j]);
dd->pdata->algs_info[i].registered--;
}
- tasklet_kill(&dd->done_task);
+ cancel_work_sync(&dd->done_task);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_disable(&pdev->dev);
if (!dd->polling_mode)
dma_release_channel(dd->dma_lch);
-
- sysfs_remove_group(&dd->dev->kobj, &omap_sham_attr_group);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int omap_sham_suspend(struct device *dev)
-{
- pm_runtime_put_sync(dev);
- return 0;
}
-static int omap_sham_resume(struct device *dev)
-{
- int err = pm_runtime_get_sync(dev);
- if (err < 0) {
- dev_err(dev, "failed to get sync: %d\n", err);
- return err;
- }
- return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(omap_sham_pm_ops, omap_sham_suspend, omap_sham_resume);
-
static struct platform_driver omap_sham_driver = {
.probe = omap_sham_probe,
- .remove = omap_sham_remove,
+ .remove = omap_sham_remove,
.driver = {
.name = "omap-sham",
- .pm = &omap_sham_pm_ops,
.of_match_table = omap_sham_of_match,
+ .dev_groups = omap_sham_groups,
},
};