Skip to content

Commit e5dd7e6

Browse files
committed
crypto: qat - add resubmit logic for decompression
jira LE-1907 Rebuild_History Non-Buildable kernel-rt-5.14.0-284.30.1.rt14.315.el9_2 commit-author Giovanni Cabiddu <[email protected]> commit 3112d0f The acomp API allows to send requests with a NULL destination buffer. In this case, the algorithm implementation needs to allocate the destination scatter list, perform the operation and return the buffer to the user. For decompression, data is likely to expand and be bigger than the allocated buffer. This implements a re-submission mechanism for decompression requests that is triggered if the destination buffer, allocated by the driver, is not sufficiently big to store the output from decompression. If an overflow is detected when processing the callback for a decompression request with a NULL destination buffer, a workqueue is scheduled. This allocates a new scatter list of size CRYPTO_ACOMP_DST_MAX, now 128KB, creates a new firmware scatter list and resubmits the job to the hardware accelerator. Suggested-by: Herbert Xu <[email protected]> Signed-off-by: Giovanni Cabiddu <[email protected]> Signed-off-by: Herbert Xu <[email protected]> (cherry picked from commit 3112d0f) Signed-off-by: Jonathan Maple <[email protected]>
1 parent 29869b6 commit e5dd7e6

File tree

4 files changed

+245
-0
lines changed

4 files changed

+245
-0
lines changed

drivers/crypto/qat/qat_common/qat_bl.c

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,162 @@ int qat_bl_sgl_to_bufl(struct adf_accel_dev *accel_dev,
222222
extra_dst_buff, sz_extra_dst_buff,
223223
flags);
224224
}
225+
226+
static void qat_bl_sgl_unmap(struct adf_accel_dev *accel_dev,
227+
struct qat_alg_buf_list *bl)
228+
{
229+
struct device *dev = &GET_DEV(accel_dev);
230+
int n = bl->num_bufs;
231+
int i;
232+
233+
for (i = 0; i < n; i++)
234+
if (!dma_mapping_error(dev, bl->bufers[i].addr))
235+
dma_unmap_single(dev, bl->bufers[i].addr,
236+
bl->bufers[i].len, DMA_FROM_DEVICE);
237+
}
238+
239+
static int qat_bl_sgl_map(struct adf_accel_dev *accel_dev,
240+
struct scatterlist *sgl,
241+
struct qat_alg_buf_list **bl)
242+
{
243+
struct device *dev = &GET_DEV(accel_dev);
244+
struct qat_alg_buf_list *bufl;
245+
int node = dev_to_node(dev);
246+
struct scatterlist *sg;
247+
int n, i, sg_nctr;
248+
size_t sz;
249+
250+
n = sg_nents(sgl);
251+
sz = struct_size(bufl, bufers, n);
252+
bufl = kzalloc_node(sz, GFP_KERNEL, node);
253+
if (unlikely(!bufl))
254+
return -ENOMEM;
255+
256+
for (i = 0; i < n; i++)
257+
bufl->bufers[i].addr = DMA_MAPPING_ERROR;
258+
259+
sg_nctr = 0;
260+
for_each_sg(sgl, sg, n, i) {
261+
int y = sg_nctr;
262+
263+
if (!sg->length)
264+
continue;
265+
266+
bufl->bufers[y].addr = dma_map_single(dev, sg_virt(sg),
267+
sg->length,
268+
DMA_FROM_DEVICE);
269+
bufl->bufers[y].len = sg->length;
270+
if (unlikely(dma_mapping_error(dev, bufl->bufers[y].addr)))
271+
goto err_map;
272+
sg_nctr++;
273+
}
274+
bufl->num_bufs = sg_nctr;
275+
bufl->num_mapped_bufs = sg_nctr;
276+
277+
*bl = bufl;
278+
279+
return 0;
280+
281+
err_map:
282+
for (i = 0; i < n; i++)
283+
if (!dma_mapping_error(dev, bufl->bufers[i].addr))
284+
dma_unmap_single(dev, bufl->bufers[i].addr,
285+
bufl->bufers[i].len,
286+
DMA_FROM_DEVICE);
287+
kfree(bufl);
288+
*bl = NULL;
289+
290+
return -ENOMEM;
291+
}
292+
293+
static void qat_bl_sgl_free_unmap(struct adf_accel_dev *accel_dev,
294+
struct scatterlist *sgl,
295+
struct qat_alg_buf_list *bl,
296+
bool free_bl)
297+
{
298+
if (bl) {
299+
qat_bl_sgl_unmap(accel_dev, bl);
300+
301+
if (free_bl)
302+
kfree(bl);
303+
}
304+
if (sgl)
305+
sgl_free(sgl);
306+
}
307+
308+
static int qat_bl_sgl_alloc_map(struct adf_accel_dev *accel_dev,
309+
struct scatterlist **sgl,
310+
struct qat_alg_buf_list **bl,
311+
unsigned int dlen,
312+
gfp_t gfp)
313+
{
314+
struct scatterlist *dst;
315+
int ret;
316+
317+
dst = sgl_alloc(dlen, gfp, NULL);
318+
if (!dst) {
319+
dev_err(&GET_DEV(accel_dev), "sg_alloc failed\n");
320+
return -ENOMEM;
321+
}
322+
323+
ret = qat_bl_sgl_map(accel_dev, dst, bl);
324+
if (ret)
325+
goto err;
326+
327+
*sgl = dst;
328+
329+
return 0;
330+
331+
err:
332+
sgl_free(dst);
333+
*sgl = NULL;
334+
return ret;
335+
}
336+
337+
int qat_bl_realloc_map_new_dst(struct adf_accel_dev *accel_dev,
338+
struct scatterlist **sg,
339+
unsigned int dlen,
340+
struct qat_request_buffs *qat_bufs,
341+
gfp_t gfp)
342+
{
343+
struct device *dev = &GET_DEV(accel_dev);
344+
dma_addr_t new_blp = DMA_MAPPING_ERROR;
345+
struct qat_alg_buf_list *new_bl;
346+
struct scatterlist *new_sg;
347+
size_t new_bl_size;
348+
int ret;
349+
350+
ret = qat_bl_sgl_alloc_map(accel_dev, &new_sg, &new_bl, dlen, gfp);
351+
if (ret)
352+
return ret;
353+
354+
new_bl_size = struct_size(new_bl, bufers, new_bl->num_bufs);
355+
356+
/* Map new firmware SGL descriptor */
357+
new_blp = dma_map_single(dev, new_bl, new_bl_size, DMA_TO_DEVICE);
358+
if (unlikely(dma_mapping_error(dev, new_blp)))
359+
goto err;
360+
361+
/* Unmap old firmware SGL descriptor */
362+
dma_unmap_single(dev, qat_bufs->bloutp, qat_bufs->sz_out, DMA_TO_DEVICE);
363+
364+
/* Free and unmap old scatterlist */
365+
qat_bl_sgl_free_unmap(accel_dev, *sg, qat_bufs->blout,
366+
!qat_bufs->sgl_dst_valid);
367+
368+
qat_bufs->sgl_dst_valid = false;
369+
qat_bufs->blout = new_bl;
370+
qat_bufs->bloutp = new_blp;
371+
qat_bufs->sz_out = new_bl_size;
372+
373+
*sg = new_sg;
374+
375+
return 0;
376+
err:
377+
qat_bl_sgl_free_unmap(accel_dev, new_sg, new_bl, true);
378+
379+
if (!dma_mapping_error(dev, new_blp))
380+
dma_unmap_single(dev, new_blp, new_bl_size, DMA_TO_DEVICE);
381+
382+
return -ENOMEM;
383+
}

