| From 049aa7f7dd1a94c5ccdc241e227d16db8642bc34 Mon Sep 17 00:00:00 2001 |
| From: Mikulas Patocka <mpatocka@redhat.com> |
| Date: Wed, 17 Jun 2020 09:48:56 -0400 |
| Subject: [PATCH] crypto: cpt - don't sleep of CRYPTO_TFM_REQ_MAY_SLEEP was not |
| specified |
| |
| commit 9e27c99104707f083dccd3b4d79762859b5a0614 upstream. |
| |
| There is this call chain: |
| cvm_encrypt -> cvm_enc_dec -> cptvf_do_request -> process_request -> kzalloc |
| where we call sleeping allocator function even if CRYPTO_TFM_REQ_MAY_SLEEP |
| was not specified. |
| |
| Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> |
| Cc: stable@vger.kernel.org # v4.11+ |
| Fixes: c694b233295b ("crypto: cavium - Add the Virtual Function driver for CPT") |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/crypto/cavium/cpt/cptvf_algs.c b/drivers/crypto/cavium/cpt/cptvf_algs.c |
| index e9f4704494fb..10fd8f314c1c 100644 |
| --- a/drivers/crypto/cavium/cpt/cptvf_algs.c |
| +++ b/drivers/crypto/cavium/cpt/cptvf_algs.c |
| @@ -201,6 +201,7 @@ static inline int cvm_enc_dec(struct ablkcipher_request *req, u32 enc) |
| int status; |
| |
| memset(req_info, 0, sizeof(struct cpt_request_info)); |
| + req_info->may_sleep = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) != 0; |
| memset(fctx, 0, sizeof(struct fc_context)); |
| create_input_list(req, enc, enc_iv_len); |
| create_output_list(req, enc_iv_len); |
| diff --git a/drivers/crypto/cavium/cpt/cptvf_reqmanager.c b/drivers/crypto/cavium/cpt/cptvf_reqmanager.c |
| index 7a24019356b5..e343249c8d05 100644 |
| --- a/drivers/crypto/cavium/cpt/cptvf_reqmanager.c |
| +++ b/drivers/crypto/cavium/cpt/cptvf_reqmanager.c |
| @@ -133,7 +133,7 @@ static inline int setup_sgio_list(struct cpt_vf *cptvf, |
| |
| /* Setup gather (input) components */ |
| g_sz_bytes = ((req->incnt + 3) / 4) * sizeof(struct sglist_component); |
| - info->gather_components = kzalloc(g_sz_bytes, GFP_KERNEL); |
| + info->gather_components = kzalloc(g_sz_bytes, req->may_sleep ? GFP_KERNEL : GFP_ATOMIC); |
| if (!info->gather_components) { |
| ret = -ENOMEM; |
| goto scatter_gather_clean; |
| @@ -150,7 +150,7 @@ static inline int setup_sgio_list(struct cpt_vf *cptvf, |
| |
| /* Setup scatter (output) components */ |
| s_sz_bytes = ((req->outcnt + 3) / 4) * sizeof(struct sglist_component); |
| - info->scatter_components = kzalloc(s_sz_bytes, GFP_KERNEL); |
| + info->scatter_components = kzalloc(s_sz_bytes, req->may_sleep ? GFP_KERNEL : GFP_ATOMIC); |
| if (!info->scatter_components) { |
| ret = -ENOMEM; |
| goto scatter_gather_clean; |
| @@ -167,7 +167,7 @@ static inline int setup_sgio_list(struct cpt_vf *cptvf, |
| |
| /* Create and initialize DPTR */ |
| info->dlen = g_sz_bytes + s_sz_bytes + SG_LIST_HDR_SIZE; |
| - info->in_buffer = kzalloc(info->dlen, GFP_KERNEL); |
| + info->in_buffer = kzalloc(info->dlen, req->may_sleep ? GFP_KERNEL : GFP_ATOMIC); |
| if (!info->in_buffer) { |
| ret = -ENOMEM; |
| goto scatter_gather_clean; |
| @@ -195,7 +195,7 @@ static inline int setup_sgio_list(struct cpt_vf *cptvf, |
| } |
| |
| /* Create and initialize RPTR */ |
| - info->out_buffer = kzalloc(COMPLETION_CODE_SIZE, GFP_KERNEL); |
| + info->out_buffer = kzalloc(COMPLETION_CODE_SIZE, req->may_sleep ? GFP_KERNEL : GFP_ATOMIC); |
| if (!info->out_buffer) { |
| ret = -ENOMEM; |
| goto scatter_gather_clean; |
| @@ -421,7 +421,7 @@ int process_request(struct cpt_vf *cptvf, struct cpt_request_info *req) |
| struct cpt_vq_command vq_cmd; |
| union cpt_inst_s cptinst; |
| |
| - info = kzalloc(sizeof(*info), GFP_KERNEL); |
| + info = kzalloc(sizeof(*info), req->may_sleep ? GFP_KERNEL : GFP_ATOMIC); |
| if (unlikely(!info)) { |
| dev_err(&pdev->dev, "Unable to allocate memory for info_buffer\n"); |
| return -ENOMEM; |
| @@ -443,7 +443,7 @@ int process_request(struct cpt_vf *cptvf, struct cpt_request_info *req) |
| * Get buffer for union cpt_res_s response |
| * structure and its physical address |
| */ |
| - info->completion_addr = kzalloc(sizeof(union cpt_res_s), GFP_KERNEL); |
| + info->completion_addr = kzalloc(sizeof(union cpt_res_s), req->may_sleep ? GFP_KERNEL : GFP_ATOMIC); |
| if (unlikely(!info->completion_addr)) { |
| dev_err(&pdev->dev, "Unable to allocate memory for completion_addr\n"); |
| ret = -ENOMEM; |
| diff --git a/drivers/crypto/cavium/cpt/request_manager.h b/drivers/crypto/cavium/cpt/request_manager.h |
| index 3514b082eca7..1e8dd9ebcc17 100644 |
| --- a/drivers/crypto/cavium/cpt/request_manager.h |
| +++ b/drivers/crypto/cavium/cpt/request_manager.h |
| @@ -62,6 +62,8 @@ struct cpt_request_info { |
| union ctrl_info ctrl; /* User control information */ |
| struct cptvf_request req; /* Request Information (Core specific) */ |
| |
| + bool may_sleep; |
| + |
| struct buf_ptr in[MAX_BUF_CNT]; |
| struct buf_ptr out[MAX_BUF_CNT]; |
| |
| -- |
| 2.27.0 |
| |