Skip to content

Commit bf8f91e

Browse files
Romain Perierherbertx
authored andcommitted
crypto: marvell - Add load balancing between engines
This commits adds support for fine grained load balancing on multi-engine IPs. The engine is pre-selected based on its current load and on the weight of the crypto request that is about to be processed. The global crypto queue is also moved to each engine. These changes are required to allow chaining crypto requests at the DMA level. By using a crypto queue per engine, we make sure that we keep the state of the tdma chain synchronized with the crypto queue. We also reduce contention on 'cesa_dev->lock' and improve parallelism. Signed-off-by: Romain Perier <[email protected]> Acked-by: Boris Brezillon <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent 2786cee commit bf8f91e

File tree

4 files changed

+84
-86
lines changed

4 files changed

+84
-86
lines changed

drivers/crypto/marvell/cesa.c

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,14 @@ MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if over
4040

4141
struct mv_cesa_dev *cesa_dev;
4242

43-
static void mv_cesa_dequeue_req_unlocked(struct mv_cesa_engine *engine)
43+
static void mv_cesa_dequeue_req_locked(struct mv_cesa_engine *engine)
4444
{
4545
struct crypto_async_request *req, *backlog;
4646
struct mv_cesa_ctx *ctx;
4747

48-
spin_lock_bh(&cesa_dev->lock);
49-
backlog = crypto_get_backlog(&cesa_dev->queue);
50-
req = crypto_dequeue_request(&cesa_dev->queue);
48+
backlog = crypto_get_backlog(&engine->queue);
49+
req = crypto_dequeue_request(&engine->queue);
5150
engine->req = req;
52-
spin_unlock_bh(&cesa_dev->lock);
5351

5452
if (!req)
5553
return;
@@ -58,7 +56,6 @@ static void mv_cesa_dequeue_req_unlocked(struct mv_cesa_engine *engine)
5856
backlog->complete(backlog, -EINPROGRESS);
5957

6058
ctx = crypto_tfm_ctx(req->tfm);
61-
ctx->ops->prepare(req, engine);
6259
ctx->ops->step(req);
6360
}
6461

@@ -96,7 +93,7 @@ static irqreturn_t mv_cesa_int(int irq, void *priv)
9693
if (res != -EINPROGRESS) {
9794
spin_lock_bh(&engine->lock);
9895
engine->req = NULL;
99-
mv_cesa_dequeue_req_unlocked(engine);
96+
mv_cesa_dequeue_req_locked(engine);
10097
spin_unlock_bh(&engine->lock);
10198
ctx->ops->complete(req);
10299
ctx->ops->cleanup(req);
@@ -116,21 +113,19 @@ int mv_cesa_queue_req(struct crypto_async_request *req,
116113
struct mv_cesa_req *creq)
117114
{
118115
int ret;
119-
int i;
116+
struct mv_cesa_engine *engine = creq->engine;
120117

121-
spin_lock_bh(&cesa_dev->lock);
122-
ret = crypto_enqueue_request(&cesa_dev->queue, req);
123-
spin_unlock_bh(&cesa_dev->lock);
118+
spin_lock_bh(&engine->lock);
119+
ret = crypto_enqueue_request(&engine->queue, req);
120+
spin_unlock_bh(&engine->lock);
124121

125122
if (ret != -EINPROGRESS)
126123
return ret;
127124

128-
for (i = 0; i < cesa_dev->caps->nengines; i++) {
129-
spin_lock_bh(&cesa_dev->engines[i].lock);
130-
if (!cesa_dev->engines[i].req)
131-
mv_cesa_dequeue_req_unlocked(&cesa_dev->engines[i]);
132-
spin_unlock_bh(&cesa_dev->engines[i].lock);
133-
}
125+
spin_lock_bh(&engine->lock);
126+
if (!engine->req)
127+
mv_cesa_dequeue_req_locked(engine);
128+
spin_unlock_bh(&engine->lock);
134129

135130
return -EINPROGRESS;
136131
}
@@ -425,7 +420,7 @@ static int mv_cesa_probe(struct platform_device *pdev)
425420
return -ENOMEM;
426421

427422
spin_lock_init(&cesa->lock);
428-
crypto_init_queue(&cesa->queue, CESA_CRYPTO_DEFAULT_MAX_QLEN);
423+
429424
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
430425
cesa->regs = devm_ioremap_resource(dev, res);
431426
if (IS_ERR(cesa->regs))
@@ -498,6 +493,9 @@ static int mv_cesa_probe(struct platform_device *pdev)
498493
engine);
499494
if (ret)
500495
goto err_cleanup;
496+
497+
crypto_init_queue(&engine->queue, CESA_CRYPTO_DEFAULT_MAX_QLEN);
498+
atomic_set(&engine->load, 0);
501499
}
502500

