MLK-17841: crypto: caam: Correct bugs in Secure Memory

This patch perform following modifications:
- Send and receive SM command regrouped in 1 function
- Verify that the JR device to use is valid
- Modification of the error handling in the probe

Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
(Vipul: Fixed merge conflicts)
Signed-off-by: Vipul Kumar <vipul_kumar@mentor.com>
This commit is contained in:
Franck LENORMAND 2018-06-14 18:28:38 +02:00 committed by Leonard Crestez
parent 02bcf5b98b
commit 345ead4338

View File

@ -59,50 +59,42 @@ void sm_show_page(struct device *dev, struct sm_page_descriptor *pgdesc)
#define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */
static __always_inline int sm_set_cmd_reg(struct caam_drv_private_sm *smpriv,
static __always_inline u32 sm_send_cmd(struct caam_drv_private_sm *smpriv,
struct caam_drv_private_jr *jrpriv,
u32 val)
u32 cmd, u32 *status)
{
void __iomem *write_address;
void __iomem *read_address;
if (smpriv->sm_reg_offset == SM_V1_OFFSET) {
struct caam_secure_mem_v1 *sm_regs_v1;
sm_regs_v1 = (struct caam_secure_mem_v1 *)
((void *)jrpriv->rregs + SM_V1_OFFSET);
wr_reg32(&sm_regs_v1->sm_cmd, val);
write_address = &sm_regs_v1->sm_cmd;
read_address = &sm_regs_v1->sm_status;
} else if (smpriv->sm_reg_offset == SM_V2_OFFSET) {
struct caam_secure_mem_v2 *sm_regs_v2;
sm_regs_v2 = (struct caam_secure_mem_v2 *)
((void *)jrpriv->rregs + SM_V2_OFFSET);
wr_reg32(&sm_regs_v2->sm_cmd, val);
write_address = &sm_regs_v2->sm_cmd;
read_address = &sm_regs_v2->sm_status;
} else {
return -EINVAL;
}
return 0;
}
wr_reg32(write_address, cmd);
static __always_inline u32 sm_get_status_reg(struct caam_drv_private_sm *smpriv,
struct caam_drv_private_jr *jrpriv,
u32 *val)
{
if (smpriv->sm_reg_offset == SM_V1_OFFSET) {
struct caam_secure_mem_v1 *sm_regs_v1;
udelay(10);
sm_regs_v1 = (struct caam_secure_mem_v1 *)
((void *)jrpriv->rregs + SM_V1_OFFSET);
*val = rd_reg32(&sm_regs_v1->sm_status);
} else if (smpriv->sm_reg_offset == SM_V2_OFFSET) {
struct caam_secure_mem_v2 *sm_regs_v2;
sm_regs_v2 = (struct caam_secure_mem_v2 *)
((void *)jrpriv->rregs + SM_V2_OFFSET);
*val = rd_reg32(&sm_regs_v2->sm_status);
} else {
return -EINVAL;
}
/* Read until the command has terminated and the status is correct */
do {
*status = rd_reg32(read_address);
} while (((*status & SMCS_CMDERR_MASK) >> SMCS_CMDERR_SHIFT)
== SMCS_CMDERR_INCOMP);
return 0;
}
@ -997,6 +989,7 @@ int caam_sm_startup(struct platform_device *pdev)
struct platform_device *sm_pdev;
struct sm_page_descriptor *lpagedesc;
u32 page, pgstat, lpagect, detectedpage, smvid, smpart;
int ret = 0;
struct device_node *np;
ctrldev = &pdev->dev;
@ -1006,8 +999,10 @@ int caam_sm_startup(struct platform_device *pdev)
* If ctrlpriv is NULL, it's probably because the caam driver wasn't
* properly initialized (e.g. RNG4 init failed). Thus, bail out here.
*/
if (!ctrlpriv)
return -ENODEV;
if (!ctrlpriv) {
ret = -ENODEV;
goto exit;
}
/*
* Set up the private block for secure memory
@ -1016,7 +1011,8 @@ int caam_sm_startup(struct platform_device *pdev)
smpriv = kzalloc(sizeof(struct caam_drv_private_sm), GFP_KERNEL);
if (smpriv == NULL) {
dev_err(ctrldev, "can't alloc private mem for secure memory\n");
return -ENOMEM;
ret = -ENOMEM;
goto exit;
}
smpriv->parentdev = ctrldev; /* copy of parent dev is handy */
spin_lock_init(&smpriv->kslock);
@ -1028,8 +1024,8 @@ int caam_sm_startup(struct platform_device *pdev)
sm_pdev = of_platform_device_create(np, "caam_sm", ctrldev);
if (sm_pdev == NULL) {
kfree(smpriv);
return -EINVAL;
ret = -EINVAL;
goto free_smpriv;
}
/* Save a pointer to the platform device for Secure Memory */
@ -1090,26 +1086,37 @@ int caam_sm_startup(struct platform_device *pdev)
* an SM instance to any ring instance).
*/
smpriv->smringdev = caam_jr_alloc();
if (!smpriv->smringdev) {
dev_err(smdev, "Device for job ring not created\n");
ret = -ENODEV;
goto unregister_smpdev;
}
jrpriv = dev_get_drvdata(smpriv->smringdev);
lpagect = 0;
pgstat = 0;
lpagedesc = kzalloc(sizeof(struct sm_page_descriptor)
* smpriv->max_pages, GFP_KERNEL);
if (lpagedesc == NULL) {
kfree(smpriv);
return -ENOMEM;
ret = -ENOMEM;
goto free_smringdev;
}
for (page = 0; page < smpriv->max_pages; page++) {
if (sm_set_cmd_reg(smpriv, jrpriv,
((page << SMC_PAGE_SHIFT) & SMC_PAGE_MASK) |
(SMC_CMD_PAGE_INQUIRY & SMC_CMD_MASK)))
return -EINVAL;
if (sm_get_status_reg(smpriv, jrpriv, &pgstat))
return -EINVAL;
u32 page_ownership;
if (((pgstat & SMCS_PGWON_MASK) >> SMCS_PGOWN_SHIFT)
== SMCS_PGOWN_OWNED) { /* our page? */
if (sm_send_cmd(smpriv, jrpriv,
((page << SMC_PAGE_SHIFT) & SMC_PAGE_MASK) |
(SMC_CMD_PAGE_INQUIRY & SMC_CMD_MASK),
&pgstat)) {
ret = -EINVAL;
goto free_lpagedesc;
}
page_ownership = (pgstat & SMCS_PGWON_MASK) >> SMCS_PGOWN_SHIFT;
if ((page_ownership == SMCS_PGOWN_OWNED)
|| (page_ownership == SMCS_PGOWN_NOOWN)) {
/* page allocated */
lpagedesc[page].phys_pagenum =
(pgstat & SMCS_PAGE_MASK) >> SMCS_PAGE_SHIFT;
lpagedesc[page].own_part =
@ -1140,9 +1147,8 @@ int caam_sm_startup(struct platform_device *pdev)
smpriv->pagedesc = kzalloc(sizeof(struct sm_page_descriptor) * lpagect,
GFP_KERNEL);
if (smpriv->pagedesc == NULL) {
kfree(lpagedesc);
kfree(smpriv);
return -ENOMEM;
ret = -ENOMEM;
goto free_lpagedesc;
}
smpriv->localpages = lpagect;
@ -1163,7 +1169,19 @@ int caam_sm_startup(struct platform_device *pdev)
sm_init_keystore(smdev);
return 0;
goto exit;
free_lpagedesc:
kfree(lpagedesc);
free_smringdev:
caam_jr_free(smpriv->smringdev);
unregister_smpdev:
of_device_unregister(smpriv->sm_pdev);
free_smpriv:
kfree(smpriv);
exit:
return ret;
}
void caam_sm_shutdown(struct platform_device *pdev)
@ -1182,6 +1200,8 @@ void caam_sm_shutdown(struct platform_device *pdev)
smpriv = dev_get_drvdata(smdev);
caam_jr_free(smpriv->smringdev);
/* Remove Secure Memory Platform Device */
of_device_unregister(smpriv->sm_pdev);