* Based on omap-aes.c and tegra-aes.c
  */
 
-#include <crypto/algapi.h>
 #include <crypto/aes.h>
-#include <crypto/hash.h>
 #include <crypto/internal/hash.h>
+#include <crypto/internal/skcipher.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/sha.h>
 
        /* AES-specific context */
        int keylen;
        u8 key[AES_KEYSIZE_128];
-       struct crypto_ablkcipher *fallback;
-
-       /* SHA-specific context */
-       struct crypto_shash *shash_fallback;
+       struct crypto_skcipher *fallback;
 };
 
 struct sahara_aes_reqctx {
                return 0;
        }
 
-       if (keylen != AES_KEYSIZE_128 &&
-           keylen != AES_KEYSIZE_192 && keylen != AES_KEYSIZE_256)
+       if (keylen != AES_KEYSIZE_192 && keylen != AES_KEYSIZE_256)
                return -EINVAL;
 
        /*
         * The requested key size is not supported by HW, do a fallback.
         */
-       ctx->fallback->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
-       ctx->fallback->base.crt_flags |=
-               (tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK);
+       crypto_skcipher_clear_flags(ctx->fallback, CRYPTO_TFM_REQ_MASK);
+       crypto_skcipher_set_flags(ctx->fallback, tfm->base.crt_flags &
+                                                CRYPTO_TFM_REQ_MASK);
 