503501
cesa_dev = cesa;

drivers/crypto/marvell/cesa.h

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,6 @@ struct mv_cesa_dev_dma {
400400
* @regs: device registers
401401
* @sram_size: usable SRAM size
402402
* @lock: device lock
403-
* @queue: crypto request queue
404403
* @engines: array of engines
405404
* @dma: dma pools
406405
*
@@ -412,7 +411,6 @@ struct mv_cesa_dev {
412411
struct device *dev;
413412
unsigned int sram_size;
414413
spinlock_t lock;
415-
struct crypto_queue queue;
416414
struct mv_cesa_engine *engines;
417415
struct mv_cesa_dev_dma *dma;
418416
};
@@ -431,6 +429,8 @@ struct mv_cesa_dev {
431429
* @int_mask: interrupt mask cache
432430
* @pool: memory pool pointing to the memory region reserved in
433431
* SRAM
432+
* @queue: fifo of the pending crypto requests
433+
* @load: engine load counter, useful for load balancing
434434
*
435435
* Structure storing CESA engine information.
436436
*/
@@ -446,11 +446,12 @@ struct mv_cesa_engine {
446446
size_t max_req_len;
447447
u32 int_mask;
448448
struct gen_pool *pool;
449+
struct crypto_queue queue;
450+
atomic_t load;
449451
};
450452

451453
/**
452454
* struct mv_cesa_req_ops - CESA request operations
453-
* @prepare: prepare a request to be executed on the specified engine
454455
* @process: process a request chunk result (should return 0 if the
455456
* operation, -EINPROGRESS if it needs more steps or an error
456457
* code)
@@ -460,8 +461,6 @@ struct mv_cesa_engine {
460461
* needed.
461462
*/
462463
struct mv_cesa_req_ops {
463-
void (*prepare)(struct crypto_async_request *req,
464-
struct mv_cesa_engine *engine);
465464
int (*process)(struct crypto_async_request *req, u32 status);
466465
void (*step)(struct crypto_async_request *req);
467466
void (*cleanup)(struct crypto_async_request *req);
@@ -690,6 +689,26 @@ static inline bool mv_cesa_mac_op_is_first_frag(const struct mv_cesa_op_ctx *op)
690689
int mv_cesa_queue_req(struct crypto_async_request *req,
691690
struct mv_cesa_req *creq);
692691

692+
static inline struct mv_cesa_engine *mv_cesa_select_engine(int weight)
693+
{
694+
int i;
695+
u32 min_load = U32_MAX;
696+
struct mv_cesa_engine *selected = NULL;
697+
698+
for (i = 0; i < cesa_dev->caps->nengines; i++) {
699+
struct mv_cesa_engine *engine = cesa_dev->engines + i;
700+
u32 load = atomic_read(&engine->load);
701+
if (load < min_load) {
702+
min_load = load;
703+
selected = engine;
704+
}
705+
}
706+
707+
atomic_add(weight, &selected->load);
708+
709+
return selected;
710+
}
711+
693712
/*
694713
* Helper function that indicates whether a crypto request needs to be
695714
* cleaned up or not after being enqueued using mv_cesa_queue_req().

drivers/crypto/marvell/cipher.c

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ mv_cesa_ablkcipher_complete(struct crypto_async_request *req)
214214
struct mv_cesa_engine *engine = creq->base.engine;
215215
unsigned int ivsize;
216216

217+
atomic_sub(ablkreq->nbytes, &engine->load);
217218
ivsize = crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(ablkreq));
218219

219220
if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ) {
@@ -231,7 +232,6 @@ mv_cesa_ablkcipher_complete(struct crypto_async_request *req)
231232
static const struct mv_cesa_req_ops mv_cesa_ablkcipher_req_ops = {
232233
.step = mv_cesa_ablkcipher_step,
233234
.process = mv_cesa_ablkcipher_process,
234-
.prepare = mv_cesa_ablkcipher_prepare,
235235
.cleanup = mv_cesa_ablkcipher_req_cleanup,
236236
.complete = mv_cesa_ablkcipher_complete,
237237
};
@@ -456,29 +456,41 @@ static int mv_cesa_ablkcipher_req_init(struct ablkcipher_request *req,
456456
return ret;
457457
}
458458

459-
static int mv_cesa_des_op(struct ablkcipher_request *req,
460-
struct mv_cesa_op_ctx *tmpl)
459+
static int mv_cesa_ablkcipher_queue_req(struct ablkcipher_request *req,
460+
struct mv_cesa_op_ctx *tmpl)
461461
{
462-
struct mv_cesa_ablkcipher_req *creq = ablkcipher_request_ctx(req);
463-
struct mv_cesa_des_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
464462
int ret;
465-
466-
mv_cesa_update_op_cfg(tmpl, CESA_SA_DESC_CFG_CRYPTM_DES,
467-
CESA_SA_DESC_CFG_CRYPTM_MSK);
468-
469-
memcpy(tmpl->ctx.blkcipher.key, ctx->key, DES_KEY_SIZE);
463+
struct mv_cesa_ablkcipher_req *creq = ablkcipher_request_ctx(req);
464+
struct mv_cesa_engine *engine;
470465

471466
ret = mv_cesa_ablkcipher_req_init(req, tmpl);
472467
if (ret)
473468
return ret;
474469

470+
engine = mv_cesa_select_engine(req->nbytes);
471+
mv_cesa_ablkcipher_prepare(&req->base, engine);
472+
475473
ret = mv_cesa_queue_req(&req->base, &creq->base);
474+
476475
if (mv_cesa_req_needs_cleanup(&req->base, ret))
477476
mv_cesa_ablkcipher_cleanup(req);
478477

479478
return ret;
480479
}
481480

481+
static int mv_cesa_des_op(struct ablkcipher_request *req,
482+
struct mv_cesa_op_ctx *tmpl)
483+
{
484+
struct mv_cesa_des_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
485+
486+
mv_cesa_update_op_cfg(tmpl, CESA_SA_DESC_CFG_CRYPTM_DES,
487+
CESA_SA_DESC_CFG_CRYPTM_MSK);
488+
489+
memcpy(tmpl->ctx.blkcipher.key, ctx->key, DES_KEY_SIZE);
490+
491+
return mv_cesa_ablkcipher_queue_req(req, tmpl);
492+
}
493+
482494
static int mv_cesa_ecb_des_encrypt(struct ablkcipher_request *req)
483495
{
484496
struct mv_cesa_op_ctx tmpl;
@@ -580,24 +592,14 @@ struct crypto_alg mv_cesa_cbc_des_alg = {
580592
static int mv_cesa_des3_op(struct ablkcipher_request *req,
581593
struct mv_cesa_op_ctx *tmpl)
582594
{
583-
struct mv_cesa_ablkcipher_req *creq = ablkcipher_request_ctx(req);
584595
struct mv_cesa_des3_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
585-
int ret;
586596

587597
mv_cesa_update_op_cfg(tmpl, CESA_SA_DESC_CFG_CRYPTM_3DES,
588598
CESA_SA_DESC_CFG_CRYPTM_MSK);
589599

590600
memcpy(tmpl->ctx.blkcipher.key, ctx->key, DES3_EDE_KEY_SIZE);
591601

592-
ret = mv_cesa_ablkcipher_req_init(req, tmpl);
593-
if (ret)
594-
return ret;
595-
596-
ret = mv_cesa_queue_req(&req->base, &creq->base);
597-
if (mv_cesa_req_needs_cleanup(&req->base, ret))
598-
mv_cesa_ablkcipher_cleanup(req);
599-
600-
return ret;
602+
return mv_cesa_ablkcipher_queue_req(req, tmpl);
601603
}
602604

603605
static int mv_cesa_ecb_des3_ede_encrypt(struct ablkcipher_request *req)
@@ -707,9 +709,8 @@ struct crypto_alg mv_cesa_cbc_des3_ede_alg = {
707709
static int mv_cesa_aes_op(struct ablkcipher_request *req,
708710
struct mv_cesa_op_ctx *tmpl)
709711
{
710-
struct mv_cesa_ablkcipher_req *creq = ablkcipher_request_ctx(req);
711712
struct mv_cesa_aes_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
712-
int ret, i;
713+
int i;
713714
u32 *key;
714715
u32 cfg;
715716

@@ -732,15 +733,7 @@ static int mv_cesa_aes_op(struct ablkcipher_request *req,
732733
CESA_SA_DESC_CFG_CRYPTM_MSK |
733734
CESA_SA_DESC_CFG_AES_LEN_MSK);
734735

735-
ret = mv_cesa_ablkcipher_req_init(req, tmpl);
736-
if (ret)
737-
return ret;
738-
739-
ret = mv_cesa_queue_req(&req->base, &creq->base);
740-
if (mv_cesa_req_needs_cleanup(&req->base, ret))
741-
mv_cesa_ablkcipher_cleanup(req);
742-
743-
return ret;
736+
return mv_cesa_ablkcipher_queue_req(req, tmpl);
744737
}
745738

746739
static int mv_cesa_ecb_aes_encrypt(struct ablkcipher_request *req)

drivers/crypto/marvell/hash.c

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,8 @@ static void mv_cesa_ahash_complete(struct crypto_async_request *req)
335335
result[i] = cpu_to_be32(creq->state[i]);
336336
}
337337
}
338+
339+
atomic_sub(ahashreq->nbytes, &engine->load);
338340
}
339341

340342
static void mv_cesa_ahash_prepare(struct crypto_async_request *req,
@@ -365,7 +367,6 @@ static void mv_cesa_ahash_req_cleanup(struct crypto_async_request *req)
365367
static const struct mv_cesa_req_ops mv_cesa_ahash_req_ops = {
366368
.step = mv_cesa_ahash_step,
367369
.process = mv_cesa_ahash_process,
368-
.prepare = mv_cesa_ahash_prepare,
369370
.cleanup = mv_cesa_ahash_req_cleanup,
370371
.complete = mv_cesa_ahash_complete,
371372
};
@@ -682,75 +683,62 @@ static int mv_cesa_ahash_req_init(struct ahash_request *req, bool *cached)
682683
return ret;
683684
}
684685

685-
static int mv_cesa_ahash_update(struct ahash_request *req)
686+
static int mv_cesa_ahash_queue_req(struct ahash_request *req)
686687
{
687688
struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
689+
struct mv_cesa_engine *engine;
688690
bool cached = false;
689691
int ret;
690692

691-
creq->len += req->nbytes;
692693
ret = mv_cesa_ahash_req_init(req, &cached);
693694
if (ret)
694695
return ret;
695696

696697
if (cached)
697698
return 0;
698699

700+
engine = mv_cesa_select_engine(req->nbytes);
701+
mv_cesa_ahash_prepare(&req->base, engine);
702+
699703
ret = mv_cesa_queue_req(&req->base, &creq->base);
704+
700705
if (mv_cesa_req_needs_cleanup(&req->base, ret))
701706
mv_cesa_ahash_cleanup(req);
702707

703708
return ret;
704709
}
705710

711+
static int mv_cesa_ahash_update(struct ahash_request *req)
712+
{
713+
struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
714+
715+
creq->len += req->nbytes;
716+
717+
return mv_cesa_ahash_queue_req(req);
718+
}
719+
706720
static int mv_cesa_ahash_final(struct ahash_request *req)
707721
{
708722
struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
709723
struct mv_cesa_op_ctx *tmpl = &creq->op_tmpl;
710-
bool cached = false;
711-
int ret;
712724

713725
mv_cesa_set_mac_op_total_len(tmpl, creq->len);
714726
creq->last_req = true;
715727
req->nbytes = 0;
716728

717-
ret = mv_cesa_ahash_req_init(req, &cached);
718-
if (ret)
719-
return ret;
720-
721-
if (cached)
722-
return 0;
723-
724-
ret = mv_cesa_queue_req(&req->base, &creq->base);
725-
if (mv_cesa_req_needs_cleanup(&req->base, ret))
726-
mv_cesa_ahash_cleanup(req);
727-
728-
return ret;
729+
return mv_cesa_ahash_queue_req(req);
729730
}
730731

731732
static int mv_cesa_ahash_finup(struct ahash_request *req)
732733
{
733734
struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
734735
struct mv_cesa_op_ctx *tmpl = &creq->op_tmpl;
735-
bool cached = false;
736-
int ret;
737736

738737
creq->len += req->nbytes;
739738
mv_cesa_set_mac_op_total_len(tmpl, creq->len);
740739
creq->last_req = true;
741740

742-
ret = mv_cesa_ahash_req_init(req, &cached);
743-
if (ret)
744-
return ret;
745-
746-
if (cached)
747-
return 0;
748-
749-
ret = mv_cesa_queue_req(&req->base, &creq->base);
750-
if (mv_cesa_req_needs_cleanup(&req->base, ret))
751-
mv_cesa_ahash_cleanup(req);
752-
753-
return ret;
741+
return mv_cesa_ahash_queue_req(req);
754742
}
755743

756744
static int mv_cesa_ahash_export(struct ahash_request *req, void *hash,

0 commit comments

Comments
 (0)