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