From 03a6f29000fdc13adc2bb2e22efd07a51d334154 Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Wed, 16 Mar 2016 09:02:26 -0500 Subject: crypto: ccp - fix lock acquisition code This patch simplifies an unneeded read-write lock. Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/crypto') diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c index 336e5b780fcb..4dbc18727235 100644 --- a/drivers/crypto/ccp/ccp-dev.c +++ b/drivers/crypto/ccp/ccp-dev.c @@ -53,7 +53,7 @@ static DEFINE_RWLOCK(ccp_unit_lock); static LIST_HEAD(ccp_units); /* Round-robin counter */ -static DEFINE_RWLOCK(ccp_rr_lock); +static DEFINE_SPINLOCK(ccp_rr_lock); static struct ccp_device *ccp_rr; /* Ever-increasing value to produce unique unit numbers */ @@ -128,14 +128,14 @@ static struct ccp_device *ccp_get_device(void) */ read_lock_irqsave(&ccp_unit_lock, flags); if (!list_empty(&ccp_units)) { - write_lock_irqsave(&ccp_rr_lock, flags); + spin_lock(&ccp_rr_lock); dp = ccp_rr; if (list_is_last(&ccp_rr->entry, &ccp_units)) ccp_rr = list_first_entry(&ccp_units, struct ccp_device, entry); else ccp_rr = list_next_entry(ccp_rr, entry); - write_unlock_irqrestore(&ccp_rr_lock, flags); + spin_unlock(&ccp_rr_lock); } read_unlock_irqrestore(&ccp_unit_lock, flags); -- cgit v1.2.1 From 7850c91b175d765f09cea3a02a20c7779c79c11d Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 17 Mar 2016 10:21:34 +0100 Subject: crypto: marvell/cesa - fix memory leak Crypto requests are not guaranteed to be finalized (->final() call), and can be freed at any moment, without getting any notification from the core. This can lead to memory leaks of the ->cache buffer. Make this buffer part of the request object, and allocate an extra buffer from the DMA cache pool when doing DMA operations. As a side effect, this patch also fixes another bug related to cache allocation and DMA operations. When the core allocates a new request and import an existing state, a cache buffer can be allocated (depending on the state). The problem is, at that very moment, we don't know yet whether the request will use DMA or not, and since everything is likely to be initialized to zero, mv_cesa_ahash_alloc_cache() thinks it should allocate a buffer for standard operation. But when mv_cesa_ahash_free_cache() is called, req->type has been set to CESA_DMA_REQ in the meantime, thus leading to an invalind dma_pool_free() call (the buffer passed in argument has not been allocated from the pool). Signed-off-by: Boris Brezillon Reported-by: Gregory CLEMENT Signed-off-by: Herbert Xu --- drivers/crypto/marvell/cesa.h | 3 +- drivers/crypto/marvell/hash.c | 86 +++++++++---------------------------------- 2 files changed, 20 insertions(+), 69 deletions(-) (limited to 'drivers/crypto') diff --git a/drivers/crypto/marvell/cesa.h b/drivers/crypto/marvell/cesa.h index bd985e72520b..74071e45ada0 100644 --- a/drivers/crypto/marvell/cesa.h +++ b/drivers/crypto/marvell/cesa.h @@ -588,6 +588,7 @@ struct mv_cesa_ahash_dma_req { struct mv_cesa_tdma_req base; u8 *padding; dma_addr_t padding_dma; + u8 *cache; dma_addr_t cache_dma; }; @@ -609,7 +610,7 @@ struct mv_cesa_ahash_req { struct mv_cesa_ahash_std_req std; } req; struct mv_cesa_op_ctx op_tmpl; - u8 *cache; + u8 cache[CESA_MAX_HASH_BLOCK_SIZE]; unsigned int cache_ptr; u64 len; int src_nents; diff --git a/drivers/crypto/marvell/hash.c b/drivers/crypto/marvell/hash.c index 683cca9ac3c4..f07c1fa31d1a 100644 --- a/drivers/crypto/marvell/hash.c +++ b/drivers/crypto/marvell/hash.c @@ -45,69 +45,25 @@ mv_cesa_ahash_req_iter_next_op(struct mv_cesa_ahash_dma_iter *iter) return mv_cesa_req_dma_iter_next_op(&iter->base); } -static inline int mv_cesa_ahash_dma_alloc_cache(struct mv_cesa_ahash_req *creq, - gfp_t flags) +static inline int +mv_cesa_ahash_dma_alloc_cache(struct mv_cesa_ahash_dma_req *req, gfp_t flags) { - struct mv_cesa_ahash_dma_req *dreq = &creq->req.dma; - - creq->cache = dma_pool_alloc(cesa_dev->dma->cache_pool, flags, - &dreq->cache_dma); - if (!creq->cache) - return -ENOMEM; - - return 0; -} - -static inline int mv_cesa_ahash_std_alloc_cache(struct mv_cesa_ahash_req *creq, - gfp_t flags) -{ - creq->cache = kzalloc(CESA_MAX_HASH_BLOCK_SIZE, flags); - if (!creq->cache) + req->cache = dma_pool_alloc(cesa_dev->dma->cache_pool, flags, + &req->cache_dma); + if (!req->cache) return -ENOMEM; return 0; } -static int mv_cesa_ahash_alloc_cache(struct ahash_request *req) -{ - struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); - gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? - GFP_KERNEL : GFP_ATOMIC; - int ret; - - if (creq->cache) - return 0; - - if (creq->req.base.type == CESA_DMA_REQ) - ret = mv_cesa_ahash_dma_alloc_cache(creq, flags); - else - ret = mv_cesa_ahash_std_alloc_cache(creq, flags); - - return ret; -} - -static inline void mv_cesa_ahash_dma_free_cache(struct mv_cesa_ahash_req *creq) -{ - dma_pool_free(cesa_dev->dma->cache_pool, creq->cache, - creq->req.dma.cache_dma); -} - -static inline void mv_cesa_ahash_std_free_cache(struct mv_cesa_ahash_req *creq) -{ - kfree(creq->cache); -} - -static void mv_cesa_ahash_free_cache(struct mv_cesa_ahash_req *creq) +static inline void +mv_cesa_ahash_dma_free_cache(struct mv_cesa_ahash_dma_req *req) { - if (!creq->cache) + if (!req->cache) return; - if (creq->req.base.type == CESA_DMA_REQ) - mv_cesa_ahash_dma_free_cache(creq); - else - mv_cesa_ahash_std_free_cache(creq); - - creq->cache = NULL; + dma_pool_free(cesa_dev->dma->cache_pool, req->cache, + req->cache_dma); } static int mv_cesa_ahash_dma_alloc_padding(struct mv_cesa_ahash_dma_req *req, @@ -146,6 +102,7 @@ static inline void mv_cesa_ahash_dma_cleanup(struct ahash_request *req) struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); dma_unmap_sg(cesa_dev->dev, req->src, creq->src_nents, DMA_TO_DEVICE); + mv_cesa_ahash_dma_free_cache(&creq->req.dma); mv_cesa_dma_cleanup(&creq->req.dma.base); } @@ -161,8 +118,6 @@ static void mv_cesa_ahash_last_cleanup(struct ahash_request *req) { struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); - mv_cesa_ahash_free_cache(creq); - if (creq->req.base.type == CESA_DMA_REQ) mv_cesa_ahash_dma_last_cleanup(req); } @@ -445,14 +400,6 @@ static inline int mv_cesa_ahash_cra_init(struct crypto_tfm *tfm) static int mv_cesa_ahash_cache_req(struct ahash_request *req, bool *cached) { struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); - int ret; - - if (((creq->cache_ptr + req->nbytes) & CESA_HASH_BLOCK_SIZE_MSK) && - !creq->last_req) { - ret = mv_cesa_ahash_alloc_cache(req); - if (ret) - return ret; - } if (creq->cache_ptr + req->nbytes < 64 && !creq->last_req) { *cached = true; @@ -505,10 +452,17 @@ mv_cesa_ahash_dma_add_cache(struct mv_cesa_tdma_chain *chain, gfp_t flags) { struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma; + int ret; if (!creq->cache_ptr) return 0; + ret = mv_cesa_ahash_dma_alloc_cache(ahashdreq, flags); + if (ret) + return ret; + + memcpy(ahashdreq->cache, creq->cache, creq->cache_ptr); + return mv_cesa_dma_add_data_transfer(chain, CESA_SA_DATA_SRAM_OFFSET, ahashdreq->cache_dma, @@ -848,10 +802,6 @@ static int mv_cesa_ahash_import(struct ahash_request *req, const void *hash, if (!cache_ptr) return 0; - ret = mv_cesa_ahash_alloc_cache(req); - if (ret) - return ret; - memcpy(creq->cache, cache, cache_ptr); creq->cache_ptr = cache_ptr; -- cgit v1.2.1 From b0ef51067cb4fa51867ede1bac1d58b3dfb42f31 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 17 Mar 2016 10:21:35 +0100 Subject: crypto: marvell/cesa - initialize hash states ->export() might be called before we have done an update operation, and in this case the ->state field is left uninitialized. Put the correct default value when initializing the request. Signed-off-by: Boris Brezillon Signed-off-by: Herbert Xu --- drivers/crypto/marvell/hash.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/crypto') diff --git a/drivers/crypto/marvell/hash.c b/drivers/crypto/marvell/hash.c index f07c1fa31d1a..7ca2e0f9dc2e 100644 --- a/drivers/crypto/marvell/hash.c +++ b/drivers/crypto/marvell/hash.c @@ -810,9 +810,14 @@ static int mv_cesa_ahash_import(struct ahash_request *req, const void *hash, static int mv_cesa_md5_init(struct ahash_request *req) { + struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); struct mv_cesa_op_ctx tmpl = { }; mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_MD5); + creq->state[0] = MD5_H0; + creq->state[1] = MD5_H1; + creq->state[2] = MD5_H2; + creq->state[3] = MD5_H3; mv_cesa_ahash_init(req, &tmpl, true); @@ -873,9 +878,15 @@ struct ahash_alg mv_md5_alg = { static int mv_cesa_sha1_init(struct ahash_request *req) { + struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); struct mv_cesa_op_ctx tmpl = { }; mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA1); + creq->state[0] = SHA1_H0; + creq->state[1] = SHA1_H1; + creq->state[2] = SHA1_H2; + creq->state[3] = SHA1_H3; + creq->state[4] = SHA1_H4; mv_cesa_ahash_init(req, &tmpl, false); @@ -936,9 +947,18 @@ struct ahash_alg mv_sha1_alg = { static int mv_cesa_sha256_init(struct ahash_request *req) { + struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); struct mv_cesa_op_ctx tmpl = { }; mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA256); + creq->state[0] = SHA256_H0; + creq->state[1] = SHA256_H1; + creq->state[2] = SHA256_H2; + creq->state[3] = SHA256_H3; + creq->state[4] = SHA256_H4; + creq->state[5] = SHA256_H5; + creq->state[6] = SHA256_H6; + creq->state[7] = SHA256_H7; mv_cesa_ahash_init(req, &tmpl, false); -- cgit v1.2.1 From dfe97ad30e8c038261663a18b9e04b8b5bc07bea Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 17 Mar 2016 10:47:10 +0100 Subject: crypto: marvell/cesa - forward devm_ioremap_resource() error code Forward devm_ioremap_resource() error code instead of returning -ENOMEM. Signed-off-by: Boris Brezillon Reported-by: Russell King - ARM Linux Fixes: f63601fd616a ("crypto: marvell/cesa - add a new driver for Marvell's CESA") Cc: # 4.2+ Signed-off-by: Herbert Xu --- drivers/crypto/marvell/cesa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/crypto') diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c index 0643e3366e33..310f4337a859 100644 --- a/drivers/crypto/marvell/cesa.c +++ b/drivers/crypto/marvell/cesa.c @@ -420,7 +420,7 @@ static int mv_cesa_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); cesa->regs = devm_ioremap_resource(dev, res); if (IS_ERR(cesa->regs)) - return -ENOMEM; + return PTR_ERR(cesa->regs); ret = mv_cesa_dev_dma_init(cesa); if (ret) -- cgit v1.2.1