Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: hisilicon - Use the offset fields in sqe to avoid need to split scatterlists

We can configure sgl offset fields in ZIP sqe to let ZIP engine read/write
sgl data with skipped data. Hence no need to splite the sgl.

Fixes: 62c455ca853e (crypto: hisilicon - add HiSilicon ZIP accelerator support)
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Jonathan Cameron and committed by
Herbert Xu
484a897f 8debacd6

+27 -70
-1
drivers/crypto/hisilicon/Kconfig
··· 44 44 depends on ARM64 || (COMPILE_TEST && 64BIT) 45 45 depends on !CPU_BIG_ENDIAN || COMPILE_TEST 46 46 select CRYPTO_DEV_HISI_QM 47 - select SG_SPLIT 48 47 help 49 48 Support for HiSilicon ZIP Driver 50 49
+4
drivers/crypto/hisilicon/zip/zip.h
··· 11 11 12 12 /* hisi_zip_sqe dw3 */ 13 13 #define HZIP_BD_STATUS_M GENMASK(7, 0) 14 + /* hisi_zip_sqe dw7 */ 15 + #define HZIP_IN_SGE_DATA_OFFSET_M GENMASK(23, 0) 16 + /* hisi_zip_sqe dw8 */ 17 + #define HZIP_OUT_SGE_DATA_OFFSET_M GENMASK(23, 0) 14 18 /* hisi_zip_sqe dw9 */ 15 19 #define HZIP_REQ_TYPE_M GENMASK(7, 0) 16 20 #define HZIP_ALG_TYPE_ZLIB 0x02
+23 -69
drivers/crypto/hisilicon/zip/zip_crypto.c
··· 46 46 47 47 struct hisi_zip_req { 48 48 struct acomp_req *req; 49 - struct scatterlist *src; 50 - struct scatterlist *dst; 51 - size_t slen; 52 - size_t dlen; 49 + int sskip; 50 + int dskip; 53 51 struct hisi_acc_hw_sgl *hw_src; 54 52 struct hisi_acc_hw_sgl *hw_dst; 55 53 dma_addr_t dma_src; ··· 117 119 118 120 static void hisi_zip_fill_sqe(struct hisi_zip_sqe *sqe, u8 req_type, 119 121 dma_addr_t s_addr, dma_addr_t d_addr, u32 slen, 120 - u32 dlen) 122 + u32 dlen, int sskip, int dskip) 121 123 { 122 124 memset(sqe, 0, sizeof(struct hisi_zip_sqe)); 123 125 124 - sqe->input_data_length = slen; 126 + sqe->input_data_length = slen - sskip; 127 + sqe->dw7 = FIELD_PREP(HZIP_IN_SGE_DATA_OFFSET_M, sskip); 128 + sqe->dw8 = FIELD_PREP(HZIP_OUT_SGE_DATA_OFFSET_M, dskip); 125 129 sqe->dw9 = FIELD_PREP(HZIP_REQ_TYPE_M, req_type); 126 - sqe->dest_avail_out = dlen; 130 + sqe->dest_avail_out = dlen - dskip; 127 131 sqe->source_addr_l = lower_32_bits(s_addr); 128 132 sqe->source_addr_h = upper_32_bits(s_addr); 129 133 sqe->dest_addr_l = lower_32_bits(d_addr); ··· 327 327 { 328 328 struct hisi_zip_req_q *req_q = &qp_ctx->req_q; 329 329 330 - if (qp_ctx->qp->alg_type == HZIP_ALG_TYPE_COMP) 331 - kfree(req->dst); 332 - else 333 - kfree(req->src); 334 - 335 330 write_lock(&req_q->req_lock); 336 331 clear_bit(req->req_id, req_q->req_bitmap); 337 332 memset(req, 0, sizeof(struct hisi_zip_req)); ··· 354 359 } 355 360 dlen = sqe->produced; 356 361 357 - hisi_acc_sg_buf_unmap(dev, req->src, req->hw_src); 358 - hisi_acc_sg_buf_unmap(dev, req->dst, req->hw_dst); 362 + hisi_acc_sg_buf_unmap(dev, acomp_req->src, req->hw_src); 363 + hisi_acc_sg_buf_unmap(dev, acomp_req->dst, req->hw_dst); 359 364 360 365 head_size = (qp->alg_type == 0) ? TO_HEAD_SIZE(qp->req_type) : 0; 361 366 acomp_req->dlen = dlen + head_size; ··· 449 454 } 450 455 } 451 456 452 - static int get_sg_skip_bytes(struct scatterlist *sgl, size_t bytes, 453 - size_t remains, struct scatterlist **out) 454 - { 455 - #define SPLIT_NUM 2 456 - size_t split_sizes[SPLIT_NUM]; 457 - int out_mapped_nents[SPLIT_NUM]; 458 - 459 - split_sizes[0] = bytes; 460 - split_sizes[1] = remains; 461 - 462 - return sg_split(sgl, 0, 0, SPLIT_NUM, split_sizes, out, 463 - out_mapped_nents, GFP_KERNEL); 464 - } 465 - 466 457 static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req, 467 458 struct hisi_zip_qp_ctx *qp_ctx, 468 459 size_t head_size, bool is_comp) ··· 456 475 struct hisi_zip_req_q *req_q = &qp_ctx->req_q; 457 476 struct hisi_zip_req *q = req_q->q; 458 477 struct hisi_zip_req *req_cache; 459 - struct scatterlist *out[2]; 460 - struct scatterlist *sgl; 461 - size_t len; 462 - int ret, req_id; 463 - 464 - /* 465 - * remove/add zlib/gzip head, as hardware operations do not include 466 - * comp head. so split req->src to get sgl without heads in acomp, or 467 - * add comp head to req->dst ahead of that hardware output compressed 468 - * data in sgl splited from req->dst without comp head. 469 - */ 470 - if (is_comp) { 471 - sgl = req->dst; 472 - len = req->dlen - head_size; 473 - } else { 474 - sgl = req->src; 475 - len = req->slen - head_size; 476 - } 477 - 478 - ret = get_sg_skip_bytes(sgl, head_size, len, out); 479 - if (ret) 480 - return ERR_PTR(ret); 481 - 482 - /* sgl for comp head is useless, so free it now */ 483 - kfree(out[0]); 478 + int req_id; 484 479 485 480 write_lock(&req_q->req_lock); 486 481 ··· 464 507 if (req_id >= req_q->size) { 465 508 write_unlock(&req_q->req_lock); 466 509 dev_dbg(&qp_ctx->qp->qm->pdev->dev, "req cache is full!\n"); 467 - kfree(out[1]); 468 510 return ERR_PTR(-EBUSY); 469 511 } 470 512 set_bit(req_id, req_q->req_bitmap); ··· 471 515 req_cache = q + req_id; 472 516 req_cache->req_id = req_id; 473 517 req_cache->req = req; 518 + 474 519 if (is_comp) { 475 - req_cache->src = req->src; 476 - req_cache->dst = out[1]; 477 - req_cache->slen = req->slen; 478 - req_cache->dlen = req->dlen - head_size; 520 + req_cache->sskip = 0; 521 + req_cache->dskip = head_size; 479 522 } else { 480 - req_cache->src = out[1]; 481 - req_cache->dst = req->dst; 482 - req_cache->slen = req->slen - head_size; 483 - req_cache->dlen = req->dlen; 523 + req_cache->sskip = head_size; 524 + req_cache->dskip = 0; 484 525 } 485 526 486 527 write_unlock(&req_q->req_lock); ··· 489 536 struct hisi_zip_qp_ctx *qp_ctx) 490 537 { 491 538 struct hisi_zip_sqe *zip_sqe = &qp_ctx->zip_sqe; 539 + struct acomp_req *a_req = req->req; 492 540 struct hisi_qp *qp = qp_ctx->qp; 493 541 struct device *dev = &qp->qm->pdev->dev; 494 542 struct hisi_acc_sgl_pool *pool = qp_ctx->sgl_pool; ··· 497 543 dma_addr_t output; 498 544 int ret; 499 545 500 - if (!req->src || !req->slen || !req->dst || !req->dlen) 546 + if (!a_req->src || !a_req->slen || !a_req->dst || !a_req->dlen) 501 547 return -EINVAL; 502 548 503 - req->hw_src = hisi_acc_sg_buf_map_to_hw_sgl(dev, req->src, pool, 549 + req->hw_src = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->src, pool, 504 550 req->req_id << 1, &input); 505 551 if (IS_ERR(req->hw_src)) 506 552 return PTR_ERR(req->hw_src); 507 553 req->dma_src = input; 508 554 509 - req->hw_dst = hisi_acc_sg_buf_map_to_hw_sgl(dev, req->dst, pool, 555 + req->hw_dst = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->dst, pool, 510 556 (req->req_id << 1) + 1, 511 557 &output); 512 558 if (IS_ERR(req->hw_dst)) { ··· 515 561 } 516 562 req->dma_dst = output; 517 563 518 - hisi_zip_fill_sqe(zip_sqe, qp->req_type, input, output, req->slen, 519 - req->dlen); 564 + hisi_zip_fill_sqe(zip_sqe, qp->req_type, input, output, a_req->slen, 565 + a_req->dlen, req->sskip, req->dskip); 520 566 hisi_zip_config_buf_type(zip_sqe, HZIP_SGL); 521 567 hisi_zip_config_tag(zip_sqe, req->req_id); 522 568 ··· 528 574 return -EINPROGRESS; 529 575 530 576 err_unmap_output: 531 - hisi_acc_sg_buf_unmap(dev, req->dst, req->hw_dst); 577 + hisi_acc_sg_buf_unmap(dev, a_req->dst, req->hw_dst); 532 578 err_unmap_input: 533 - hisi_acc_sg_buf_unmap(dev, req->src, req->hw_src); 579 + hisi_acc_sg_buf_unmap(dev, a_req->src, req->hw_src); 534 580 return ret; 535 581 } 536 582