xref: /dpdk/drivers/baseband/null/bbdev_null.c (revision bbbe38a6d59ccdda25917712701e629d0b10af6f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Intel Corporation
3  */
4 
5 #include <string.h>
6 
7 #include <rte_common.h>
8 #include <rte_bus_vdev.h>
9 #include <rte_malloc.h>
10 #include <rte_ring.h>
11 #include <rte_kvargs.h>
12 
13 #include <rte_bbdev.h>
14 #include <rte_bbdev_pmd.h>
15 
16 #define DRIVER_NAME baseband_null
17 
18 RTE_LOG_REGISTER_DEFAULT(bbdev_null_logtype, NOTICE);
19 
20 /* Helper macro for logging */
21 #define rte_bbdev_log(level, fmt, ...) \
22 	rte_log(RTE_LOG_ ## level, bbdev_null_logtype, fmt "\n", ##__VA_ARGS__)
23 
24 #define rte_bbdev_log_debug(fmt, ...) \
25 	rte_bbdev_log(DEBUG, RTE_STR(__LINE__) ":%s() " fmt, __func__, \
26 		##__VA_ARGS__)
27 
28 /*  Initialisation params structure that can be used by null BBDEV driver */
29 struct bbdev_null_params {
30 	int socket_id;  /*< Null BBDEV socket */
31 	uint16_t queues_num;  /*< Null BBDEV queues number */
32 };
33 
34 /* Accecptable params for null BBDEV devices */
35 #define BBDEV_NULL_MAX_NB_QUEUES_ARG  "max_nb_queues"
36 #define BBDEV_NULL_SOCKET_ID_ARG      "socket_id"
37 
38 static const char * const bbdev_null_valid_params[] = {
39 	BBDEV_NULL_MAX_NB_QUEUES_ARG,
40 	BBDEV_NULL_SOCKET_ID_ARG
41 };
42 
43 /* private data structure */
44 struct bbdev_private {
45 	unsigned int max_nb_queues;  /**< Max number of queues */
46 };
47 
48 /* queue */
49 struct bbdev_queue {
50 	struct rte_ring *processed_pkts;  /* Ring for processed packets */
51 } __rte_cache_aligned;
52 
53 /* Get device info */
54 static void
55 info_get(struct rte_bbdev *dev, struct rte_bbdev_driver_info *dev_info)
56 {
57 	struct bbdev_private *internals = dev->data->dev_private;
58 
59 	static const struct rte_bbdev_op_cap bbdev_capabilities[] = {
60 		RTE_BBDEV_END_OF_CAPABILITIES_LIST(),
61 	};
62 
63 	static struct rte_bbdev_queue_conf default_queue_conf = {
64 		.queue_size = RTE_BBDEV_QUEUE_SIZE_LIMIT,
65 	};
66 
67 	default_queue_conf.socket = dev->data->socket_id;
68 
69 	dev_info->driver_name = RTE_STR(DRIVER_NAME);
70 	dev_info->max_num_queues = internals->max_nb_queues;
71 	dev_info->queue_size_lim = RTE_BBDEV_QUEUE_SIZE_LIMIT;
72 	dev_info->hardware_accelerated = false;
73 	dev_info->max_dl_queue_priority = 0;
74 	dev_info->max_ul_queue_priority = 0;
75 	dev_info->default_queue_conf = default_queue_conf;
76 	dev_info->capabilities = bbdev_capabilities;
77 	dev_info->cpu_flag_reqs = NULL;
78 	dev_info->min_alignment = 0;
79 
80 	rte_bbdev_log_debug("got device info from %u", dev->data->dev_id);
81 }
82 
83 /* Release queue */
84 static int
85 q_release(struct rte_bbdev *dev, uint16_t q_id)
86 {
87 	struct bbdev_queue *q = dev->data->queues[q_id].queue_private;
88 
89 	if (q != NULL) {
90 		rte_ring_free(q->processed_pkts);
91 		rte_free(q);
92 		dev->data->queues[q_id].queue_private = NULL;
93 	}
94 
95 	rte_bbdev_log_debug("released device queue %u:%u",
96 			dev->data->dev_id, q_id);
97 	return 0;
98 }
99 
100 /* Setup a queue */
101 static int
102 q_setup(struct rte_bbdev *dev, uint16_t q_id,
103 		const struct rte_bbdev_queue_conf *queue_conf)
104 {
105 	struct bbdev_queue *q;
106 	char ring_name[RTE_RING_NAMESIZE];
107 	snprintf(ring_name, RTE_RING_NAMESIZE, RTE_STR(DRIVER_NAME) "%u:%u",
108 				dev->data->dev_id, q_id);
109 
110 	/* Allocate the queue data structure. */
111 	q = rte_zmalloc_socket(RTE_STR(DRIVER_NAME), sizeof(*q),
112 			RTE_CACHE_LINE_SIZE, queue_conf->socket);
113 	if (q == NULL) {
114 		rte_bbdev_log(ERR, "Failed to allocate queue memory");
115 		return -ENOMEM;
116 	}
117 
118 	q->processed_pkts = rte_ring_create(ring_name, queue_conf->queue_size,
119 			queue_conf->socket, RING_F_SP_ENQ | RING_F_SC_DEQ);
120 	if (q->processed_pkts == NULL) {
121 		rte_bbdev_log(ERR, "Failed to create ring");
122 		goto free_q;
123 	}
124 
125 	dev->data->queues[q_id].queue_private = q;
126 	rte_bbdev_log_debug("setup device queue %s", ring_name);
127 	return 0;
128 
129 free_q:
130 	rte_free(q);
131 	return -EFAULT;
132 }
133 
134 static const struct rte_bbdev_ops pmd_ops = {
135 	.info_get = info_get,
136 	.queue_setup = q_setup,
137 	.queue_release = q_release
138 };
139 
140 /* Enqueue decode burst */
141 static uint16_t
142 enqueue_dec_ops(struct rte_bbdev_queue_data *q_data,
143 		struct rte_bbdev_dec_op **ops, uint16_t nb_ops)
144 {
145 	struct bbdev_queue *q = q_data->queue_private;
146 	uint16_t nb_enqueued = rte_ring_enqueue_burst(q->processed_pkts,
147 			(void **)ops, nb_ops, NULL);
148 
149 	q_data->queue_stats.enqueue_err_count += nb_ops - nb_enqueued;
150 	q_data->queue_stats.enqueued_count += nb_enqueued;
151 
152 	return nb_enqueued;
153 }
154 
155 /* Enqueue encode burst */
156 static uint16_t
157 enqueue_enc_ops(struct rte_bbdev_queue_data *q_data,
158 		struct rte_bbdev_enc_op **ops, uint16_t nb_ops)
159 {
160 	struct bbdev_queue *q = q_data->queue_private;
161 	uint16_t nb_enqueued = rte_ring_enqueue_burst(q->processed_pkts,
162 			(void **)ops, nb_ops, NULL);
163 
164 	q_data->queue_stats.enqueue_err_count += nb_ops - nb_enqueued;
165 	q_data->queue_stats.enqueued_count += nb_enqueued;
166 
167 	return nb_enqueued;
168 }
169 
170 /* Dequeue decode burst */
171 static uint16_t
172 dequeue_dec_ops(struct rte_bbdev_queue_data *q_data,
173 		struct rte_bbdev_dec_op **ops, uint16_t nb_ops)
174 {
175 	struct bbdev_queue *q = q_data->queue_private;
176 	uint16_t nb_dequeued = rte_ring_dequeue_burst(q->processed_pkts,
177 			(void **)ops, nb_ops, NULL);
178 	q_data->queue_stats.dequeued_count += nb_dequeued;
179 
180 	return nb_dequeued;
181 }
182 
183 /* Dequeue encode burst */
184 static uint16_t
185 dequeue_enc_ops(struct rte_bbdev_queue_data *q_data,
186 		struct rte_bbdev_enc_op **ops, uint16_t nb_ops)
187 {
188 	struct bbdev_queue *q = q_data->queue_private;
189 	uint16_t nb_dequeued = rte_ring_dequeue_burst(q->processed_pkts,
190 			(void **)ops, nb_ops, NULL);
191 	q_data->queue_stats.dequeued_count += nb_dequeued;
192 
193 	return nb_dequeued;
194 }
195 
196 /* Parse 16bit integer from string argument */
197 static inline int
198 parse_u16_arg(const char *key, const char *value, void *extra_args)
199 {
200 	uint16_t *u16 = extra_args;
201 	unsigned int long result;
202 
203 	if ((value == NULL) || (extra_args == NULL))
204 		return -EINVAL;
205 	errno = 0;
206 	result = strtoul(value, NULL, 0);
207 	if ((result >= (1 << 16)) || (errno != 0)) {
208 		rte_bbdev_log(ERR, "Invalid value %lu for %s", result, key);
209 		return -ERANGE;
210 	}
211 	*u16 = (uint16_t)result;
212 	return 0;
213 }
214 
215 /* Parse parameters used to create device */
216 static int
217 parse_bbdev_null_params(struct bbdev_null_params *params,
218 		const char *input_args)
219 {
220 	struct rte_kvargs *kvlist = NULL;
221 	int ret = 0;
222 
223 	if (params == NULL)
224 		return -EINVAL;
225 	if (input_args) {
226 		kvlist = rte_kvargs_parse(input_args, bbdev_null_valid_params);
227 		if (kvlist == NULL)
228 			return -EFAULT;
229 
230 		ret = rte_kvargs_process(kvlist, bbdev_null_valid_params[0],
231 					&parse_u16_arg, &params->queues_num);
232 		if (ret < 0)
233 			goto exit;
234 
235 		ret = rte_kvargs_process(kvlist, bbdev_null_valid_params[1],
236 					&parse_u16_arg, &params->socket_id);
237 		if (ret < 0)
238 			goto exit;
239 
240 		if (params->socket_id >= RTE_MAX_NUMA_NODES) {
241 			rte_bbdev_log(ERR, "Invalid socket, must be < %u",
242 					RTE_MAX_NUMA_NODES);
243 			goto exit;
244 		}
245 	}
246 
247 exit:
248 	if (kvlist)
249 		rte_kvargs_free(kvlist);
250 	return ret;
251 }
252 
253 /* Create device */
254 static int
255 null_bbdev_create(struct rte_vdev_device *vdev,
256 		struct bbdev_null_params *init_params)
257 {
258 	struct rte_bbdev *bbdev;
259 	const char *name = rte_vdev_device_name(vdev);
260 
261 	bbdev = rte_bbdev_allocate(name);
262 	if (bbdev == NULL)
263 		return -ENODEV;
264 
265 	bbdev->data->dev_private = rte_zmalloc_socket(name,
266 			sizeof(struct bbdev_private), RTE_CACHE_LINE_SIZE,
267 			init_params->socket_id);
268 	if (bbdev->data->dev_private == NULL) {
269 		rte_bbdev_release(bbdev);
270 		return -ENOMEM;
271 	}
272 
273 	bbdev->dev_ops = &pmd_ops;
274 	bbdev->device = &vdev->device;
275 	bbdev->data->socket_id = init_params->socket_id;
276 	bbdev->intr_handle = NULL;
277 
278 	/* register rx/tx burst functions for data path */
279 	bbdev->dequeue_enc_ops = dequeue_enc_ops;
280 	bbdev->dequeue_dec_ops = dequeue_dec_ops;
281 	bbdev->enqueue_enc_ops = enqueue_enc_ops;
282 	bbdev->enqueue_dec_ops = enqueue_dec_ops;
283 	((struct bbdev_private *) bbdev->data->dev_private)->max_nb_queues =
284 			init_params->queues_num;
285 
286 	return 0;
287 }
288 
289 /* Initialise device */
290 static int
291 null_bbdev_probe(struct rte_vdev_device *vdev)
292 {
293 	struct bbdev_null_params init_params = {
294 		rte_socket_id(),
295 		RTE_BBDEV_DEFAULT_MAX_NB_QUEUES
296 	};
297 	const char *name;
298 	const char *input_args;
299 
300 	if (vdev == NULL)
301 		return -EINVAL;
302 
303 	name = rte_vdev_device_name(vdev);
304 	if (name == NULL)
305 		return -EINVAL;
306 
307 	input_args = rte_vdev_device_args(vdev);
308 	parse_bbdev_null_params(&init_params, input_args);
309 
310 	rte_bbdev_log_debug("Init %s on NUMA node %d with max queues: %d",
311 			name, init_params.socket_id, init_params.queues_num);
312 
313 	return null_bbdev_create(vdev, &init_params);
314 }
315 
316 /* Uninitialise device */
317 static int
318 null_bbdev_remove(struct rte_vdev_device *vdev)
319 {
320 	struct rte_bbdev *bbdev;
321 	const char *name;
322 
323 	if (vdev == NULL)
324 		return -EINVAL;
325 
326 	name = rte_vdev_device_name(vdev);
327 	if (name == NULL)
328 		return -EINVAL;
329 
330 	bbdev = rte_bbdev_get_named_dev(name);
331 	if (bbdev == NULL)
332 		return -EINVAL;
333 
334 	rte_free(bbdev->data->dev_private);
335 
336 	return rte_bbdev_release(bbdev);
337 }
338 
339 static struct rte_vdev_driver bbdev_null_pmd_drv = {
340 	.probe = null_bbdev_probe,
341 	.remove = null_bbdev_remove
342 };
343 
344 RTE_PMD_REGISTER_VDEV(DRIVER_NAME, bbdev_null_pmd_drv);
345 RTE_PMD_REGISTER_PARAM_STRING(DRIVER_NAME,
346 	BBDEV_NULL_MAX_NB_QUEUES_ARG"=<int> "
347 	BBDEV_NULL_SOCKET_ID_ARG"=<int>");
348 RTE_PMD_REGISTER_ALIAS(DRIVER_NAME, bbdev_null);
349