From 7191bc627c7038611663f90c7dd053733bc5586b Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 15 May 2015 16:48:49 +0300 Subject: crypto: caampkc - workaround for erratum A-006899 The problem will occur only in T1040R1. A workaround has been verified; set a Scatter Gather (SG) flag on the Q or G Pointers on KPG, which will give the PKHA unload time to complete. It's sufficient to have the SG flag set for only one of these. Change-Id: I5a403576c6e995110227872c84de7e74da0144c5 Signed-off-by: Tudor Ambarus Reviewed-on: http://git.am.freescale.net:8181/36617 Tested-by: Review Code-CDREVIEW Reviewed-by: Horia Ioan Geanta Neag Reviewed-by: Honghua Yin diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index f98abfb..e9944a4 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -30,6 +30,12 @@ struct caam_pkc_context_s { struct device *dev; }; +struct caam_pkc_alg { + struct list_head entry; + struct device *ctrldev; + struct crypto_alg crypto_alg; +}; + static void rsa_unmap(struct device *dev, struct rsa_edesc *edesc, struct pkc_request *req) { @@ -484,6 +490,10 @@ static int caam_keygen_edesc(struct pkc_request *req, { struct crypto_pkc *tfm = crypto_pkc_reqtfm(req); struct caam_pkc_context_s *ctxt = crypto_pkc_ctx(tfm); + struct crypto_alg *alg = crypto_pkc_tfm(tfm)->__crt_alg; + struct caam_pkc_alg *caam_alg = + container_of(alg, struct caam_pkc_alg, crypto_alg); + struct caam_drv_private *caam_priv = dev_get_drvdata(caam_alg->ctrldev); struct device *dev = ctxt->dev; struct keygen_req_s *key_req = &req->req_u.keygen; @@ -491,6 +501,7 @@ static int caam_keygen_edesc(struct pkc_request *req, edesc->n_len = key_req->r_len; edesc->req_type = req->type; edesc->curve_type = req->curve_type; + edesc->erratum_A_006899 = caam_priv->errata & SEC_ERRATUM_A_006899; edesc->q_dma = dma_map_single(dev, key_req->q, key_req->q_len, DMA_TO_DEVICE); @@ -513,6 +524,20 @@ static int caam_keygen_edesc(struct pkc_request *req, goto g_map_fail; } + if (edesc->erratum_A_006899) { + dma_to_sec4_sg_one(&(edesc->g_sg), edesc->g_dma, + key_req->g_len, 0); + edesc->g_sg.len |= SEC4_SG_LEN_FIN; + + edesc->g_sg_dma = dma_map_single(dev, &(edesc->g_sg), + sizeof(struct sec4_sg_entry), + DMA_TO_DEVICE); + if (dma_mapping_error(dev, edesc->g_sg_dma)) { + dev_err(dev, "unable to map S/G table\n"); + goto g_sg_dma_fail; + } + } + edesc->key_dma = dma_map_single(dev, key_req->pub_key, key_req->pub_key_len, DMA_FROM_DEVICE); if (dma_mapping_error(dev, edesc->key_dma)) { @@ -545,6 +570,10 @@ s_map_fail: dma_unmap_single(dev, edesc->key_dma, key_req->pub_key_len, DMA_FROM_DEVICE); key_map_fail: + if (edesc->erratum_A_006899) + dma_unmap_single(dev, edesc->g_sg_dma, key_req->g_len, + DMA_TO_DEVICE); +g_sg_dma_fail: dma_unmap_single(dev, edesc->g_dma, key_req->g_len, DMA_TO_DEVICE); g_map_fail: dma_unmap_single(dev, edesc->r_dma, key_req->r_len, DMA_TO_DEVICE); @@ -1324,12 +1353,6 @@ static struct caam_pkc_template driver_pkc[] = { } }; -struct caam_pkc_alg { - struct list_head entry; - struct device *ctrldev; - struct crypto_alg crypto_alg; -}; - /* Per session pkc's driver context creation function */ static int caam_pkc_cra_init(struct crypto_tfm *tfm) { diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 7a22427..321deb0 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -480,6 +480,7 @@ static int caam_probe(struct platform_device *pdev) { int ret, ring, rspec; u64 caam_id; + u32 caam_id_ms; struct device *dev; struct device_node *nprop, *np; struct caam_ctrl __iomem *ctrl; @@ -660,7 +661,12 @@ static int caam_probe(struct platform_device *pdev) /* NOTE: RTIC detection ought to go here, around Si time */ ctrlpriv->era = caam_get_era(); - caam_id = (u64)rd_reg32(&ctrl->perfmon.caam_id_ms) << 32 | + + caam_id_ms = rd_reg32(&ctrl->perfmon.caam_id_ms); + if (caam_id_ms == SEC_ID_MS_T1040) + ctrlpriv->errata |= SEC_ERRATUM_A_006899; + + caam_id = (u64)caam_id_ms << 32 | (u64)rd_reg32(&ctrl->perfmon.caam_id_ls); /* Report "alive" for developer to see */ diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h index 43596fe..9faf832 100644 --- a/drivers/crypto/caam/intern.h +++ b/drivers/crypto/caam/intern.h @@ -95,6 +95,11 @@ struct caam_drv_private { struct list_head pkc_list; int era; /* SEC Era */ + +#define SEC_ERRATUM_A_006899 0x01 + /* SEC errata bitmask */ + u32 errata; + int virt_en; /* Virtualization enabled in CAAM */ #define RNG4_MAX_HANDLES 2 diff --git a/drivers/crypto/caam/pkc_desc.c b/drivers/crypto/caam/pkc_desc.c index 5bcf5d3..2e81519 100644 --- a/drivers/crypto/caam/pkc_desc.c +++ b/drivers/crypto/caam/pkc_desc.c @@ -271,10 +271,15 @@ void *caam_keygen_desc(struct dsa_edesc_s *edesc) (start_idx << HDR_START_IDX_SHIFT) | (start_idx & HDR_DESCLEN_MASK) | HDR_ONE); ecc_desc->sgf_ln = (edesc->l_len << DSA_PDB_L_SHIFT) | - ((edesc->n_len & DSA_PDB_N_MASK)); + (edesc->n_len & DSA_PDB_N_MASK); + if (edesc->erratum_A_006899) { + ecc_desc->sgf_ln |= DSA_PDB_SGF_G; + ecc_desc->g_dma = edesc->g_sg_dma; + } else { + ecc_desc->g_dma = edesc->g_dma; + } ecc_desc->q_dma = edesc->q_dma; ecc_desc->r_dma = edesc->r_dma; - ecc_desc->g_dma = edesc->g_dma; ecc_desc->s_dma = edesc->s_dma; ecc_desc->w_dma = edesc->key_dma; ecc_desc->ab_dma = edesc->ab_dma; diff --git a/drivers/crypto/caam/pkc_desc.h b/drivers/crypto/caam/pkc_desc.h index 03013c2..e859e40 100644 --- a/drivers/crypto/caam/pkc_desc.h +++ b/drivers/crypto/caam/pkc_desc.h @@ -20,6 +20,7 @@ #include "desc_constr.h" #include "jr.h" #include "error.h" +#include "sg_sw_sec4.h" #include #include "pdb.h" @@ -187,8 +188,11 @@ struct dsa_edesc_s { dma_addr_t d_dma; dma_addr_t ab_dma; dma_addr_t g_dma; + dma_addr_t g_sg_dma; dma_addr_t tmp_dma; uint8_t *tmp; /* Allocate locally for dsa_verify */ + struct sec4_sg_entry g_sg; + bool erratum_A_006899; u32 hw_desc[]; }; diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h index 928cb53..72193f8 100644 --- a/drivers/crypto/caam/regs.h +++ b/drivers/crypto/caam/regs.h @@ -182,6 +182,8 @@ struct sec_vid { u8 min_rev; }; +#define SEC_ID_MS_T1040 0x0A120400 + struct caam_perfmon { /* Performance Monitor Registers f00-f9f */ u64 req_dequeued; /* PC_REQ_DEQ - Dequeued Requests */ diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h index eef6345..752134c 100644 --- a/drivers/crypto/caam/sg_sw_sec4.h +++ b/drivers/crypto/caam/sg_sw_sec4.h @@ -90,9 +90,9 @@ static inline int sg_count(struct scatterlist *sg_list, int nbytes, return sg_nents; } -static int dma_map_sg_chained(struct device *dev, struct scatterlist *sg, - unsigned int nents, enum dma_data_direction dir, - bool chained) +static int __maybe_unused dma_map_sg_chained(struct device *dev, + struct scatterlist *sg, unsigned int nents, enum dma_data_direction dir, + bool chained) { if (!sg || !nents) return 0; @@ -109,9 +109,9 @@ static int dma_map_sg_chained(struct device *dev, struct scatterlist *sg, return nents; } -static void dma_unmap_sg_chained(struct device *dev, struct scatterlist *sg, - unsigned int nents, enum dma_data_direction dir, - bool chained) +static void __maybe_unused dma_unmap_sg_chained(struct device *dev, + struct scatterlist *sg, unsigned int nents, enum dma_data_direction dir, + bool chained) { if (!sg || !nents) return; -- cgit v0.10.2