mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
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:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user