crypto: rockchip: cryptodev_linux: added non-multithreaded protection

CRYPTO V1/V2 do not support multi-threading, so it is necessary
 to add a hold mechanism in Cryptodev to prevent abnormal consequences
 caused by multi-threading calls.

Signed-off-by: Lin Jinhan <troy.lin@rock-chips.com>
Change-Id: Ifd5ff6b102c81c8ac44c16f9689d5219c7fa5a56
This commit is contained in:
Lin Jinhan
2022-02-25 14:20:21 +08:00
committed by Tao Huang
parent dfe02a6b7b
commit 0053651587
5 changed files with 57 additions and 2 deletions

View File

@@ -103,6 +103,7 @@ struct crypt_priv {
/* cryptodev's own workqueue, keeps crypto tasks from disturbing the force */
static struct workqueue_struct *cryptodev_wq;
static atomic_t cryptodev_sess = ATOMIC_INIT(1);
/* Prepare session for future use. */
static int
@@ -322,6 +323,16 @@ crypto_create_session(struct fcrypt *fcr, struct session_op *sop)
goto session_error;
}
/* Non-multithreaded can only create one session */
if (!rk_cryptodev_multi_thread(NULL) &&
!atomic_dec_and_test(&cryptodev_sess)) {
atomic_inc(&cryptodev_sess);
ddebug(2, "Non-multithreaded can only create one session. sess = %d",
atomic_read(&cryptodev_sess));
ret = -EBUSY;
goto session_error;
}
/* put the new session to the list */
get_random_bytes(&ses_new->sid, sizeof(ses_new->sid));
mutex_init(&ses_new->sem);
@@ -375,6 +386,12 @@ crypto_destroy_session(struct csession *ses_ptr)
mutex_unlock(&ses_ptr->sem);
mutex_destroy(&ses_ptr->sem);
kfree(ses_ptr);
/* Non-multithreaded can only create one session */
if (!rk_cryptodev_multi_thread(NULL)) {
atomic_inc(&cryptodev_sess);
ddebug(2, "Release cryptodev_sess = %d", atomic_read(&cryptodev_sess));
}
}
/* Look up a session by ID and remove. */
@@ -549,6 +566,7 @@ static void cryptask_routine(struct work_struct *work)
}
/* ====== /dev/crypto ====== */
static atomic_t cryptodev_node = ATOMIC_INIT(1);
static int
cryptodev_open(struct inode *inode, struct file *filp)
@@ -557,6 +575,18 @@ cryptodev_open(struct inode *inode, struct file *filp)
struct crypt_priv *pcr;
int i;
/* Non-multithreaded can only be opened once */
if (!rk_cryptodev_multi_thread(NULL) &&
!atomic_dec_and_test(&cryptodev_node)) {
atomic_inc(&cryptodev_node);
ddebug(2, "Non-multithreaded can only be opened once. node = %d",
atomic_read(&cryptodev_node));
return -EBUSY;
}
/* make sure sess == 1 after open */
atomic_set(&cryptodev_sess, 1);
pcr = kzalloc(sizeof(*pcr), GFP_KERNEL);
if (!pcr)
return -ENOMEM;
@@ -615,6 +645,12 @@ cryptodev_release(struct inode *inode, struct file *filp)
if (!pcr)
return 0;
/* Non-multithreaded can only be opened once */
if (!rk_cryptodev_multi_thread(NULL)) {
atomic_inc(&cryptodev_node);
ddebug(2, "Release cryptodev_node = %d", atomic_read(&cryptodev_node));
}
cancel_work_sync(&pcr->cryptask);
list_splice_tail(&pcr->todo.list, &pcr->free.list);

View File

@@ -36,6 +36,7 @@ struct dma_fd_map_node {
struct crypto_dev_info {
struct device *dev;
char name[MAX_CRYPTO_NAME_LEN];
bool is_multi_thread;
};
static struct crypto_dev_info g_dev_infos[MAX_CRYPTO_DEV];
@@ -61,6 +62,8 @@ int rk_cryptodev_register_dev(struct device *dev, const char *name)
g_dev_infos[i].dev = dev;
strncpy(g_dev_infos[i].name, name, sizeof(g_dev_infos[i].name));
g_dev_infos[i].is_multi_thread = strstr(g_dev_infos[i].name, "multi");
dev_info(dev, "register to cryptodev ok!\n");
return 0;
}
@@ -954,3 +957,14 @@ const char *rk_get_hash_name(uint32_t id, int *is_hmac)
return NULL;
}
bool rk_cryptodev_multi_thread(const char *name)
{
uint32_t i;
for (i = 0; i < ARRAY_SIZE(g_dev_infos); i++) {
if (g_dev_infos[i].dev)
return g_dev_infos[i].is_multi_thread;
}
return false;
}

View File

@@ -85,4 +85,6 @@ const char *rk_get_cipher_name(uint32_t id, int *is_stream, int *is_aead);
const char *rk_get_hash_name(uint32_t id, int *is_hmac);
bool rk_cryptodev_multi_thread(const char *name);
#endif

View File

@@ -25,6 +25,7 @@
#include "cryptodev_linux/rk_cryptodev_int.h"
#define RK_CRYPTO_V1_SOC_DATA_INIT(names) {\
.crypto_ver = "CRYPTO V1.0.0.0",\
.use_soft_aes192 = false,\
.valid_algs_name = (names),\
.valid_algs_num = ARRAY_SIZE(names),\
@@ -39,6 +40,7 @@
}
#define RK_CRYPTO_V2_SOC_DATA_INIT(names, soft_aes_192) {\
.crypto_ver = "CRYPTO V2.0.0.0",\
.use_soft_aes192 = soft_aes_192,\
.valid_algs_name = (names),\
.valid_algs_num = ARRAY_SIZE(names),\
@@ -835,9 +837,9 @@ static int rk_crypto_probe(struct platform_device *pdev)
goto err_register_alg;
}
rk_cryptodev_register_dev(rk_dev->dev, "rk_crypto");
rk_cryptodev_register_dev(rk_dev->dev, soc_data->crypto_ver);
dev_info(dev, "Crypto Accelerator successfully registered\n");
dev_info(dev, "%s Accelerator successfully registered\n", soc_data->crypto_ver);
return 0;
err_register_alg:

View File

@@ -44,6 +44,7 @@
#define sha224_state sha256_state
struct rk_crypto_soc_data {
const char *crypto_ver;
char **valid_algs_name;
int valid_algs_num;
struct rk_crypto_algt **total_algs;