xref: /dpdk/drivers/compress/zlib/zlib_pmd_ops.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Cavium Networks
3  */
4 
5 #include <string.h>
6 
7 #include <dev_driver.h>
8 #include <rte_common.h>
9 #include <rte_malloc.h>
10 
11 #include "zlib_pmd_private.h"
12 
13 static const struct rte_compressdev_capabilities zlib_pmd_capabilities[] = {
14 	{   /* Deflate */
15 		.algo = RTE_COMP_ALGO_DEFLATE,
16 		.comp_feature_flags = (RTE_COMP_FF_NONCOMPRESSED_BLOCKS |
17 					RTE_COMP_FF_HUFFMAN_FIXED |
18 					RTE_COMP_FF_HUFFMAN_DYNAMIC),
19 		.window_size = {
20 			.min = 8,
21 			.max = 15,
22 			.increment = 1
23 		},
24 	},
25 
26 	RTE_COMP_END_OF_CAPABILITIES_LIST()
27 
28 };
29 
30 /** Configure device */
31 static int
32 zlib_pmd_config(struct rte_compressdev *dev,
33 		struct rte_compressdev_config *config)
34 {
35 	struct rte_mempool *mp;
36 	char mp_name[RTE_MEMPOOL_NAMESIZE];
37 	struct zlib_private *internals = dev->data->dev_private;
38 
39 	snprintf(mp_name, RTE_MEMPOOL_NAMESIZE,
40 			"stream_mp_%u", dev->data->dev_id);
41 	mp = internals->mp;
42 	if (mp == NULL) {
43 		mp = rte_mempool_create(mp_name,
44 				config->max_nb_priv_xforms +
45 				config->max_nb_streams,
46 				sizeof(struct zlib_priv_xform),
47 				0, 0, NULL, NULL, NULL,
48 				NULL, config->socket_id,
49 				0);
50 		if (mp == NULL) {
51 			ZLIB_PMD_ERR("Cannot create private xform pool on socket %d",
52 				config->socket_id);
53 			return -ENOMEM;
54 		}
55 		internals->mp = mp;
56 	}
57 	return 0;
58 }
59 
60 /** Start device */
61 static int
62 zlib_pmd_start(__rte_unused struct rte_compressdev *dev)
63 {
64 	return 0;
65 }
66 
67 /** Stop device */
68 static void
69 zlib_pmd_stop(__rte_unused struct rte_compressdev *dev)
70 {
71 }
72 
73 /** Close device */
74 static int
75 zlib_pmd_close(struct rte_compressdev *dev)
76 {
77 	struct zlib_private *internals = dev->data->dev_private;
78 	rte_mempool_free(internals->mp);
79 	internals->mp = NULL;
80 	return 0;
81 }
82 
83 /** Get device statistics */
84 static void
85 zlib_pmd_stats_get(struct rte_compressdev *dev,
86 		struct rte_compressdev_stats *stats)
87 {
88 	int qp_id;
89 
90 	for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
91 		struct zlib_qp *qp = dev->data->queue_pairs[qp_id];
92 
93 		stats->enqueued_count += qp->qp_stats.enqueued_count;
94 		stats->dequeued_count += qp->qp_stats.dequeued_count;
95 
96 		stats->enqueue_err_count += qp->qp_stats.enqueue_err_count;
97 		stats->dequeue_err_count += qp->qp_stats.dequeue_err_count;
98 	}
99 }
100 
101 /** Reset device statistics */
102 static void
103 zlib_pmd_stats_reset(struct rte_compressdev *dev)
104 {
105 	int qp_id;
106 
107 	for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
108 		struct zlib_qp *qp = dev->data->queue_pairs[qp_id];
109 
110 		memset(&qp->qp_stats, 0, sizeof(qp->qp_stats));
111 	}
112 }
113 
114 /** Get device info */
115 static void
116 zlib_pmd_info_get(struct rte_compressdev *dev,
117 		struct rte_compressdev_info *dev_info)
118 {
119 	if (dev_info != NULL) {
120 		dev_info->driver_name = dev->device->name;
121 		dev_info->feature_flags = dev->feature_flags;
122 		dev_info->capabilities = zlib_pmd_capabilities;
123 	}
124 }
125 
126 /** Release queue pair */
127 static int
128 zlib_pmd_qp_release(struct rte_compressdev *dev, uint16_t qp_id)
129 {
130 	struct zlib_qp *qp = dev->data->queue_pairs[qp_id];
131 
132 	if (qp != NULL) {
133 		rte_ring_free(qp->processed_pkts);
134 		rte_free(qp);
135 		dev->data->queue_pairs[qp_id] = NULL;
136 	}
137 	return 0;
138 }
139 
140 /** set a unique name for the queue pair based on its name, dev_id and qp_id */
141 static int
142 zlib_pmd_qp_set_unique_name(struct rte_compressdev *dev,
143 		struct zlib_qp *qp)
144 {
145 	unsigned int n = snprintf(qp->name, sizeof(qp->name),
146 				"zlib_pmd_%u_qp_%u",
147 				dev->data->dev_id, qp->id);
148 
149 	if (n >= sizeof(qp->name))
150 		return -1;
151 
152 	return 0;
153 }
154 
155 /** Create a ring to place process packets on */
156 static struct rte_ring *
157 zlib_pmd_qp_create_processed_pkts_ring(struct zlib_qp *qp,
158 		unsigned int ring_size, int socket_id)
159 {
160 	struct rte_ring *r = qp->processed_pkts;
161 
162 	if (r) {
163 		if (rte_ring_get_size(r) >= ring_size) {
164 			ZLIB_PMD_INFO("Reusing existing ring %s for processed"
165 					" packets", qp->name);
166 			return r;
167 		}
168 
169 		ZLIB_PMD_ERR("Unable to reuse existing ring %s for processed"
170 				" packets", qp->name);
171 		return NULL;
172 	}
173 
174 	return rte_ring_create(qp->name, ring_size, socket_id,
175 						RING_F_EXACT_SZ);
176 }
177 
178 /** Setup a queue pair */
179 static int
180 zlib_pmd_qp_setup(struct rte_compressdev *dev, uint16_t qp_id,
181 		uint32_t max_inflight_ops, int socket_id)
182 {
183 	struct zlib_qp *qp = NULL;
184 
185 	/* Free memory prior to re-allocation if needed. */
186 	if (dev->data->queue_pairs[qp_id] != NULL)
187 		zlib_pmd_qp_release(dev, qp_id);
188 
189 	/* Allocate the queue pair data structure. */
190 	qp = rte_zmalloc_socket("ZLIB PMD Queue Pair", sizeof(*qp),
191 					RTE_CACHE_LINE_SIZE, socket_id);
192 	if (qp == NULL)
193 		return (-ENOMEM);
194 
195 	qp->id = qp_id;
196 	dev->data->queue_pairs[qp_id] = qp;
197 
198 	if (zlib_pmd_qp_set_unique_name(dev, qp))
199 		goto qp_setup_cleanup;
200 
201 	qp->processed_pkts = zlib_pmd_qp_create_processed_pkts_ring(qp,
202 			max_inflight_ops, socket_id);
203 	if (qp->processed_pkts == NULL)
204 		goto qp_setup_cleanup;
205 
206 	memset(&qp->qp_stats, 0, sizeof(qp->qp_stats));
207 	return 0;
208 
209 qp_setup_cleanup:
210 	if (qp) {
211 		rte_free(qp);
212 		qp = NULL;
213 	}
214 	return -1;
215 }
216 
217 /** Configure stream */
218 static int
219 zlib_pmd_stream_create(struct rte_compressdev *dev,
220 		const struct rte_comp_xform *xform,
221 		void **zstream)
222 {
223 	int ret = 0;
224 	struct zlib_stream *stream;
225 	struct zlib_private *internals = dev->data->dev_private;
226 
227 	if (xform == NULL) {
228 		ZLIB_PMD_ERR("invalid xform struct");
229 		return -EINVAL;
230 	}
231 
232 	if (rte_mempool_get(internals->mp, zstream)) {
233 		ZLIB_PMD_ERR("Couldn't get object from session mempool");
234 		return -ENOMEM;
235 	}
236 	stream = *((struct zlib_stream **)zstream);
237 
238 	ret = zlib_set_stream_parameters(xform, stream);
239 
240 	if (ret < 0) {
241 		ZLIB_PMD_ERR("failed configure session parameters");
242 
243 		memset(stream, 0, sizeof(struct zlib_stream));
244 		/* Return session to mempool */
245 		rte_mempool_put(internals->mp, stream);
246 		return ret;
247 	}
248 
249 	return 0;
250 }
251 
252 /** Configure private xform */
253 static int
254 zlib_pmd_private_xform_create(struct rte_compressdev *dev,
255 		const struct rte_comp_xform *xform,
256 		void **private_xform)
257 {
258 	return zlib_pmd_stream_create(dev, xform, private_xform);
259 }
260 
261 /** Clear the memory of stream so it doesn't leave key material behind */
262 static int
263 zlib_pmd_stream_free(__rte_unused struct rte_compressdev *dev,
264 		void *zstream)
265 {
266 	struct zlib_stream *stream = (struct zlib_stream *)zstream;
267 	if (!stream)
268 		return -EINVAL;
269 
270 	stream->free(&stream->strm);
271 	/* Zero out the whole structure */
272 	memset(stream, 0, sizeof(struct zlib_stream));
273 	struct rte_mempool *mp = rte_mempool_from_obj(stream);
274 	rte_mempool_put(mp, stream);
275 
276 	return 0;
277 }
278 
279 /** Clear the memory of stream so it doesn't leave key material behind */
280 static int
281 zlib_pmd_private_xform_free(struct rte_compressdev *dev,
282 		void *private_xform)
283 {
284 	return zlib_pmd_stream_free(dev, private_xform);
285 }
286 
287 struct rte_compressdev_ops zlib_pmd_ops = {
288 		.dev_configure		= zlib_pmd_config,
289 		.dev_start		= zlib_pmd_start,
290 		.dev_stop		= zlib_pmd_stop,
291 		.dev_close		= zlib_pmd_close,
292 
293 		.stats_get		= zlib_pmd_stats_get,
294 		.stats_reset		= zlib_pmd_stats_reset,
295 
296 		.dev_infos_get		= zlib_pmd_info_get,
297 
298 		.queue_pair_setup	= zlib_pmd_qp_setup,
299 		.queue_pair_release	= zlib_pmd_qp_release,
300 
301 		.private_xform_create	= zlib_pmd_private_xform_create,
302 		.private_xform_free	= zlib_pmd_private_xform_free,
303 
304 		.stream_create	= NULL,
305 		.stream_free	= NULL
306 };
307 
308 struct rte_compressdev_ops *rte_zlib_pmd_ops = &zlib_pmd_ops;
309