drivers/crypto/qat/qat_common/qat_bl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,10 @@ static inline gfp_t qat_algs_alloc_flags(struct crypto_async_request *req)
5858
return req->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC;
5959
}
6060

61+
int qat_bl_realloc_map_new_dst(struct adf_accel_dev *accel_dev,
62+
struct scatterlist **newd,
63+
unsigned int dlen,
64+
struct qat_request_buffs *qat_bufs,
65+
gfp_t gfp);
66+
6167
#endif

drivers/crypto/qat/qat_common/qat_comp_algs.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <crypto/internal/acompress.h>
66
#include <crypto/scatterwalk.h>
77
#include <linux/dma-mapping.h>
8+
#include <linux/workqueue.h>
89
#include "adf_accel_devices.h"
910
#include "adf_common_drv.h"
1011
#include "qat_bl.h"
@@ -25,6 +26,11 @@ struct qat_compression_ctx {
2526
struct qat_compression_instance *inst;
2627
};
2728

29+
struct qat_dst {
30+
bool is_null;
31+
int resubmitted;
32+
};
33+
2834
struct qat_compression_req {
2935
u8 req[QAT_COMP_REQ_SIZE];
3036
struct qat_compression_ctx *qat_compression_ctx;
@@ -33,6 +39,8 @@ struct qat_compression_req {
3339
enum direction dir;
3440
int actual_dlen;
3541
struct qat_alg_req alg_req;
42+
struct work_struct resubmit;
43+
struct qat_dst dst;
3644
};
3745

3846
static int qat_alg_send_dc_message(struct qat_compression_req *qat_req,
@@ -49,6 +57,46 @@ static int qat_alg_send_dc_message(struct qat_compression_req *qat_req,
4957
return qat_alg_send_message(alg_req);
5058
}
5159

60+
static void qat_comp_resubmit(struct work_struct *work)
61+
{
62+
struct qat_compression_req *qat_req =
63+
container_of(work, struct qat_compression_req, resubmit);
64+
struct qat_compression_ctx *ctx = qat_req->qat_compression_ctx;
65+
struct adf_accel_dev *accel_dev = ctx->inst->accel_dev;
66+
struct qat_request_buffs *qat_bufs = &qat_req->buf;
67+
struct qat_compression_instance *inst = ctx->inst;
68+
struct acomp_req *areq = qat_req->acompress_req;
69+
struct crypto_acomp *tfm = crypto_acomp_reqtfm(areq);
70+
unsigned int dlen = CRYPTO_ACOMP_DST_MAX;
71+
u8 *req = qat_req->req;
72+
dma_addr_t dfbuf;
73+
int ret;
74+
75+
areq->dlen = dlen;
76+
77+
dev_dbg(&GET_DEV(accel_dev), "[%s][%s] retry NULL dst request - dlen = %d\n",
78+
crypto_tfm_alg_driver_name(crypto_acomp_tfm(tfm)),
79+
qat_req->dir == COMPRESSION ? "comp" : "decomp", dlen);
80+
81+
ret = qat_bl_realloc_map_new_dst(accel_dev, &areq->dst, dlen, qat_bufs,
82+
qat_algs_alloc_flags(&areq->base));
83+
if (ret)
84+
goto err;
85+
86+
qat_req->dst.resubmitted = true;
87+
88+
dfbuf = qat_req->buf.bloutp;
89+
qat_comp_override_dst(req, dfbuf, dlen);
90+
91+
ret = qat_alg_send_dc_message(qat_req, inst, &areq->base);
92+
if (ret != -ENOSPC)
93+
return;
94+
95+
err:
96+
qat_bl_free_bufl(accel_dev, qat_bufs);
97+
areq->base.complete(&areq->base, ret);
98+
}
99+
52100
static void qat_comp_generic_callback(struct qat_compression_req *qat_req,
53101
void *resp)
54102
{
@@ -80,6 +128,21 @@ static void qat_comp_generic_callback(struct qat_compression_req *qat_req,
80128

81129
areq->dlen = 0;
82130

131+
if (qat_req->dir == DECOMPRESSION && qat_req->dst.is_null) {
132+
if (cmp_err == ERR_CODE_OVERFLOW_ERROR) {
133+
if (qat_req->dst.resubmitted) {
134+
dev_dbg(&GET_DEV(accel_dev),
135+
"Output does not fit destination buffer\n");
136+
res = -EOVERFLOW;
137+
goto end;
138+
}
139+
140+
INIT_WORK(&qat_req->resubmit, qat_comp_resubmit);
141+
adf_misc_wq_queue_work(&qat_req->resubmit);
142+
return;
143+
}
144+
}
145+
83146
if (unlikely(status != ICP_QAT_FW_COMN_STATUS_FLAG_OK))
84147
goto end;
85148

@@ -176,16 +239,23 @@ static int qat_comp_alg_compress_decompress(struct acomp_req *areq,
176239
if (areq->dst && !dlen)
177240
return -EINVAL;
178241

242+
qat_req->dst.is_null = false;
243+
179244
/* Handle acomp requests that require the allocation of a destination
180245
* buffer. The size of the destination buffer is double the source
181246
* buffer (rounded up to the size of a page) to fit the decompressed
182247
* output or an expansion on the data for compression.
183248
*/
184249
if (!areq->dst) {
250+
qat_req->dst.is_null = true;
251+
185252
dlen = round_up(2 * slen, PAGE_SIZE);
186253
areq->dst = sgl_alloc(dlen, f, NULL);
187254
if (!areq->dst)
188255
return -ENOMEM;
256+
257+
areq->dlen = dlen;
258+
qat_req->dst.resubmitted = false;
189259
}
190260

191261
if (dir == COMPRESSION) {

drivers/crypto/qat/qat_common/qat_comp_req.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ static inline void qat_comp_create_req(void *ctx, void *req, u64 src, u32 slen,
2525
req_pars->out_buffer_sz = dlen;
2626
}
2727

28+
static inline void qat_comp_override_dst(void *req, u64 dst, u32 dlen)
29+
{
30+
struct icp_qat_fw_comp_req *fw_req = req;
31+
struct icp_qat_fw_comp_req_params *req_pars = &fw_req->comp_pars;
32+
33+
fw_req->comn_mid.dest_data_addr = dst;
34+
fw_req->comn_mid.dst_length = dlen;
35+
req_pars->out_buffer_sz = dlen;
36+
}
37+
2838
static inline void qat_comp_create_compression_req(void *ctx, void *req,
2939
u64 src, u32 slen,
3040
u64 dst, u32 dlen,

0 commit comments

Comments
 (0)