From 64baf3cfea974d2b9e671ccfdbc03e030ea5ebc6 Mon Sep 17 00:00:00 2001
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Thu, 1 Sep 2005 17:43:05 -0700
Subject: [PATCH] [CRYPTO]: Added CRYPTO_TFM_REQ_MAY_SLEEP flag

The crypto layer currently uses in_atomic() to determine whether it is
allowed to sleep.  This is incorrect since spin locks don't always cause
in_atomic() to return true.

Instead of that, this patch returns to an earlier idea of a per-tfm flag
which determines whether sleeping is allowed.  Unlike the earlier version,
the default is to not allow sleeping.  This ensures that no existing code
can break.

As usual, this flag may either be set through crypto_alloc_tfm(), or
just before a specific crypto operation.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 crypto/api.c           | 3 ++-
 crypto/cipher.c        | 4 ----
 crypto/internal.h      | 3 ++-
 include/linux/crypto.h | 1 +
 4 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/crypto/api.c b/crypto/api.c
index b4728811ce3b1..959c4e5f264f4 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -66,7 +66,8 @@ static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name)
 
 static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags)
 {
-	tfm->crt_flags = 0;
+	tfm->crt_flags = flags & CRYPTO_TFM_REQ_MASK;
+	flags &= ~CRYPTO_TFM_REQ_MASK;
 	
 	switch (crypto_tfm_alg_type(tfm)) {
 	case CRYPTO_ALG_TYPE_CIPHER:
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 8da644364cb42..3df47f93c9db0 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -377,11 +377,7 @@ static int nocrypt_iv(struct crypto_tfm *tfm,
 int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
 {
 	u32 mode = flags & CRYPTO_TFM_MODE_MASK;
-	
 	tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB;
-	if (flags & CRYPTO_TFM_REQ_WEAK_KEY)
-		tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY;
-	
 	return 0;
 }
 
diff --git a/crypto/internal.h b/crypto/internal.h
index 37515beafc8ce..37aa652ce5ce6 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <asm/kmap_types.h>
 
 extern enum km_type crypto_km_types[];
@@ -38,7 +39,7 @@ static inline void crypto_kunmap(void *vaddr, int out)
 
 static inline void crypto_yield(struct crypto_tfm *tfm)
 {
-	if (!in_atomic())
+	if (tfm->crt_flags & CRYPTO_TFM_REQ_MAY_SLEEP)
 		cond_resched();
 }
 
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 5e2bcc636a02f..3c89df6e77684 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -45,6 +45,7 @@
 #define CRYPTO_TFM_MODE_CTR		0x00000008
 
 #define CRYPTO_TFM_REQ_WEAK_KEY		0x00000100
+#define CRYPTO_TFM_REQ_MAY_SLEEP	0x00000200
 #define CRYPTO_TFM_RES_WEAK_KEY		0x00100000
 #define CRYPTO_TFM_RES_BAD_KEY_LEN   	0x00200000
 #define CRYPTO_TFM_RES_BAD_KEY_SCHED 	0x00400000
-- 
GitLab