1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 /**
5  *****************************************************************************
6  * @file dc_buffers.c
7  *
8  * @defgroup Dc_DataCompression DC Data Compression
9  *
10  * @ingroup Dc_DataCompression
11  *
12  * @description
13  *      Implementation of the buffer management operations for
14  *      Data Compression service.
15  *
16  *****************************************************************************/
17 
18 /*
19 *******************************************************************************
20 * Include public/global header files
21 *******************************************************************************
22 */
23 #include "cpa.h"
24 #include "cpa_dc.h"
25 #include "cpa_dc_bp.h"
26 
27 #include "sal_types_compression.h"
28 #include "icp_qat_fw_comp.h"
29 #include "sal_hw_gen.h"
30 
31 #define CPA_DC_CEIL_DIV(x, y) (((x) + (y)-1) / (y))
32 #define DC_DEST_BUFF_EXTRA_DEFLATE_GEN2 (55)
33 #define DC_DEST_BUFF_EXTRA_DEFLATE_GEN4_STATIC (1029)
34 #define DC_DEST_BUFF_EXTRA_DEFLATE_GEN4_DYN (512)
35 #define DC_DEST_BUFF_MIN_EXTRA_BYTES(x) ((x < 8) ? (8 - x) : 0)
36 #define DC_BUF_MAX_SIZE (0xFFFFFFFF)
37 
38 CpaStatus
39 cpaDcBufferListGetMetaSize(const CpaInstanceHandle instanceHandle,
40 			   Cpa32U numBuffers,
41 			   Cpa32U *pSizeInBytes)
42 {
43 	CpaInstanceHandle insHandle = NULL;
44 
45 	if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) {
46 		insHandle = dcGetFirstHandle();
47 	} else {
48 		insHandle = instanceHandle;
49 	}
50 
51 	LAC_CHECK_INSTANCE_HANDLE(insHandle);
52 	LAC_CHECK_NULL_PARAM(pSizeInBytes);
53 
54 	/* Ensure this is a compression instance */
55 	SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
56 
57 	if (0 == numBuffers) {
58 		QAT_UTILS_LOG("Number of buffers is 0.\n");
59 		return CPA_STATUS_INVALID_PARAM;
60 	}
61 
62 	*pSizeInBytes = (sizeof(icp_buffer_list_desc_t) +
63 			 (sizeof(icp_flat_buffer_desc_t) * (numBuffers + 1)) +
64 			 ICP_DESCRIPTOR_ALIGNMENT_BYTES);
65 
66 	return CPA_STATUS_SUCCESS;
67 }
68 
69 CpaStatus
70 cpaDcBnpBufferListGetMetaSize(const CpaInstanceHandle instanceHandle,
71 			      Cpa32U numJobs,
72 			      Cpa32U *pSizeInBytes)
73 {
74 	return CPA_STATUS_UNSUPPORTED;
75 }
76 
77 static inline CpaStatus
78 dcDeflateBoundGen2(CpaDcHuffType huffType, Cpa32U inputSize, Cpa32U *outputSize)
79 {
80 	Cpa64U inBufferSize = inputSize;
81 	Cpa64U outBufferSize = 0;
82 
83 	/* Formula for GEN2 deflate:
84 	 * ceil(9 * Total input bytes / 8) + 55 bytes.
85 	 * 55 bytes is the skid pad value for GEN2 devices.
86 	 * Adding extra bytes = `DC_DEST_BUFF_MIN_EXTRA_BYTES(inputSize)`
87 	 * when calculated value from `CPA_DC_CEIL_DIV(9 * inputSize, 8) +
88 	 * DC_DEST_BUFF_EXTRA_DEFLATE_GEN2` is less than 64 bytes to
89 	 * achieve a safer output buffer size of 64 bytes.
90 	 */
91 	outBufferSize = CPA_DC_CEIL_DIV(9 * inBufferSize, 8) +
92 	    DC_DEST_BUFF_EXTRA_DEFLATE_GEN2 +
93 	    DC_DEST_BUFF_MIN_EXTRA_BYTES(inputSize);
94 
95 	if (outBufferSize > DC_BUF_MAX_SIZE)
96 		*outputSize = DC_BUF_MAX_SIZE;
97 	else
98 		*outputSize = (Cpa32U)outBufferSize;
99 
100 	return CPA_STATUS_SUCCESS;
101 }
102 
103 static inline CpaStatus
104 dcDeflateBoundGen4(CpaDcHuffType huffType, Cpa32U inputSize, Cpa32U *outputSize)
105 {
106 	Cpa64U outputSizeLong;
107 	Cpa64U inputSizeLong = (Cpa64U)inputSize;
108 
109 	switch (huffType) {
110 	case CPA_DC_HT_STATIC:
111 		/* Formula for GEN4 static deflate:
112 		 * ceil((9*sourceLen)/8) + 5 + 1024. */
113 		outputSizeLong = CPA_DC_CEIL_DIV(9 * inputSizeLong, 8) +
114 		    DC_DEST_BUFF_EXTRA_DEFLATE_GEN4_STATIC;
115 		break;
116 	case CPA_DC_HT_FULL_DYNAMIC:
117 		/* Formula for GEN4 dynamic deflate:
118 		 * Ceil ((9*sourceLen)/8)▒| +
119 		 * ((((8/7) * sourceLen)/ 16KB) * (150+5)) + 512
120 		 */
121 		outputSizeLong = DC_DEST_BUFF_EXTRA_DEFLATE_GEN4_DYN;
122 		outputSizeLong += CPA_DC_CEIL_DIV(9 * inputSizeLong, 8);
123 		outputSizeLong += ((8 * inputSizeLong * 155) / 7) / (16 * 1024);
124 		break;
125 	default:
126 		return CPA_STATUS_INVALID_PARAM;
127 	}
128 
129 	/* Avoid output size overflow */
130 	if (outputSizeLong & 0xffffffff00000000UL)
131 		return CPA_STATUS_INVALID_PARAM;
132 
133 	*outputSize = (Cpa32U)outputSizeLong;
134 	return CPA_STATUS_SUCCESS;
135 }
136 
137 CpaStatus
138 cpaDcDeflateCompressBound(const CpaInstanceHandle dcInstance,
139 			  CpaDcHuffType huffType,
140 			  Cpa32U inputSize,
141 			  Cpa32U *outputSize)
142 {
143 	sal_compression_service_t *pService = NULL;
144 	CpaInstanceHandle insHandle = NULL;
145 
146 	if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
147 		insHandle = dcGetFirstHandle();
148 	} else {
149 		insHandle = dcInstance;
150 	}
151 
152 	LAC_CHECK_INSTANCE_HANDLE(insHandle);
153 	LAC_CHECK_NULL_PARAM(outputSize);
154 	/* Ensure this is a compression instance */
155 	SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
156 	if (!inputSize) {
157 		QAT_UTILS_LOG(
158 		    "The input size needs to be greater than zero.\n");
159 		return CPA_STATUS_INVALID_PARAM;
160 	}
161 
162 	if ((CPA_DC_HT_STATIC != huffType) &&
163 	    (CPA_DC_HT_FULL_DYNAMIC != huffType)) {
164 		QAT_UTILS_LOG("Invalid huffType value.\n");
165 		return CPA_STATUS_INVALID_PARAM;
166 	}
167 
168 	pService = (sal_compression_service_t *)insHandle;
169 	if (isDcGen4x(pService)) {
170 		return dcDeflateBoundGen4(huffType, inputSize, outputSize);
171 	} else {
172 		return dcDeflateBoundGen2(huffType, inputSize, outputSize);
173 	}
174 }
175