This patch series adds i.MX6 support to the Freescale CAAM driver. Please use
these patches with the understanding that changes may occur. The patches are
provided for review at this time, in order to incur comments for permanent
inclusion.
Modifications include:
- explicit cache coherency support in the driver
- register I/O primitive support
- clocking support
- scatter/gather entry modifications
- DMA fixes
- RNG buffer cache alignment fix
These patches have been tested on the i.MX6 and regression tested
on QorIQ platforms.
Fix a "Trying to vfree() nonexistent vm area" error when unloading the CAAM
controller module by providing the correct pointer value to iounmap().
Signed-off-by: Victoria Milhoan <[email protected]>
---
drivers/crypto/caam/ctrl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 3226eb8..8a4b239 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -301,7 +301,7 @@ static int caam_remove(struct platform_device *pdev)
#endif
/* Unmap controller region */
- iounmap(&ctrl);
+ iounmap(ctrl);
#ifdef CONFIG_ARM
/* shut clocks off before finalizing shutdown */
@@ -577,7 +577,7 @@ static int caam_probe(struct platform_device *pdev)
sizeof(struct platform_device *) * rspec,
GFP_KERNEL);
if (ctrlpriv->jrpdev == NULL) {
- iounmap(&ctrl);
+ iounmap(ctrl);
return -ENOMEM;
}
--
2.1.4
Move the dma unmap calls for data to occur before printing the data in
debug print statements.
Signed-off-by: Victoria Milhoan <[email protected]>
---
drivers/crypto/caam/caamalg.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 29071a1..291a1a7 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -2234,6 +2234,11 @@ static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
edesc = (struct aead_edesc *)((char *)desc -
offsetof(struct aead_edesc, hw_desc));
+ if (err)
+ caam_jr_strstatus(jrdev, err);
+
+ aead_unmap(jrdev, edesc, req);
+
#ifdef DEBUG
print_hex_dump(KERN_ERR, "dstiv @"__stringify(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4, req->iv,
@@ -2243,11 +2248,6 @@ static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
req->cryptlen - ctx->authsize, 1);
#endif
- if (err)
- caam_jr_strstatus(jrdev, err);
-
- aead_unmap(jrdev, edesc, req);
-
/*
* verify hw auth check passed else return -EBADMSG
*/
@@ -2292,6 +2292,8 @@ static void ablkcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
if (err)
caam_jr_strstatus(jrdev, err);
+ ablkcipher_unmap(jrdev, edesc, req);
+
#ifdef DEBUG
print_hex_dump(KERN_ERR, "dstiv @"__stringify(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4, req->info,
@@ -2301,7 +2303,6 @@ static void ablkcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
edesc->dst_nents > 1 ? 100 : req->nbytes, 1);
#endif
- ablkcipher_unmap(jrdev, edesc, req);
kfree(edesc);
ablkcipher_request_complete(req, err);
@@ -2324,6 +2325,8 @@ static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
if (err)
caam_jr_strstatus(jrdev, err);
+ ablkcipher_unmap(jrdev, edesc, req);
+
#ifdef DEBUG
print_hex_dump(KERN_ERR, "dstiv @"__stringify(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4, req->info,
@@ -2333,7 +2336,6 @@ static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
edesc->dst_nents > 1 ? 100 : req->nbytes, 1);
#endif
- ablkcipher_unmap(jrdev, edesc, req);
kfree(edesc);
ablkcipher_request_complete(req, err);
--
2.1.4
From: Steve Cornelius <[email protected]>
Multiple function in asynchronous hashing use a saved-state block,
a.k.a. struct caam_hash_state, which holds a stash of information
between requests (init/update/final). Certain values in this state
block are loaded for processing using an inline-if, and when this
is done, the potential for uninitialized data can pose conflicts.
Therefore, this patch improves initialization of state data to
prevent false assignments using uninitialized data in the state block.
This patch addresses the following traceback, originating in
ahash_final_ctx(), although a problem like this could certainly
exhibit other symptoms:
kernel BUG at arch/arm/mm/dma-mapping.c:465!
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = 80004000
[00000000] *pgd=00000000
Internal error: Oops: 805 [#1] PREEMPT SMP
Modules linked in:
CPU: 0 Not tainted (3.0.15-01752-gdd441b9-dirty #40)
PC is at __bug+0x1c/0x28
LR is at __bug+0x18/0x28
pc : [<80043240>] lr : [<8004323c>] psr: 60000013
sp : e423fd98 ip : 60000013 fp : 0000001c
r10: e4191b84 r9 : 00000020 r8 : 00000009
r7 : 88005038 r6 : 00000001 r5 : 2d676572 r4 : e4191a60
r3 : 00000000 r2 : 00000001 r1 : 60000093 r0 : 00000033
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
Control: 10c53c7d Table: 1000404a DAC: 00000015
Process cryptomgr_test (pid: 1306, stack limit = 0xe423e2f0)
Stack: (0xe423fd98 to 0xe4240000)
fd80: 11807fd1 80048544
fda0: 88005000 e4191a00 e5178040 8039dda0 00000000 00000014 2d676572 e4191008
fdc0: 88005018 e4191a60 00100100 e4191a00 00000000 8039ce0c e423fea8 00000007
fde0: e4191a00 e4227000 e5178000 8039ce18 e419183c 80203808 80a94a44 00000006
fe00: 00000000 80207180 00000000 00000006 e423ff08 00000000 00000007 e5178000
fe20: e41918a4 80a949b4 8c4844e2 00000000 00000049 74227000 8c4844e2 00000e90
fe40: 0000000e 74227e90 ffff8c58 80ac29e0 e423fed4 8006a350 8c81625c e423ff5c
fe60: 00008576 e4002500 00000003 00030010 e4002500 00000003 e5180000 e4002500
fe80: e5178000 800e6d24 007fffff 00000000 00000010 e4001280 e4002500 60000013
fea0: 000000d0 804df078 00000000 00000000 00000000 00000000 00000000 00000000
fec0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
fee0: 00000000 00000000 e4227000 e4226000 e4753000 e4752000 e40a5000 e40a4000
ff00: e41e7000 e41e6000 00000000 00000000 00000000 e423ff14 e423ff14 00000000
ff20: 00000400 804f9080 e5178000 e4db0b40 00000000 e4db0b80 0000047c 00000400
ff40: 00000000 8020758c 00000400 ffffffff 0000008a 00000000 e4db0b40 80206e00
ff60: e4049dbc 00000000 00000000 00000003 e423ffa4 80062978 e41a8bfc 00000000
ff80: 00000000 e4049db4 00000013 e4049db0 00000013 00000000 00000000 00000000
ffa0: e4db0b40 e4db0b40 80204cbc 00000013 00000000 00000000 00000000 80204cfc
ffc0: e4049da0 80089544 80040a40 00000000 e4db0b40 00000000 00000000 00000000
ffe0: e423ffe0 e423ffe0 e4049da0 800894c4 80040a40 80040a40 00000000 00000000
[<80043240>] (__bug+0x1c/0x28) from [<80048544>] (___dma_single_dev_to_cpu+0x84)
[<80048544>] (___dma_single_dev_to_cpu+0x84/0x94) from [<8039dda0>] (ahash_fina)
[<8039dda0>] (ahash_final_ctx+0x180/0x428) from [<8039ce18>] (ahash_final+0xc/0)
[<8039ce18>] (ahash_final+0xc/0x10) from [<80203808>] (crypto_ahash_op+0x28/0xc)
[<80203808>] (crypto_ahash_op+0x28/0xc0) from [<80207180>] (test_hash+0x214/0x5)
[<80207180>] (test_hash+0x214/0x5b8) from [<8020758c>] (alg_test_hash+0x68/0x8c)
[<8020758c>] (alg_test_hash+0x68/0x8c) from [<80206e00>] (alg_test+0x7c/0x1b8)
[<80206e00>] (alg_test+0x7c/0x1b8) from [<80204cfc>] (cryptomgr_test+0x40/0x48)
[<80204cfc>] (cryptomgr_test+0x40/0x48) from [<80089544>] (kthread+0x80/0x88)
[<80089544>] (kthread+0x80/0x88) from [<80040a40>] (kernel_thread_exit+0x0/0x8)
Code: e59f0010 e1a01003 eb126a8d e3a03000 (e5833000)
---[ end trace d52a403a1d1eaa86 ]---
Signed-off-by: Steve Cornelius <[email protected]>
Signed-off-by: Victoria Milhoan <[email protected]>
---
drivers/crypto/caam/caamhash.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 1662c65..f2f1e87 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -1552,6 +1552,8 @@ static int ahash_init(struct ahash_request *req)
state->current_buf = 0;
state->buf_dma = 0;
+ state->buflen_0 = 0;
+ state->buflen_1 = 0;
return 0;
}
--
2.1.4
Modify the Scatter-Gather entry definitions for the Freescale
CAAM driver.
Signed-off-by: Victoria Milhoan <[email protected]>
---
drivers/crypto/caam/desc.h | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index d397ff9..67e3c89 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -8,13 +8,29 @@
#ifndef DESC_H
#define DESC_H
+/*
+ * 16-byte hardware scatter/gather table
+ * An 8-byte table exists in the hardware spec, but has never been
+ * implemented to date. The 8/16 option is selected at RTL-compile-time.
+ * and this selection is visible in the Compile Time Parameters Register
+ */
+
+#define SEC4_SG_LEN_EXT 0x80000000 /* Entry points to table */
+#define SEC4_SG_LEN_FIN 0x40000000 /* Last ent in table */
+#define SEC4_SG_BPID_MASK 0x000000ff
+#define SEC4_SG_BPID_SHIFT 16
+#define SEC4_SG_LEN_MASK 0x3fffffff /* Excludes EXT and FINAL */
+#define SEC4_SG_OFFS_MASK 0x00001fff
+
struct sec4_sg_entry {
+#ifdef CONFIG_64BIT
u64 ptr;
-#define SEC4_SG_LEN_FIN 0x40000000
-#define SEC4_SG_LEN_EXT 0x80000000
+#else
+ u32 reserved;
+ u32 ptr;
+#endif
u32 len;
- u8 reserved;
- u8 buf_pool_id;
+ u16 buf_pool_id;
u16 offset;
};
--
2.1.4
From: Steve Cornelius <[email protected]>
The hwrng output buffers (2) are cast inside of a a struct (caam_rng_ctx)
allocated in one DMA-tagged region. While the kernel's heap allocator
should place the overall struct on a cacheline aligned boundary, the 2
buffers contained within may not necessarily align. Consenquently, the ends
of unaligned buffers may not fully flush, and if so, stale data will be left
behind, resulting in small repeating patterns.
This fix aligns the buffers inside the struct.
Note that not all of the data inside caam_rng_ctx necessarily needs to be
DMA-tagged, only the buffers themselves require this. However, a fix would
incur the expense of error-handling bloat in the case of allocation failure.
Signed-off-by: Steve Cornelius <[email protected]>
Signed-off-by: Victoria Milhoan <[email protected]>
---
drivers/crypto/caam/caamrng.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
index a8c4af9..dbec737 100644
--- a/drivers/crypto/caam/caamrng.c
+++ b/drivers/crypto/caam/caamrng.c
@@ -56,7 +56,7 @@
/* Buffer, its dma address and lock */
struct buf_data {
- u8 buf[RN_BUF_SIZE];
+ u8 buf[RN_BUF_SIZE] ____cacheline_aligned;
dma_addr_t addr;
struct completion filled;
u32 hw_desc[DESC_JOB_O_LEN];
--
2.1.4
The CAAM driver uses two data buffers to store data for a hashing operation,
with one buffer defined as active. This change forces switching of the
active buffer when executing a hashing operation to avoid a later DMA unmap
using the length of the opposite buffer.
Signed-off-by: Victoria Milhoan <[email protected]>
---
drivers/crypto/caam/caamhash.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index f2f1e87..6720332 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -843,17 +843,17 @@ static int ahash_update_ctx(struct ahash_request *req)
src_map_to_sec4_sg(jrdev, req->src, src_nents,
edesc->sec4_sg + sec4_sg_src_index,
chained);
- if (*next_buflen) {
+ if (*next_buflen)
scatterwalk_map_and_copy(next_buf, req->src,
to_hash - *buflen,
*next_buflen, 0);
- state->current_buf = !state->current_buf;
- }
} else {
(edesc->sec4_sg + sec4_sg_src_index - 1)->len |=
SEC4_SG_LEN_FIN;
}
+ state->current_buf = !state->current_buf;
+
sh_len = desc_len(sh_desc);
desc = edesc->hw_desc;
init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER |
@@ -1276,9 +1276,10 @@ static int ahash_update_no_ctx(struct ahash_request *req)
scatterwalk_map_and_copy(next_buf, req->src,
to_hash - *buflen,
*next_buflen, 0);
- state->current_buf = !state->current_buf;
}
+ state->current_buf = !state->current_buf;
+
sh_len = desc_len(sh_desc);
desc = edesc->hw_desc;
init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER |
--
2.1.4
From: Steve Cornelius <[email protected]>
Allow CAAM to be selected in the kernel for Freescale i.MX6 devices if
ARCH_MXC is enabled.
Signed-off-by: Steve Cornelius <[email protected]>
Signed-off-by: Victoria Milhoan <[email protected]>
---
drivers/crypto/caam/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index e7555ff..bc9aa07 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -1,6 +1,6 @@
config CRYPTO_DEV_FSL_CAAM
tristate "Freescale CAAM-Multicore driver backend"
- depends on FSL_SOC
+ depends on FSL_SOC || ARCH_MXC
help
Enables the driver module for Freescale's Cryptographic Accelerator
and Assurance Module (CAAM), also known as the SEC version 4 (SEC4).
--
2.1.4
Freescale i.MX6 ARM platforms do not support hardware cache coherency. This
patch adds cache coherency support to the CAAM driver.
Signed-off-by: Victoria Milhoan <[email protected]>
---
drivers/crypto/caam/caamhash.c | 28 +++++++++++++++++----------
drivers/crypto/caam/caamrng.c | 10 +++++++++-
drivers/crypto/caam/jr.c | 42 +++++++++++++++++++++++++++++++++++++++-
drivers/crypto/caam/key_gen.c | 4 +++-
drivers/crypto/caam/sg_sw_sec4.h | 1 +
5 files changed, 72 insertions(+), 13 deletions(-)
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index ba0532e..1662c65 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -500,6 +500,7 @@ static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
#endif
}
dma_unmap_single(jrdev, src_dma, *keylen, DMA_TO_DEVICE);
+ dma_sync_single_for_cpu(jrdev, dst_dma, digestsize, DMA_FROM_DEVICE);
dma_unmap_single(jrdev, dst_dma, digestsize, DMA_FROM_DEVICE);
*keylen = digestsize;
@@ -608,8 +609,11 @@ static inline void ahash_unmap(struct device *dev,
if (edesc->src_nents)
dma_unmap_sg_chained(dev, req->src, edesc->src_nents,
DMA_TO_DEVICE, edesc->chained);
- if (edesc->dst_dma)
+ if (edesc->dst_dma) {
+ dma_sync_single_for_cpu(dev, edesc->dst_dma, dst_len,
+ DMA_FROM_DEVICE);
dma_unmap_single(dev, edesc->dst_dma, dst_len, DMA_FROM_DEVICE);
+ }
if (edesc->sec4_sg_bytes)
dma_unmap_single(dev, edesc->sec4_sg_dma,
@@ -624,8 +628,12 @@ static inline void ahash_unmap_ctx(struct device *dev,
struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
struct caam_hash_state *state = ahash_request_ctx(req);
- if (state->ctx_dma)
+ if (state->ctx_dma) {
+ if ((flag == DMA_FROM_DEVICE) || (flag == DMA_BIDIRECTIONAL))
+ dma_sync_single_for_cpu(dev, state->ctx_dma,
+ ctx->ctx_len, flag);
dma_unmap_single(dev, state->ctx_dma, ctx->ctx_len, flag);
+ }
ahash_unmap(dev, edesc, req, dst_len);
}
@@ -807,7 +815,7 @@ static int ahash_update_ctx(struct ahash_request *req)
* allocate space for base edesc and hw desc commands,
* link tables
*/
- edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
sec4_sg_bytes, GFP_DMA | flags);
if (!edesc) {
dev_err(jrdev,
@@ -918,7 +926,7 @@ static int ahash_final_ctx(struct ahash_request *req)
sec4_sg_bytes = (1 + (buflen ? 1 : 0)) * sizeof(struct sec4_sg_entry);
/* allocate space for base edesc and hw desc commands, link tables */
- edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
sec4_sg_bytes, GFP_DMA | flags);
if (!edesc) {
dev_err(jrdev, "could not allocate extended descriptor\n");
@@ -1005,7 +1013,7 @@ static int ahash_finup_ctx(struct ahash_request *req)
sizeof(struct sec4_sg_entry);
/* allocate space for base edesc and hw desc commands, link tables */
- edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
sec4_sg_bytes, GFP_DMA | flags);
if (!edesc) {
dev_err(jrdev, "could not allocate extended descriptor\n");
@@ -1091,7 +1099,7 @@ static int ahash_digest(struct ahash_request *req)
sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry);
/* allocate space for base edesc and hw desc commands, link tables */
- edesc = kmalloc(sizeof(struct ahash_edesc) + sec4_sg_bytes +
+ edesc = kzalloc(sizeof(struct ahash_edesc) + sec4_sg_bytes +
DESC_JOB_IO_LEN, GFP_DMA | flags);
if (!edesc) {
dev_err(jrdev, "could not allocate extended descriptor\n");
@@ -1165,7 +1173,7 @@ static int ahash_final_no_ctx(struct ahash_request *req)
int sh_len;
/* allocate space for base edesc and hw desc commands, link tables */
- edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN,
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN,
GFP_DMA | flags);
if (!edesc) {
dev_err(jrdev, "could not allocate extended descriptor\n");
@@ -1245,7 +1253,7 @@ static int ahash_update_no_ctx(struct ahash_request *req)
* allocate space for base edesc and hw desc commands,
* link tables
*/
- edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
sec4_sg_bytes, GFP_DMA | flags);
if (!edesc) {
dev_err(jrdev,
@@ -1352,7 +1360,7 @@ static int ahash_finup_no_ctx(struct ahash_request *req)
sizeof(struct sec4_sg_entry);
/* allocate space for base edesc and hw desc commands, link tables */
- edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
sec4_sg_bytes, GFP_DMA | flags);
if (!edesc) {
dev_err(jrdev, "could not allocate extended descriptor\n");
@@ -1447,7 +1455,7 @@ static int ahash_update_first(struct ahash_request *req)
* allocate space for base edesc and hw desc commands,
* link tables
*/
- edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
sec4_sg_bytes, GFP_DMA | flags);
if (!edesc) {
dev_err(jrdev,
diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
index 26a544b..a8c4af9 100644
--- a/drivers/crypto/caam/caamrng.c
+++ b/drivers/crypto/caam/caamrng.c
@@ -80,9 +80,12 @@ static struct caam_rng_ctx *rng_ctx;
static inline void rng_unmap_buf(struct device *jrdev, struct buf_data *bd)
{
- if (bd->addr)
+ if (bd->addr) {
+ dma_sync_single_for_cpu(jrdev, bd->addr, RN_BUF_SIZE,
+ DMA_FROM_DEVICE);
dma_unmap_single(jrdev, bd->addr, RN_BUF_SIZE,
DMA_FROM_DEVICE);
+ }
}
static inline void rng_unmap_ctx(struct caam_rng_ctx *ctx)
@@ -108,6 +111,10 @@ static void rng_done(struct device *jrdev, u32 *desc, u32 err, void *context)
atomic_set(&bd->empty, BUF_NOT_EMPTY);
complete(&bd->filled);
+
+ /* Buffer refilled, invalidate cache */
+ dma_sync_single_for_cpu(jrdev, bd->addr, RN_BUF_SIZE, DMA_FROM_DEVICE);
+
#ifdef DEBUG
print_hex_dump(KERN_ERR, "rng refreshed buf@: ",
DUMP_PREFIX_ADDRESS, 16, 4, bd->buf, RN_BUF_SIZE, 1);
@@ -211,6 +218,7 @@ static inline int rng_create_sh_desc(struct caam_rng_ctx *ctx)
print_hex_dump(KERN_ERR, "rng shdesc@: ", DUMP_PREFIX_ADDRESS, 16, 4,
desc, desc_bytes(desc), 1);
#endif
+
return 0;
}
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index b8b5d47..a693bf7 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -168,6 +168,9 @@ static void caam_jr_dequeue(unsigned long devarg)
void (*usercall)(struct device *dev, u32 *desc, u32 status, void *arg);
u32 *userdesc, userstatus;
void *userarg;
+ dma_addr_t outbusaddr;
+
+ outbusaddr = rd_reg64(&jrp->rregs->outring_base);
while (rd_reg32(&jrp->rregs->outring_used)) {
@@ -177,10 +180,19 @@ static void caam_jr_dequeue(unsigned long devarg)
sw_idx = tail = jrp->tail;
hw_idx = jrp->out_ring_read_index;
+ dma_sync_single_for_cpu(dev, outbusaddr,
+ sizeof(struct jr_outentry) * JOBR_DEPTH,
+ DMA_FROM_DEVICE);
for (i = 0; CIRC_CNT(head, tail + i, JOBR_DEPTH) >= 1; i++) {
sw_idx = (tail + i) & (JOBR_DEPTH - 1);
+ /*
+ * Ensure that tail is read before using it as part of
+ * the index into the software ring.
+ */
+ smp_read_barrier_depends();
+
if (jrp->outring[hw_idx].desc ==
jrp->entinfo[sw_idx].desc_addr_dma)
break; /* found */
@@ -202,6 +214,13 @@ static void caam_jr_dequeue(unsigned long devarg)
userdesc = jrp->entinfo[sw_idx].desc_addr_virt;
userstatus = jrp->outring[hw_idx].jrstatus;
+ /*
+ * Make sure all information from the job has been obtained
+ * before telling CAAM that the job has been removed from the
+ * output ring.
+ */
+ smp_mb();
+
/* set done */
wr_reg32(&jrp->rregs->outring_rmvd, 1);
@@ -216,6 +235,12 @@ static void caam_jr_dequeue(unsigned long devarg)
if (sw_idx == tail) {
do {
tail = (tail + 1) & (JOBR_DEPTH - 1);
+
+ /*
+ * Ensure that tail is read before using it to
+ * update the software ring's tail index
+ */
+ smp_read_barrier_depends();
} while (CIRC_CNT(head, tail, JOBR_DEPTH) >= 1 &&
jrp->entinfo[tail].desc_addr_dma == 0);
@@ -321,7 +346,7 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
struct caam_jrentry_info *head_entry;
int head, tail, desc_size;
- dma_addr_t desc_dma;
+ dma_addr_t desc_dma, inpbusaddr;
desc_size = (*desc & HDR_JD_LENGTH_MASK) * sizeof(u32);
desc_dma = dma_map_single(dev, desc, desc_size, DMA_TO_DEVICE);
@@ -330,6 +355,11 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
return -EIO;
}
+ inpbusaddr = rd_reg64(&jrp->rregs->inpring_base);
+ dma_sync_single_for_device(dev, inpbusaddr,
+ sizeof(dma_addr_t) * JOBR_DEPTH,
+ DMA_TO_DEVICE);
+
spin_lock_bh(&jrp->inplock);
head = jrp->head;
@@ -351,12 +381,22 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
jrp->inpring[jrp->inp_ring_write_index] = desc_dma;
+ dma_sync_single_for_device(dev, inpbusaddr,
+ sizeof(dma_addr_t) * JOBR_DEPTH,
+ DMA_TO_DEVICE);
+
smp_wmb();
jrp->inp_ring_write_index = (jrp->inp_ring_write_index + 1) &
(JOBR_DEPTH - 1);
jrp->head = (head + 1) & (JOBR_DEPTH - 1);
+ /*
+ * Ensure that all job information has been written before
+ * notifying CAAM that a new job was added to the input ring.
+ */
+ wmb();
+
wr_reg32(&jrp->rregs->inpring_jobadd, 1);
spin_unlock_bh(&jrp->inplock);
diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c
index e1eaf4f..6481f71 100644
--- a/drivers/crypto/caam/key_gen.c
+++ b/drivers/crypto/caam/key_gen.c
@@ -71,6 +71,7 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
}
init_job_desc(desc, 0);
+
append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG);
/* Sets MDHA up into an HMAC-INIT */
@@ -111,7 +112,8 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
split_key_pad_len, 1);
#endif
}
-
+ dma_sync_single_for_cpu(jrdev, dma_addr_out, split_key_pad_len,
+ DMA_FROM_DEVICE);
dma_unmap_single(jrdev, dma_addr_out, split_key_pad_len,
DMA_FROM_DEVICE);
out_unmap_in:
diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h
index 3b91821..6365585 100644
--- a/drivers/crypto/caam/sg_sw_sec4.h
+++ b/drivers/crypto/caam/sg_sw_sec4.h
@@ -98,6 +98,7 @@ static int dma_map_sg_chained(struct device *dev, struct scatterlist *sg,
} else {
dma_map_sg(dev, sg, nents, dir);
}
+
return nents;
}
--
2.1.4
ARM-based systems may disable clocking to the CAAM device on the
Freescale i.MX platform for power management purposes. This patch
enables the required clocks when the CAAM module is initialized and
disables the required clocks when the CAAM module is shut down.
Signed-off-by: Victoria Milhoan <[email protected]>
---
drivers/crypto/caam/compat.h | 4 +++
drivers/crypto/caam/ctrl.c | 81 ++++++++++++++++++++++++++++++++++++++++++++
drivers/crypto/caam/intern.h | 7 ++++
3 files changed, 92 insertions(+)
diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h
index acd7743..3148985 100644
--- a/drivers/crypto/caam/compat.h
+++ b/drivers/crypto/caam/compat.h
@@ -23,6 +23,10 @@
#include <linux/types.h>
#include <linux/debugfs.h>
#include <linux/circ_buf.h>
+
+#ifdef CONFIG_ARM /* needs the clock control subsystem */
+#include <linux/clk.h>
+#endif
#include <net/xfrm.h>
#include <crypto/algapi.h>
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index efba4cc..3226eb8 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -303,6 +303,14 @@ static int caam_remove(struct platform_device *pdev)
/* Unmap controller region */
iounmap(&ctrl);
+#ifdef CONFIG_ARM
+ /* shut clocks off before finalizing shutdown */
+ clk_disable_unprepare(ctrlpriv->caam_ipg);
+ clk_disable_unprepare(ctrlpriv->caam_mem);
+ clk_disable_unprepare(ctrlpriv->caam_aclk);
+ clk_disable_unprepare(ctrlpriv->caam_emi_slow);
+#endif
+
return ret;
}
@@ -408,6 +416,79 @@ static int caam_probe(struct platform_device *pdev)
ctrlpriv->pdev = pdev;
nprop = pdev->dev.of_node;
+/*
+ * ARM targets tend to have clock control subsystems that can
+ * enable/disable clocking to our device. Turn clocking on to proceed
+ */
+#ifdef CONFIG_ARM
+ ctrlpriv->caam_ipg = devm_clk_get(&pdev->dev, "caam_ipg");
+ if (IS_ERR(ctrlpriv->caam_ipg)) {
+ ret = PTR_ERR(ctrlpriv->caam_ipg);
+ dev_err(&pdev->dev,
+ "can't identify CAAM ipg clk: %d\n", ret);
+ return -ENODEV;
+ }
+
+ ctrlpriv->caam_mem = devm_clk_get(&pdev->dev, "caam_mem");
+ if (IS_ERR(ctrlpriv->caam_mem)) {
+ ret = PTR_ERR(ctrlpriv->caam_mem);
+ dev_err(&pdev->dev,
+ "can't identify CAAM secure mem clk: %d\n", ret);
+ return -ENODEV;
+ }
+
+ ctrlpriv->caam_aclk = devm_clk_get(&pdev->dev, "caam_aclk");
+ if (IS_ERR(ctrlpriv->caam_aclk)) {
+ ret = PTR_ERR(ctrlpriv->caam_aclk);
+ dev_err(&pdev->dev,
+ "can't identify CAAM aclk clk: %d\n", ret);
+ return -ENODEV;
+ }
+
+ ctrlpriv->caam_emi_slow = devm_clk_get(&pdev->dev, "caam_emi_slow");
+ if (IS_ERR(ctrlpriv->caam_emi_slow)) {
+ ret = PTR_ERR(ctrlpriv->caam_emi_slow);
+ dev_err(&pdev->dev,
+ "can't identify CAAM emi slow clk: %d\n", ret);
+ return -ENODEV;
+ }
+
+ ret = clk_prepare_enable(ctrlpriv->caam_ipg);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can't enable CAAM ipg clock: %d\n", ret);
+ return -ENODEV;
+ }
+
+ ret = clk_prepare_enable(ctrlpriv->caam_mem);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can't enable CAAM secure mem clock: %d\n",
+ ret);
+ return -ENODEV;
+ }
+
+ ret = clk_prepare_enable(ctrlpriv->caam_aclk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can't enable CAAM aclk clock: %d\n", ret);
+ return -ENODEV;
+ }
+
+ ret = clk_prepare_enable(ctrlpriv->caam_emi_slow);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n",
+ ret);
+ return -ENODEV;
+ }
+
+ dev_info(dev, "%s caam_ipg clock:%d\n", __func__,
+ (int)clk_get_rate(ctrlpriv->caam_ipg));
+ dev_info(dev, "%s caam_mem clock:%d\n", __func__,
+ (int)clk_get_rate(ctrlpriv->caam_mem));
+ dev_info(dev, "%s caam_aclk clock:%d\n", __func__,
+ (int)clk_get_rate(ctrlpriv->caam_aclk));
+ dev_info(dev, "%s caam_emi_slow clock:%d\n", __func__,
+ (int)clk_get_rate(ctrlpriv->caam_emi_slow));
+#endif
+
/* Get configuration properties from device tree */
/* First, get register page */
ctrl = of_iomap(nprop, 0);
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 89b94cc..54f82dd 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -91,6 +91,13 @@ struct caam_drv_private {
Handles of the RNG4 block are initialized
by this driver */
+#ifdef CONFIG_ARM
+ struct clk *caam_ipg;
+ struct clk *caam_mem;
+ struct clk *caam_aclk;
+ struct clk *caam_emi_slow;
+#endif
+
/*
* debugfs entries for developer view into driver/device
* variables at runtime.
--
2.1.4
From: Steve Cornelius <[email protected]>
Add appropriate read/write register handling to support ARM/Little Endian
devices.
Add set/clear 32-bit primitives for compatibility with ARM devices since
the primitives were previously only defined for the Power architecture.
Signed-off-by: Steve Cornelius <[email protected]>
[<[email protected]>: Edit to accomodate __BIG_ENDIAN and __LITTLE_ENDIAN changes]
Signed-off-by: Victoria Milhoan <[email protected]>
---
drivers/crypto/caam/regs.h | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 378ddc1..9cca14e 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -74,17 +74,23 @@
#endif
#else
#ifdef __LITTLE_ENDIAN
-#define wr_reg32(reg, data) __raw_writel(data, reg)
-#define rd_reg32(reg) __raw_readl(reg)
+#define wr_reg32(reg, data) writel(data, reg)
+#define rd_reg32(reg) readl(reg)
#ifdef CONFIG_64BIT
-#define wr_reg64(reg, data) __raw_writeq(data, reg)
-#define rd_reg64(reg) __raw_readq(reg)
+#define wr_reg64(reg, data) writeq(data, reg)
+#define rd_reg64(reg) readq(reg)
#endif
#endif
#endif
+#ifdef CONFIG_ARM
+/* These are common macros for Power, put here for ARM */
+#define setbits32(_addr, _v) writel((readl(_addr) | (_v)), (_addr))
+#define clrbits32(_addr, _v) writel((readl(_addr) & ~(_v)), (_addr))
+#endif
+
#ifndef CONFIG_64BIT
-#ifdef __BIG_ENDIAN
+#if defined(__BIG_ENDIAN) || defined(CONFIG_ARCH_MXC)
static inline void wr_reg64(u64 __iomem *reg, u64 data)
{
wr_reg32((u32 __iomem *)reg, (data & 0xffffffff00000000ull) >> 32);
--
2.1.4
Add cache coherency support to the CAAM scatterlist implementation.
Signed-off-by: Victoria Milhoan <[email protected]>
---
drivers/crypto/caam/sg_sw_sec4.h | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h
index 6365585..6730b01 100644
--- a/drivers/crypto/caam/sg_sw_sec4.h
+++ b/drivers/crypto/caam/sg_sw_sec4.h
@@ -91,9 +91,14 @@ static int dma_map_sg_chained(struct device *dev, struct scatterlist *sg,
{
if (unlikely(chained)) {
int i;
+ struct scatterlist *tsg = sg;
+
+ /* We use a local copy of the sg pointer to avoid moving the
+ * head of the list pointed to by sg as we wall the list.
+ */
for (i = 0; i < nents; i++) {
- dma_map_sg(dev, sg, 1, dir);
- sg = sg_next(sg);
+ dma_map_sg(dev, tsg, 1, dir);
+ tsg = scatterwalk_sg_next(tsg);
}
} else {
dma_map_sg(dev, sg, nents, dir);
@@ -106,6 +111,9 @@ static int dma_unmap_sg_chained(struct device *dev, struct scatterlist *sg,
unsigned int nents, enum dma_data_direction dir,
bool chained)
{
+ if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))
+ dma_sync_sg_for_cpu(dev, sg, nents, dir);
+
if (unlikely(chained)) {
int i;
for (i = 0; i < nents; i++) {
--
2.1.4
On Mon, Jun 15, 2015 at 04:52:48PM -0700, Victoria Milhoan wrote:
> This patch series adds i.MX6 support to the Freescale CAAM driver. Please use
> these patches with the understanding that changes may occur. The patches are
> provided for review at this time, in order to incur comments for permanent
> inclusion.
How timely :) Please have a look at this thread and chime in if
you wish to add anything:
https://www.mail-archive.com/[email protected]/msg14890.html
Thanks,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On Mon, Jun 15, 2015 at 04:52:49PM -0700, Victoria Milhoan wrote:
>
> @@ -177,10 +180,19 @@ static void caam_jr_dequeue(unsigned long devarg)
>
> sw_idx = tail = jrp->tail;
> hw_idx = jrp->out_ring_read_index;
> + dma_sync_single_for_cpu(dev, outbusaddr,
> + sizeof(struct jr_outentry) * JOBR_DEPTH,
> + DMA_FROM_DEVICE);
>
> for (i = 0; CIRC_CNT(head, tail + i, JOBR_DEPTH) >= 1; i++) {
> sw_idx = (tail + i) & (JOBR_DEPTH - 1);
>
> + /*
> + * Ensure that tail is read before using it as part of
> + * the index into the software ring.
> + */
> + smp_read_barrier_depends();
> +
> if (jrp->outring[hw_idx].desc ==
> jrp->entinfo[sw_idx].desc_addr_dma)
> break; /* found */
smp_read_barrier_depends should be avoided and replaced with RCU
helpers where possible. So what you could do here is mark jrp->tail
as rcu and then use the correct RCU helper to access it which will
do the smp_rad_barrier_depends for you.
Thanks,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On Mon, Jun 15, 2015 at 04:52:49PM -0700, Victoria Milhoan wrote:
>
> @@ -202,6 +214,13 @@ static void caam_jr_dequeue(unsigned long devarg)
> userdesc = jrp->entinfo[sw_idx].desc_addr_virt;
> userstatus = jrp->outring[hw_idx].jrstatus;
>
> + /*
> + * Make sure all information from the job has been obtained
> + * before telling CAAM that the job has been removed from the
> + * output ring.
> + */
> + smp_mb();
So you're not actually guarding against another CPU here, right?
In that case shouldn't this be mb()?
Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On Mon, Jun 15, 2015 at 04:52:49PM -0700, Victoria Milhoan wrote:
> Freescale i.MX6 ARM platforms do not support hardware cache coherency. This
> patch adds cache coherency support to the CAAM driver.
>
> Signed-off-by: Victoria Milhoan <[email protected]>
What about caamalg.c?
> @@ -807,7 +815,7 @@ static int ahash_update_ctx(struct ahash_request *req)
> * allocate space for base edesc and hw desc commands,
> * link tables
> */
> - edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
> + edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
Please put this into a separate patch as it appears to have nothing
to do with the change description.
> @@ -351,12 +381,22 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
>
> jrp->inpring[jrp->inp_ring_write_index] = desc_dma;
>
> + dma_sync_single_for_device(dev, inpbusaddr,
> + sizeof(dma_addr_t) * JOBR_DEPTH,
> + DMA_TO_DEVICE);
> +
> smp_wmb();
While you're at it can you add a comment regarding what this
barrier is meant to protect?
> jrp->inp_ring_write_index = (jrp->inp_ring_write_index + 1) &
> (JOBR_DEPTH - 1);
> jrp->head = (head + 1) & (JOBR_DEPTH - 1);
>
> + /*
> + * Ensure that all job information has been written before
> + * notifying CAAM that a new job was added to the input ring.
> + */
> + wmb();
> +
> wr_reg32(&jrp->rregs->inpring_jobadd, 1);
>
> spin_unlock_bh(&jrp->inplock);
> diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c
> index e1eaf4f..6481f71 100644
> --- a/drivers/crypto/caam/key_gen.c
> +++ b/drivers/crypto/caam/key_gen.c
> @@ -71,6 +71,7 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
> }
>
> init_job_desc(desc, 0);
> +
> append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG);
Please remove this unrelated hunk.
> diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h
> index 3b91821..6365585 100644
> --- a/drivers/crypto/caam/sg_sw_sec4.h
> +++ b/drivers/crypto/caam/sg_sw_sec4.h
> @@ -98,6 +98,7 @@ static int dma_map_sg_chained(struct device *dev, struct scatterlist *sg,
> } else {
> dma_map_sg(dev, sg, nents, dir);
> }
> +
> return nents;
Ditto
Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On Mon, Jun 15, 2015 at 04:52:51PM -0700, Victoria Milhoan wrote:
>
> +#ifdef CONFIG_ARM
> + /* shut clocks off before finalizing shutdown */
> + clk_disable_unprepare(ctrlpriv->caam_ipg);
> + clk_disable_unprepare(ctrlpriv->caam_mem);
> + clk_disable_unprepare(ctrlpriv->caam_aclk);
> + clk_disable_unprepare(ctrlpriv->caam_emi_slow);
> +#endif
Can we restructure this so that it is always compiled regardless
of architecture? This will reduce the chance of build errors.
You could do this by first of all hiding ctrlpriv->caam_XXX behind
accessor functions, e.g.:
#ifdef CONFIG_ARM
static inline struct clk *caam_drv_get_ipg(struct caam_drv_private *drv)
{
return drv->caam_ipg;
}
static inline void caam_drv_set_ipg(struct caam_drv_private *drv,
struct clk *clk)
{
drv->caam_ipg = clk;
}
#else
static inline struct clk *caam_drv_get_ipg(struct caam_drv_private *drv)
{
return NULL;
}
static inline void caam_drv_set_ipg(struct caam_drv_private *drv,
struct clk *clk)
{
}
#endif
Then you could do
clk_disable_unprepare(caam_drv_get_ipg(ctrlpriv));
> +/*
> + * ARM targets tend to have clock control subsystems that can
> + * enable/disable clocking to our device. Turn clocking on to proceed
> + */
> +#ifdef CONFIG_ARM
> + ctrlpriv->caam_ipg = devm_clk_get(&pdev->dev, "caam_ipg");
> + if (IS_ERR(ctrlpriv->caam_ipg)) {
> + ret = PTR_ERR(ctrlpriv->caam_ipg);
> + dev_err(&pdev->dev,
> + "can't identify CAAM ipg clk: %d\n", ret);
> + return -ENODEV;
> + }
This then becomes:
struct clk *clk;
clk = devm_clk_get(&pdev->dev, "caam_ipg");
if (IS_ERR(clk))
ret = PTR_ERR(clk);
dev_err(&pdev->dev,
"can't identify CAAM ipg clk: %d\n", ret);
return -ENODEV;
}
caam_drv_set_ipg(ctrlpriv, clk);
And it should all compile away on powerpc.
Thanks,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On Mon, Jun 15, 2015 at 04:52:51PM -0700, Victoria Milhoan wrote:
>
> + ret = clk_prepare_enable(ctrlpriv->caam_ipg);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "can't enable CAAM ipg clock: %d\n", ret);
> + return -ENODEV;
> + }
> +
> + ret = clk_prepare_enable(ctrlpriv->caam_mem);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "can't enable CAAM secure mem clock: %d\n",
> + ret);
> + return -ENODEV;
> + }
Shouldn't this disable caam_ipg?
> + ret = clk_prepare_enable(ctrlpriv->caam_aclk);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "can't enable CAAM aclk clock: %d\n", ret);
> + return -ENODEV;
> + }
> +
> + ret = clk_prepare_enable(ctrlpriv->caam_emi_slow);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n",
> + ret);
> + return -ENODEV;
> + }
And these two as well.
Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On Mon, Jun 15, 2015 at 04:52:53PM -0700, Victoria Milhoan wrote:
>
> @@ -91,9 +91,14 @@ static int dma_map_sg_chained(struct device *dev, struct scatterlist *sg,
> {
> if (unlikely(chained)) {
> int i;
> + struct scatterlist *tsg = sg;
> +
> + /* We use a local copy of the sg pointer to avoid moving the
> + * head of the list pointed to by sg as we wall the list.
> + */
> for (i = 0; i < nents; i++) {
> - dma_map_sg(dev, sg, 1, dir);
> - sg = sg_next(sg);
> + dma_map_sg(dev, tsg, 1, dir);
> + tsg = scatterwalk_sg_next(tsg);
Please do not use scatterwalk_sg_next as it is obsolete and is
otherwise identical to sg_next.
Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On Mon, Jun 15, 2015 at 04:52:56PM -0700, Victoria Milhoan wrote:
> From: Steve Cornelius <[email protected]>
>
> Multiple function in asynchronous hashing use a saved-state block,
> a.k.a. struct caam_hash_state, which holds a stash of information
> between requests (init/update/final). Certain values in this state
> block are loaded for processing using an inline-if, and when this
> is done, the potential for uninitialized data can pose conflicts.
> Therefore, this patch improves initialization of state data to
> prevent false assignments using uninitialized data in the state block.
Applied to crypto with stable CC.
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On Mon, Jun 15, 2015 at 04:52:57PM -0700, Victoria Milhoan wrote:
> The CAAM driver uses two data buffers to store data for a hashing operation,
> with one buffer defined as active. This change forces switching of the
> active buffer when executing a hashing operation to avoid a later DMA unmap
> using the length of the opposite buffer.
>
> Signed-off-by: Victoria Milhoan <[email protected]>
Applied.
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On Mon, Jun 15, 2015 at 04:52:58PM -0700, Victoria Milhoan wrote:
> Fix a "Trying to vfree() nonexistent vm area" error when unloading the CAAM
> controller module by providing the correct pointer value to iounmap().
>
> Signed-off-by: Victoria Milhoan <[email protected]>
Applied.
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On Mon, Jun 15, 2015 at 04:52:59PM -0700, Victoria Milhoan wrote:
> From: Steve Cornelius <[email protected]>
>
> The hwrng output buffers (2) are cast inside of a a struct (caam_rng_ctx)
> allocated in one DMA-tagged region. While the kernel's heap allocator
> should place the overall struct on a cacheline aligned boundary, the 2
> buffers contained within may not necessarily align. Consenquently, the ends
> of unaligned buffers may not fully flush, and if so, stale data will be left
> behind, resulting in small repeating patterns.
Applied to crypto with stable CC.
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On Mon, Jun 15, 2015 at 04:52:54PM -0700, Victoria Milhoan wrote:
> From: Steve Cornelius <[email protected]>
>
> Allow CAAM to be selected in the kernel for Freescale i.MX6 devices if
> ARCH_MXC is enabled.
>
> Signed-off-by: Steve Cornelius <[email protected]>
> Signed-off-by: Victoria Milhoan <[email protected]>
> ---
> drivers/crypto/caam/Kconfig | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
> index e7555ff..bc9aa07 100644
> --- a/drivers/crypto/caam/Kconfig
> +++ b/drivers/crypto/caam/Kconfig
> @@ -1,6 +1,6 @@
> config CRYPTO_DEV_FSL_CAAM
> tristate "Freescale CAAM-Multicore driver backend"
> - depends on FSL_SOC
> + depends on FSL_SOC || ARCH_MXC
Is this right? Are there other i.MX that have the CAAM IP core?
Sounds like it should be SOC_IMX6 instead.
Regards,
Steffen
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Mon, Jun 15, 2015 at 04:52:53PM -0700, Victoria Milhoan wrote:
> Add cache coherency support to the CAAM scatterlist implementation.
>
> Signed-off-by: Victoria Milhoan <[email protected]>
> ---
> drivers/crypto/caam/sg_sw_sec4.h | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h
> index 6365585..6730b01 100644
> --- a/drivers/crypto/caam/sg_sw_sec4.h
> +++ b/drivers/crypto/caam/sg_sw_sec4.h
> @@ -91,9 +91,14 @@ static int dma_map_sg_chained(struct device *dev, struct scatterlist *sg,
> {
> if (unlikely(chained)) {
> int i;
> + struct scatterlist *tsg = sg;
> +
> + /* We use a local copy of the sg pointer to avoid moving the
> + * head of the list pointed to by sg as we wall the list.
> + */
> for (i = 0; i < nents; i++) {
> - dma_map_sg(dev, sg, 1, dir);
> - sg = sg_next(sg);
> + dma_map_sg(dev, tsg, 1, dir);
> + tsg = scatterwalk_sg_next(tsg);
> }
> } else {
> dma_map_sg(dev, sg, nents, dir);
> @@ -106,6 +111,9 @@ static int dma_unmap_sg_chained(struct device *dev, struct scatterlist *sg,
> unsigned int nents, enum dma_data_direction dir,
> bool chained)
> {
> + if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))
> + dma_sync_sg_for_cpu(dev, sg, nents, dir);
> +
> if (unlikely(chained)) {
> int i;
> for (i = 0; i < nents; i++) {
You don't need to sync here, because you unmap it directly afterwards.
Regards,
Steffen
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Mon, Jun 15, 2015 at 04:52:49PM -0700, Victoria Milhoan wrote:
> Freescale i.MX6 ARM platforms do not support hardware cache coherency. This
> patch adds cache coherency support to the CAAM driver.
>
> Signed-off-by: Victoria Milhoan <[email protected]>
> ---
> drivers/crypto/caam/caamhash.c | 28 +++++++++++++++++----------
> drivers/crypto/caam/caamrng.c | 10 +++++++++-
> drivers/crypto/caam/jr.c | 42 +++++++++++++++++++++++++++++++++++++++-
> drivers/crypto/caam/key_gen.c | 4 +++-
> drivers/crypto/caam/sg_sw_sec4.h | 1 +
> 5 files changed, 72 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
> index ba0532e..1662c65 100644
> --- a/drivers/crypto/caam/caamhash.c
> +++ b/drivers/crypto/caam/caamhash.c
> @@ -500,6 +500,7 @@ static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
> #endif
> }
> dma_unmap_single(jrdev, src_dma, *keylen, DMA_TO_DEVICE);
> + dma_sync_single_for_cpu(jrdev, dst_dma, digestsize, DMA_FROM_DEVICE);
> dma_unmap_single(jrdev, dst_dma, digestsize, DMA_FROM_DEVICE);
>
> *keylen = digestsize;
> @@ -608,8 +609,11 @@ static inline void ahash_unmap(struct device *dev,
> if (edesc->src_nents)
> dma_unmap_sg_chained(dev, req->src, edesc->src_nents,
> DMA_TO_DEVICE, edesc->chained);
> - if (edesc->dst_dma)
> + if (edesc->dst_dma) {
> + dma_sync_single_for_cpu(dev, edesc->dst_dma, dst_len,
> + DMA_FROM_DEVICE);
> dma_unmap_single(dev, edesc->dst_dma, dst_len, DMA_FROM_DEVICE);
> + }
>
> if (edesc->sec4_sg_bytes)
> dma_unmap_single(dev, edesc->sec4_sg_dma,
> @@ -624,8 +628,12 @@ static inline void ahash_unmap_ctx(struct device *dev,
> struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
> struct caam_hash_state *state = ahash_request_ctx(req);
>
> - if (state->ctx_dma)
> + if (state->ctx_dma) {
> + if ((flag == DMA_FROM_DEVICE) || (flag == DMA_BIDIRECTIONAL))
> + dma_sync_single_for_cpu(dev, state->ctx_dma,
> + ctx->ctx_len, flag);
> dma_unmap_single(dev, state->ctx_dma, ctx->ctx_len, flag);
> + }
> ahash_unmap(dev, edesc, req, dst_len);
> }
Unneeded syncing, dma_unmap does it as long as it is not told otherwise.
(...)
> diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
> index 26a544b..a8c4af9 100644
> --- a/drivers/crypto/caam/caamrng.c
> +++ b/drivers/crypto/caam/caamrng.c
> @@ -80,9 +80,12 @@ static struct caam_rng_ctx *rng_ctx;
>
> static inline void rng_unmap_buf(struct device *jrdev, struct buf_data *bd)
> {
> - if (bd->addr)
> + if (bd->addr) {
> + dma_sync_single_for_cpu(jrdev, bd->addr, RN_BUF_SIZE,
> + DMA_FROM_DEVICE);
> dma_unmap_single(jrdev, bd->addr, RN_BUF_SIZE,
> DMA_FROM_DEVICE);
> + }
> }
>
dito
> static inline void rng_unmap_ctx(struct caam_rng_ctx *ctx)
> @@ -108,6 +111,10 @@ static void rng_done(struct device *jrdev, u32 *desc, u32 err, void *context)
>
> atomic_set(&bd->empty, BUF_NOT_EMPTY);
> complete(&bd->filled);
> +
> + /* Buffer refilled, invalidate cache */
> + dma_sync_single_for_cpu(jrdev, bd->addr, RN_BUF_SIZE, DMA_FROM_DEVICE);
> +
This seems to be okay, though.
> #ifdef DEBUG
> print_hex_dump(KERN_ERR, "rng refreshed buf@: ",
> DUMP_PREFIX_ADDRESS, 16, 4, bd->buf, RN_BUF_SIZE, 1);
> @@ -211,6 +218,7 @@ static inline int rng_create_sh_desc(struct caam_rng_ctx *ctx)
> print_hex_dump(KERN_ERR, "rng shdesc@: ", DUMP_PREFIX_ADDRESS, 16, 4,
> desc, desc_bytes(desc), 1);
> #endif
> +
> return 0;
> }
>
> diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
> index b8b5d47..a693bf7 100644
> --- a/drivers/crypto/caam/jr.c
> +++ b/drivers/crypto/caam/jr.c
> @@ -168,6 +168,9 @@ static void caam_jr_dequeue(unsigned long devarg)
> void (*usercall)(struct device *dev, u32 *desc, u32 status, void *arg);
> u32 *userdesc, userstatus;
> void *userarg;
> + dma_addr_t outbusaddr;
> +
> + outbusaddr = rd_reg64(&jrp->rregs->outring_base);
>
> while (rd_reg32(&jrp->rregs->outring_used)) {
>
> @@ -177,10 +180,19 @@ static void caam_jr_dequeue(unsigned long devarg)
>
> sw_idx = tail = jrp->tail;
> hw_idx = jrp->out_ring_read_index;
> + dma_sync_single_for_cpu(dev, outbusaddr,
> + sizeof(struct jr_outentry) * JOBR_DEPTH,
> + DMA_FROM_DEVICE);
>
This one and ...
(...)
> @@ -321,7 +346,7 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
> struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
> struct caam_jrentry_info *head_entry;
> int head, tail, desc_size;
> - dma_addr_t desc_dma;
> + dma_addr_t desc_dma, inpbusaddr;
>
> desc_size = (*desc & HDR_JD_LENGTH_MASK) * sizeof(u32);
> desc_dma = dma_map_single(dev, desc, desc_size, DMA_TO_DEVICE);
> @@ -330,6 +355,11 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
> return -EIO;
> }
>
> + inpbusaddr = rd_reg64(&jrp->rregs->inpring_base);
> + dma_sync_single_for_device(dev, inpbusaddr,
> + sizeof(dma_addr_t) * JOBR_DEPTH,
> + DMA_TO_DEVICE);
> +
> spin_lock_bh(&jrp->inplock);
>
> head = jrp->head;
> @@ -351,12 +381,22 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
>
> jrp->inpring[jrp->inp_ring_write_index] = desc_dma;
>
> + dma_sync_single_for_device(dev, inpbusaddr,
> + sizeof(dma_addr_t) * JOBR_DEPTH,
> + DMA_TO_DEVICE);
> +
... these one are also unnecessary, because the buffers are mapped with
dma_alloc_coherent.
> smp_wmb();
>
> jrp->inp_ring_write_index = (jrp->inp_ring_write_index + 1) &
> (JOBR_DEPTH - 1);
> jrp->head = (head + 1) & (JOBR_DEPTH - 1);
>
> + /*
> + * Ensure that all job information has been written before
> + * notifying CAAM that a new job was added to the input ring.
> + */
> + wmb();
> +
> wr_reg32(&jrp->rregs->inpring_jobadd, 1);
>
> spin_unlock_bh(&jrp->inplock);
> diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c
> index e1eaf4f..6481f71 100644
> --- a/drivers/crypto/caam/key_gen.c
> +++ b/drivers/crypto/caam/key_gen.c
> @@ -71,6 +71,7 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
> }
>
> init_job_desc(desc, 0);
> +
> append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG);
>
> /* Sets MDHA up into an HMAC-INIT */
> @@ -111,7 +112,8 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
> split_key_pad_len, 1);
> #endif
> }
> -
> + dma_sync_single_for_cpu(jrdev, dma_addr_out, split_key_pad_len,
> + DMA_FROM_DEVICE);
> dma_unmap_single(jrdev, dma_addr_out, split_key_pad_len,
> DMA_FROM_DEVICE);
> out_unmap_in:
unneeded.
Regards,
Steffen
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On 6/17/2015 10:27 AM, Steffen Trumtrar wrote:
> On Mon, Jun 15, 2015 at 04:52:54PM -0700, Victoria Milhoan wrote:
>> From: Steve Cornelius <[email protected]>
>>
>> Allow CAAM to be selected in the kernel for Freescale i.MX6 devices if
>> ARCH_MXC is enabled.
>>
>> Signed-off-by: Steve Cornelius <[email protected]>
>> Signed-off-by: Victoria Milhoan <[email protected]>
>> ---
>> drivers/crypto/caam/Kconfig | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
>> index e7555ff..bc9aa07 100644
>> --- a/drivers/crypto/caam/Kconfig
>> +++ b/drivers/crypto/caam/Kconfig
>> @@ -1,6 +1,6 @@
>> config CRYPTO_DEV_FSL_CAAM
>> tristate "Freescale CAAM-Multicore driver backend"
>> - depends on FSL_SOC
>> + depends on FSL_SOC || ARCH_MXC
>
> Is this right? Are there other i.MX that have the CAAM IP core?
> Sounds like it should be SOC_IMX6 instead.
Even more, not all SOC_IMX6 variants have a CAAM block.
Not sure what's better:
-try to exactly indicate the HW that has the IP
-only name the arch / SoC (provided compilation passes), and then depend
on defconfig and/or device tree (and possibly boot loader dynamically
fixing the DT)
For e.g. Sahara crypto driver also depends on ARCH_MXC and it's not
available on all i.MX SoCs.
Thanks,
Horia
On Fri, Jul 24, 2015 at 08:14:31PM +0300, Horia Geantă wrote:
>
> Even more, not all SOC_IMX6 variants have a CAAM block.
>
> Not sure what's better:
> -try to exactly indicate the HW that has the IP
> -only name the arch / SoC (provided compilation passes), and then depend
> on defconfig and/or device tree (and possibly boot loader dynamically
> fixing the DT)
>
> For e.g. Sahara crypto driver also depends on ARCH_MXC and it's not
> available on all i.MX SoCs.
Kconfig entry dependencies do not have to guarantee the existence
of the device. It only has to guarantee the ability to compile the
code.
Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt