Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018-2021 Intel Corporation
3 : : */
4 : :
5 : : #include <rte_mempool.h>
6 : : #include <rte_mbuf.h>
7 : : #include <rte_hexdump.h>
8 : : #include <rte_comp.h>
9 : : #include <bus_pci_driver.h>
10 : : #include <rte_byteorder.h>
11 : : #include <rte_memcpy.h>
12 : : #include <rte_common.h>
13 : : #include <rte_spinlock.h>
14 : : #include <rte_log.h>
15 : : #include <rte_malloc.h>
16 : : #include <rte_memzone.h>
17 : :
18 : : #include "qat_logs.h"
19 : : #include "qat_comp.h"
20 : : #include "qat_comp_pmd.h"
21 : :
22 : : static void
23 : 0 : qat_comp_fallback_to_fixed(struct icp_qat_fw_comp_req *comp_req)
24 : : {
25 : 0 : QAT_DP_LOG(DEBUG, "QAT PMD: fallback to fixed compression!");
26 : :
27 : 0 : comp_req->comn_hdr.service_cmd_id =
28 : : ICP_QAT_FW_COMP_CMD_STATIC;
29 : :
30 : 0 : ICP_QAT_FW_COMN_NEXT_ID_SET(
31 : : &comp_req->comp_cd_ctrl,
32 : : ICP_QAT_FW_SLICE_DRAM_WR);
33 : :
34 : : ICP_QAT_FW_COMN_NEXT_ID_SET(
35 : : &comp_req->u2.xlt_cd_ctrl,
36 : : ICP_QAT_FW_SLICE_NULL);
37 : 0 : ICP_QAT_FW_COMN_CURR_ID_SET(
38 : : &comp_req->u2.xlt_cd_ctrl,
39 : : ICP_QAT_FW_SLICE_NULL);
40 : 0 : }
41 : :
42 : : void
43 : 0 : qat_comp_free_split_op_memzones(struct qat_comp_op_cookie *cookie,
44 : : unsigned int nb_children)
45 : : {
46 : : unsigned int i;
47 : :
48 : : /* free all memzones allocated for child descriptors */
49 [ # # ]: 0 : for (i = 0; i < nb_children; i++)
50 : 0 : rte_memzone_free(cookie->dst_memzones[i]);
51 : :
52 : : /* and free the pointer table */
53 : 0 : rte_free(cookie->dst_memzones);
54 : 0 : cookie->dst_memzones = NULL;
55 : 0 : }
56 : :
57 : : static int
58 : 0 : qat_comp_allocate_split_op_memzones(struct qat_comp_op_cookie *cookie,
59 : : unsigned int nb_descriptors_needed)
60 : : {
61 : 0 : struct qat_queue *txq = &(cookie->qp->tx_q);
62 : : char dst_memz_name[RTE_MEMZONE_NAMESIZE];
63 : : unsigned int i;
64 : :
65 : : /* allocate the array of memzone pointers */
66 : 0 : cookie->dst_memzones = rte_zmalloc_socket("qat PMD im buf mz pointers",
67 : 0 : (nb_descriptors_needed - 1) *
68 : : sizeof(const struct rte_memzone *),
69 : 0 : RTE_CACHE_LINE_SIZE, cookie->socket_id);
70 : :
71 [ # # ]: 0 : if (cookie->dst_memzones == NULL) {
72 : 0 : QAT_DP_LOG(ERR,
73 : : "QAT PMD: failed to allocate im buf mz pointers");
74 : 0 : return -ENOMEM;
75 : : }
76 : :
77 [ # # ]: 0 : for (i = 0; i < nb_descriptors_needed - 1; i++) {
78 : 0 : snprintf(dst_memz_name,
79 : : sizeof(dst_memz_name),
80 : : "dst_%u_%u_%u_%u_%u",
81 : 0 : cookie->qp->qat_dev->qat_dev_id,
82 : 0 : txq->hw_bundle_number, txq->hw_queue_number,
83 : : cookie->cookie_index, i);
84 : :
85 : 0 : cookie->dst_memzones[i] = rte_memzone_reserve_aligned(
86 : : dst_memz_name, RTE_PMD_QAT_COMP_IM_BUFFER_SIZE,
87 : 0 : cookie->socket_id, RTE_MEMZONE_IOVA_CONTIG,
88 : : RTE_CACHE_LINE_SIZE);
89 : :
90 [ # # ]: 0 : if (cookie->dst_memzones[i] == NULL) {
91 : 0 : QAT_DP_LOG(ERR,
92 : : "QAT PMD: failed to allocate dst buffer memzone");
93 : :
94 : : /* let's free all memzones allocated up to now */
95 : 0 : qat_comp_free_split_op_memzones(cookie, i);
96 : :
97 : 0 : return -ENOMEM;
98 : : }
99 : : }
100 : :
101 : : return 0;
102 : : }
103 : :
104 : : int
105 : 0 : qat_comp_build_request(void *in_op, uint8_t *out_msg,
106 : : void *op_cookie,
107 : : enum qat_device_gen qat_dev_gen __rte_unused)
108 : : {
109 : : struct rte_comp_op *op = in_op;
110 : : struct qat_comp_op_cookie *cookie =
111 : : (struct qat_comp_op_cookie *)op_cookie;
112 : : struct qat_comp_stream *stream;
113 : : struct qat_comp_xform *qat_xform;
114 : : const uint8_t *tmpl;
115 : : struct icp_qat_fw_comp_req *comp_req =
116 : : (struct icp_qat_fw_comp_req *)out_msg;
117 : :
118 [ # # ]: 0 : if (op->op_type == RTE_COMP_OP_STATEFUL) {
119 : 0 : stream = op->stream;
120 : 0 : qat_xform = &stream->qat_xform;
121 [ # # ]: 0 : if (unlikely(qat_xform->qat_comp_request_type !=
122 : : QAT_COMP_REQUEST_DECOMPRESS)) {
123 : 0 : QAT_DP_LOG(ERR, "QAT PMD does not support stateful compression");
124 : 0 : op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
125 : 0 : return -EINVAL;
126 : : }
127 [ # # ]: 0 : if (unlikely(stream->op_in_progress)) {
128 : 0 : QAT_DP_LOG(ERR, "QAT PMD does not support running multiple stateful operations on the same stream at once");
129 : 0 : op->status = RTE_COMP_OP_STATUS_INVALID_STATE;
130 : 0 : return -EINVAL;
131 : : }
132 : 0 : stream->op_in_progress = 1;
133 : : } else {
134 : : stream = NULL;
135 : 0 : qat_xform = op->private_xform;
136 : : }
137 : : tmpl = (uint8_t *)&qat_xform->qat_comp_req_tmpl;
138 : :
139 : : rte_mov128(out_msg, tmpl);
140 : 0 : comp_req->comn_mid.opaque_data = (uint64_t)(uintptr_t)op;
141 : :
142 [ # # ]: 0 : if (likely(qat_xform->qat_comp_request_type ==
143 : : QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS)) {
144 : :
145 [ # # ]: 0 : if (unlikely(op->src.length > QAT_FALLBACK_THLD)) {
146 : : /* the operation must be split into pieces */
147 [ # # ]: 0 : if (qat_xform->checksum_type !=
148 : : RTE_COMP_CHECKSUM_NONE) {
149 : : /* fallback to fixed compression in case any
150 : : * checksum calculation was requested
151 : : */
152 : 0 : qat_comp_fallback_to_fixed(comp_req);
153 : : } else {
154 : : /* calculate num. of descriptors for split op */
155 : 0 : unsigned int nb_descriptors_needed =
156 : 0 : op->src.length / QAT_FALLBACK_THLD + 1;
157 : : /* allocate memzone for output data */
158 [ # # ]: 0 : if (qat_comp_allocate_split_op_memzones(
159 : : cookie, nb_descriptors_needed)) {
160 : : /* out of memory, fallback to fixed */
161 : 0 : qat_comp_fallback_to_fixed(comp_req);
162 : : } else {
163 : 0 : QAT_DP_LOG(DEBUG,
164 : : "Input data is too big, op must be split into %u descriptors",
165 : : nb_descriptors_needed);
166 : 0 : return (int) nb_descriptors_needed;
167 : : }
168 : : }
169 : : }
170 : :
171 : : /* set BFINAL bit according to flush_flag */
172 : 0 : comp_req->comp_pars.req_par_flags =
173 [ # # ]: 0 : ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(
174 : : ICP_QAT_FW_COMP_SOP,
175 : : ICP_QAT_FW_COMP_EOP,
176 : : op->flush_flag == RTE_COMP_FLUSH_FINAL ?
177 : : ICP_QAT_FW_COMP_BFINAL
178 : : : ICP_QAT_FW_COMP_NOT_BFINAL,
179 : : ICP_QAT_FW_COMP_CNV,
180 : : ICP_QAT_FW_COMP_CNV_RECOVERY);
181 : :
182 [ # # ]: 0 : } else if (op->op_type == RTE_COMP_OP_STATEFUL) {
183 : :
184 : 0 : comp_req->comp_pars.req_par_flags =
185 [ # # ]: 0 : ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(
186 : : (stream->start_of_packet) ?
187 : : ICP_QAT_FW_COMP_SOP
188 : : : ICP_QAT_FW_COMP_NOT_SOP,
189 : : (op->flush_flag == RTE_COMP_FLUSH_FULL ||
190 : : op->flush_flag == RTE_COMP_FLUSH_FINAL) ?
191 : : ICP_QAT_FW_COMP_EOP
192 : : : ICP_QAT_FW_COMP_NOT_EOP,
193 : : ICP_QAT_FW_COMP_NOT_BFINAL,
194 : : ICP_QAT_FW_COMP_CNV,
195 : : ICP_QAT_FW_COMP_CNV_RECOVERY);
196 : : }
197 : :
198 : : /* common for sgl and flat buffers */
199 : 0 : comp_req->comp_pars.comp_len = op->src.length;
200 : 0 : comp_req->comp_pars.out_buffer_sz = rte_pktmbuf_pkt_len(op->m_dst) -
201 : 0 : op->dst.offset;
202 : :
203 [ # # # # ]: 0 : if (op->m_src->next != NULL || op->m_dst->next != NULL) {
204 : : /* sgl */
205 : : int ret = 0;
206 : :
207 : 0 : ICP_QAT_FW_COMN_PTR_TYPE_SET(comp_req->comn_hdr.comn_req_flags,
208 : : QAT_COMN_PTR_TYPE_SGL);
209 : :
210 [ # # ]: 0 : if (unlikely(op->m_src->nb_segs > cookie->src_nb_elems)) {
211 : : /* we need to allocate more elements in SGL*/
212 : : void *tmp;
213 : :
214 : 0 : tmp = rte_realloc_socket(cookie->qat_sgl_src_d,
215 : 0 : sizeof(struct qat_sgl) +
216 : : sizeof(struct qat_flat_buf) *
217 : 0 : op->m_src->nb_segs, 64,
218 : 0 : cookie->socket_id);
219 : :
220 [ # # ]: 0 : if (unlikely(tmp == NULL)) {
221 : 0 : QAT_DP_LOG(ERR, "QAT PMD can't allocate memory"
222 : : " for %d elements of SGL",
223 : : op->m_src->nb_segs);
224 : 0 : op->status = RTE_COMP_OP_STATUS_ERROR;
225 : : /* clear op-in-progress flag */
226 [ # # ]: 0 : if (stream)
227 : 0 : stream->op_in_progress = 0;
228 : 0 : return -ENOMEM;
229 : : }
230 : : /* new SGL is valid now */
231 : 0 : cookie->qat_sgl_src_d = (struct qat_sgl *)tmp;
232 : 0 : cookie->src_nb_elems = op->m_src->nb_segs;
233 : 0 : cookie->qat_sgl_src_phys_addr =
234 : 0 : rte_malloc_virt2iova(cookie->qat_sgl_src_d);
235 : : }
236 : :
237 : 0 : ret = qat_sgl_fill_array(op->m_src,
238 : 0 : op->src.offset,
239 : 0 : cookie->qat_sgl_src_d,
240 : : op->src.length,
241 : 0 : cookie->src_nb_elems);
242 [ # # ]: 0 : if (ret) {
243 : 0 : QAT_DP_LOG(ERR, "QAT PMD Cannot fill source sgl array");
244 : 0 : op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
245 : : /* clear op-in-progress flag */
246 [ # # ]: 0 : if (stream)
247 : 0 : stream->op_in_progress = 0;
248 : 0 : return ret;
249 : : }
250 : :
251 [ # # ]: 0 : if (unlikely(op->m_dst->nb_segs > cookie->dst_nb_elems)) {
252 : : /* we need to allocate more elements in SGL*/
253 : : struct qat_sgl *tmp;
254 : :
255 : 0 : tmp = rte_realloc_socket(cookie->qat_sgl_dst_d,
256 : 0 : sizeof(struct qat_sgl) +
257 : : sizeof(struct qat_flat_buf) *
258 : 0 : op->m_dst->nb_segs, 64,
259 : 0 : cookie->socket_id);
260 : :
261 [ # # ]: 0 : if (unlikely(tmp == NULL)) {
262 : 0 : QAT_DP_LOG(ERR, "QAT PMD can't allocate memory"
263 : : " for %d elements of SGL",
264 : : op->m_dst->nb_segs);
265 : 0 : op->status = RTE_COMP_OP_STATUS_ERROR;
266 : : /* clear op-in-progress flag */
267 [ # # ]: 0 : if (stream)
268 : 0 : stream->op_in_progress = 0;
269 : 0 : return -ENOMEM;
270 : : }
271 : : /* new SGL is valid now */
272 : 0 : cookie->qat_sgl_dst_d = (struct qat_sgl *)tmp;
273 : 0 : cookie->dst_nb_elems = op->m_dst->nb_segs;
274 : 0 : cookie->qat_sgl_dst_phys_addr =
275 : 0 : rte_malloc_virt2iova(cookie->qat_sgl_dst_d);
276 : : }
277 : :
278 : 0 : ret = qat_sgl_fill_array(op->m_dst,
279 : 0 : op->dst.offset,
280 : 0 : cookie->qat_sgl_dst_d,
281 : : comp_req->comp_pars.out_buffer_sz,
282 : 0 : cookie->dst_nb_elems);
283 [ # # ]: 0 : if (ret) {
284 : 0 : QAT_DP_LOG(ERR, "QAT PMD Cannot fill dest. sgl array");
285 : 0 : op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
286 : : /* clear op-in-progress flag */
287 [ # # ]: 0 : if (stream)
288 : 0 : stream->op_in_progress = 0;
289 : 0 : return ret;
290 : : }
291 : :
292 : 0 : comp_req->comn_mid.src_data_addr =
293 : 0 : cookie->qat_sgl_src_phys_addr;
294 : 0 : comp_req->comn_mid.dest_data_addr =
295 : 0 : cookie->qat_sgl_dst_phys_addr;
296 : 0 : comp_req->comn_mid.src_length = 0;
297 : 0 : comp_req->comn_mid.dst_length = 0;
298 : :
299 : : } else {
300 : : /* flat aka linear buffer */
301 : 0 : ICP_QAT_FW_COMN_PTR_TYPE_SET(comp_req->comn_hdr.comn_req_flags,
302 : : QAT_COMN_PTR_TYPE_FLAT);
303 : 0 : comp_req->comn_mid.src_length = op->src.length;
304 : 0 : comp_req->comn_mid.dst_length =
305 : : comp_req->comp_pars.out_buffer_sz;
306 : :
307 : 0 : comp_req->comn_mid.src_data_addr =
308 : 0 : rte_pktmbuf_iova_offset(op->m_src, op->src.offset);
309 : 0 : comp_req->comn_mid.dest_data_addr =
310 : 0 : rte_pktmbuf_iova_offset(op->m_dst, op->dst.offset);
311 : : }
312 : :
313 [ # # ]: 0 : if (unlikely(rte_pktmbuf_pkt_len(op->m_dst) < QAT_MIN_OUT_BUF_SIZE)) {
314 : : /* QAT doesn't support dest. buffer lower
315 : : * than QAT_MIN_OUT_BUF_SIZE. Propagate error mark
316 : : * by converting this request to the null one
317 : : * and check the status in the response.
318 : : */
319 : 0 : QAT_DP_LOG(WARNING, "QAT destination buffer too small - resend with larger buffer");
320 : 0 : comp_req->comn_hdr.service_type = ICP_QAT_FW_COMN_REQ_NULL;
321 : 0 : comp_req->comn_hdr.service_cmd_id = ICP_QAT_FW_NULL_REQ_SERV_ID;
322 : 0 : cookie->error = RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED;
323 : : }
324 : :
325 : : #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
326 : : QAT_DP_LOG(DEBUG, "Direction: %s",
327 : : qat_xform->qat_comp_request_type == QAT_COMP_REQUEST_DECOMPRESS ?
328 : : "decompression" : "compression");
329 : : QAT_DP_HEXDUMP_LOG(DEBUG, "qat compression message:", comp_req,
330 : : sizeof(struct icp_qat_fw_comp_req));
331 : : #endif
332 : : return 0;
333 : : }
334 : :
335 : : static inline uint32_t
336 : : adf_modulo(uint32_t data, uint32_t modulo_mask)
337 : : {
338 : 0 : return data & modulo_mask;
339 : : }
340 : :
341 : : static inline void
342 : : qat_comp_mbuf_skip(struct rte_mbuf **mbuf, uint32_t *offset, uint32_t len)
343 : : {
344 [ # # ]: 0 : while (*offset + len >= rte_pktmbuf_data_len(*mbuf)) {
345 : 0 : len -= (rte_pktmbuf_data_len(*mbuf) - *offset);
346 : 0 : *mbuf = (*mbuf)->next;
347 : 0 : *offset = 0;
348 : : }
349 : 0 : *offset = len;
350 : 0 : }
351 : :
352 : : int
353 : 0 : qat_comp_build_multiple_requests(void *in_op, struct qat_qp *qp,
354 : : uint32_t parent_tail, int nb_descr)
355 : : {
356 : : struct rte_comp_op op_backup;
357 : : struct rte_mbuf dst_mbuf;
358 : : struct rte_comp_op *op = in_op;
359 : : struct qat_queue *txq = &(qp->tx_q);
360 : 0 : uint8_t *base_addr = (uint8_t *)txq->base_addr;
361 : 0 : uint8_t *out_msg = base_addr + parent_tail;
362 : : uint32_t tail = parent_tail;
363 : : struct icp_qat_fw_comp_req *comp_req =
364 : : (struct icp_qat_fw_comp_req *)out_msg;
365 : 0 : struct qat_comp_op_cookie *parent_cookie =
366 : : (struct qat_comp_op_cookie *)
367 : 0 : qp->op_cookies[parent_tail / txq->msg_size];
368 : : struct qat_comp_op_cookie *child_cookie;
369 : : uint16_t dst_data_size =
370 : : RTE_MIN(RTE_PMD_QAT_COMP_IM_BUFFER_SIZE, 65535);
371 : 0 : uint32_t data_to_enqueue = op->src.length - QAT_FALLBACK_THLD;
372 : : int num_descriptors_built = 1;
373 : : int ret;
374 : :
375 : 0 : QAT_DP_LOG(DEBUG, "op %p, parent_cookie %p", op, parent_cookie);
376 : :
377 : : /* copy original op to the local variable for restoring later */
378 : : rte_memcpy(&op_backup, op, sizeof(op_backup));
379 : :
380 : 0 : parent_cookie->nb_child_responses = 0;
381 : 0 : parent_cookie->nb_children = 0;
382 : 0 : parent_cookie->split_op = 1;
383 : 0 : parent_cookie->dst_data = op->m_dst;
384 : 0 : parent_cookie->dst_data_offset = op->dst.offset;
385 : :
386 : 0 : op->src.length = QAT_FALLBACK_THLD;
387 : 0 : op->flush_flag = RTE_COMP_FLUSH_FULL;
388 : :
389 : 0 : QAT_DP_LOG(DEBUG, "parent op src len %u dst len %u",
390 : : op->src.length, op->m_dst->pkt_len);
391 : :
392 : 0 : ret = qat_comp_build_request(in_op, out_msg, parent_cookie,
393 : : qp->qat_dev_gen);
394 [ # # ]: 0 : if (ret != 0) {
395 : : /* restore op and clear cookie */
396 : 0 : QAT_DP_LOG(WARNING, "Failed to build parent descriptor");
397 : 0 : op->src.length = op_backup.src.length;
398 : 0 : op->flush_flag = op_backup.flush_flag;
399 : 0 : parent_cookie->split_op = 0;
400 : 0 : return ret;
401 : : }
402 : :
403 : : /* prepare local dst mbuf */
404 [ # # ]: 0 : rte_memcpy(&dst_mbuf, op->m_dst, sizeof(dst_mbuf));
405 : : rte_pktmbuf_reset(&dst_mbuf);
406 : 0 : dst_mbuf.buf_len = dst_data_size;
407 : 0 : dst_mbuf.data_len = dst_data_size;
408 : 0 : dst_mbuf.pkt_len = dst_data_size;
409 : 0 : dst_mbuf.data_off = 0;
410 : :
411 : : /* update op for the child operations */
412 : 0 : op->m_dst = &dst_mbuf;
413 : 0 : op->dst.offset = 0;
414 : :
415 [ # # ]: 0 : while (data_to_enqueue) {
416 : 0 : const struct rte_memzone *mz =
417 : 0 : parent_cookie->dst_memzones[num_descriptors_built - 1];
418 : 0 : uint32_t src_data_size = RTE_MIN(data_to_enqueue,
419 : : QAT_FALLBACK_THLD);
420 : : uint32_t cookie_index;
421 : :
422 : : /* update params for the next op */
423 : 0 : op->src.offset += QAT_FALLBACK_THLD;
424 : 0 : op->src.length = src_data_size;
425 : 0 : op->flush_flag = (src_data_size == data_to_enqueue) ?
426 [ # # ]: 0 : op_backup.flush_flag : RTE_COMP_FLUSH_FULL;
427 : :
428 : : /* update dst mbuf for the next op (use memzone for dst data) */
429 : 0 : dst_mbuf.buf_addr = mz->addr;
430 : 0 : dst_mbuf.buf_iova = mz->iova;
431 : :
432 : : /* move the tail and calculate next cookie index */
433 : 0 : tail = adf_modulo(tail + txq->msg_size, txq->modulo_mask);
434 : 0 : cookie_index = tail / txq->msg_size;
435 : 0 : child_cookie = (struct qat_comp_op_cookie *)
436 : 0 : qp->op_cookies[cookie_index];
437 : 0 : comp_req = (struct icp_qat_fw_comp_req *)(base_addr + tail);
438 : :
439 : : /* update child cookie */
440 : 0 : child_cookie->split_op = 1; /* must be set for child as well */
441 : 0 : child_cookie->parent_cookie = parent_cookie; /* same as above */
442 : 0 : child_cookie->nb_children = 0;
443 : 0 : child_cookie->dest_buffer = mz->addr;
444 : :
445 : 0 : QAT_DP_LOG(DEBUG,
446 : : "cookie_index %u, child_cookie %p, comp_req %p",
447 : : cookie_index, child_cookie, comp_req);
448 : 0 : QAT_DP_LOG(DEBUG,
449 : : "data_to_enqueue %u, num_descriptors_built %d",
450 : : data_to_enqueue, num_descriptors_built);
451 : 0 : QAT_DP_LOG(DEBUG, "child op src len %u dst len %u",
452 : : op->src.length, op->m_dst->pkt_len);
453 : :
454 : : /* build the request */
455 : 0 : ret = qat_comp_build_request(op, (uint8_t *)comp_req,
456 : : child_cookie, qp->qat_dev_gen);
457 [ # # ]: 0 : if (ret < 0) {
458 : 0 : QAT_DP_LOG(WARNING, "Failed to build child descriptor");
459 : : /* restore op and clear cookie */
460 : : rte_memcpy(op, &op_backup, sizeof(op_backup));
461 : 0 : parent_cookie->split_op = 0;
462 : 0 : parent_cookie->nb_children = 0;
463 : 0 : return ret;
464 : : }
465 : :
466 : 0 : data_to_enqueue -= src_data_size;
467 : 0 : num_descriptors_built++;
468 : : }
469 : :
470 : : /* restore backed up original op */
471 : : rte_memcpy(op, &op_backup, sizeof(op_backup));
472 : :
473 [ # # ]: 0 : if (nb_descr != num_descriptors_built)
474 : 0 : QAT_DP_LOG(ERR, "split op. expected %d, built %d",
475 : : nb_descr, num_descriptors_built);
476 : :
477 : 0 : parent_cookie->nb_children = num_descriptors_built - 1;
478 : 0 : return num_descriptors_built;
479 : : }
480 : :
481 : : static inline void
482 : 0 : qat_comp_response_data_copy(struct qat_comp_op_cookie *cookie,
483 : : struct rte_comp_op *rx_op)
484 : : {
485 : 0 : struct qat_comp_op_cookie *pc = cookie->parent_cookie;
486 : 0 : struct rte_mbuf *sgl_buf = pc->dst_data;
487 : 0 : void *op_dst_addr = rte_pktmbuf_mtod_offset(sgl_buf, uint8_t *,
488 : : pc->dst_data_offset);
489 : :
490 : : /* number of bytes left in the current segment */
491 : 0 : uint32_t left_in_current = rte_pktmbuf_data_len(sgl_buf) -
492 : : pc->dst_data_offset;
493 : :
494 : : uint32_t prod, sent;
495 : :
496 [ # # ]: 0 : if (rx_op->produced <= left_in_current) {
497 [ # # ]: 0 : rte_memcpy(op_dst_addr, cookie->dest_buffer,
498 : : rx_op->produced);
499 : : /* calculate dst mbuf and offset for the next child op */
500 [ # # ]: 0 : if (rx_op->produced == left_in_current) {
501 : 0 : pc->dst_data = sgl_buf->next;
502 : 0 : pc->dst_data_offset = 0;
503 : : } else
504 : 0 : pc->dst_data_offset += rx_op->produced;
505 : : } else {
506 [ # # ]: 0 : rte_memcpy(op_dst_addr, cookie->dest_buffer,
507 : : left_in_current);
508 : 0 : sgl_buf = sgl_buf->next;
509 : 0 : prod = rx_op->produced - left_in_current;
510 : : sent = left_in_current;
511 [ # # ]: 0 : while (prod > rte_pktmbuf_data_len(sgl_buf)) {
512 : 0 : op_dst_addr = rte_pktmbuf_mtod_offset(sgl_buf,
513 : : uint8_t *, 0);
514 : :
515 : 0 : rte_memcpy(op_dst_addr,
516 [ # # ]: 0 : ((uint8_t *)cookie->dest_buffer) +
517 : : sent,
518 : : rte_pktmbuf_data_len(sgl_buf));
519 : :
520 : 0 : prod -= rte_pktmbuf_data_len(sgl_buf);
521 : 0 : sent += rte_pktmbuf_data_len(sgl_buf);
522 : :
523 : 0 : sgl_buf = sgl_buf->next;
524 : : }
525 : :
526 : 0 : op_dst_addr = rte_pktmbuf_mtod_offset(sgl_buf, uint8_t *, 0);
527 : :
528 : 0 : rte_memcpy(op_dst_addr,
529 [ # # ]: 0 : ((uint8_t *)cookie->dest_buffer) + sent,
530 : : prod);
531 : :
532 : : /* calculate dst mbuf and offset for the next child op */
533 [ # # ]: 0 : if (prod == rte_pktmbuf_data_len(sgl_buf)) {
534 : 0 : pc->dst_data = sgl_buf->next;
535 : 0 : pc->dst_data_offset = 0;
536 : : } else {
537 : 0 : pc->dst_data = sgl_buf;
538 : 0 : pc->dst_data_offset = prod;
539 : : }
540 : : }
541 : 0 : }
542 : :
543 : : int
544 : 0 : qat_comp_process_response(void **op, uint8_t *resp, void *op_cookie,
545 : : uint64_t *dequeue_err_count)
546 : : {
547 : : struct icp_qat_fw_comp_resp *resp_msg =
548 : : (struct icp_qat_fw_comp_resp *)resp;
549 : : struct qat_comp_op_cookie *cookie =
550 : : (struct qat_comp_op_cookie *)op_cookie;
551 : :
552 : : struct icp_qat_fw_resp_comp_pars *comp_resp1 =
553 : : (struct icp_qat_fw_resp_comp_pars *)&resp_msg->comp_resp_pars;
554 : :
555 : 0 : QAT_DP_LOG(DEBUG, "input counter = %u, output counter = %u",
556 : : comp_resp1->input_byte_counter,
557 : : comp_resp1->output_byte_counter);
558 : :
559 : 0 : struct rte_comp_op *rx_op = (struct rte_comp_op *)(uintptr_t)
560 : 0 : (resp_msg->opaque_data);
561 : : struct qat_comp_stream *stream;
562 : : struct qat_comp_xform *qat_xform;
563 : 0 : int err = resp_msg->comn_resp.comn_status &
564 : : ((1 << QAT_COMN_RESP_CMP_STATUS_BITPOS) |
565 : : (1 << QAT_COMN_RESP_XLAT_STATUS_BITPOS));
566 : :
567 [ # # ]: 0 : if (rx_op->op_type == RTE_COMP_OP_STATEFUL) {
568 : 0 : stream = rx_op->stream;
569 : 0 : qat_xform = &stream->qat_xform;
570 : : /* clear op-in-progress flag */
571 : 0 : stream->op_in_progress = 0;
572 : : } else {
573 : : stream = NULL;
574 : 0 : qat_xform = rx_op->private_xform;
575 : : }
576 : :
577 : : #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
578 : : QAT_DP_LOG(DEBUG, "Direction: %s",
579 : : qat_xform->qat_comp_request_type == QAT_COMP_REQUEST_DECOMPRESS ?
580 : : "decompression" : "compression");
581 : : QAT_DP_HEXDUMP_LOG(DEBUG, "qat_response:", (uint8_t *)resp_msg,
582 : : sizeof(struct icp_qat_fw_comp_resp));
583 : : #endif
584 : :
585 [ # # ]: 0 : if (unlikely(cookie->error)) {
586 : 0 : rx_op->status = cookie->error;
587 : 0 : cookie->error = 0;
588 : 0 : ++(*dequeue_err_count);
589 : 0 : rx_op->debug_status = 0;
590 : 0 : rx_op->consumed = 0;
591 : 0 : rx_op->produced = 0;
592 : 0 : *op = (void *)rx_op;
593 : : /* also in this case number of returned ops */
594 : : /* must be equal to one, */
595 : : /* appropriate status (error) must be set as well */
596 : 0 : return 1;
597 : : }
598 : :
599 [ # # ]: 0 : if (likely(qat_xform->qat_comp_request_type
600 : : != QAT_COMP_REQUEST_DECOMPRESS)) {
601 [ # # ]: 0 : if (unlikely(ICP_QAT_FW_COMN_HDR_CNV_FLAG_GET(
602 : : resp_msg->comn_resp.hdr_flags)
603 : : == ICP_QAT_FW_COMP_NO_CNV)) {
604 : 0 : rx_op->status = RTE_COMP_OP_STATUS_ERROR;
605 : 0 : rx_op->debug_status = ERR_CODE_QAT_COMP_WRONG_FW;
606 : 0 : *op = (void *)rx_op;
607 : 0 : QAT_DP_LOG(ERR,
608 : : "This QAT hardware doesn't support compression operation");
609 : 0 : ++(*dequeue_err_count);
610 : 0 : return 1;
611 : : }
612 : : }
613 : :
614 [ # # ]: 0 : if (err) {
615 [ # # # # ]: 0 : if (unlikely((err & (1 << QAT_COMN_RESP_XLAT_STATUS_BITPOS))
616 : : && (qat_xform->qat_comp_request_type
617 : : == QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS))) {
618 : 0 : QAT_DP_LOG(ERR, "QAT intermediate buffer may be too "
619 : : "small for output, try configuring a larger size");
620 : : }
621 : :
622 : 0 : int8_t cmp_err_code =
623 : 0 : (int8_t)resp_msg->comn_resp.comn_error.cmp_err_code;
624 : 0 : int8_t xlat_err_code =
625 : 0 : (int8_t)resp_msg->comn_resp.comn_error.xlat_err_code;
626 : :
627 : : /* handle recoverable out-of-buffer condition in stateful
628 : : * decompression scenario
629 : : */
630 [ # # ]: 0 : if (cmp_err_code == ERR_CODE_OVERFLOW_ERROR && !xlat_err_code
631 [ # # ]: 0 : && qat_xform->qat_comp_request_type
632 : : == QAT_COMP_REQUEST_DECOMPRESS
633 [ # # ]: 0 : && rx_op->op_type == RTE_COMP_OP_STATEFUL) {
634 : : struct icp_qat_fw_resp_comp_pars *comp_resp =
635 : : &resp_msg->comp_resp_pars;
636 : 0 : rx_op->status =
637 : : RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE;
638 : 0 : rx_op->consumed = comp_resp->input_byte_counter;
639 : 0 : rx_op->produced = comp_resp->output_byte_counter;
640 : 0 : stream->start_of_packet = 0;
641 [ # # ]: 0 : } else if ((cmp_err_code == ERR_CODE_OVERFLOW_ERROR
642 : : && !xlat_err_code)
643 : 0 : ||
644 [ # # ]: 0 : (!cmp_err_code && xlat_err_code == ERR_CODE_OVERFLOW_ERROR)
645 : 0 : ||
646 [ # # ]: 0 : (cmp_err_code == ERR_CODE_OVERFLOW_ERROR &&
647 : : xlat_err_code == ERR_CODE_OVERFLOW_ERROR)){
648 : :
649 : : struct icp_qat_fw_resp_comp_pars *comp_resp =
650 : : (struct icp_qat_fw_resp_comp_pars *)
651 : : &resp_msg->comp_resp_pars;
652 : :
653 : : /* handle recoverable out-of-buffer condition
654 : : * in stateless compression scenario
655 : : */
656 [ # # ]: 0 : if (comp_resp->input_byte_counter) {
657 [ # # ]: 0 : if ((qat_xform->qat_comp_request_type
658 : : == QAT_COMP_REQUEST_FIXED_COMP_STATELESS) ||
659 : : (qat_xform->qat_comp_request_type
660 : : == QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS)) {
661 : :
662 : 0 : rx_op->status =
663 : : RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE;
664 : 0 : rx_op->consumed =
665 : : comp_resp->input_byte_counter;
666 : 0 : rx_op->produced =
667 : 0 : comp_resp->output_byte_counter;
668 : : } else
669 : 0 : rx_op->status =
670 : : RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED;
671 : : } else
672 : 0 : rx_op->status =
673 : : RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED;
674 : : } else
675 : 0 : rx_op->status = RTE_COMP_OP_STATUS_ERROR;
676 : :
677 : 0 : ++(*dequeue_err_count);
678 : 0 : rx_op->debug_status =
679 : 0 : *((uint16_t *)(&resp_msg->comn_resp.comn_error));
680 : : } else {
681 : : struct icp_qat_fw_resp_comp_pars *comp_resp =
682 : : (struct icp_qat_fw_resp_comp_pars *)&resp_msg->comp_resp_pars;
683 : :
684 : 0 : rx_op->status = RTE_COMP_OP_STATUS_SUCCESS;
685 : 0 : rx_op->consumed = comp_resp->input_byte_counter;
686 : 0 : rx_op->produced = comp_resp->output_byte_counter;
687 [ # # ]: 0 : if (stream)
688 : 0 : stream->start_of_packet = 0;
689 : :
690 [ # # ]: 0 : if (qat_xform->checksum_type != RTE_COMP_CHECKSUM_NONE) {
691 [ # # ]: 0 : if (qat_xform->checksum_type == RTE_COMP_CHECKSUM_CRC32)
692 : 0 : rx_op->output_chksum = comp_resp->curr_crc32;
693 [ # # ]: 0 : else if (qat_xform->checksum_type ==
694 : : RTE_COMP_CHECKSUM_ADLER32)
695 : 0 : rx_op->output_chksum = comp_resp->curr_adler_32;
696 : : else
697 : 0 : rx_op->output_chksum = comp_resp->curr_chksum;
698 : : }
699 : : }
700 : 0 : QAT_DP_LOG(DEBUG, "About to check for split op :cookies: %p %p, split:%u",
701 : : cookie, cookie->parent_cookie, cookie->split_op);
702 : :
703 [ # # ]: 0 : if (cookie->split_op) {
704 : 0 : *op = NULL;
705 : 0 : struct qat_comp_op_cookie *pc = cookie->parent_cookie;
706 : :
707 [ # # ]: 0 : if (cookie->nb_children > 0) {
708 : 0 : QAT_DP_LOG(DEBUG, "Parent");
709 : : /* parent - don't return until all children
710 : : * responses are collected
711 : : */
712 : 0 : cookie->total_consumed = rx_op->consumed;
713 : 0 : cookie->total_produced = rx_op->produced;
714 [ # # ]: 0 : if (err) {
715 : 0 : cookie->error = rx_op->status;
716 : 0 : rx_op->status = RTE_COMP_OP_STATUS_SUCCESS;
717 : : } else {
718 : : /* calculate dst mbuf and offset for child op */
719 : : qat_comp_mbuf_skip(&cookie->dst_data,
720 : : &cookie->dst_data_offset,
721 : : rx_op->produced);
722 : : }
723 : : } else {
724 : 0 : QAT_DP_LOG(DEBUG, "Child");
725 [ # # ]: 0 : if (pc->error == RTE_COMP_OP_STATUS_SUCCESS) {
726 [ # # ]: 0 : if (err)
727 : 0 : pc->error = rx_op->status;
728 [ # # ]: 0 : if (rx_op->produced) {
729 : : /* this covers both SUCCESS and
730 : : * OUT_OF_SPACE_RECOVERABLE cases
731 : : */
732 : 0 : qat_comp_response_data_copy(cookie,
733 : : rx_op);
734 : 0 : pc->total_consumed += rx_op->consumed;
735 : 0 : pc->total_produced += rx_op->produced;
736 : : }
737 : : }
738 : 0 : rx_op->status = RTE_COMP_OP_STATUS_SUCCESS;
739 : :
740 : 0 : pc->nb_child_responses++;
741 : :
742 : : /* (child) cookie fields have to be reset
743 : : * to avoid problems with reusability -
744 : : * rx and tx queue starting from index zero
745 : : */
746 : 0 : cookie->nb_children = 0;
747 : 0 : cookie->split_op = 0;
748 : 0 : cookie->nb_child_responses = 0;
749 : 0 : cookie->dest_buffer = NULL;
750 : :
751 [ # # ]: 0 : if (pc->nb_child_responses == pc->nb_children) {
752 : : uint8_t child_resp;
753 : :
754 : : /* parent should be included as well */
755 : 0 : child_resp = pc->nb_child_responses + 1;
756 : :
757 : 0 : rx_op->status = pc->error;
758 : 0 : rx_op->consumed = pc->total_consumed;
759 : 0 : rx_op->produced = pc->total_produced;
760 : 0 : *op = (void *)rx_op;
761 : :
762 : : /* free memzones used for dst data */
763 : 0 : qat_comp_free_split_op_memzones(pc,
764 : : pc->nb_children);
765 : :
766 : : /* (parent) cookie fields have to be reset
767 : : * to avoid problems with reusability -
768 : : * rx and tx queue starting from index zero
769 : : */
770 : 0 : pc->nb_children = 0;
771 : 0 : pc->split_op = 0;
772 : 0 : pc->nb_child_responses = 0;
773 : 0 : pc->error = RTE_COMP_OP_STATUS_SUCCESS;
774 : :
775 : 0 : return child_resp;
776 : : }
777 : : }
778 : 0 : return 0;
779 : : }
780 : :
781 : 0 : *op = (void *)rx_op;
782 : 0 : return 1;
783 : : }
784 : :
785 : : unsigned int
786 : 0 : qat_comp_xform_size(void)
787 : : {
788 : 0 : return RTE_ALIGN_CEIL(sizeof(struct qat_comp_xform), 8);
789 : : }
790 : :
791 : : unsigned int
792 : 0 : qat_comp_stream_size(void)
793 : : {
794 : 0 : return RTE_ALIGN_CEIL(sizeof(struct qat_comp_stream), 8);
795 : : }
796 : :
797 : : static void
798 : : qat_comp_create_req_hdr(struct icp_qat_fw_comn_req_hdr *header,
799 : : enum qat_comp_request_type request)
800 : : {
801 : 0 : if (request == QAT_COMP_REQUEST_FIXED_COMP_STATELESS)
802 : 0 : header->service_cmd_id = ICP_QAT_FW_COMP_CMD_STATIC;
803 [ # # ]: 0 : else if (request == QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS)
804 : 0 : header->service_cmd_id = ICP_QAT_FW_COMP_CMD_DYNAMIC;
805 [ # # ]: 0 : else if (request == QAT_COMP_REQUEST_DECOMPRESS)
806 : 0 : header->service_cmd_id = ICP_QAT_FW_COMP_CMD_DECOMPRESS;
807 : :
808 : 0 : header->service_type = ICP_QAT_FW_COMN_REQ_CPM_FW_COMP;
809 : 0 : header->hdr_flags =
810 : : ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET);
811 : :
812 : 0 : header->comn_req_flags = ICP_QAT_FW_COMN_FLAGS_BUILD(
813 : : QAT_COMN_CD_FLD_TYPE_16BYTE_DATA, QAT_COMN_PTR_TYPE_FLAT);
814 : : }
815 : :
816 : : static int
817 : 0 : qat_comp_create_templates(struct qat_comp_xform *qat_xform,
818 : : const struct rte_memzone *interm_buff_mz,
819 : : const struct rte_comp_xform *xform,
820 : : const struct qat_comp_stream *stream,
821 : : enum rte_comp_op_type op_type,
822 : : enum qat_device_gen qat_dev_gen)
823 : : {
824 : : struct icp_qat_fw_comp_req *comp_req;
825 : : uint32_t req_par_flags;
826 : : int res;
827 : :
828 [ # # ]: 0 : if (unlikely(qat_xform == NULL)) {
829 : 0 : QAT_LOG(ERR, "Session was not created for this device");
830 : 0 : return -EINVAL;
831 : : }
832 : :
833 [ # # ]: 0 : if (op_type == RTE_COMP_OP_STATEFUL) {
834 [ # # ]: 0 : if (unlikely(stream == NULL)) {
835 : 0 : QAT_LOG(ERR, "Stream must be non null for stateful op");
836 : 0 : return -EINVAL;
837 : : }
838 [ # # ]: 0 : if (unlikely(qat_xform->qat_comp_request_type !=
839 : : QAT_COMP_REQUEST_DECOMPRESS)) {
840 : 0 : QAT_LOG(ERR, "QAT PMD does not support stateful compression");
841 : 0 : return -ENOTSUP;
842 : : }
843 : : }
844 : :
845 [ # # ]: 0 : if (qat_xform->qat_comp_request_type == QAT_COMP_REQUEST_DECOMPRESS)
846 : : req_par_flags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(
847 : : ICP_QAT_FW_COMP_SOP, ICP_QAT_FW_COMP_EOP,
848 : : ICP_QAT_FW_COMP_BFINAL,
849 : : ICP_QAT_FW_COMP_CNV,
850 : : ICP_QAT_FW_COMP_CNV_RECOVERY);
851 : : else
852 : : req_par_flags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(
853 : : ICP_QAT_FW_COMP_SOP, ICP_QAT_FW_COMP_EOP,
854 : : ICP_QAT_FW_COMP_BFINAL, ICP_QAT_FW_COMP_CNV,
855 : : ICP_QAT_FW_COMP_CNV_RECOVERY);
856 : :
857 : : comp_req = &qat_xform->qat_comp_req_tmpl;
858 : :
859 : : /* Initialize header */
860 : : qat_comp_create_req_hdr(&comp_req->comn_hdr,
861 : : qat_xform->qat_comp_request_type);
862 : :
863 [ # # ]: 0 : if (op_type == RTE_COMP_OP_STATEFUL) {
864 : 0 : comp_req->comn_hdr.serv_specif_flags =
865 : : ICP_QAT_FW_COMP_FLAGS_BUILD(
866 : : ICP_QAT_FW_COMP_STATEFUL_SESSION,
867 : : ICP_QAT_FW_COMP_NOT_AUTO_SELECT_BEST,
868 : : ICP_QAT_FW_COMP_NOT_ENH_AUTO_SELECT_BEST,
869 : : ICP_QAT_FW_COMP_NOT_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST,
870 : : ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF);
871 : :
872 : : /* Decompression state registers */
873 : 0 : comp_req->comp_cd_ctrl.comp_state_addr =
874 : 0 : stream->state_registers_decomp_phys;
875 : :
876 : : /* RAM bank flags */
877 : 0 : comp_req->comp_cd_ctrl.ram_bank_flags =
878 : 0 : qat_comp_gen_dev_ops[qat_dev_gen]
879 : 0 : .qat_comp_get_ram_bank_flags();
880 : :
881 : 0 : comp_req->comp_cd_ctrl.ram_banks_addr =
882 : 0 : stream->inflate_context_phys;
883 : : } else {
884 : 0 : comp_req->comn_hdr.serv_specif_flags =
885 : : ICP_QAT_FW_COMP_FLAGS_BUILD(
886 : : ICP_QAT_FW_COMP_STATELESS_SESSION,
887 : : ICP_QAT_FW_COMP_NOT_AUTO_SELECT_BEST,
888 : : ICP_QAT_FW_COMP_NOT_ENH_AUTO_SELECT_BEST,
889 : : ICP_QAT_FW_COMP_NOT_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST,
890 : : ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF);
891 : : }
892 : :
893 : 0 : res = qat_comp_gen_dev_ops[qat_dev_gen].qat_comp_set_slice_cfg_word(
894 : : qat_xform, xform, op_type,
895 : 0 : comp_req->cd_pars.sl.comp_slice_cfg_word);
896 [ # # ]: 0 : if (res)
897 : : return res;
898 : :
899 : 0 : comp_req->comp_pars.initial_adler = 1;
900 : 0 : comp_req->comp_pars.initial_crc32 = 0;
901 : 0 : comp_req->comp_pars.req_par_flags = req_par_flags;
902 : :
903 : :
904 : 0 : if (qat_xform->qat_comp_request_type ==
905 [ # # ]: 0 : QAT_COMP_REQUEST_FIXED_COMP_STATELESS ||
906 : : qat_xform->qat_comp_request_type == QAT_COMP_REQUEST_DECOMPRESS) {
907 : : ICP_QAT_FW_COMN_NEXT_ID_SET(&comp_req->comp_cd_ctrl,
908 : : ICP_QAT_FW_SLICE_DRAM_WR);
909 : 0 : ICP_QAT_FW_COMN_CURR_ID_SET(&comp_req->comp_cd_ctrl,
910 : : ICP_QAT_FW_SLICE_COMP);
911 [ # # ]: 0 : } else if (qat_xform->qat_comp_request_type ==
912 : : QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS) {
913 : :
914 : : ICP_QAT_FW_COMN_NEXT_ID_SET(&comp_req->comp_cd_ctrl,
915 : : ICP_QAT_FW_SLICE_XLAT);
916 : 0 : ICP_QAT_FW_COMN_CURR_ID_SET(&comp_req->comp_cd_ctrl,
917 : : ICP_QAT_FW_SLICE_COMP);
918 : :
919 : : ICP_QAT_FW_COMN_NEXT_ID_SET(&comp_req->u2.xlt_cd_ctrl,
920 : : ICP_QAT_FW_SLICE_DRAM_WR);
921 : 0 : ICP_QAT_FW_COMN_CURR_ID_SET(&comp_req->u2.xlt_cd_ctrl,
922 : : ICP_QAT_FW_SLICE_XLAT);
923 : :
924 : 0 : comp_req->u1.xlt_pars.inter_buff_ptr =
925 : : (qat_comp_get_num_im_bufs_required(qat_dev_gen)
926 [ # # ]: 0 : == 0) ? 0 : interm_buff_mz->iova;
927 : : }
928 : :
929 : : #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
930 : : QAT_DP_HEXDUMP_LOG(DEBUG, "qat compression message template:", comp_req,
931 : : sizeof(struct icp_qat_fw_comp_req));
932 : : #endif
933 : : return 0;
934 : : }
935 : :
936 : : /**
937 : : * Create driver private_xform data.
938 : : *
939 : : * @param dev
940 : : * Compressdev device
941 : : * @param xform
942 : : * xform data from application
943 : : * @param private_xform
944 : : * ptr where handle of pmd's private_xform data should be stored
945 : : * @return
946 : : * - if successful returns 0
947 : : * and valid private_xform handle
948 : : * - <0 in error cases
949 : : * - Returns -EINVAL if input parameters are invalid.
950 : : * - Returns -ENOTSUP if comp device does not support the comp transform.
951 : : * - Returns -ENOMEM if the private_xform could not be allocated.
952 : : */
953 : : int
954 : 0 : qat_comp_private_xform_create(struct rte_compressdev *dev,
955 : : const struct rte_comp_xform *xform,
956 : : void **private_xform)
957 : : {
958 : 0 : struct qat_comp_dev_private *qat = dev->data->dev_private;
959 : 0 : enum qat_device_gen qat_dev_gen = qat->qat_dev->qat_dev_gen;
960 : : unsigned int im_bufs = qat_comp_get_num_im_bufs_required(qat_dev_gen);
961 : :
962 [ # # ]: 0 : if (unlikely(private_xform == NULL)) {
963 : 0 : QAT_LOG(ERR, "QAT: private_xform parameter is NULL");
964 : 0 : return -EINVAL;
965 : : }
966 [ # # ]: 0 : if (unlikely(qat->xformpool == NULL)) {
967 : 0 : QAT_LOG(ERR, "QAT device has no private_xform mempool");
968 : 0 : return -ENOMEM;
969 : : }
970 [ # # ]: 0 : if (rte_mempool_get(qat->xformpool, private_xform)) {
971 : 0 : QAT_LOG(ERR, "Couldn't get object from qat xform mempool");
972 : 0 : return -ENOMEM;
973 : : }
974 : :
975 : 0 : struct qat_comp_xform *qat_xform =
976 : : (struct qat_comp_xform *)*private_xform;
977 : :
978 [ # # ]: 0 : if (xform->type == RTE_COMP_COMPRESS) {
979 : :
980 [ # # # # ]: 0 : if (xform->compress.deflate.huffman == RTE_COMP_HUFFMAN_FIXED ||
981 : : ((xform->compress.deflate.huffman == RTE_COMP_HUFFMAN_DEFAULT)
982 [ # # ]: 0 : && qat->interm_buff_mz == NULL
983 [ # # ]: 0 : && im_bufs > 0))
984 : 0 : qat_xform->qat_comp_request_type =
985 : : QAT_COMP_REQUEST_FIXED_COMP_STATELESS;
986 : :
987 : 0 : else if ((xform->compress.deflate.huffman ==
988 [ # # ]: 0 : RTE_COMP_HUFFMAN_DYNAMIC ||
989 : : xform->compress.deflate.huffman ==
990 : 0 : RTE_COMP_HUFFMAN_DEFAULT) &&
991 [ # # # # ]: 0 : (qat->interm_buff_mz != NULL ||
992 : : im_bufs == 0))
993 : :
994 : 0 : qat_xform->qat_comp_request_type =
995 : : QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS;
996 : :
997 : : else {
998 : 0 : QAT_LOG(ERR,
999 : : "IM buffers needed for dynamic deflate. Set size in config file");
1000 : 0 : return -EINVAL;
1001 : : }
1002 : :
1003 : 0 : qat_xform->checksum_type = xform->compress.chksum;
1004 : :
1005 : : } else {
1006 : 0 : qat_xform->qat_comp_request_type = QAT_COMP_REQUEST_DECOMPRESS;
1007 : 0 : qat_xform->checksum_type = xform->decompress.chksum;
1008 : : }
1009 : :
1010 [ # # ]: 0 : if (qat_comp_create_templates(qat_xform, qat->interm_buff_mz, xform,
1011 : : NULL, RTE_COMP_OP_STATELESS,
1012 : : qat_dev_gen)) {
1013 : 0 : QAT_LOG(ERR, "QAT: Problem with setting compression");
1014 : 0 : return -EINVAL;
1015 : : }
1016 : : return 0;
1017 : : }
1018 : :
1019 : : /**
1020 : : * Free driver private_xform data.
1021 : : *
1022 : : * @param dev
1023 : : * Compressdev device
1024 : : * @param private_xform
1025 : : * handle of pmd's private_xform data
1026 : : * @return
1027 : : * - 0 if successful
1028 : : * - <0 in error cases
1029 : : * - Returns -EINVAL if input parameters are invalid.
1030 : : */
1031 : : int
1032 : 0 : qat_comp_private_xform_free(struct rte_compressdev *dev __rte_unused,
1033 : : void *private_xform)
1034 : : {
1035 : : struct qat_comp_xform *qat_xform =
1036 : : (struct qat_comp_xform *)private_xform;
1037 : :
1038 [ # # ]: 0 : if (qat_xform) {
1039 [ # # ]: 0 : memset(qat_xform, 0, qat_comp_xform_size());
1040 : : struct rte_mempool *mp = rte_mempool_from_obj(qat_xform);
1041 : :
1042 : 0 : rte_mempool_put(mp, qat_xform);
1043 : 0 : return 0;
1044 : : }
1045 : : return -EINVAL;
1046 : : }
1047 : :
1048 : : /**
1049 : : * Reset stream state for the next use.
1050 : : *
1051 : : * @param stream
1052 : : * handle of pmd's private stream data
1053 : : */
1054 : : static void
1055 : : qat_comp_stream_reset(struct qat_comp_stream *stream)
1056 : : {
1057 : 0 : if (stream) {
1058 : 0 : memset(&stream->qat_xform, 0, sizeof(struct qat_comp_xform));
1059 : 0 : stream->start_of_packet = 1;
1060 : 0 : stream->op_in_progress = 0;
1061 : : }
1062 : : }
1063 : :
1064 : : /**
1065 : : * Create driver private stream data.
1066 : : *
1067 : : * @param dev
1068 : : * Compressdev device
1069 : : * @param xform
1070 : : * xform data
1071 : : * @param stream
1072 : : * ptr where handle of pmd's private stream data should be stored
1073 : : * @return
1074 : : * - Returns 0 if private stream structure has been created successfully.
1075 : : * - Returns -EINVAL if input parameters are invalid.
1076 : : * - Returns -ENOTSUP if comp device does not support STATEFUL operations.
1077 : : * - Returns -ENOTSUP if comp device does not support the comp transform.
1078 : : * - Returns -ENOMEM if the private stream could not be allocated.
1079 : : */
1080 : : int
1081 : 0 : qat_comp_stream_create(struct rte_compressdev *dev,
1082 : : const struct rte_comp_xform *xform,
1083 : : void **stream)
1084 : : {
1085 : 0 : struct qat_comp_dev_private *qat = dev->data->dev_private;
1086 : : struct qat_comp_stream *ptr;
1087 : :
1088 [ # # ]: 0 : if (unlikely(stream == NULL)) {
1089 : 0 : QAT_LOG(ERR, "QAT: stream parameter is NULL");
1090 : 0 : return -EINVAL;
1091 : : }
1092 [ # # ]: 0 : if (unlikely(xform->type == RTE_COMP_COMPRESS)) {
1093 : 0 : QAT_LOG(ERR, "QAT: stateful compression not supported");
1094 : 0 : return -ENOTSUP;
1095 : : }
1096 [ # # ]: 0 : if (unlikely(qat->streampool == NULL)) {
1097 : 0 : QAT_LOG(ERR, "QAT device has no stream mempool");
1098 : 0 : return -ENOMEM;
1099 : : }
1100 [ # # ]: 0 : if (rte_mempool_get(qat->streampool, stream)) {
1101 : 0 : QAT_LOG(ERR, "Couldn't get object from qat stream mempool");
1102 : 0 : return -ENOMEM;
1103 : : }
1104 : :
1105 [ # # ]: 0 : ptr = (struct qat_comp_stream *) *stream;
1106 : : qat_comp_stream_reset(ptr);
1107 : 0 : ptr->qat_xform.qat_comp_request_type = QAT_COMP_REQUEST_DECOMPRESS;
1108 : 0 : ptr->qat_xform.checksum_type = xform->decompress.chksum;
1109 : :
1110 [ # # ]: 0 : if (qat_comp_create_templates(&ptr->qat_xform, qat->interm_buff_mz,
1111 : : xform, ptr, RTE_COMP_OP_STATEFUL,
1112 : 0 : qat->qat_dev->qat_dev_gen)) {
1113 : 0 : QAT_LOG(ERR, "QAT: problem with creating descriptor template for stream");
1114 [ # # ]: 0 : rte_mempool_put(qat->streampool, *stream);
1115 : 0 : *stream = NULL;
1116 : 0 : return -EINVAL;
1117 : : }
1118 : :
1119 : : return 0;
1120 : : }
1121 : :
1122 : : /**
1123 : : * Free driver private stream data.
1124 : : *
1125 : : * @param dev
1126 : : * Compressdev device
1127 : : * @param stream
1128 : : * handle of pmd's private stream data
1129 : : * @return
1130 : : * - 0 if successful
1131 : : * - <0 in error cases
1132 : : * - Returns -EINVAL if input parameters are invalid.
1133 : : * - Returns -ENOTSUP if comp device does not support STATEFUL operations.
1134 : : * - Returns -EBUSY if can't free stream as there are inflight operations
1135 : : */
1136 : : int
1137 : 0 : qat_comp_stream_free(struct rte_compressdev *dev, void *stream)
1138 : : {
1139 [ # # ]: 0 : if (stream) {
1140 [ # # ]: 0 : struct qat_comp_dev_private *qat = dev->data->dev_private;
1141 : : qat_comp_stream_reset((struct qat_comp_stream *) stream);
1142 [ # # ]: 0 : rte_mempool_put(qat->streampool, stream);
1143 : 0 : return 0;
1144 : : }
1145 : : return -EINVAL;
1146 : : }
1147 : :
1148 : : /**
1149 : : * Enqueue packets for processing on queue pair of a device
1150 : : *
1151 : : * @param qp
1152 : : * qat queue pair
1153 : : * @param ops
1154 : : * Compressdev operation
1155 : : * @param nb_ops
1156 : : * number of operations
1157 : : * @return
1158 : : * - nb_ops_sent if successful
1159 : : */
1160 : : uint16_t
1161 : 0 : qat_enqueue_comp_op_burst(void *qp, void **ops, uint16_t nb_ops)
1162 : : {
1163 : : register struct qat_queue *queue;
1164 : : struct qat_qp *tmp_qp = (struct qat_qp *)qp;
1165 : : register uint32_t nb_ops_sent = 0;
1166 : : register int nb_desc_to_build;
1167 : : uint16_t nb_ops_possible = nb_ops;
1168 : : register uint8_t *base_addr;
1169 : : register uint32_t tail;
1170 : :
1171 : : int descriptors_built, total_descriptors_built = 0;
1172 : : int nb_remaining_descriptors;
1173 : : int overflow = 0;
1174 : :
1175 [ # # ]: 0 : if (unlikely(nb_ops == 0))
1176 : : return 0;
1177 : :
1178 : : /* read params used a lot in main loop into registers */
1179 : 0 : queue = &(tmp_qp->tx_q);
1180 : 0 : base_addr = (uint8_t *)queue->base_addr;
1181 : 0 : tail = queue->tail;
1182 : :
1183 : : /* Find how many can actually fit on the ring */
1184 : : {
1185 : : /* dequeued can only be written by one thread, but it may not
1186 : : * be this thread. As it's 4-byte aligned it will be read
1187 : : * atomically here by any Intel CPU.
1188 : : * enqueued can wrap before dequeued, but cannot
1189 : : * lap it as var size of enq/deq (uint32_t) > var size of
1190 : : * max_inflights (uint16_t). In reality inflights is never
1191 : : * even as big as max uint16_t, as it's <= ADF_MAX_DESC.
1192 : : * On wrapping, the calculation still returns the correct
1193 : : * positive value as all three vars are unsigned.
1194 : : */
1195 : 0 : uint32_t inflights =
1196 : 0 : tmp_qp->enqueued - tmp_qp->dequeued;
1197 : :
1198 : : /* Find how many can actually fit on the ring */
1199 : 0 : overflow = (inflights + nb_ops) - tmp_qp->max_inflights;
1200 [ # # ]: 0 : if (overflow > 0) {
1201 : 0 : nb_ops_possible = nb_ops - overflow;
1202 [ # # ]: 0 : if (nb_ops_possible == 0)
1203 : : return 0;
1204 : : }
1205 : :
1206 : : /* QAT has plenty of work queued already, so don't waste cycles
1207 : : * enqueueing, wait til the application has gathered a bigger
1208 : : * burst or some completed ops have been dequeued
1209 : : */
1210 [ # # # # ]: 0 : if (tmp_qp->min_enq_burst_threshold && inflights >
1211 [ # # ]: 0 : QAT_QP_MIN_INFL_THRESHOLD && nb_ops_possible <
1212 : : tmp_qp->min_enq_burst_threshold) {
1213 : 0 : tmp_qp->stats.threshold_hit_count++;
1214 : 0 : return 0;
1215 : : }
1216 : : }
1217 : :
1218 : : /* At this point nb_ops_possible is assuming a 1:1 mapping
1219 : : * between ops and descriptors.
1220 : : * Fewer may be sent if some ops have to be split.
1221 : : * nb_ops_possible is <= burst size.
1222 : : * Find out how many spaces are actually available on the qp in case
1223 : : * more are needed.
1224 : : */
1225 : 0 : nb_remaining_descriptors = nb_ops_possible
1226 [ # # ]: 0 : + ((overflow >= 0) ? 0 : overflow * (-1));
1227 : 0 : QAT_DP_LOG(DEBUG, "Nb ops requested %d, nb descriptors remaining %d",
1228 : : nb_ops, nb_remaining_descriptors);
1229 : :
1230 [ # # # # ]: 0 : while (nb_ops_sent != nb_ops_possible &&
1231 : : nb_remaining_descriptors > 0) {
1232 : 0 : struct qat_comp_op_cookie *cookie =
1233 : 0 : tmp_qp->op_cookies[tail >> queue->trailz];
1234 : :
1235 : : descriptors_built = 0;
1236 : :
1237 : 0 : QAT_DP_LOG(DEBUG, "--- data length: %u",
1238 : : ((struct rte_comp_op *)*ops)->src.length);
1239 : :
1240 : 0 : nb_desc_to_build = qat_comp_build_request(*ops,
1241 : : base_addr + tail, cookie, tmp_qp->qat_dev_gen);
1242 : 0 : QAT_DP_LOG(DEBUG, "%d descriptors built, %d remaining, "
1243 : : "%d ops sent, %d descriptors needed",
1244 : : total_descriptors_built, nb_remaining_descriptors,
1245 : : nb_ops_sent, nb_desc_to_build);
1246 : :
1247 [ # # ]: 0 : if (unlikely(nb_desc_to_build < 0)) {
1248 : : /* this message cannot be enqueued */
1249 : 0 : tmp_qp->stats.enqueue_err_count++;
1250 [ # # ]: 0 : if (nb_ops_sent == 0)
1251 : : return 0;
1252 : 0 : goto kick_tail;
1253 [ # # ]: 0 : } else if (unlikely(nb_desc_to_build > 1)) {
1254 : : /* this op is too big and must be split - get more
1255 : : * descriptors and retry
1256 : : */
1257 : :
1258 : 0 : QAT_DP_LOG(DEBUG, "Build %d descriptors for this op",
1259 : : nb_desc_to_build);
1260 : :
1261 : 0 : nb_remaining_descriptors -= nb_desc_to_build;
1262 [ # # ]: 0 : if (nb_remaining_descriptors >= 0) {
1263 : : /* There are enough remaining descriptors
1264 : : * so retry
1265 : : */
1266 : 0 : int ret2 = qat_comp_build_multiple_requests(
1267 : : *ops, tmp_qp, tail,
1268 : : nb_desc_to_build);
1269 : :
1270 [ # # ]: 0 : if (unlikely(ret2 < 1)) {
1271 : 0 : QAT_DP_LOG(DEBUG,
1272 : : "Failed to build (%d) descriptors, status %d",
1273 : : nb_desc_to_build, ret2);
1274 : :
1275 : 0 : qat_comp_free_split_op_memzones(cookie,
1276 : 0 : nb_desc_to_build - 1);
1277 : :
1278 : 0 : tmp_qp->stats.enqueue_err_count++;
1279 : :
1280 : : /* This message cannot be enqueued */
1281 [ # # ]: 0 : if (nb_ops_sent == 0)
1282 : : return 0;
1283 : 0 : goto kick_tail;
1284 : : } else {
1285 : : descriptors_built = ret2;
1286 : 0 : total_descriptors_built +=
1287 : : descriptors_built;
1288 : 0 : nb_remaining_descriptors -=
1289 : : descriptors_built;
1290 : 0 : QAT_DP_LOG(DEBUG,
1291 : : "Multiple descriptors (%d) built ok",
1292 : : descriptors_built);
1293 : : }
1294 : : } else {
1295 : 0 : QAT_DP_LOG(ERR, "For the current op, number of requested descriptors (%d) "
1296 : : "exceeds number of available descriptors (%d)",
1297 : : nb_desc_to_build,
1298 : : nb_remaining_descriptors +
1299 : : nb_desc_to_build);
1300 : :
1301 : 0 : qat_comp_free_split_op_memzones(cookie,
1302 : 0 : nb_desc_to_build - 1);
1303 : :
1304 : : /* Not enough extra descriptors */
1305 [ # # ]: 0 : if (nb_ops_sent == 0)
1306 : : return 0;
1307 : 0 : goto kick_tail;
1308 : : }
1309 : : } else {
1310 : : descriptors_built = 1;
1311 : 0 : total_descriptors_built++;
1312 : 0 : nb_remaining_descriptors--;
1313 : 0 : QAT_DP_LOG(DEBUG, "Single descriptor built ok");
1314 : : }
1315 : :
1316 : 0 : tail = adf_modulo(tail + (queue->msg_size * descriptors_built),
1317 : : queue->modulo_mask);
1318 : 0 : ops++;
1319 : 0 : nb_ops_sent++;
1320 : : }
1321 : :
1322 : 0 : kick_tail:
1323 : 0 : queue->tail = tail;
1324 : 0 : tmp_qp->enqueued += total_descriptors_built;
1325 : 0 : tmp_qp->stats.enqueued_count += nb_ops_sent;
1326 : 0 : txq_write_tail(tmp_qp->qat_dev_gen, tmp_qp, queue);
1327 : 0 : return nb_ops_sent;
1328 : : }
|