/* Prepare the command and submit for execution */
        cmdlen = tegra_aes_prep_cmd(ctx, rctx);
-       ret = tegra_se_host1x_submit(se, cmdlen);
+       ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
 
        /* Copy the result */
        tegra_aes_update_iv(req, ctx);
 
        cmdlen = tegra_gmac_prep_cmd(ctx, rctx);
 
-       return tegra_se_host1x_submit(se, cmdlen);
+       return tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
 }
 
 static int tegra_gcm_do_crypt(struct tegra_aead_ctx *ctx, struct tegra_aead_reqctx *rctx)
 
        /* Prepare command and submit */
        cmdlen = tegra_gcm_crypt_prep_cmd(ctx, rctx);
-       ret = tegra_se_host1x_submit(se, cmdlen);
+       ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
        if (ret)
                return ret;
 
 
        /* Prepare command and submit */
        cmdlen = tegra_gcm_prep_final_cmd(se, cpuvaddr, rctx);
-       ret = tegra_se_host1x_submit(se, cmdlen);
+       ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
        if (ret)
                return ret;
 
        /* Prepare command and submit */
        cmdlen = tegra_cbcmac_prep_cmd(ctx, rctx);
 
-       return tegra_se_host1x_submit(se, cmdlen);
+       return tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
 }
 
 static int tegra_ccm_set_msg_len(u8 *block, unsigned int msglen, int csize)
 
        /* Prepare command and submit */
        cmdlen = tegra_ctr_prep_cmd(ctx, rctx);
-       ret = tegra_se_host1x_submit(se, cmdlen);
+       ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
        if (ret)
                return ret;
 
                tegra_cmac_paste_result(ctx->se, rctx);
 
        cmdlen = tegra_cmac_prep_cmd(ctx, rctx);
+       ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
 
-       ret = tegra_se_host1x_submit(se, cmdlen);
        /*
         * If this is not the final update, copy the intermediate results
         * from the registers so that it can be used in the next 'update'
 
        /* Prepare command and submit */
        cmdlen = tegra_cmac_prep_cmd(ctx, rctx);
-       ret = tegra_se_host1x_submit(se, cmdlen);
+       ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
        if (ret)
                goto out;
 
 
 {
        struct tegra_sha_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
        struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
+       struct tegra_se *se = ctx->se;
        unsigned int nblks, nresidue, size, ret;
-       u32 *cpuvaddr = ctx->se->cmdbuf->addr;
+       u32 *cpuvaddr = se->cmdbuf->addr;
 
        nresidue = (req->nbytes + rctx->residue.size) % rctx->blk_size;
        nblks = (req->nbytes + rctx->residue.size) / rctx->blk_size;
         * This is to support the import/export functionality.
         */
        if (!(rctx->task & SHA_FIRST))
-               tegra_sha_paste_hash_result(ctx->se, rctx);
+               tegra_sha_paste_hash_result(se, rctx);
 
-       size = tegra_sha_prep_cmd(ctx->se, cpuvaddr, rctx);
+       size = tegra_sha_prep_cmd(se, cpuvaddr, rctx);
 
-       ret = tegra_se_host1x_submit(ctx->se, size);
+       ret = tegra_se_host1x_submit(se, se->cmdbuf, size);
 
        /*
         * If this is not the final update, copy the intermediate results
         * call. This is to support the import/export functionality.
         */
        if (!(rctx->task & SHA_FINAL))
-               tegra_sha_copy_hash_result(ctx->se, rctx);
+               tegra_sha_copy_hash_result(se, rctx);
 
        return ret;
 }
 
        size = tegra_sha_prep_cmd(se, cpuvaddr, rctx);
 
-       ret = tegra_se_host1x_submit(se, size);
+       ret = tegra_se_host1x_submit(se, se->cmdbuf, size);
        if (ret)
                goto out;
 
 
                            u32 keylen, u16 slot, u32 alg)
 {
        const u32 *keyval = (u32 *)key;
-       u32 *addr = se->cmdbuf->addr, size;
+       u32 *addr = se->keybuf->addr, size;
+       int ret;
+
+       mutex_lock(&kslt_lock);
 
        size = tegra_key_prep_ins_cmd(se, addr, keyval, keylen, slot, alg);
+       ret = tegra_se_host1x_submit(se, se->keybuf, size);
 
-       return tegra_se_host1x_submit(se, size);
+       mutex_unlock(&kslt_lock);
+
+       return ret;
 }
 
 void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg)
 
        return cmdbuf;
 }
 
-int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
+int tegra_se_host1x_submit(struct tegra_se *se, struct tegra_se_cmdbuf *cmdbuf, u32 size)
 {
        struct host1x_job *job;
        int ret;
        job->engine_fallback_streamid = se->stream_id;
        job->engine_streamid_offset = SE_STREAM_ID;
 
-       se->cmdbuf->words = size;
+       cmdbuf->words = size;
 
-       host1x_job_add_gather(job, &se->cmdbuf->bo, size, 0);
+       host1x_job_add_gather(job, &cmdbuf->bo, size, 0);
 
        ret = host1x_job_pin(job, se->dev);
        if (ret) {
                goto syncpt_put;
        }
 
+       se->keybuf = tegra_se_host1x_bo_alloc(se, SZ_4K);
+       if (!se->keybuf) {
+               ret = -ENOMEM;
+               goto cmdbuf_put;
+       }
+
        ret = se->hw->init_alg(se);
        if (ret) {
                dev_err(se->dev, "failed to register algorithms\n");
-               goto cmdbuf_put;
+               goto keybuf_put;
        }
 
        return 0;
 
+keybuf_put:
+       tegra_se_cmdbuf_put(&se->keybuf->bo);
 cmdbuf_put:
        tegra_se_cmdbuf_put(&se->cmdbuf->bo);
 syncpt_put:
 
        struct host1x_client client;
        struct host1x_channel *channel;
        struct tegra_se_cmdbuf *cmdbuf;
+       struct tegra_se_cmdbuf *keybuf;
        struct crypto_engine *engine;
        struct host1x_syncpt *syncpt;
        struct device *dev;
 int tegra_key_submit(struct tegra_se *se, const u8 *key,
                     u32 keylen, u32 alg, u32 *keyid);
 void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg);
-int tegra_se_host1x_submit(struct tegra_se *se, u32 size);
+int tegra_se_host1x_submit(struct tegra_se *se, struct tegra_se_cmdbuf *cmdbuf, u32 size);
 
 /* HOST1x OPCODES */
 static inline u32 host1x_opcode_setpayload(unsigned int payload)