1
0
Fork 0

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

commit 484a897ffa upstream.

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: 62c455ca85 (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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
5.4-rM2-2.2.x-imx-squashed
Jonathan Cameron 2019-11-19 13:42:57 +08:00 committed by Greg Kroah-Hartman
parent a791fc62a5
commit 58d8f2dec6
3 changed files with 27 additions and 70 deletions

View File

@ -35,6 +35,5 @@ config CRYPTO_DEV_HISI_ZIP
depends on ARM64 && PCI && PCI_MSI
select CRYPTO_DEV_HISI_QM
select CRYPTO_HISI_SGL
select SG_SPLIT
help
Support for HiSilicon ZIP Driver

View File

@ -12,6 +12,10 @@
/* hisi_zip_sqe dw3 */
#define HZIP_BD_STATUS_M GENMASK(7, 0)
/* hisi_zip_sqe dw7 */
#define HZIP_IN_SGE_DATA_OFFSET_M GENMASK(23, 0)
/* hisi_zip_sqe dw8 */
#define HZIP_OUT_SGE_DATA_OFFSET_M GENMASK(23, 0)
/* hisi_zip_sqe dw9 */
#define HZIP_REQ_TYPE_M GENMASK(7, 0)
#define HZIP_ALG_TYPE_ZLIB 0x02

View File

@ -45,10 +45,8 @@ enum hisi_zip_alg_type {
struct hisi_zip_req {
struct acomp_req *req;
struct scatterlist *src;
struct scatterlist *dst;
size_t slen;
size_t dlen;
int sskip;
int dskip;
struct hisi_acc_hw_sgl *hw_src;
struct hisi_acc_hw_sgl *hw_dst;
dma_addr_t dma_src;
@ -94,13 +92,15 @@ static void hisi_zip_config_tag(struct hisi_zip_sqe *sqe, u32 tag)
static void hisi_zip_fill_sqe(struct hisi_zip_sqe *sqe, u8 req_type,
dma_addr_t s_addr, dma_addr_t d_addr, u32 slen,
u32 dlen)
u32 dlen, int sskip, int dskip)
{
memset(sqe, 0, sizeof(struct hisi_zip_sqe));
sqe->input_data_length = slen;
sqe->input_data_length = slen - sskip;
sqe->dw7 = FIELD_PREP(HZIP_IN_SGE_DATA_OFFSET_M, sskip);
sqe->dw8 = FIELD_PREP(HZIP_OUT_SGE_DATA_OFFSET_M, dskip);
sqe->dw9 = FIELD_PREP(HZIP_REQ_TYPE_M, req_type);
sqe->dest_avail_out = dlen;
sqe->dest_avail_out = dlen - dskip;
sqe->source_addr_l = lower_32_bits(s_addr);
sqe->source_addr_h = upper_32_bits(s_addr);
sqe->dest_addr_l = lower_32_bits(d_addr);
@ -301,11 +301,6 @@ static void hisi_zip_remove_req(struct hisi_zip_qp_ctx *qp_ctx,
{
struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
if (qp_ctx->qp->alg_type == HZIP_ALG_TYPE_COMP)
kfree(req->dst);
else
kfree(req->src);
write_lock(&req_q->req_lock);
clear_bit(req->req_id, req_q->req_bitmap);
memset(req, 0, sizeof(struct hisi_zip_req));
@ -333,8 +328,8 @@ static void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data)
}
dlen = sqe->produced;
hisi_acc_sg_buf_unmap(dev, req->src, req->hw_src);
hisi_acc_sg_buf_unmap(dev, req->dst, req->hw_dst);
hisi_acc_sg_buf_unmap(dev, acomp_req->src, req->hw_src);
hisi_acc_sg_buf_unmap(dev, acomp_req->dst, req->hw_dst);
head_size = (qp->alg_type == 0) ? TO_HEAD_SIZE(qp->req_type) : 0;
acomp_req->dlen = dlen + head_size;
@ -428,20 +423,6 @@ static size_t get_comp_head_size(struct scatterlist *src, u8 req_type)
}
}
static int get_sg_skip_bytes(struct scatterlist *sgl, size_t bytes,
size_t remains, struct scatterlist **out)
{
#define SPLIT_NUM 2
size_t split_sizes[SPLIT_NUM];
int out_mapped_nents[SPLIT_NUM];
split_sizes[0] = bytes;
split_sizes[1] = remains;
return sg_split(sgl, 0, 0, SPLIT_NUM, split_sizes, out,
out_mapped_nents, GFP_KERNEL);
}
static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
struct hisi_zip_qp_ctx *qp_ctx,
size_t head_size, bool is_comp)
@ -449,31 +430,7 @@ static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
struct hisi_zip_req *q = req_q->q;
struct hisi_zip_req *req_cache;
struct scatterlist *out[2];
struct scatterlist *sgl;
size_t len;
int ret, req_id;
/*
* remove/add zlib/gzip head, as hardware operations do not include
* comp head. so split req->src to get sgl without heads in acomp, or
* add comp head to req->dst ahead of that hardware output compressed
* data in sgl splited from req->dst without comp head.
*/
if (is_comp) {
sgl = req->dst;
len = req->dlen - head_size;
} else {
sgl = req->src;
len = req->slen - head_size;
}
ret = get_sg_skip_bytes(sgl, head_size, len, out);
if (ret)
return ERR_PTR(ret);
/* sgl for comp head is useless, so free it now */
kfree(out[0]);
int req_id;
write_lock(&req_q->req_lock);
@ -481,7 +438,6 @@ static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
if (req_id >= req_q->size) {
write_unlock(&req_q->req_lock);
dev_dbg(&qp_ctx->qp->qm->pdev->dev, "req cache is full!\n");
kfree(out[1]);
return ERR_PTR(-EBUSY);
}
set_bit(req_id, req_q->req_bitmap);
@ -489,16 +445,13 @@ static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
req_cache = q + req_id;
req_cache->req_id = req_id;
req_cache->req = req;
if (is_comp) {
req_cache->src = req->src;
req_cache->dst = out[1];
req_cache->slen = req->slen;
req_cache->dlen = req->dlen - head_size;
req_cache->sskip = 0;
req_cache->dskip = head_size;
} else {
req_cache->src = out[1];
req_cache->dst = req->dst;
req_cache->slen = req->slen - head_size;
req_cache->dlen = req->dlen;
req_cache->sskip = head_size;
req_cache->dskip = 0;
}
write_unlock(&req_q->req_lock);
@ -510,6 +463,7 @@ static int hisi_zip_do_work(struct hisi_zip_req *req,
struct hisi_zip_qp_ctx *qp_ctx)
{
struct hisi_zip_sqe *zip_sqe = &qp_ctx->zip_sqe;
struct acomp_req *a_req = req->req;
struct hisi_qp *qp = qp_ctx->qp;
struct device *dev = &qp->qm->pdev->dev;
struct hisi_acc_sgl_pool *pool = &qp_ctx->sgl_pool;
@ -517,16 +471,16 @@ static int hisi_zip_do_work(struct hisi_zip_req *req,
dma_addr_t output;
int ret;
if (!req->src || !req->slen || !req->dst || !req->dlen)
if (!a_req->src || !a_req->slen || !a_req->dst || !a_req->dlen)
return -EINVAL;
req->hw_src = hisi_acc_sg_buf_map_to_hw_sgl(dev, req->src, pool,
req->hw_src = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->src, pool,
req->req_id << 1, &input);
if (IS_ERR(req->hw_src))
return PTR_ERR(req->hw_src);
req->dma_src = input;
req->hw_dst = hisi_acc_sg_buf_map_to_hw_sgl(dev, req->dst, pool,
req->hw_dst = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->dst, pool,
(req->req_id << 1) + 1,
&output);
if (IS_ERR(req->hw_dst)) {
@ -535,8 +489,8 @@ static int hisi_zip_do_work(struct hisi_zip_req *req,
}
req->dma_dst = output;
hisi_zip_fill_sqe(zip_sqe, qp->req_type, input, output, req->slen,
req->dlen);
hisi_zip_fill_sqe(zip_sqe, qp->req_type, input, output, a_req->slen,
a_req->dlen, req->sskip, req->dskip);
hisi_zip_config_buf_type(zip_sqe, HZIP_SGL);
hisi_zip_config_tag(zip_sqe, req->req_id);
@ -548,9 +502,9 @@ static int hisi_zip_do_work(struct hisi_zip_req *req,
return -EINPROGRESS;
err_unmap_output:
hisi_acc_sg_buf_unmap(dev, req->dst, req->hw_dst);
hisi_acc_sg_buf_unmap(dev, a_req->dst, req->hw_dst);
err_unmap_input:
hisi_acc_sg_buf_unmap(dev, req->src, req->hw_src);
hisi_acc_sg_buf_unmap(dev, a_req->src, req->hw_src);
return ret;
}