-       ret = crypto_ablkcipher_setkey(ctx->fallback, key, keylen);
-       if (ret) {
-               struct crypto_tfm *tfm_aux = crypto_ablkcipher_tfm(tfm);
+       ret = crypto_skcipher_setkey(ctx->fallback, key, keylen);
 
-               tfm_aux->crt_flags &= ~CRYPTO_TFM_RES_MASK;
-               tfm_aux->crt_flags |=
-                       (ctx->fallback->base.crt_flags & CRYPTO_TFM_RES_MASK);
-       }
+       tfm->base.crt_flags &= ~CRYPTO_TFM_RES_MASK;
+       tfm->base.crt_flags |= crypto_skcipher_get_flags(ctx->fallback) &
+                              CRYPTO_TFM_RES_MASK;
        return ret;
 }
 
 
 static int sahara_aes_ecb_encrypt(struct ablkcipher_request *req)
 {
-       struct crypto_tfm *tfm =
-               crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
        struct sahara_ctx *ctx = crypto_ablkcipher_ctx(
                crypto_ablkcipher_reqtfm(req));
        int err;
 
        if (unlikely(ctx->keylen != AES_KEYSIZE_128)) {
-               ablkcipher_request_set_tfm(req, ctx->fallback);
-               err = crypto_ablkcipher_encrypt(req);
-               ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+               SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
+
+               skcipher_request_set_tfm(subreq, ctx->fallback);
+               skcipher_request_set_callback(subreq, req->base.flags,
+                                             NULL, NULL);
+               skcipher_request_set_crypt(subreq, req->src, req->dst,
+                                          req->nbytes, req->info);
+               err = crypto_skcipher_encrypt(subreq);
+               skcipher_request_zero(subreq);
                return err;
        }
 
 
 static int sahara_aes_ecb_decrypt(struct ablkcipher_request *req)
 {
-       struct crypto_tfm *tfm =
-               crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
        struct sahara_ctx *ctx = crypto_ablkcipher_ctx(
                crypto_ablkcipher_reqtfm(req));
        int err;
 
        if (unlikely(ctx->keylen != AES_KEYSIZE_128)) {
-               ablkcipher_request_set_tfm(req, ctx->fallback);
-               err = crypto_ablkcipher_decrypt(req);
-               ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+               SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
+
+               skcipher_request_set_tfm(subreq, ctx->fallback);
+               skcipher_request_set_callback(subreq, req->base.flags,
+                                             NULL, NULL);
+               skcipher_request_set_crypt(subreq, req->src, req->dst,
+                                          req->nbytes, req->info);
+               err = crypto_skcipher_decrypt(subreq);
+               skcipher_request_zero(subreq);
                return err;
        }
 
 
 static int sahara_aes_cbc_encrypt(struct ablkcipher_request *req)
 {
-       struct crypto_tfm *tfm =
-               crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
        struct sahara_ctx *ctx = crypto_ablkcipher_ctx(
                crypto_ablkcipher_reqtfm(req));
        int err;
 
        if (unlikely(ctx->keylen != AES_KEYSIZE_128)) {
-               ablkcipher_request_set_tfm(req, ctx->fallback);
-               err = crypto_ablkcipher_encrypt(req);
-               ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+               SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
+
+               skcipher_request_set_tfm(subreq, ctx->fallback);
+               skcipher_request_set_callback(subreq, req->base.flags,
+                                             NULL, NULL);
+               skcipher_request_set_crypt(subreq, req->src, req->dst,
+                                          req->nbytes, req->info);
+               err = crypto_skcipher_encrypt(subreq);
+               skcipher_request_zero(subreq);
                return err;
        }
 
 
 static int sahara_aes_cbc_decrypt(struct ablkcipher_request *req)
 {
-       struct crypto_tfm *tfm =
-               crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
        struct sahara_ctx *ctx = crypto_ablkcipher_ctx(
                crypto_ablkcipher_reqtfm(req));
        int err;
 
        if (unlikely(ctx->keylen != AES_KEYSIZE_128)) {
-               ablkcipher_request_set_tfm(req, ctx->fallback);
-               err = crypto_ablkcipher_decrypt(req);
-               ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+               SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
+
+               skcipher_request_set_tfm(subreq, ctx->fallback);
+               skcipher_request_set_callback(subreq, req->base.flags,
+                                             NULL, NULL);
+               skcipher_request_set_crypt(subreq, req->src, req->dst,
+                                          req->nbytes, req->info);
+               err = crypto_skcipher_decrypt(subreq);
+               skcipher_request_zero(subreq);
                return err;
        }
 
        const char *name = crypto_tfm_alg_name(tfm);
        struct sahara_ctx *ctx = crypto_tfm_ctx(tfm);
 
-       ctx->fallback = crypto_alloc_ablkcipher(name, 0,
-                               CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
+       ctx->fallback = crypto_alloc_skcipher(name, 0,
+                                             CRYPTO_ALG_ASYNC |
+                                             CRYPTO_ALG_NEED_FALLBACK);
        if (IS_ERR(ctx->fallback)) {
                pr_err("Error allocating fallback algo %s\n", name);
                return PTR_ERR(ctx->fallback);
 {
        struct sahara_ctx *ctx = crypto_tfm_ctx(tfm);
 
-       if (ctx->fallback)
-               crypto_free_ablkcipher(ctx->fallback);
-       ctx->fallback = NULL;
+       crypto_free_skcipher(ctx->fallback);
 }
 
 static u32 sahara_sha_init_hdr(struct sahara_dev *dev,
 
 static int sahara_sha_cra_init(struct crypto_tfm *tfm)
 {
-       const char *name = crypto_tfm_alg_name(tfm);
-       struct sahara_ctx *ctx = crypto_tfm_ctx(tfm);
-
-       ctx->shash_fallback = crypto_alloc_shash(name, 0,
-                                       CRYPTO_ALG_NEED_FALLBACK);
-       if (IS_ERR(ctx->shash_fallback)) {
-               pr_err("Error allocating fallback algo %s\n", name);
-               return PTR_ERR(ctx->shash_fallback);
-       }
        crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
                                 sizeof(struct sahara_sha_reqctx) +
                                 SHA_BUFFER_LEN + SHA256_BLOCK_SIZE);
        return 0;
 }
 
-static void sahara_sha_cra_exit(struct crypto_tfm *tfm)
-{
-       struct sahara_ctx *ctx = crypto_tfm_ctx(tfm);
-
-       crypto_free_shash(ctx->shash_fallback);
-       ctx->shash_fallback = NULL;
-}
-
 static struct crypto_alg aes_algs[] = {
 {
        .cra_name               = "ecb(aes)",
                .cra_alignmask          = 0,
                .cra_module             = THIS_MODULE,
                .cra_init               = sahara_sha_cra_init,
-               .cra_exit               = sahara_sha_cra_exit,
        }
 },
 };
                .cra_alignmask          = 0,
                .cra_module             = THIS_MODULE,
                .cra_init               = sahara_sha_cra_init,
-               .cra_exit               = sahara_sha_cra_exit,
        }
 },
 };