From 7b11cccd6733b2d19289ed58b3f87c26a8e50cd3 Mon Sep 17 00:00:00 2001 From: Fede2782 <78815152+Fede2782@users.noreply.github.com> Date: Sun, 12 May 2024 11:29:35 +0200 Subject: [PATCH] hwrng: exysdw-rng: Update from P615XXS7FWK1 --- drivers/char/hw_random/exyswd-rng.c | 85 ++++++++++++++--------------- 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/drivers/char/hw_random/exyswd-rng.c b/drivers/char/hw_random/exyswd-rng.c index fb116a2a9c0c..64e209f24de9 100644 --- a/drivers/char/hw_random/exyswd-rng.c +++ b/drivers/char/hw_random/exyswd-rng.c @@ -43,6 +43,12 @@ static int hwrng_disabled; #endif static int start_up_test; +atomic_t hwrng_suspend_flag; +atomic_t hwrng_running_flag; + +/* Protects exyswd read functions */ +static DEFINE_SPINLOCK(rng_running_lock); + #ifdef CONFIG_EXYRNG_DEBUG #define exyrng_debug(args...) printk(KERN_INFO args) #else @@ -165,6 +171,7 @@ static int exynos_swd_read(struct hwrng *rng, void *data, size_t max, bool wait) uint32_t *read_buf = data; uint32_t read_size = max; unsigned long flag; + unsigned long running_flag; uint32_t retry_cnt; int ret = HWRNG_RET_OK; @@ -172,6 +179,17 @@ static int exynos_swd_read(struct hwrng *rng, void *data, size_t max, bool wait) if (hwrng_disabled) return -EPERM; #endif + spin_lock_irqsave(&rng_running_lock, running_flag); + if (atomic_read(&hwrng_suspend_flag) == 1) { + atomic_set(&hwrng_running_flag, 0); + spin_unlock_irqrestore(&rng_running_lock, running_flag); + printk("[ExyRNG] exynos_swd_read is failed because of suspend flag\n"); + return -EFAULT; + } + + atomic_set(&hwrng_running_flag, 1); + spin_unlock_irqrestore(&rng_running_lock, running_flag); + retry_cnt = 0; do { spin_lock_irqsave(&hwrandom_lock, flag); @@ -204,7 +222,8 @@ static int exynos_swd_read(struct hwrng *rng, void *data, size_t max, bool wait) } while (ret == HWRNG_RET_RETRY_ERROR); if (ret != HWRNG_RET_OK) { msleep(1); - return -EFAULT; + ret = -EFAULT; + goto err; } if (start_up_test) { @@ -283,6 +302,11 @@ static int exynos_swd_read(struct hwrng *rng, void *data, size_t max, bool wait) usleep_range(50, 100); } while(1); +err: + spin_lock_irqsave(&rng_running_lock, running_flag); + atomic_set(&hwrng_running_flag, 0); + spin_unlock_irqrestore(&rng_running_lock, running_flag); + return ret; } @@ -299,6 +323,9 @@ static int exyswd_rng_probe(struct platform_device *pdev) start_up_test = 1; #endif + atomic_set(&hwrng_suspend_flag, 0); + atomic_set(&hwrng_running_flag, 0); + ret = hwrng_register(&rng); if (ret) return ret; @@ -318,62 +345,32 @@ static int exyswd_rng_remove(struct platform_device *pdev) #if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME) static int exyswd_rng_suspend(struct device *dev) { - uint64_t reg0; - uint64_t reg1; - uint64_t reg2; - uint64_t reg3; unsigned long flag; int ret = HWRNG_RET_OK; - spin_lock_irqsave(&hwrandom_lock, flag); - if (hwrng_read_flag) { - reg0 = SMC_CMD_RANDOM; - reg1 = HWRNG_EXIT; - reg2 = 0; - reg3 = 0; - - ret = exynos_cm_smc(®0, ®1, ®2, ®3); - if (ret != HWRNG_RET_OK) - printk("[ExyRNG] failed to enter suspend with %d\n", ret); + spin_lock_irqsave(&rng_running_lock, flag); + if (atomic_read(&hwrng_running_flag) == 1) { + printk("[ExyRNG] exyswd_rng_suspend: hwrng_running_flag is 1.\n"); + ret = -EFAULT; + goto out; } - spin_unlock_irqrestore(&hwrandom_lock, flag); + + atomic_set(&hwrng_suspend_flag, 1); +out: + spin_unlock_irqrestore(&rng_running_lock, flag); return ret; } static int exyswd_rng_resume(struct device *dev) { - uint64_t reg0; - uint64_t reg1; - uint64_t reg2; - uint64_t reg3; unsigned long flag; - int ret = HWRNG_RET_OK; - - spin_lock_irqsave(&hwrandom_lock, flag); -#if defined(CONFIG_EXYRNG_FIPS_COMPLIANCE) - reg0 = SMC_CMD_RANDOM; - reg1 = HWRNG_RESUME; - reg2 = 0; - reg3 = 0; - - ret = exynos_cm_smc(®0, ®1, ®2, ®3); - if (ret != HWRNG_RET_OK) - printk("[ExyRNG] failed to resume with %d\n", ret); -#endif - if (hwrng_read_flag) { - reg0 = SMC_CMD_RANDOM; - reg1 = HWRNG_INIT; - reg2 = 0; - reg3 = 0; - ret = exynos_cm_smc(®0, ®1, ®2, ®3); - if (ret != HWRNG_RET_OK) - printk("[ExyRNG] failed to resume with %d\n", ret); - } - spin_unlock_irqrestore(&hwrandom_lock, flag); + spin_lock_irqsave(&rng_running_lock, flag); + atomic_set(&hwrng_suspend_flag, 0); + spin_unlock_irqrestore(&rng_running_lock, flag); - return ret; + return HWRNG_RET_OK; } #endif