summaryrefslogtreecommitdiff
path: root/drivers/crypto
diff options
context:
space:
mode:
authorSanjay Singh Rawat <srawat@nvidia.com>2012-03-14 18:48:29 +0530
committerSimone Willett <swillett@nvidia.com>2012-03-26 17:50:35 -0700
commitfb23fdbe8951e1a11d13b921ae2fde91857ae55c (patch)
tree838de25988ed03a1b0ffe15a56e3d73a709bf1a5 /drivers/crypto
parent510025691c27b040c030c915c7a18feb016862c4 (diff)
crypto: tegra-aes: save key during key call
Save the key in hardware when the key setting call comes. Currently it is set at later time. Bug 917607 Change-Id: Ibdacb07c16c161eeba00eda6716884518e40c40a Signed-off-by: Sanjay Singh Rawat <srawat@nvidia.com> Reviewed-on: http://git-master/r/90072 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Varun Wadekar <vwadekar@nvidia.com>
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/tegra-aes.c76
1 files changed, 61 insertions, 15 deletions
diff --git a/drivers/crypto/tegra-aes.c b/drivers/crypto/tegra-aes.c
index 6a5b5655a486..22a96ed343eb 100644
--- a/drivers/crypto/tegra-aes.c
+++ b/drivers/crypto/tegra-aes.c
@@ -33,6 +33,7 @@
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/workqueue.h>
+#include <linux/delay.h>
#include <mach/arb_sema.h>
#include <mach/clk.h>
@@ -166,7 +167,6 @@ struct tegra_aes_engine {
int res_id;
unsigned long busy;
u8 irq;
- bool new_key;
u32 status;
};
@@ -615,15 +615,6 @@ static int tegra_aes_handle_req(struct tegra_aes_engine *eng)
dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode;
eng->ctx = ctx;
- if (eng->new_key) {
- if (ctx->use_ssk)
- aes_set_key(eng, SSK_SLOT_NUM);
- else
- aes_set_key(eng, ctx->slot->slot_num);
-
- eng->new_key = false;
- }
-
if (((dd->flags & FLAGS_CBC) || (dd->flags & FLAGS_OFB)) && req->info) {
/* set iv to the aes hw slot
* Hw generates updated iv only after iv is set in slot.
@@ -690,12 +681,67 @@ out:
return ret;
}
+static int tegra_aes_key_save(struct tegra_aes_ctx *ctx)
+{
+ struct tegra_aes_dev *dd = aes_dev;
+ int retry_count, eng_busy, ret, eng_no;
+ struct tegra_aes_engine *eng[2] = {&dd->bsev, &dd->bsea};
+ unsigned long flags;
+
+ /* check for engine free state */
+ for (eng_no = 0; eng_no < ARRAY_SIZE(eng); eng_no++) {
+ for (retry_count = 0; retry_count <= 10; retry_count++) {
+ spin_lock_irqsave(&dd->lock, flags);
+ eng_busy = test_and_set_bit(FLAGS_BUSY,
+ &eng[eng_no]->busy);
+ spin_unlock_irqrestore(&dd->lock, flags);
+
+ if (!eng_busy)
+ break;
+
+ if (retry_count == 10) {
+ dev_err(dd->dev,
+ "%s: eng=%d busy, wait timeout\n",
+ __func__, eng[eng_no]->res_id);
+ ret = -EBUSY;
+ goto out;
+ }
+ mdelay(5);
+ }
+ }
+
+ /* save key in the engine */
+ for (eng_no = 0; eng_no < ARRAY_SIZE(eng); eng_no++) {
+ ret = aes_hw_init(eng[eng_no]);
+ if (ret < 0) {
+ dev_err(dd->dev, "%s: eng=%d hw init fail(%d)\n",
+ __func__, eng[eng_no]->res_id, ret);
+ goto out;
+ }
+ eng[eng_no]->ctx = ctx;
+ if (ctx->use_ssk)
+ aes_set_key(eng[eng_no], SSK_SLOT_NUM);
+ else
+ aes_set_key(eng[eng_no], ctx->slot->slot_num);
+
+ aes_hw_deinit(eng[eng_no]);
+ }
+out:
+ spin_lock_irqsave(&dd->lock, flags);
+ while (--eng_no >= 0)
+ clear_bit(FLAGS_BUSY, &eng[eng_no]->busy);
+ spin_unlock_irqrestore(&dd->lock, flags);
+
+ return ret;
+}
+
static int tegra_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
unsigned int keylen)
{
struct tegra_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
struct tegra_aes_dev *dd = aes_dev;
struct tegra_aes_slot *key_slot;
+ int ret = 0;
if (!ctx || !dd) {
pr_err("ctx=0x%x, dd=0x%x\n",
@@ -722,7 +768,6 @@ static int tegra_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
}
dev_dbg(dd->dev, "keylen: %d\n", keylen);
-
ctx->dd = dd;
if (key) {
@@ -730,6 +775,7 @@ static int tegra_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
key_slot = aes_find_key_slot(dd);
if (!key_slot) {
dev_err(dd->dev, "no empty slot\n");
+ ret = -EBUSY;
goto out;
}
ctx->slot = key_slot;
@@ -745,14 +791,14 @@ static int tegra_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
ctx->keylen = AES_KEYSIZE_128;
}
- dd->bsev.new_key = true;
- dd->bsea.new_key = true;
-
+ ret = tegra_aes_key_save(ctx);
+ if (ret != 0)
+ dev_err(dd->dev, "%s failed\n", __func__);
out:
tegra_arb_mutex_unlock(dd->bsev.res_id);
tegra_arb_mutex_unlock(dd->bsea.res_id);
dev_dbg(dd->dev, "done\n");
- return 0;
+ return ret;
}
static void bsev_workqueue_handler(struct work_struct *work)