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,51 +59,43 @@ void sm_show_page(struct device *dev, struct sm_page_descriptor *pgdesc)
#define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */ #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)
{
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);
} 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);
} else {
return -EINVAL;
}
return 0;
}
static __always_inline u32 sm_get_status_reg(struct caam_drv_private_sm *smpriv,
struct caam_drv_private_jr *jrpriv, 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) { if (smpriv->sm_reg_offset == SM_V1_OFFSET) {
struct caam_secure_mem_v1 *sm_regs_v1; struct caam_secure_mem_v1 *sm_regs_v1;
sm_regs_v1 = (struct caam_secure_mem_v1 *) sm_regs_v1 = (struct caam_secure_mem_v1 *)
((void *)jrpriv->rregs + SM_V1_OFFSET); ((void *)jrpriv->rregs + SM_V1_OFFSET);
*val = rd_reg32(&sm_regs_v1->sm_status); write_address = &sm_regs_v1->sm_cmd;
read_address = &sm_regs_v1->sm_status;
} else if (smpriv->sm_reg_offset == SM_V2_OFFSET) { } else if (smpriv->sm_reg_offset == SM_V2_OFFSET) {
struct caam_secure_mem_v2 *sm_regs_v2; struct caam_secure_mem_v2 *sm_regs_v2;
sm_regs_v2 = (struct caam_secure_mem_v2 *) sm_regs_v2 = (struct caam_secure_mem_v2 *)
((void *)jrpriv->rregs + SM_V2_OFFSET); ((void *)jrpriv->rregs + SM_V2_OFFSET);
*val = rd_reg32(&sm_regs_v2->sm_status); write_address = &sm_regs_v2->sm_cmd;
read_address = &sm_regs_v2->sm_status;
} else { } else {
return -EINVAL; return -EINVAL;
} }
wr_reg32(write_address, cmd);
udelay(10);
/* 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; return 0;
} }
@ -997,6 +989,7 @@ int caam_sm_startup(struct platform_device *pdev)
struct platform_device *sm_pdev; struct platform_device *sm_pdev;
struct sm_page_descriptor *lpagedesc; struct sm_page_descriptor *lpagedesc;
u32 page, pgstat, lpagect, detectedpage, smvid, smpart; u32 page, pgstat, lpagect, detectedpage, smvid, smpart;
int ret = 0;
struct device_node *np; struct device_node *np;
ctrldev = &pdev->dev; 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 * If ctrlpriv is NULL, it's probably because the caam driver wasn't
* properly initialized (e.g. RNG4 init failed). Thus, bail out here. * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
*/ */
if (!ctrlpriv) if (!ctrlpriv) {
return -ENODEV; ret = -ENODEV;
goto exit;
}
/* /*
* Set up the private block for secure memory * 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); smpriv = kzalloc(sizeof(struct caam_drv_private_sm), GFP_KERNEL);
if (smpriv == NULL) { if (smpriv == NULL) {
dev_err(ctrldev, "can't alloc private mem for secure memory\n"); 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 */ smpriv->parentdev = ctrldev; /* copy of parent dev is handy */
spin_lock_init(&smpriv->kslock); 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); sm_pdev = of_platform_device_create(np, "caam_sm", ctrldev);
if (sm_pdev == NULL) { if (sm_pdev == NULL) {
kfree(smpriv); ret = -EINVAL;
return -EINVAL; goto free_smpriv;
} }
/* Save a pointer to the platform device for Secure Memory */ /* 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). * an SM instance to any ring instance).
*/ */
smpriv->smringdev = caam_jr_alloc(); 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); jrpriv = dev_get_drvdata(smpriv->smringdev);
lpagect = 0; lpagect = 0;
pgstat = 0; pgstat = 0;
lpagedesc = kzalloc(sizeof(struct sm_page_descriptor) lpagedesc = kzalloc(sizeof(struct sm_page_descriptor)
* smpriv->max_pages, GFP_KERNEL); * smpriv->max_pages, GFP_KERNEL);
if (lpagedesc == NULL) { if (lpagedesc == NULL) {
kfree(smpriv); ret = -ENOMEM;
return -ENOMEM; goto free_smringdev;
} }
for (page = 0; page < smpriv->max_pages; page++) { for (page = 0; page < smpriv->max_pages; page++) {
if (sm_set_cmd_reg(smpriv, jrpriv, u32 page_ownership;
((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;
if (((pgstat & SMCS_PGWON_MASK) >> SMCS_PGOWN_SHIFT) if (sm_send_cmd(smpriv, jrpriv,
== SMCS_PGOWN_OWNED) { /* our page? */ ((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 = lpagedesc[page].phys_pagenum =
(pgstat & SMCS_PAGE_MASK) >> SMCS_PAGE_SHIFT; (pgstat & SMCS_PAGE_MASK) >> SMCS_PAGE_SHIFT;
lpagedesc[page].own_part = 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, smpriv->pagedesc = kzalloc(sizeof(struct sm_page_descriptor) * lpagect,
GFP_KERNEL); GFP_KERNEL);
if (smpriv->pagedesc == NULL) { if (smpriv->pagedesc == NULL) {
kfree(lpagedesc); ret = -ENOMEM;
kfree(smpriv); goto free_lpagedesc;
return -ENOMEM;
} }
smpriv->localpages = lpagect; smpriv->localpages = lpagect;
@ -1163,7 +1169,19 @@ int caam_sm_startup(struct platform_device *pdev)
sm_init_keystore(smdev); 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) 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); smpriv = dev_get_drvdata(smdev);
caam_jr_free(smpriv->smringdev);
/* Remove Secure Memory Platform Device */ /* Remove Secure Memory Platform Device */
of_device_unregister(smpriv->sm_pdev); of_device_unregister(smpriv->sm_pdev);