| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- From 8ef8d195430ca3542d0434cf25e5115484b9fa32 Mon Sep 17 00:00:00 2001
- From: Christian Lamparter <[email protected]>
- Date: Wed, 4 Oct 2017 01:00:09 +0200
- Subject: [PATCH 17/25] crypto: crypto4xx - add backlog queue support
- Previously, If the crypto4xx driver used all available
- security contexts, it would simply refuse new requests
- with -EAGAIN. CRYPTO_TFM_REQ_MAY_BACKLOG was ignored.
- in case of dm-crypt.c's crypt_convert() function this was
- causing the following errors to manifest, if the system was
- pushed hard enough:
- | EXT4-fs warning (dm-1): ext4_end_bio:314: I/O error -5 writing to ino ..
- | EXT4-fs warning (dm-1): ext4_end_bio:314: I/O error -5 writing to ino ..
- | EXT4-fs warning (dm-1): ext4_end_bio:314: I/O error -5 writing to ino ..
- | JBD2: Detected IO errors while flushing file data on dm-1-8
- | Aborting journal on device dm-1-8.
- | EXT4-fs error : ext4_journal_check_start:56: Detected aborted journal
- | EXT4-fs (dm-1): Remounting filesystem read-only
- | EXT4-fs : ext4_writepages: jbd2_start: 2048 pages, inode 498...; err -30
- (This did cause corruptions due to failed writes)
- To fix this mess, the crypto4xx driver needs to notifiy the
- user to slow down. This can be achieved by returning -EBUSY
- on requests, once the crypto hardware was falling behind.
- Note: -EBUSY has two different meanings. Setting the flag
- CRYPTO_TFM_REQ_MAY_BACKLOG implies that the request was
- successfully queued, by the crypto driver. To achieve this
- requirement, the implementation introduces a threshold check and
- adds logic to the completion routines in much the same way as
- AMD's Cryptographic Coprocessor (CCP) driver do.
- Note2: Tests showed that dm-crypt starved ipsec traffic.
- Under load, ipsec links dropped to 0 Kbits/s. This is because
- dm-crypt's callback would instantly queue the next request.
- In order to not starve ipsec, the driver reserves a small
- portion of the available crypto contexts for this purpose.
- Signed-off-by: Christian Lamparter <[email protected]>
- Signed-off-by: Herbert Xu <[email protected]>
- ---
- drivers/crypto/amcc/crypto4xx_core.c | 47 ++++++++++++++++++++++++++++++------
- drivers/crypto/amcc/crypto4xx_core.h | 3 ++-
- 2 files changed, 41 insertions(+), 9 deletions(-)
- --- a/drivers/crypto/amcc/crypto4xx_core.c
- +++ b/drivers/crypto/amcc/crypto4xx_core.c
- @@ -39,6 +39,7 @@
- #include <crypto/ctr.h>
- #include <crypto/sha.h>
- #include <crypto/scatterwalk.h>
- +#include <crypto/internal/skcipher.h>
- #include "crypto4xx_reg_def.h"
- #include "crypto4xx_core.h"
- #include "crypto4xx_sa.h"
- @@ -573,8 +574,10 @@ static u32 crypto4xx_ablkcipher_done(str
- dst->offset, dst->length, DMA_FROM_DEVICE);
- }
- crypto4xx_ret_sg_desc(dev, pd_uinfo);
- - if (ablk_req->base.complete != NULL)
- - ablk_req->base.complete(&ablk_req->base, 0);
- +
- + if (pd_uinfo->state & PD_ENTRY_BUSY)
- + ablkcipher_request_complete(ablk_req, -EINPROGRESS);
- + ablkcipher_request_complete(ablk_req, 0);
-
- return 0;
- }
- @@ -591,9 +594,10 @@ static u32 crypto4xx_ahash_done(struct c
- crypto4xx_copy_digest_to_dst(pd_uinfo,
- crypto_tfm_ctx(ahash_req->base.tfm));
- crypto4xx_ret_sg_desc(dev, pd_uinfo);
- - /* call user provided callback function x */
- - if (ahash_req->base.complete != NULL)
- - ahash_req->base.complete(&ahash_req->base, 0);
- +
- + if (pd_uinfo->state & PD_ENTRY_BUSY)
- + ahash_request_complete(ahash_req, -EINPROGRESS);
- + ahash_request_complete(ahash_req, 0);
-
- return 0;
- }
- @@ -704,6 +708,7 @@ u32 crypto4xx_build_pd(struct crypto_asy
- struct pd_uinfo *pd_uinfo = NULL;
- unsigned int nbytes = datalen, idx;
- u32 gd_idx = 0;
- + bool is_busy;
-
- /* figure how many gd is needed */
- num_gd = sg_nents_for_len(src, datalen);
- @@ -734,6 +739,31 @@ u32 crypto4xx_build_pd(struct crypto_asy
- * already got must be return the original place.
- */
- spin_lock_irqsave(&dev->core_dev->lock, flags);
- + /*
- + * Let the caller know to slow down, once more than 13/16ths = 81%
- + * of the available data contexts are being used simultaneously.
- + *
- + * With PPC4XX_NUM_PD = 256, this will leave a "backlog queue" for
- + * 31 more contexts. Before new requests have to be rejected.
- + */
- + if (req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG) {
- + is_busy = ((dev->pdr_head - dev->pdr_tail) % PPC4XX_NUM_PD) >=
- + ((PPC4XX_NUM_PD * 13) / 16);
- + } else {
- + /*
- + * To fix contention issues between ipsec (no blacklog) and
- + * dm-crypto (backlog) reserve 32 entries for "no backlog"
- + * data contexts.
- + */
- + is_busy = ((dev->pdr_head - dev->pdr_tail) % PPC4XX_NUM_PD) >=
- + ((PPC4XX_NUM_PD * 15) / 16);
- +
- + if (is_busy) {
- + spin_unlock_irqrestore(&dev->core_dev->lock, flags);
- + return -EBUSY;
- + }
- + }
- +
- if (num_gd) {
- fst_gd = crypto4xx_get_n_gd(dev, num_gd);
- if (fst_gd == ERING_WAS_FULL) {
- @@ -888,11 +918,12 @@ u32 crypto4xx_build_pd(struct crypto_asy
- sa->sa_command_1.bf.hash_crypto_offset = 0;
- pd->pd_ctl.w = ctx->pd_ctl;
- pd->pd_ctl_len.w = 0x00400000 | datalen;
- - pd_uinfo->state = PD_ENTRY_INUSE;
- + pd_uinfo->state = PD_ENTRY_INUSE | (is_busy ? PD_ENTRY_BUSY : 0);
- +
- wmb();
- /* write any value to push engine to read a pd */
- writel(1, dev->ce_base + CRYPTO4XX_INT_DESCR_RD);
- - return -EINPROGRESS;
- + return is_busy ? -EBUSY : -EINPROGRESS;
- }
-
- /**
- @@ -997,7 +1028,7 @@ static void crypto4xx_bh_tasklet_cb(unsi
- tail = core_dev->dev->pdr_tail;
- pd_uinfo = &core_dev->dev->pdr_uinfo[tail];
- pd = &core_dev->dev->pdr[tail];
- - if ((pd_uinfo->state == PD_ENTRY_INUSE) &&
- + if ((pd_uinfo->state & PD_ENTRY_INUSE) &&
- pd->pd_ctl.bf.pe_done &&
- !pd->pd_ctl.bf.host_ready) {
- pd->pd_ctl.bf.pe_done = 0;
- --- a/drivers/crypto/amcc/crypto4xx_core.h
- +++ b/drivers/crypto/amcc/crypto4xx_core.h
- @@ -44,7 +44,8 @@
- #define PPC4XX_LAST_SD (PPC4XX_NUM_SD - 1)
- #define PPC4XX_SD_BUFFER_SIZE 2048
-
- -#define PD_ENTRY_INUSE 1
- +#define PD_ENTRY_BUSY BIT(1)
- +#define PD_ENTRY_INUSE BIT(0)
- #define PD_ENTRY_FREE 0
- #define ERING_WAS_FULL 0xffffffff
-
|