mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
msm_rng: Resolve race condition issues
Resolve race condition between initializing the mutex vs hwrng register. Remove the HWRNG FIFO, not required in Software. Change-Id: I9fa3e5c7e2e9e14feb88a4656dcfab7dec3cbd67 Signed-off-by: Dinesh K Garg <dineshg@codeaurora.org>
This commit is contained in:
parent
bb004d0fe3
commit
0382d97866
2 changed files with 40 additions and 25 deletions
|
@ -27,6 +27,7 @@
|
|||
#include <linux/qrng.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/platform_data/qcom_crypto_device.h>
|
||||
|
||||
|
@ -115,10 +116,13 @@ int msm_rng_direct_read(struct msm_rng_device *msm_rng_dev, void *data)
|
|||
unsigned long val;
|
||||
unsigned long *retdata = data;
|
||||
int ret;
|
||||
int failed = 0;
|
||||
|
||||
pdev = msm_rng_dev->pdev;
|
||||
base = msm_rng_dev->base;
|
||||
|
||||
mutex_lock(&msm_rng_dev->rng_lock);
|
||||
|
||||
if (msm_rng_dev->qrng_perf_client) {
|
||||
ret = msm_bus_scale_client_update_request(
|
||||
msm_rng_dev->qrng_perf_client, 1);
|
||||
|
@ -129,13 +133,21 @@ int msm_rng_direct_read(struct msm_rng_device *msm_rng_dev, void *data)
|
|||
ret = clk_prepare_enable(msm_rng_dev->prng_clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to enable clock in callback\n");
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
/* read random data from h/w */
|
||||
do {
|
||||
/* check status bit if data is available */
|
||||
if (!(readl_relaxed(base + PRNG_STATUS_OFFSET) & 0x00000001))
|
||||
break; /* no data to read so just bail */
|
||||
while (!(readl_relaxed(base + PRNG_STATUS_OFFSET)
|
||||
& 0x00000001)) {
|
||||
if (failed == 10) {
|
||||
pr_err("Data not available after retry\n");
|
||||
break;
|
||||
}
|
||||
pr_err("msm_rng:Data not available!\n");
|
||||
msleep_interruptible(10);
|
||||
failed++;
|
||||
}
|
||||
|
||||
/* read FIFO */
|
||||
val = readl_relaxed(base + PRNG_DATA_OUT_OFFSET);
|
||||
|
@ -150,17 +162,17 @@ int msm_rng_direct_read(struct msm_rng_device *msm_rng_dev, void *data)
|
|||
|
||||
/* vote to turn off clock */
|
||||
clk_disable_unprepare(msm_rng_dev->prng_clk);
|
||||
|
||||
err:
|
||||
if (msm_rng_dev->qrng_perf_client) {
|
||||
ret = msm_bus_scale_client_update_request(
|
||||
msm_rng_dev->qrng_perf_client, 0);
|
||||
if (ret)
|
||||
pr_err("bus_scale_client_update_req failed!\n");
|
||||
}
|
||||
mutex_unlock(&msm_rng_dev->rng_lock);
|
||||
|
||||
val = 0L;
|
||||
return currsize;
|
||||
|
||||
}
|
||||
|
||||
static int msm_rng_drbg_read(struct hwrng *rng,
|
||||
|
@ -169,29 +181,25 @@ static int msm_rng_drbg_read(struct hwrng *rng,
|
|||
struct msm_rng_device *msm_rng_dev;
|
||||
struct platform_device *pdev;
|
||||
void __iomem *base;
|
||||
size_t maxsize;
|
||||
size_t currsize = 0;
|
||||
unsigned long val;
|
||||
unsigned long *retdata = data;
|
||||
int ret, ret1;
|
||||
int failed = 0;
|
||||
|
||||
msm_rng_dev = (struct msm_rng_device *)rng->priv;
|
||||
pdev = msm_rng_dev->pdev;
|
||||
base = msm_rng_dev->base;
|
||||
|
||||
|
||||
down(&msm_rng_dev->drbg_sem);
|
||||
|
||||
/* calculate max size bytes to transfer back to caller */
|
||||
maxsize = min_t(size_t, MAX_HW_FIFO_SIZE, max);
|
||||
|
||||
/* no room for word data */
|
||||
if (maxsize < 4)
|
||||
if (max < 4)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&msm_rng_dev->rng_lock);
|
||||
|
||||
/* read random data from CTR-AES based DRBG */
|
||||
if (FIPS140_DRBG_ENABLED == msm_rng_dev->fips140_drbg_enabled) {
|
||||
ret1 = fips_drbg_gen(msm_rng_dev->drbg_ctx, data, maxsize);
|
||||
ret1 = fips_drbg_gen(msm_rng_dev->drbg_ctx, data, max);
|
||||
if (FIPS140_PRNG_ERR == ret1)
|
||||
panic("random number generator generator error.\n");
|
||||
} else
|
||||
|
@ -209,14 +217,21 @@ static int msm_rng_drbg_read(struct hwrng *rng,
|
|||
ret = clk_prepare_enable(msm_rng_dev->prng_clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to enable clock in callback\n");
|
||||
up(&msm_rng_dev->drbg_sem);
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
/* read random data from h/w */
|
||||
do {
|
||||
/* check status bit if data is available */
|
||||
if (!(readl_relaxed(base + PRNG_STATUS_OFFSET) & 0x00000001))
|
||||
break; /* no data to read so just bail */
|
||||
while (!(readl_relaxed(base + PRNG_STATUS_OFFSET)
|
||||
& 0x00000001)) {
|
||||
if (failed == 10) {
|
||||
pr_err("Data not available after retry\n");
|
||||
break;
|
||||
}
|
||||
pr_err("msm_rng:Data not available!\n");
|
||||
msleep_interruptible(10);
|
||||
failed++;
|
||||
}
|
||||
|
||||
/* read FIFO */
|
||||
val = readl_relaxed(base + PRNG_DATA_OUT_OFFSET);
|
||||
|
@ -229,12 +244,12 @@ static int msm_rng_drbg_read(struct hwrng *rng,
|
|||
currsize += 4;
|
||||
|
||||
/* make sure we stay on 32bit boundary */
|
||||
if ((maxsize - currsize) < 4)
|
||||
if ((max - currsize) < 4)
|
||||
break;
|
||||
} while (currsize < maxsize);
|
||||
} while (currsize < max);
|
||||
/* vote to turn off clock */
|
||||
clk_disable_unprepare(msm_rng_dev->prng_clk);
|
||||
|
||||
err:
|
||||
if (msm_rng_dev->qrng_perf_client) {
|
||||
ret = msm_bus_scale_client_update_request(
|
||||
msm_rng_dev->qrng_perf_client, 0);
|
||||
|
@ -242,7 +257,7 @@ static int msm_rng_drbg_read(struct hwrng *rng,
|
|||
pr_err("bus_scale_client_update_req failed!\n");
|
||||
}
|
||||
|
||||
up(&msm_rng_dev->drbg_sem);
|
||||
mutex_unlock(&msm_rng_dev->rng_lock);
|
||||
|
||||
return currsize;
|
||||
}
|
||||
|
@ -502,6 +517,8 @@ static int msm_rng_probe(struct platform_device *pdev)
|
|||
if (error)
|
||||
goto rollback_clk;
|
||||
|
||||
mutex_init(&msm_rng_dev->rng_lock);
|
||||
|
||||
/* register with hwrng framework */
|
||||
msm_rng.priv = (unsigned long) msm_rng_dev;
|
||||
error = hwrng_register(&msm_rng);
|
||||
|
@ -527,8 +544,6 @@ static int msm_rng_probe(struct platform_device *pdev)
|
|||
}
|
||||
cdev_init(&msm_rng_cdev, &msm_rng_fops);
|
||||
|
||||
sema_init(&msm_rng_dev->drbg_sem, 1);
|
||||
|
||||
_first_msm_drbg_init(msm_rng_dev);
|
||||
|
||||
return error;
|
||||
|
|
|
@ -31,7 +31,7 @@ struct msm_rng_device {
|
|||
void __iomem *base;
|
||||
struct clk *prng_clk;
|
||||
uint32_t qrng_perf_client;
|
||||
struct semaphore drbg_sem;
|
||||
struct mutex rng_lock;
|
||||
struct fips_drbg_ctx_s *drbg_ctx;
|
||||
int fips140_drbg_enabled;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue