Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2017 Intel Corporation
3 : : */
4 : :
5 : : #include <stdint.h>
6 : : #include <string.h>
7 : : #include <stdbool.h>
8 : : #include <sys/queue.h>
9 : :
10 : : #include <rte_common.h>
11 : : #include <rte_errno.h>
12 : : #include <rte_log.h>
13 : : #include <rte_eal.h>
14 : : #include <rte_malloc.h>
15 : : #include <rte_mempool.h>
16 : : #include <rte_memzone.h>
17 : : #include <rte_lcore.h>
18 : : #include <rte_spinlock.h>
19 : : #include <rte_interrupts.h>
20 : :
21 : : #include "rte_bbdev_op.h"
22 : : #include "rte_bbdev.h"
23 : : #include "rte_bbdev_pmd.h"
24 : : #include "bbdev_trace.h"
25 : :
26 : : #define DEV_NAME "BBDEV"
27 : :
28 : : /* Number of supported operation types in *rte_bbdev_op_type*. */
29 : : #define BBDEV_OP_TYPE_COUNT 7
30 : :
31 : : /* BBDev library logging ID */
32 [ - + ]: 252 : RTE_LOG_REGISTER_DEFAULT(bbdev_logtype, NOTICE);
33 : : #define RTE_LOGTYPE_BBDEV bbdev_logtype
34 : :
35 : : /* Helper macro for logging */
36 : : #define rte_bbdev_log(level, ...) \
37 : : RTE_LOG_LINE(level, BBDEV, "" __VA_ARGS__)
38 : :
39 : : #define rte_bbdev_log_debug(fmt, ...) \
40 : : rte_bbdev_log(DEBUG, RTE_STR(__LINE__) ":%s() " fmt, __func__, \
41 : : ##__VA_ARGS__)
42 : :
43 : : /* Helper macro to check dev_id is valid */
44 : : #define VALID_DEV_OR_RET_ERR(dev, dev_id) do { \
45 : : if (dev == NULL) { \
46 : : rte_bbdev_log(ERR, "device %u is invalid", dev_id); \
47 : : return -ENODEV; \
48 : : } \
49 : : } while (0)
50 : :
51 : : /* Helper macro to check dev_ops is valid */
52 : : #define VALID_DEV_OPS_OR_RET_ERR(dev, dev_id) do { \
53 : : if (dev->dev_ops == NULL) { \
54 : : rte_bbdev_log(ERR, "NULL dev_ops structure in device %u", \
55 : : dev_id); \
56 : : return -ENODEV; \
57 : : } \
58 : : } while (0)
59 : :
60 : : /* Helper macro to check that driver implements required function pointer */
61 : : #define VALID_FUNC_OR_RET_ERR(func, dev_id) do { \
62 : : if (func == NULL) { \
63 : : rte_bbdev_log(ERR, "device %u does not support %s", \
64 : : dev_id, #func); \
65 : : return -ENOTSUP; \
66 : : } \
67 : : } while (0)
68 : :
69 : : /* Helper macro to check that queue is valid */
70 : : #define VALID_QUEUE_OR_RET_ERR(queue_id, dev) do { \
71 : : if (queue_id >= dev->data->num_queues) { \
72 : : rte_bbdev_log(ERR, "Invalid queue_id %u for device %u", \
73 : : queue_id, dev->data->dev_id); \
74 : : return -ERANGE; \
75 : : } \
76 : : } while (0)
77 : :
78 : : /* List of callback functions registered by an application */
79 : : struct rte_bbdev_callback {
80 : : TAILQ_ENTRY(rte_bbdev_callback) next; /* Callbacks list */
81 : : rte_bbdev_cb_fn cb_fn; /* Callback address */
82 : : void *cb_arg; /* Parameter for callback */
83 : : void *ret_param; /* Return parameter */
84 : : enum rte_bbdev_event_type event; /* Interrupt event type */
85 : : uint32_t active; /* Callback is executing */
86 : : };
87 : :
88 : : /* spinlock for bbdev device callbacks */
89 : : static rte_spinlock_t rte_bbdev_cb_lock = RTE_SPINLOCK_INITIALIZER;
90 : :
91 : : /*
92 : : * Global array of all devices. This is not static because it's used by the
93 : : * inline enqueue and dequeue functions
94 : : */
95 : : struct rte_bbdev rte_bbdev_devices[RTE_BBDEV_MAX_DEVS];
96 : :
97 : : /* Global array with rte_bbdev_data structures */
98 : : static struct rte_bbdev_data *rte_bbdev_data;
99 : :
100 : : /* Memzone name for global bbdev data pool */
101 : : static const char *MZ_RTE_BBDEV_DATA = "rte_bbdev_data";
102 : :
103 : : /* Number of currently valid devices */
104 : : static uint16_t num_devs;
105 : :
106 : : /* Return pointer to device structure, with validity check */
107 : : static struct rte_bbdev *
108 : : get_dev(uint16_t dev_id)
109 : : {
110 [ # # # # : 0 : if (rte_bbdev_is_valid(dev_id))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
111 : 0 : return &rte_bbdev_devices[dev_id];
112 : : return NULL;
113 : : }
114 : :
115 : : /* Allocate global data array */
116 : : static int
117 : 0 : rte_bbdev_data_alloc(void)
118 : : {
119 : : const unsigned int flags = 0;
120 : : const struct rte_memzone *mz;
121 : :
122 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
123 : 0 : mz = rte_memzone_reserve(MZ_RTE_BBDEV_DATA,
124 : : RTE_BBDEV_MAX_DEVS * sizeof(*rte_bbdev_data),
125 : 0 : rte_socket_id(), flags);
126 : : } else
127 : 0 : mz = rte_memzone_lookup(MZ_RTE_BBDEV_DATA);
128 [ # # ]: 0 : if (mz == NULL) {
129 : 0 : rte_bbdev_log(CRIT,
130 : : "Cannot allocate memzone for bbdev port data");
131 : 0 : return -ENOMEM;
132 : : }
133 : :
134 : 0 : rte_bbdev_data = mz->addr;
135 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY)
136 : 0 : memset(rte_bbdev_data, 0,
137 : : RTE_BBDEV_MAX_DEVS * sizeof(*rte_bbdev_data));
138 : : return 0;
139 : : }
140 : :
141 : : /*
142 : : * Find data allocated for the device or if not found return first unused bbdev
143 : : * data. If all structures are in use and none is used by the device return
144 : : * NULL.
145 : : */
146 : : static struct rte_bbdev_data *
147 : 0 : find_bbdev_data(const char *name)
148 : : {
149 : : uint16_t data_id;
150 : :
151 [ # # ]: 0 : for (data_id = 0; data_id < RTE_BBDEV_MAX_DEVS; ++data_id) {
152 [ # # ]: 0 : if (strlen(rte_bbdev_data[data_id].name) == 0) {
153 : : memset(&rte_bbdev_data[data_id], 0,
154 : : sizeof(struct rte_bbdev_data));
155 : 0 : return &rte_bbdev_data[data_id];
156 [ # # ]: 0 : } else if (strncmp(rte_bbdev_data[data_id].name, name,
157 : : RTE_BBDEV_NAME_MAX_LEN) == 0)
158 : 0 : return &rte_bbdev_data[data_id];
159 : : }
160 : :
161 : : return NULL;
162 : : }
163 : :
164 : : /* Find lowest device id with no attached device */
165 : : static uint16_t
166 : : find_free_dev_id(void)
167 : : {
168 : : uint16_t i;
169 [ # # ]: 0 : for (i = 0; i < RTE_BBDEV_MAX_DEVS; i++) {
170 [ # # ]: 0 : if (rte_bbdev_devices[i].state == RTE_BBDEV_UNUSED)
171 : : return i;
172 : : }
173 : : return RTE_BBDEV_MAX_DEVS;
174 : : }
175 : :
176 : : struct rte_bbdev *
177 : 0 : rte_bbdev_allocate(const char *name)
178 : : {
179 : : int ret;
180 : : struct rte_bbdev *bbdev;
181 : : uint16_t dev_id;
182 : :
183 [ # # ]: 0 : if (name == NULL) {
184 : 0 : rte_bbdev_log(ERR, "Invalid null device name");
185 : 0 : return NULL;
186 : : }
187 : :
188 [ # # ]: 0 : if (rte_bbdev_get_named_dev(name) != NULL) {
189 : 0 : rte_bbdev_log(ERR, "Device \"%s\" is already allocated", name);
190 : 0 : return NULL;
191 : : }
192 : :
193 : : dev_id = find_free_dev_id();
194 [ # # ]: 0 : if (dev_id == RTE_BBDEV_MAX_DEVS) {
195 : 0 : rte_bbdev_log(ERR, "Reached maximum number of devices");
196 : 0 : return NULL;
197 : : }
198 : :
199 : 0 : bbdev = &rte_bbdev_devices[dev_id];
200 : :
201 [ # # ]: 0 : if (rte_bbdev_data == NULL) {
202 : 0 : ret = rte_bbdev_data_alloc();
203 [ # # ]: 0 : if (ret != 0)
204 : : return NULL;
205 : : }
206 : :
207 : 0 : bbdev->data = find_bbdev_data(name);
208 [ # # ]: 0 : if (bbdev->data == NULL) {
209 : 0 : rte_bbdev_log(ERR,
210 : : "Max BBDevs already allocated in multi-process environment!");
211 : 0 : return NULL;
212 : : }
213 : :
214 : 0 : rte_atomic_fetch_add_explicit(&bbdev->data->process_cnt, 1, rte_memory_order_relaxed);
215 : 0 : bbdev->data->dev_id = dev_id;
216 : 0 : bbdev->state = RTE_BBDEV_INITIALIZED;
217 : :
218 [ # # ]: 0 : ret = snprintf(bbdev->data->name, RTE_BBDEV_NAME_MAX_LEN, "%s", name);
219 [ # # ]: 0 : if ((ret < 0) || (ret >= RTE_BBDEV_NAME_MAX_LEN)) {
220 : 0 : rte_bbdev_log(ERR, "Copying device name \"%s\" failed", name);
221 : 0 : return NULL;
222 : : }
223 : :
224 : : /* init user callbacks */
225 : 0 : TAILQ_INIT(&(bbdev->list_cbs));
226 : :
227 : 0 : num_devs++;
228 : :
229 : 0 : rte_bbdev_log_debug("Initialised device %s (id = %u). Num devices = %u",
230 : : name, dev_id, num_devs);
231 : :
232 : 0 : return bbdev;
233 : : }
234 : :
235 : : int
236 : 0 : rte_bbdev_release(struct rte_bbdev *bbdev)
237 : : {
238 : : uint16_t dev_id;
239 : : struct rte_bbdev_callback *cb, *next;
240 : :
241 [ # # ]: 0 : if (bbdev == NULL) {
242 : 0 : rte_bbdev_log(ERR, "NULL bbdev");
243 : 0 : return -ENODEV;
244 : : }
245 : 0 : dev_id = bbdev->data->dev_id;
246 : :
247 : : /* free all callbacks from the device's list */
248 [ # # ]: 0 : for (cb = TAILQ_FIRST(&bbdev->list_cbs); cb != NULL; cb = next) {
249 : :
250 : 0 : next = TAILQ_NEXT(cb, next);
251 [ # # ]: 0 : TAILQ_REMOVE(&(bbdev->list_cbs), cb, next);
252 : 0 : rte_free(cb);
253 : : }
254 : :
255 : : /* clear shared BBDev Data if no process is using the device anymore */
256 [ # # ]: 0 : if (rte_atomic_fetch_sub_explicit(&bbdev->data->process_cnt, 1,
257 : : rte_memory_order_relaxed) - 1 == 0)
258 : 0 : memset(bbdev->data, 0, sizeof(*bbdev->data));
259 : :
260 : : memset(bbdev, 0, sizeof(*bbdev));
261 : 0 : num_devs--;
262 : : bbdev->state = RTE_BBDEV_UNUSED;
263 : :
264 : 0 : rte_bbdev_log_debug(
265 : : "Un-initialised device id = %u. Num devices = %u",
266 : : dev_id, num_devs);
267 : 0 : return 0;
268 : : }
269 : :
270 : : struct rte_bbdev *
271 : 0 : rte_bbdev_get_named_dev(const char *name)
272 : : {
273 : : unsigned int i;
274 : :
275 [ # # ]: 0 : if (name == NULL) {
276 : 0 : rte_bbdev_log(ERR, "NULL driver name");
277 : 0 : return NULL;
278 : : }
279 : :
280 [ # # ]: 0 : for (i = 0; i < RTE_BBDEV_MAX_DEVS; i++) {
281 : 0 : struct rte_bbdev *dev = get_dev(i);
282 [ # # ]: 0 : if (dev && (strncmp(dev->data->name,
283 : : name, RTE_BBDEV_NAME_MAX_LEN) == 0))
284 : 0 : return dev;
285 : : }
286 : :
287 : : return NULL;
288 : : }
289 : :
290 : : uint16_t
291 : 0 : rte_bbdev_count(void)
292 : : {
293 : 0 : return num_devs;
294 : : }
295 : :
296 : : bool
297 : 0 : rte_bbdev_is_valid(uint16_t dev_id)
298 : : {
299 [ # # ]: 0 : if ((dev_id < RTE_BBDEV_MAX_DEVS) &&
300 [ # # ]: 0 : rte_bbdev_devices[dev_id].state == RTE_BBDEV_INITIALIZED)
301 : 0 : return true;
302 : : return false;
303 : : }
304 : :
305 : : uint16_t
306 : 0 : rte_bbdev_find_next(uint16_t dev_id)
307 : : {
308 : 0 : dev_id++;
309 [ # # ]: 0 : for (; dev_id < RTE_BBDEV_MAX_DEVS; dev_id++)
310 [ # # ]: 0 : if (rte_bbdev_is_valid(dev_id))
311 : : break;
312 : 0 : return dev_id;
313 : : }
314 : :
315 : : int
316 : 0 : rte_bbdev_setup_queues(uint16_t dev_id, uint16_t num_queues, int socket_id)
317 : : {
318 : : unsigned int i;
319 : : int ret;
320 : : struct rte_bbdev_driver_info dev_info;
321 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
322 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
323 : :
324 [ # # ]: 0 : VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
325 : :
326 [ # # ]: 0 : rte_bbdev_trace_setup_queues(dev_id, num_queues, socket_id);
327 : :
328 [ # # ]: 0 : if (dev->data->started) {
329 : 0 : rte_bbdev_log(ERR,
330 : : "Device %u cannot be configured when started",
331 : : dev_id);
332 : 0 : return -EBUSY;
333 : : }
334 : :
335 : : /* Get device driver information to get max number of queues */
336 [ # # ]: 0 : VALID_FUNC_OR_RET_ERR(dev->dev_ops->info_get, dev_id);
337 : : memset(&dev_info, 0, sizeof(dev_info));
338 : 0 : dev->dev_ops->info_get(dev, &dev_info);
339 : :
340 [ # # # # ]: 0 : if ((num_queues == 0) || (num_queues > dev_info.max_num_queues)) {
341 : 0 : rte_bbdev_log(ERR,
342 : : "Device %u supports 0 < N <= %u queues, not %u",
343 : : dev_id, dev_info.max_num_queues, num_queues);
344 : 0 : return -EINVAL;
345 : : }
346 : :
347 : : /* If re-configuration, get driver to free existing internal memory */
348 [ # # ]: 0 : if (dev->data->queues != NULL) {
349 [ # # ]: 0 : VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_release, dev_id);
350 [ # # ]: 0 : for (i = 0; i < dev->data->num_queues; i++) {
351 : 0 : int ret = dev->dev_ops->queue_release(dev, i);
352 [ # # ]: 0 : if (ret < 0) {
353 : 0 : rte_bbdev_log(ERR,
354 : : "Device %u queue %u release failed",
355 : : dev_id, i);
356 : 0 : return ret;
357 : : }
358 : : }
359 : : /* Call optional device close */
360 [ # # ]: 0 : if (dev->dev_ops->close) {
361 : 0 : ret = dev->dev_ops->close(dev);
362 [ # # ]: 0 : if (ret < 0) {
363 : 0 : rte_bbdev_log(ERR,
364 : : "Device %u couldn't be closed",
365 : : dev_id);
366 : 0 : return ret;
367 : : }
368 : : }
369 : 0 : rte_free(dev->data->queues);
370 : : }
371 : :
372 : : /* Allocate queue pointers */
373 : 0 : dev->data->queues = rte_calloc_socket(DEV_NAME, num_queues,
374 : : sizeof(dev->data->queues[0]), RTE_CACHE_LINE_SIZE,
375 : 0 : dev->data->socket_id);
376 [ # # ]: 0 : if (dev->data->queues == NULL) {
377 : 0 : rte_bbdev_log(ERR,
378 : : "calloc of %u queues for device %u on socket %i failed",
379 : : num_queues, dev_id, dev->data->socket_id);
380 : 0 : return -ENOMEM;
381 : : }
382 : :
383 : 0 : dev->data->num_queues = num_queues;
384 : :
385 : : /* Call optional device configuration */
386 [ # # ]: 0 : if (dev->dev_ops->setup_queues) {
387 : 0 : ret = dev->dev_ops->setup_queues(dev, num_queues, socket_id);
388 [ # # ]: 0 : if (ret < 0) {
389 : 0 : rte_bbdev_log(ERR,
390 : : "Device %u memory configuration failed",
391 : : dev_id);
392 : 0 : goto error;
393 : : }
394 : : }
395 : :
396 : 0 : rte_bbdev_log_debug("Device %u set up with %u queues", dev_id,
397 : : num_queues);
398 : 0 : return 0;
399 : :
400 : : error:
401 : 0 : dev->data->num_queues = 0;
402 : 0 : rte_free(dev->data->queues);
403 : 0 : dev->data->queues = NULL;
404 : 0 : return ret;
405 : : }
406 : :
407 : : int
408 : 0 : rte_bbdev_intr_enable(uint16_t dev_id)
409 : : {
410 : : int ret;
411 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
412 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
413 : :
414 [ # # ]: 0 : VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
415 : :
416 [ # # ]: 0 : if (dev->data->started) {
417 : 0 : rte_bbdev_log(ERR,
418 : : "Device %u cannot be configured when started",
419 : : dev_id);
420 : 0 : return -EBUSY;
421 : : }
422 : :
423 [ # # ]: 0 : if (dev->dev_ops->intr_enable) {
424 : 0 : ret = dev->dev_ops->intr_enable(dev);
425 [ # # ]: 0 : if (ret < 0) {
426 : 0 : rte_bbdev_log(ERR,
427 : : "Device %u interrupts configuration failed",
428 : : dev_id);
429 : 0 : return ret;
430 : : }
431 : 0 : rte_bbdev_log_debug("Enabled interrupts for dev %u", dev_id);
432 : 0 : return 0;
433 : : }
434 : :
435 : 0 : rte_bbdev_log(ERR, "Device %u doesn't support interrupts", dev_id);
436 : 0 : return -ENOTSUP;
437 : : }
438 : :
439 : : int
440 : 0 : rte_bbdev_queue_configure(uint16_t dev_id, uint16_t queue_id,
441 : : const struct rte_bbdev_queue_conf *conf)
442 : : {
443 : :
444 [ # # ]: 0 : rte_bbdev_trace_queue_configure(dev_id, queue_id, rte_bbdev_op_type_str(conf->op_type),
445 : 0 : conf->priority);
446 : :
447 : : int ret = 0;
448 : : struct rte_bbdev_driver_info dev_info;
449 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
450 : : const struct rte_bbdev_op_cap *p;
451 : : struct rte_bbdev_queue_conf *stored_conf;
452 : : const char *op_type_str;
453 : : unsigned int max_priority;
454 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
455 : :
456 [ # # ]: 0 : VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
457 : :
458 [ # # ]: 0 : VALID_QUEUE_OR_RET_ERR(queue_id, dev);
459 : :
460 [ # # # # ]: 0 : if (dev->data->queues[queue_id].started || dev->data->started) {
461 : 0 : rte_bbdev_log(ERR,
462 : : "Queue %u of device %u cannot be configured when started",
463 : : queue_id, dev_id);
464 : 0 : return -EBUSY;
465 : : }
466 : :
467 [ # # ]: 0 : VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_release, dev_id);
468 [ # # ]: 0 : VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_setup, dev_id);
469 : :
470 : : /* Get device driver information to verify config is valid */
471 [ # # ]: 0 : VALID_FUNC_OR_RET_ERR(dev->dev_ops->info_get, dev_id);
472 : : memset(&dev_info, 0, sizeof(dev_info));
473 : 0 : dev->dev_ops->info_get(dev, &dev_info);
474 : :
475 : : /* Check configuration is valid */
476 : : if (conf != NULL) {
477 [ # # ]: 0 : if ((conf->op_type == RTE_BBDEV_OP_NONE) &&
478 [ # # ]: 0 : (dev_info.capabilities[0].type ==
479 : : RTE_BBDEV_OP_NONE)) {
480 : : ret = 1;
481 : : } else {
482 : 0 : for (p = dev_info.capabilities;
483 [ # # ]: 0 : p->type != RTE_BBDEV_OP_NONE; p++) {
484 [ # # ]: 0 : if (conf->op_type == p->type) {
485 : : ret = 1;
486 : : break;
487 : : }
488 : : }
489 : : }
490 [ # # ]: 0 : if (ret == 0) {
491 : 0 : rte_bbdev_log(ERR, "Invalid operation type");
492 : 0 : return -EINVAL;
493 : : }
494 [ # # ]: 0 : if (conf->queue_size > dev_info.queue_size_lim) {
495 : 0 : rte_bbdev_log(ERR,
496 : : "Size (%u) of queue %u of device %u must be: <= %u",
497 : : conf->queue_size, queue_id, dev_id,
498 : : dev_info.queue_size_lim);
499 : 0 : return -EINVAL;
500 : : }
501 : : if (!rte_is_power_of_2(conf->queue_size)) {
502 : 0 : rte_bbdev_log(ERR,
503 : : "Size (%u) of queue %u of device %u must be a power of 2",
504 : : conf->queue_size, queue_id, dev_id);
505 : 0 : return -EINVAL;
506 : : }
507 [ # # ]: 0 : if ((uint8_t)conf->op_type >= RTE_BBDEV_OP_TYPE_SIZE_MAX) {
508 : 0 : rte_bbdev_log(ERR,
509 : : "Invalid operation type (%u) ", conf->op_type);
510 : 0 : return -EINVAL;
511 : : }
512 : 0 : max_priority = dev_info.queue_priority[conf->op_type];
513 [ # # ]: 0 : if (conf->priority > max_priority) {
514 : 0 : rte_bbdev_log(ERR,
515 : : "Priority (%u) of queue %u of bbdev %u must be <= %u",
516 : : conf->priority, queue_id, dev_id, max_priority);
517 : 0 : return -EINVAL;
518 : : }
519 : : }
520 : :
521 : : /* Release existing queue (in case of queue reconfiguration) */
522 [ # # ]: 0 : if (dev->data->queues[queue_id].queue_private != NULL) {
523 : 0 : ret = dev->dev_ops->queue_release(dev, queue_id);
524 [ # # ]: 0 : if (ret < 0) {
525 : 0 : rte_bbdev_log(ERR, "Device %u queue %u release failed",
526 : : dev_id, queue_id);
527 : 0 : return ret;
528 : : }
529 : : }
530 : :
531 : : /* Get driver to setup the queue */
532 : 0 : ret = dev->dev_ops->queue_setup(dev, queue_id, (conf != NULL) ?
533 : : conf : &dev_info.default_queue_conf);
534 [ # # ]: 0 : if (ret < 0) {
535 : : /* This may happen when trying different priority levels */
536 : 0 : rte_bbdev_log(INFO,
537 : : "Device %u queue %u setup failed",
538 : : dev_id, queue_id);
539 : 0 : return ret;
540 : : }
541 : :
542 : : /* Store configuration */
543 : 0 : stored_conf = &dev->data->queues[queue_id].conf;
544 : : memcpy(stored_conf,
545 : : (conf != NULL) ? conf : &dev_info.default_queue_conf,
546 : : sizeof(*stored_conf));
547 : :
548 : 0 : op_type_str = rte_bbdev_op_type_str(stored_conf->op_type);
549 [ # # ]: 0 : if (op_type_str == NULL)
550 : : return -EINVAL;
551 : :
552 : 0 : rte_bbdev_log_debug("Configured dev%uq%u (size=%u, type=%s, prio=%u)",
553 : : dev_id, queue_id, stored_conf->queue_size, op_type_str,
554 : : stored_conf->priority);
555 : :
556 : 0 : return 0;
557 : : }
558 : :
559 : : int
560 : 0 : rte_bbdev_start(uint16_t dev_id)
561 : : {
562 : : int i;
563 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
564 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
565 : :
566 [ # # ]: 0 : VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
567 : :
568 [ # # ]: 0 : rte_bbdev_trace_start(dev_id);
569 : :
570 [ # # ]: 0 : if (dev->data->started) {
571 : 0 : rte_bbdev_log_debug("Device %u is already started", dev_id);
572 : 0 : return 0;
573 : : }
574 : :
575 [ # # ]: 0 : if (dev->dev_ops->start) {
576 : 0 : int ret = dev->dev_ops->start(dev);
577 [ # # ]: 0 : if (ret < 0) {
578 : 0 : rte_bbdev_log(ERR, "Device %u start failed", dev_id);
579 : 0 : return ret;
580 : : }
581 : : }
582 : :
583 : : /* Store new state */
584 [ # # ]: 0 : for (i = 0; i < dev->data->num_queues; i++)
585 [ # # ]: 0 : if (!dev->data->queues[i].conf.deferred_start)
586 : 0 : dev->data->queues[i].started = true;
587 : 0 : dev->data->started = true;
588 : :
589 : 0 : rte_bbdev_log_debug("Started device %u", dev_id);
590 : 0 : return 0;
591 : : }
592 : :
593 : : int
594 : 0 : rte_bbdev_stop(uint16_t dev_id)
595 : : {
596 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
597 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
598 : :
599 [ # # ]: 0 : VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
600 : :
601 [ # # ]: 0 : rte_bbdev_trace_stop(dev_id);
602 : :
603 [ # # ]: 0 : if (!dev->data->started) {
604 : 0 : rte_bbdev_log_debug("Device %u is already stopped", dev_id);
605 : 0 : return 0;
606 : : }
607 : :
608 [ # # ]: 0 : if (dev->dev_ops->stop)
609 : 0 : dev->dev_ops->stop(dev);
610 : 0 : dev->data->started = false;
611 : :
612 : 0 : rte_bbdev_log_debug("Stopped device %u", dev_id);
613 : 0 : return 0;
614 : : }
615 : :
616 : : int
617 : 0 : rte_bbdev_close(uint16_t dev_id)
618 : : {
619 : : int ret;
620 : : uint16_t i;
621 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
622 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
623 : :
624 [ # # ]: 0 : VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
625 : :
626 [ # # ]: 0 : rte_bbdev_trace_close(dev_id);
627 : :
628 [ # # ]: 0 : if (dev->data->started) {
629 : 0 : ret = rte_bbdev_stop(dev_id);
630 [ # # ]: 0 : if (ret < 0) {
631 : 0 : rte_bbdev_log(ERR, "Device %u stop failed", dev_id);
632 : 0 : return ret;
633 : : }
634 : : }
635 : :
636 : : /* Free memory used by queues */
637 [ # # ]: 0 : for (i = 0; i < dev->data->num_queues; i++) {
638 : 0 : ret = dev->dev_ops->queue_release(dev, i);
639 [ # # ]: 0 : if (ret < 0) {
640 : 0 : rte_bbdev_log(ERR, "Device %u queue %u release failed",
641 : : dev_id, i);
642 : 0 : return ret;
643 : : }
644 : : }
645 : 0 : rte_free(dev->data->queues);
646 : :
647 [ # # ]: 0 : if (dev->dev_ops->close) {
648 : 0 : ret = dev->dev_ops->close(dev);
649 [ # # ]: 0 : if (ret < 0) {
650 : 0 : rte_bbdev_log(ERR, "Device %u close failed", dev_id);
651 : 0 : return ret;
652 : : }
653 : : }
654 : :
655 : : /* Clear configuration */
656 : 0 : dev->data->queues = NULL;
657 : 0 : dev->data->num_queues = 0;
658 : :
659 : 0 : rte_bbdev_log_debug("Closed device %u", dev_id);
660 : 0 : return 0;
661 : : }
662 : :
663 : : int
664 : 0 : rte_bbdev_queue_start(uint16_t dev_id, uint16_t queue_id)
665 : : {
666 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
667 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
668 : :
669 [ # # ]: 0 : VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
670 : :
671 [ # # ]: 0 : VALID_QUEUE_OR_RET_ERR(queue_id, dev);
672 : :
673 [ # # ]: 0 : rte_bbdev_trace_queue_start(dev_id, queue_id);
674 : :
675 [ # # ]: 0 : if (dev->data->queues[queue_id].started) {
676 : 0 : rte_bbdev_log_debug("Queue %u of device %u already started",
677 : : queue_id, dev_id);
678 : 0 : return 0;
679 : : }
680 : :
681 [ # # ]: 0 : if (dev->dev_ops->queue_start) {
682 : 0 : int ret = dev->dev_ops->queue_start(dev, queue_id);
683 [ # # ]: 0 : if (ret < 0) {
684 : 0 : rte_bbdev_log(ERR, "Device %u queue %u start failed",
685 : : dev_id, queue_id);
686 : 0 : return ret;
687 : : }
688 : : }
689 : 0 : dev->data->queues[queue_id].started = true;
690 : :
691 : 0 : rte_bbdev_log_debug("Started queue %u of device %u", queue_id, dev_id);
692 : 0 : return 0;
693 : : }
694 : :
695 : : int
696 : 0 : rte_bbdev_queue_stop(uint16_t dev_id, uint16_t queue_id)
697 : : {
698 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
699 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
700 : :
701 [ # # ]: 0 : VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
702 : :
703 [ # # ]: 0 : VALID_QUEUE_OR_RET_ERR(queue_id, dev);
704 : :
705 [ # # ]: 0 : rte_bbdev_trace_queue_stop(dev_id, queue_id);
706 : :
707 [ # # ]: 0 : if (!dev->data->queues[queue_id].started) {
708 : 0 : rte_bbdev_log_debug("Queue %u of device %u already stopped",
709 : : queue_id, dev_id);
710 : 0 : return 0;
711 : : }
712 : :
713 [ # # ]: 0 : if (dev->dev_ops->queue_stop) {
714 : 0 : int ret = dev->dev_ops->queue_stop(dev, queue_id);
715 [ # # ]: 0 : if (ret < 0) {
716 : 0 : rte_bbdev_log(ERR, "Device %u queue %u stop failed",
717 : : dev_id, queue_id);
718 : 0 : return ret;
719 : : }
720 : : }
721 : 0 : dev->data->queues[queue_id].started = false;
722 : :
723 : 0 : rte_bbdev_log_debug("Stopped queue %u of device %u", queue_id, dev_id);
724 : 0 : return 0;
725 : : }
726 : :
727 : : /* Get device statistics */
728 : : static void
729 : 0 : get_stats_from_queues(struct rte_bbdev *dev, struct rte_bbdev_stats *stats)
730 : : {
731 : : unsigned int q_id;
732 [ # # ]: 0 : for (q_id = 0; q_id < dev->data->num_queues; q_id++) {
733 : : struct rte_bbdev_stats *q_stats =
734 : 0 : &dev->data->queues[q_id].queue_stats;
735 : :
736 : 0 : stats->enqueued_count += q_stats->enqueued_count;
737 : 0 : stats->dequeued_count += q_stats->dequeued_count;
738 : 0 : stats->enqueue_err_count += q_stats->enqueue_err_count;
739 : 0 : stats->dequeue_err_count += q_stats->dequeue_err_count;
740 : 0 : stats->enqueue_warn_count += q_stats->enqueue_warn_count;
741 : 0 : stats->dequeue_warn_count += q_stats->dequeue_warn_count;
742 : : }
743 : 0 : rte_bbdev_log_debug("Got stats on %u", dev->data->dev_id);
744 : 0 : }
745 : :
746 : : static void
747 : 0 : reset_stats_in_queues(struct rte_bbdev *dev)
748 : : {
749 : : unsigned int q_id;
750 [ # # ]: 0 : for (q_id = 0; q_id < dev->data->num_queues; q_id++) {
751 : 0 : struct rte_bbdev_stats *q_stats =
752 : 0 : &dev->data->queues[q_id].queue_stats;
753 : :
754 : : memset(q_stats, 0, sizeof(*q_stats));
755 : : }
756 : 0 : rte_bbdev_log_debug("Reset stats on %u", dev->data->dev_id);
757 : 0 : }
758 : :
759 : : int
760 : 0 : rte_bbdev_stats_get(uint16_t dev_id, struct rte_bbdev_stats *stats)
761 : : {
762 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
763 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
764 : :
765 [ # # ]: 0 : VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
766 : :
767 [ # # ]: 0 : if (stats == NULL) {
768 : 0 : rte_bbdev_log(ERR, "NULL stats structure");
769 : 0 : return -EINVAL;
770 : : }
771 : :
772 : : memset(stats, 0, sizeof(*stats));
773 [ # # ]: 0 : if (dev->dev_ops->stats_get != NULL)
774 : 0 : dev->dev_ops->stats_get(dev, stats);
775 : : else
776 : 0 : get_stats_from_queues(dev, stats);
777 : :
778 : 0 : rte_bbdev_log_debug("Retrieved stats of device %u", dev_id);
779 : 0 : return 0;
780 : : }
781 : :
782 : : int
783 : 0 : rte_bbdev_stats_reset(uint16_t dev_id)
784 : : {
785 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
786 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
787 : :
788 [ # # ]: 0 : VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
789 : :
790 [ # # ]: 0 : if (dev->dev_ops->stats_reset != NULL)
791 : 0 : dev->dev_ops->stats_reset(dev);
792 : : else
793 : 0 : reset_stats_in_queues(dev);
794 : :
795 : 0 : rte_bbdev_log_debug("Reset stats of device %u", dev_id);
796 : 0 : return 0;
797 : : }
798 : :
799 : : int
800 : 0 : rte_bbdev_info_get(uint16_t dev_id, struct rte_bbdev_info *dev_info)
801 : : {
802 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
803 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
804 : :
805 [ # # ]: 0 : VALID_FUNC_OR_RET_ERR(dev->dev_ops->info_get, dev_id);
806 : :
807 [ # # ]: 0 : if (dev_info == NULL) {
808 : 0 : rte_bbdev_log(ERR, "NULL dev info structure");
809 : 0 : return -EINVAL;
810 : : }
811 : :
812 : : /* Copy data maintained by device interface layer */
813 : : memset(dev_info, 0, sizeof(*dev_info));
814 : 0 : dev_info->dev_name = dev->data->name;
815 : 0 : dev_info->num_queues = dev->data->num_queues;
816 : 0 : dev_info->device = dev->device;
817 : 0 : dev_info->socket_id = dev->data->socket_id;
818 : 0 : dev_info->started = dev->data->started;
819 : :
820 : : /* Copy data maintained by device driver layer */
821 : 0 : dev->dev_ops->info_get(dev, &dev_info->drv);
822 : :
823 : 0 : rte_bbdev_log_debug("Retrieved info of device %u", dev_id);
824 : 0 : return 0;
825 : : }
826 : :
827 : : int
828 : 0 : rte_bbdev_queue_info_get(uint16_t dev_id, uint16_t queue_id,
829 : : struct rte_bbdev_queue_info *queue_info)
830 : : {
831 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
832 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
833 : :
834 [ # # ]: 0 : VALID_QUEUE_OR_RET_ERR(queue_id, dev);
835 : :
836 [ # # ]: 0 : if (queue_info == NULL) {
837 : 0 : rte_bbdev_log(ERR, "NULL queue info structure");
838 : 0 : return -EINVAL;
839 : : }
840 : :
841 : : /* Copy data to output */
842 : : memset(queue_info, 0, sizeof(*queue_info));
843 : 0 : queue_info->conf = dev->data->queues[queue_id].conf;
844 : 0 : queue_info->started = dev->data->queues[queue_id].started;
845 : :
846 : 0 : rte_bbdev_log_debug("Retrieved info of queue %u of device %u",
847 : : queue_id, dev_id);
848 : 0 : return 0;
849 : : }
850 : :
851 : : /* Calculate size needed to store bbdev_op, depending on type */
852 : : static unsigned int
853 : : get_bbdev_op_size(enum rte_bbdev_op_type type)
854 : : {
855 : : unsigned int result = 0;
856 : : switch (type) {
857 : : case RTE_BBDEV_OP_NONE:
858 : : result = RTE_MAX(sizeof(struct rte_bbdev_dec_op),
859 : : sizeof(struct rte_bbdev_enc_op));
860 : : break;
861 : : case RTE_BBDEV_OP_TURBO_DEC:
862 : : result = sizeof(struct rte_bbdev_dec_op);
863 : : break;
864 : : case RTE_BBDEV_OP_TURBO_ENC:
865 : : result = sizeof(struct rte_bbdev_enc_op);
866 : : break;
867 : : case RTE_BBDEV_OP_LDPC_DEC:
868 : : result = sizeof(struct rte_bbdev_dec_op);
869 : : break;
870 : : case RTE_BBDEV_OP_LDPC_ENC:
871 : : result = sizeof(struct rte_bbdev_enc_op);
872 : : break;
873 : : case RTE_BBDEV_OP_FFT:
874 : : result = sizeof(struct rte_bbdev_fft_op);
875 : : break;
876 : : case RTE_BBDEV_OP_MLDTS:
877 : : result = sizeof(struct rte_bbdev_mldts_op);
878 : : break;
879 : : default:
880 : : break;
881 : : }
882 : :
883 : : return result;
884 : : }
885 : :
886 : : /* Initialise a bbdev_op structure */
887 : : static void
888 : 0 : bbdev_op_init(struct rte_mempool *mempool, void *arg, void *element,
889 : : __rte_unused unsigned int n)
890 : : {
891 : 0 : enum rte_bbdev_op_type type = *(enum rte_bbdev_op_type *)arg;
892 : :
893 [ # # ]: 0 : if (type == RTE_BBDEV_OP_TURBO_DEC || type == RTE_BBDEV_OP_LDPC_DEC) {
894 : : struct rte_bbdev_dec_op *op = element;
895 : 0 : memset(op, 0, mempool->elt_size);
896 : 0 : op->mempool = mempool;
897 : 0 : } else if (type == RTE_BBDEV_OP_TURBO_ENC ||
898 [ # # ]: 0 : type == RTE_BBDEV_OP_LDPC_ENC) {
899 : : struct rte_bbdev_enc_op *op = element;
900 : 0 : memset(op, 0, mempool->elt_size);
901 : 0 : op->mempool = mempool;
902 [ # # ]: 0 : } else if (type == RTE_BBDEV_OP_FFT) {
903 : : struct rte_bbdev_fft_op *op = element;
904 : 0 : memset(op, 0, mempool->elt_size);
905 : 0 : op->mempool = mempool;
906 [ # # ]: 0 : } else if (type == RTE_BBDEV_OP_MLDTS) {
907 : : struct rte_bbdev_mldts_op *op = element;
908 : 0 : memset(op, 0, mempool->elt_size);
909 : 0 : op->mempool = mempool;
910 : : }
911 : 0 : }
912 : :
913 : : struct rte_mempool *
914 : 0 : rte_bbdev_op_pool_create(const char *name, enum rte_bbdev_op_type type,
915 : : unsigned int num_elements, unsigned int cache_size,
916 : : int socket_id)
917 : : {
918 : : struct rte_bbdev_op_pool_private *priv;
919 : : struct rte_mempool *mp;
920 : : const char *op_type_str;
921 : :
922 [ # # ]: 0 : if (name == NULL) {
923 : 0 : rte_bbdev_log(ERR, "NULL name for op pool");
924 : 0 : return NULL;
925 : : }
926 : :
927 [ # # ]: 0 : if (type >= BBDEV_OP_TYPE_COUNT) {
928 : 0 : rte_bbdev_log(ERR,
929 : : "Invalid op type (%u), should be less than %u",
930 : : type, BBDEV_OP_TYPE_COUNT);
931 : 0 : return NULL;
932 : : }
933 : :
934 : 0 : mp = rte_mempool_create(name, num_elements, get_bbdev_op_size(type),
935 : : cache_size, sizeof(struct rte_bbdev_op_pool_private),
936 : : NULL, NULL, bbdev_op_init, &type, socket_id, 0);
937 [ # # ]: 0 : if (mp == NULL) {
938 [ # # ]: 0 : rte_bbdev_log(ERR,
939 : : "Failed to create op pool %s (num ops=%u, op size=%u) with error: %s",
940 : : name, num_elements, get_bbdev_op_size(type),
941 : : rte_strerror(rte_errno));
942 : 0 : return NULL;
943 : : }
944 : :
945 : 0 : op_type_str = rte_bbdev_op_type_str(type);
946 [ # # ]: 0 : if (op_type_str == NULL)
947 : : return NULL;
948 : :
949 [ # # ]: 0 : rte_bbdev_log_debug(
950 : : "Op pool %s created for %u ops (type=%s, cache=%u, socket=%u, size=%u)",
951 : : name, num_elements, op_type_str, cache_size, socket_id,
952 : : get_bbdev_op_size(type));
953 : :
954 : : priv = (struct rte_bbdev_op_pool_private *)rte_mempool_get_priv(mp);
955 : 0 : priv->type = type;
956 : :
957 : 0 : return mp;
958 : : }
959 : :
960 : : int
961 : 0 : rte_bbdev_callback_register(uint16_t dev_id, enum rte_bbdev_event_type event,
962 : : rte_bbdev_cb_fn cb_fn, void *cb_arg)
963 : : {
964 : : struct rte_bbdev_callback *user_cb;
965 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
966 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
967 : :
968 [ # # ]: 0 : if (event >= RTE_BBDEV_EVENT_MAX) {
969 : 0 : rte_bbdev_log(ERR,
970 : : "Invalid event type (%u), should be less than %u",
971 : : event, RTE_BBDEV_EVENT_MAX);
972 : 0 : return -EINVAL;
973 : : }
974 : :
975 [ # # ]: 0 : if (cb_fn == NULL) {
976 : 0 : rte_bbdev_log(ERR, "NULL callback function");
977 : 0 : return -EINVAL;
978 : : }
979 : :
980 : : rte_spinlock_lock(&rte_bbdev_cb_lock);
981 : :
982 [ # # ]: 0 : TAILQ_FOREACH(user_cb, &(dev->list_cbs), next) {
983 [ # # ]: 0 : if (user_cb->cb_fn == cb_fn &&
984 [ # # ]: 0 : user_cb->cb_arg == cb_arg &&
985 [ # # ]: 0 : user_cb->event == event)
986 : : break;
987 : : }
988 : :
989 : : /* create a new callback. */
990 [ # # ]: 0 : if (user_cb == NULL) {
991 : 0 : user_cb = rte_zmalloc("INTR_USER_CALLBACK",
992 : : sizeof(struct rte_bbdev_callback), 0);
993 [ # # ]: 0 : if (user_cb != NULL) {
994 : 0 : user_cb->cb_fn = cb_fn;
995 : 0 : user_cb->cb_arg = cb_arg;
996 : 0 : user_cb->event = event;
997 : 0 : TAILQ_INSERT_TAIL(&(dev->list_cbs), user_cb, next);
998 : : }
999 : : }
1000 : :
1001 : : rte_spinlock_unlock(&rte_bbdev_cb_lock);
1002 [ # # ]: 0 : return (user_cb == NULL) ? -ENOMEM : 0;
1003 : : }
1004 : :
1005 : : int
1006 : 0 : rte_bbdev_callback_unregister(uint16_t dev_id, enum rte_bbdev_event_type event,
1007 : : rte_bbdev_cb_fn cb_fn, void *cb_arg)
1008 : : {
1009 : : int ret = 0;
1010 : : struct rte_bbdev_callback *cb, *next;
1011 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
1012 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
1013 : :
1014 [ # # ]: 0 : if (event >= RTE_BBDEV_EVENT_MAX) {
1015 : 0 : rte_bbdev_log(ERR,
1016 : : "Invalid event type (%u), should be less than %u",
1017 : : event, RTE_BBDEV_EVENT_MAX);
1018 : 0 : return -EINVAL;
1019 : : }
1020 : :
1021 [ # # ]: 0 : if (cb_fn == NULL) {
1022 : 0 : rte_bbdev_log(ERR,
1023 : : "NULL callback function cannot be unregistered");
1024 : 0 : return -EINVAL;
1025 : : }
1026 : :
1027 : : dev = &rte_bbdev_devices[dev_id];
1028 : : rte_spinlock_lock(&rte_bbdev_cb_lock);
1029 : :
1030 [ # # ]: 0 : for (cb = TAILQ_FIRST(&dev->list_cbs); cb != NULL; cb = next) {
1031 : :
1032 : 0 : next = TAILQ_NEXT(cb, next);
1033 : :
1034 [ # # # # : 0 : if (cb->cb_fn != cb_fn || cb->event != event ||
# # ]
1035 [ # # ]: 0 : (cb_arg != (void *)-1 && cb->cb_arg != cb_arg))
1036 : 0 : continue;
1037 : :
1038 : : /* If this callback is not executing right now, remove it. */
1039 [ # # ]: 0 : if (cb->active == 0) {
1040 [ # # ]: 0 : TAILQ_REMOVE(&(dev->list_cbs), cb, next);
1041 : 0 : rte_free(cb);
1042 : : } else
1043 : : ret = -EAGAIN;
1044 : : }
1045 : :
1046 : : rte_spinlock_unlock(&rte_bbdev_cb_lock);
1047 : 0 : return ret;
1048 : : }
1049 : :
1050 : : void
1051 : 0 : rte_bbdev_pmd_callback_process(struct rte_bbdev *dev,
1052 : : enum rte_bbdev_event_type event, void *ret_param)
1053 : : {
1054 : : struct rte_bbdev_callback *cb_lst;
1055 : : struct rte_bbdev_callback dev_cb;
1056 : :
1057 [ # # ]: 0 : if (dev == NULL) {
1058 : 0 : rte_bbdev_log(ERR, "NULL device");
1059 : 0 : return;
1060 : : }
1061 : :
1062 [ # # ]: 0 : if (dev->data == NULL) {
1063 : 0 : rte_bbdev_log(ERR, "NULL data structure");
1064 : 0 : return;
1065 : : }
1066 : :
1067 [ # # ]: 0 : if (event >= RTE_BBDEV_EVENT_MAX) {
1068 : 0 : rte_bbdev_log(ERR,
1069 : : "Invalid event type (%u), should be less than %u",
1070 : : event, RTE_BBDEV_EVENT_MAX);
1071 : 0 : return;
1072 : : }
1073 : :
1074 : : rte_spinlock_lock(&rte_bbdev_cb_lock);
1075 [ # # ]: 0 : TAILQ_FOREACH(cb_lst, &(dev->list_cbs), next) {
1076 [ # # # # ]: 0 : if (cb_lst->cb_fn == NULL || cb_lst->event != event)
1077 : 0 : continue;
1078 : 0 : dev_cb = *cb_lst;
1079 : 0 : cb_lst->active = 1;
1080 [ # # ]: 0 : if (ret_param != NULL)
1081 : : dev_cb.ret_param = ret_param;
1082 : :
1083 : : rte_spinlock_unlock(&rte_bbdev_cb_lock);
1084 : 0 : dev_cb.cb_fn(dev->data->dev_id, dev_cb.event,
1085 : : dev_cb.cb_arg, dev_cb.ret_param);
1086 : : rte_spinlock_lock(&rte_bbdev_cb_lock);
1087 : 0 : cb_lst->active = 0;
1088 : : }
1089 : : rte_spinlock_unlock(&rte_bbdev_cb_lock);
1090 : : }
1091 : :
1092 : : int
1093 : 0 : rte_bbdev_queue_intr_enable(uint16_t dev_id, uint16_t queue_id)
1094 : : {
1095 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
1096 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
1097 [ # # ]: 0 : VALID_QUEUE_OR_RET_ERR(queue_id, dev);
1098 [ # # ]: 0 : VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
1099 [ # # ]: 0 : VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_intr_enable, dev_id);
1100 : 0 : return dev->dev_ops->queue_intr_enable(dev, queue_id);
1101 : : }
1102 : :
1103 : : int
1104 : 0 : rte_bbdev_queue_intr_disable(uint16_t dev_id, uint16_t queue_id)
1105 : : {
1106 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
1107 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
1108 [ # # ]: 0 : VALID_QUEUE_OR_RET_ERR(queue_id, dev);
1109 [ # # ]: 0 : VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
1110 [ # # ]: 0 : VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_intr_disable, dev_id);
1111 : 0 : return dev->dev_ops->queue_intr_disable(dev, queue_id);
1112 : : }
1113 : :
1114 : : int
1115 : 0 : rte_bbdev_queue_intr_ctl(uint16_t dev_id, uint16_t queue_id, int epfd, int op,
1116 : : void *data)
1117 : : {
1118 : : uint32_t vec;
1119 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
1120 : : struct rte_intr_handle *intr_handle;
1121 : : int ret;
1122 : :
1123 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
1124 [ # # ]: 0 : VALID_QUEUE_OR_RET_ERR(queue_id, dev);
1125 : :
1126 : 0 : intr_handle = dev->intr_handle;
1127 [ # # ]: 0 : if (intr_handle == NULL) {
1128 : 0 : rte_bbdev_log(ERR, "Device %u intr handle unset", dev_id);
1129 : 0 : return -ENOTSUP;
1130 : : }
1131 : :
1132 [ # # ]: 0 : if (queue_id >= RTE_MAX_RXTX_INTR_VEC_ID) {
1133 : 0 : rte_bbdev_log(ERR, "Device %u queue_id %u is too big",
1134 : : dev_id, queue_id);
1135 : 0 : return -ENOTSUP;
1136 : : }
1137 : :
1138 : 0 : vec = rte_intr_vec_list_index_get(intr_handle, queue_id);
1139 : 0 : ret = rte_intr_rx_ctl(intr_handle, epfd, op, vec, data);
1140 [ # # ]: 0 : if (ret && (ret != -EEXIST)) {
1141 : 0 : rte_bbdev_log(ERR,
1142 : : "dev %u q %u int ctl error op %d epfd %d vec %u",
1143 : : dev_id, queue_id, op, epfd, vec);
1144 : 0 : return ret;
1145 : : }
1146 : :
1147 : : return 0;
1148 : : }
1149 : :
1150 : :
1151 : : const char *
1152 : 0 : rte_bbdev_op_type_str(enum rte_bbdev_op_type op_type)
1153 : : {
1154 : : static const char * const op_types[] = {
1155 : : "RTE_BBDEV_OP_NONE",
1156 : : "RTE_BBDEV_OP_TURBO_DEC",
1157 : : "RTE_BBDEV_OP_TURBO_ENC",
1158 : : "RTE_BBDEV_OP_LDPC_DEC",
1159 : : "RTE_BBDEV_OP_LDPC_ENC",
1160 : : "RTE_BBDEV_OP_FFT",
1161 : : "RTE_BBDEV_OP_MLDTS",
1162 : : };
1163 : :
1164 [ # # ]: 0 : if (op_type < BBDEV_OP_TYPE_COUNT)
1165 : 0 : return op_types[op_type];
1166 : :
1167 : 0 : rte_bbdev_log(ERR, "Invalid operation type");
1168 : 0 : return NULL;
1169 : : }
1170 : :
1171 : : const char *
1172 : 0 : rte_bbdev_device_status_str(enum rte_bbdev_device_status status)
1173 : : {
1174 : : static const char * const dev_sta_string[] = {
1175 : : "RTE_BBDEV_DEV_NOSTATUS",
1176 : : "RTE_BBDEV_DEV_NOT_SUPPORTED",
1177 : : "RTE_BBDEV_DEV_RESET",
1178 : : "RTE_BBDEV_DEV_CONFIGURED",
1179 : : "RTE_BBDEV_DEV_ACTIVE",
1180 : : "RTE_BBDEV_DEV_FATAL_ERR",
1181 : : "RTE_BBDEV_DEV_RESTART_REQ",
1182 : : "RTE_BBDEV_DEV_RECONFIG_REQ",
1183 : : "RTE_BBDEV_DEV_CORRECT_ERR",
1184 : : };
1185 : :
1186 : : /* Cast from enum required for clang. */
1187 [ # # ]: 0 : if ((uint8_t)status < sizeof(dev_sta_string) / sizeof(char *))
1188 : 0 : return dev_sta_string[status];
1189 : :
1190 : 0 : rte_bbdev_log(ERR, "Invalid device status");
1191 : 0 : return NULL;
1192 : : }
1193 : :
1194 : : const char *
1195 : 0 : rte_bbdev_enqueue_status_str(enum rte_bbdev_enqueue_status status)
1196 : : {
1197 : : static const char * const enq_sta_string[] = {
1198 : : "RTE_BBDEV_ENQ_STATUS_NONE",
1199 : : "RTE_BBDEV_ENQ_STATUS_QUEUE_FULL",
1200 : : "RTE_BBDEV_ENQ_STATUS_RING_FULL",
1201 : : "RTE_BBDEV_ENQ_STATUS_INVALID_OP",
1202 : : };
1203 : :
1204 : : /* Cast from enum required for clang. */
1205 [ # # ]: 0 : if ((uint8_t)status < sizeof(enq_sta_string) / sizeof(char *))
1206 : 0 : return enq_sta_string[status];
1207 : :
1208 : 0 : rte_bbdev_log(ERR, "Invalid enqueue status");
1209 : 0 : return NULL;
1210 : : }
1211 : :
1212 : :
1213 : : int
1214 : 0 : rte_bbdev_queue_ops_dump(uint16_t dev_id, uint16_t queue_id, FILE *f)
1215 : : {
1216 : : struct rte_bbdev_queue_data *q_data;
1217 : : struct rte_bbdev_stats *stats;
1218 : : uint16_t i;
1219 : 0 : struct rte_bbdev *dev = get_dev(dev_id);
1220 : :
1221 : 0 : VALID_DEV_OR_RET_ERR(dev, dev_id);
1222 [ # # ]: 0 : VALID_QUEUE_OR_RET_ERR(queue_id, dev);
1223 [ # # ]: 0 : VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
1224 [ # # ]: 0 : VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_ops_dump, dev_id);
1225 : :
1226 : 0 : q_data = &dev->data->queues[queue_id];
1227 : :
1228 [ # # ]: 0 : if (f == NULL)
1229 : : return -EINVAL;
1230 : :
1231 : 0 : fprintf(f, "Dump of operations on %s queue %d\n",
1232 : 0 : dev->data->name, queue_id);
1233 : 0 : fprintf(f, " Last Enqueue Status %s\n",
1234 : : rte_bbdev_enqueue_status_str(q_data->enqueue_status));
1235 [ # # ]: 0 : for (i = 0; i < RTE_BBDEV_ENQ_STATUS_SIZE_MAX; i++)
1236 [ # # ]: 0 : if (q_data->queue_stats.enqueue_status_count[i] > 0)
1237 : 0 : fprintf(f, " Enqueue Status Counters %s %" PRIu64 "\n",
1238 : : rte_bbdev_enqueue_status_str(i),
1239 : : q_data->queue_stats.enqueue_status_count[i]);
1240 : 0 : stats = &dev->data->queues[queue_id].queue_stats;
1241 : :
1242 : 0 : fprintf(f, " Enqueue Count %" PRIu64 " Warning %" PRIu64 " Error %" PRIu64 "\n",
1243 : : stats->enqueued_count, stats->enqueue_warn_count,
1244 : : stats->enqueue_err_count);
1245 : 0 : fprintf(f, " Dequeue Count %" PRIu64 " Warning %" PRIu64 " Error %" PRIu64 "\n",
1246 : : stats->dequeued_count, stats->dequeue_warn_count,
1247 : : stats->dequeue_err_count);
1248 : :
1249 : 0 : return dev->dev_ops->queue_ops_dump(dev, queue_id, f);
1250 : : }
1251 : :
1252 : : char *
1253 : 0 : rte_bbdev_ops_param_string(void *op, enum rte_bbdev_op_type op_type, char *str, uint32_t len)
1254 : : {
1255 : : static char partial[1024];
1256 : : struct rte_bbdev_dec_op *op_dec;
1257 : : struct rte_bbdev_enc_op *op_enc;
1258 : : struct rte_bbdev_fft_op *op_fft;
1259 : : struct rte_bbdev_mldts_op *op_mldts;
1260 : :
1261 : : rte_iova_t add0 = 0, add1 = 0, add2 = 0, add3 = 0, add4 = 0;
1262 : :
1263 [ # # ]: 0 : if (op == NULL) {
1264 : 0 : snprintf(str, len, "Invalid Operation pointer\n");
1265 : 0 : return str;
1266 : : }
1267 : :
1268 : : if (op_type == RTE_BBDEV_OP_LDPC_DEC) {
1269 : : op_dec = op;
1270 [ # # ]: 0 : if (op_dec->ldpc_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
1271 : 0 : snprintf(partial, sizeof(partial), "C %d Cab %d Ea %d Eb %d r %d",
1272 : 0 : op_dec->ldpc_dec.tb_params.c,
1273 : 0 : op_dec->ldpc_dec.tb_params.cab,
1274 : : op_dec->ldpc_dec.tb_params.ea,
1275 : : op_dec->ldpc_dec.tb_params.eb,
1276 : 0 : op_dec->ldpc_dec.tb_params.r);
1277 : : else
1278 : 0 : snprintf(partial, sizeof(partial), "E %d", op_dec->ldpc_dec.cb_params.e);
1279 [ # # ]: 0 : if (op_dec->ldpc_dec.input.data != NULL)
1280 : 0 : add0 = rte_pktmbuf_iova_offset(op_dec->ldpc_dec.input.data, 0);
1281 [ # # ]: 0 : if (op_dec->ldpc_dec.hard_output.data != NULL)
1282 : 0 : add1 = rte_pktmbuf_iova_offset(op_dec->ldpc_dec.hard_output.data, 0);
1283 [ # # ]: 0 : if (op_dec->ldpc_dec.soft_output.data != NULL)
1284 : 0 : add2 = rte_pktmbuf_iova_offset(op_dec->ldpc_dec.soft_output.data, 0);
1285 [ # # ]: 0 : if (op_dec->ldpc_dec.harq_combined_input.data != NULL)
1286 : 0 : add3 = rte_pktmbuf_iova_offset(op_dec->ldpc_dec.harq_combined_input.data,
1287 : : 0);
1288 [ # # ]: 0 : if (op_dec->ldpc_dec.harq_combined_output.data != NULL)
1289 : 0 : add4 = rte_pktmbuf_iova_offset(op_dec->ldpc_dec.harq_combined_output.data,
1290 : : 0);
1291 : 0 : snprintf(str, len, "op %x st %x BG %d Zc %d Ncb %d qm %d F %d Rv %d It %d It %d "
1292 : : "HARQin %d in %" PRIx64 " ho %" PRIx64 " so %" PRIx64 " hi %" PRIx64 " "
1293 : : "ho %" PRIx64 " %s\n",
1294 : : op_dec->ldpc_dec.op_flags, op_dec->status,
1295 : 0 : op_dec->ldpc_dec.basegraph, op_dec->ldpc_dec.z_c,
1296 : 0 : op_dec->ldpc_dec.n_cb, op_dec->ldpc_dec.q_m,
1297 : 0 : op_dec->ldpc_dec.n_filler, op_dec->ldpc_dec.rv_index,
1298 : 0 : op_dec->ldpc_dec.iter_max, op_dec->ldpc_dec.iter_count,
1299 : : op_dec->ldpc_dec.harq_combined_input.length,
1300 : : add0, add1, add2, add3, add4, partial);
1301 : : } else if (op_type == RTE_BBDEV_OP_TURBO_DEC) {
1302 : : op_dec = op;
1303 [ # # ]: 0 : if (op_dec->turbo_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
1304 : 0 : snprintf(partial, sizeof(partial), "C %d Cab %d Ea %d Eb %d r %d K %d",
1305 : 0 : op_dec->turbo_dec.tb_params.c,
1306 : 0 : op_dec->turbo_dec.tb_params.cab,
1307 : : op_dec->turbo_dec.tb_params.ea,
1308 : : op_dec->turbo_dec.tb_params.eb,
1309 : 0 : op_dec->turbo_dec.tb_params.r,
1310 : 0 : op_dec->turbo_dec.tb_params.k_neg);
1311 : : else
1312 : 0 : snprintf(partial, sizeof(partial), "E %d K %d",
1313 : : op_dec->turbo_dec.cb_params.e,
1314 : 0 : op_dec->turbo_dec.cb_params.k);
1315 [ # # ]: 0 : if (op_dec->turbo_dec.input.data != NULL)
1316 : 0 : add0 = rte_pktmbuf_iova_offset(op_dec->turbo_dec.input.data, 0);
1317 [ # # ]: 0 : if (op_dec->turbo_dec.hard_output.data != NULL)
1318 : 0 : add1 = rte_pktmbuf_iova_offset(op_dec->turbo_dec.hard_output.data, 0);
1319 [ # # ]: 0 : if (op_dec->turbo_dec.soft_output.data != NULL)
1320 : 0 : add2 = rte_pktmbuf_iova_offset(op_dec->turbo_dec.soft_output.data, 0);
1321 : 0 : snprintf(str, len, "op %x st %x CBM %d Iter %d map %d Rv %d ext %d "
1322 : : "in %" PRIx64 " ho %" PRIx64 " so %" PRIx64 " %s\n",
1323 : : op_dec->turbo_dec.op_flags, op_dec->status,
1324 : 0 : op_dec->turbo_dec.code_block_mode,
1325 : 0 : op_dec->turbo_dec.iter_max, op_dec->turbo_dec.num_maps,
1326 : 0 : op_dec->turbo_dec.rv_index, op_dec->turbo_dec.ext_scale,
1327 : : add0, add1, add2, partial);
1328 : : } else if (op_type == RTE_BBDEV_OP_LDPC_ENC) {
1329 : : op_enc = op;
1330 [ # # ]: 0 : if (op_enc->ldpc_enc.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
1331 : 0 : snprintf(partial, sizeof(partial), "C %d Cab %d Ea %d Eb %d r %d",
1332 : 0 : op_enc->ldpc_enc.tb_params.c,
1333 : 0 : op_enc->ldpc_enc.tb_params.cab,
1334 : : op_enc->ldpc_enc.tb_params.ea,
1335 : : op_enc->ldpc_enc.tb_params.eb,
1336 : 0 : op_enc->ldpc_enc.tb_params.r);
1337 : : else
1338 : 0 : snprintf(partial, sizeof(partial), "E %d",
1339 : : op_enc->ldpc_enc.cb_params.e);
1340 [ # # ]: 0 : if (op_enc->ldpc_enc.input.data != NULL)
1341 : 0 : add0 = rte_pktmbuf_iova_offset(op_enc->ldpc_enc.input.data, 0);
1342 [ # # ]: 0 : if (op_enc->ldpc_enc.output.data != NULL)
1343 : 0 : add1 = rte_pktmbuf_iova_offset(op_enc->ldpc_enc.output.data, 0);
1344 : 0 : snprintf(str, len, "op %x st %x BG %d Zc %d Ncb %d q_m %d F %d Rv %d "
1345 : : "in %" PRIx64 " out %" PRIx64 " %s\n",
1346 : : op_enc->ldpc_enc.op_flags, op_enc->status,
1347 : 0 : op_enc->ldpc_enc.basegraph, op_enc->ldpc_enc.z_c,
1348 : 0 : op_enc->ldpc_enc.n_cb, op_enc->ldpc_enc.q_m,
1349 : 0 : op_enc->ldpc_enc.n_filler, op_enc->ldpc_enc.rv_index,
1350 : : add0, add1, partial);
1351 : : } else if (op_type == RTE_BBDEV_OP_TURBO_ENC) {
1352 : : op_enc = op;
1353 [ # # ]: 0 : if (op_enc->turbo_enc.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
1354 : 0 : snprintf(partial, sizeof(partial),
1355 : : "C %d Cab %d Ea %d Eb %d r %d K %d Ncb %d",
1356 : 0 : op_enc->turbo_enc.tb_params.c,
1357 : 0 : op_enc->turbo_enc.tb_params.cab,
1358 : : op_enc->turbo_enc.tb_params.ea,
1359 : : op_enc->turbo_enc.tb_params.eb,
1360 : 0 : op_enc->turbo_enc.tb_params.r,
1361 : 0 : op_enc->turbo_enc.tb_params.k_neg,
1362 : 0 : op_enc->turbo_enc.tb_params.ncb_neg);
1363 : : else
1364 : 0 : snprintf(partial, sizeof(partial), "E %d K %d",
1365 : : op_enc->turbo_enc.cb_params.e,
1366 : 0 : op_enc->turbo_enc.cb_params.k);
1367 [ # # ]: 0 : if (op_enc->turbo_enc.input.data != NULL)
1368 : 0 : add0 = rte_pktmbuf_iova_offset(op_enc->turbo_enc.input.data, 0);
1369 [ # # ]: 0 : if (op_enc->turbo_enc.output.data != NULL)
1370 : 0 : add1 = rte_pktmbuf_iova_offset(op_enc->turbo_enc.output.data, 0);
1371 : 0 : snprintf(str, len, "op %x st %x CBM %d Rv %d In %" PRIx64 " Out %" PRIx64 " %s\n",
1372 : : op_enc->turbo_enc.op_flags, op_enc->status,
1373 : 0 : op_enc->turbo_enc.code_block_mode, op_enc->turbo_enc.rv_index,
1374 : : add0, add1, partial);
1375 : : } else if (op_type == RTE_BBDEV_OP_FFT) {
1376 : : op_fft = op;
1377 [ # # ]: 0 : if (op_fft->fft.base_input.data != NULL)
1378 : 0 : add0 = rte_pktmbuf_iova_offset(op_fft->fft.base_input.data, 0);
1379 [ # # ]: 0 : if (op_fft->fft.base_output.data != NULL)
1380 : 0 : add1 = rte_pktmbuf_iova_offset(op_fft->fft.base_output.data, 0);
1381 [ # # ]: 0 : if (op_fft->fft.dewindowing_input.data != NULL)
1382 : 0 : add2 = rte_pktmbuf_iova_offset(op_fft->fft.dewindowing_input.data, 0);
1383 [ # # ]: 0 : if (op_fft->fft.power_meas_output.data != NULL)
1384 : 0 : add3 = rte_pktmbuf_iova_offset(op_fft->fft.power_meas_output.data, 0);
1385 : 0 : snprintf(str, len, "op %x st %x in %d inl %d out %d outl %d cs %x ants %d "
1386 : : "idft %d dft %d cst %d ish %d dsh %d ncs %d pwsh %d fp16 %d fr %d "
1387 : : "outde %d in %" PRIx64 " out %" PRIx64 " dw %" PRIx64 " "
1388 : : "pm %" PRIx64 "\n",
1389 : : op_fft->fft.op_flags, op_fft->status,
1390 : 0 : op_fft->fft.input_sequence_size, op_fft->fft.input_leading_padding,
1391 : 0 : op_fft->fft.output_sequence_size,
1392 : 0 : op_fft->fft.output_leading_depadding,
1393 : 0 : op_fft->fft.cs_bitmap, op_fft->fft.num_antennas_log2,
1394 : 0 : op_fft->fft.idft_log2, op_fft->fft.dft_log2,
1395 : 0 : op_fft->fft.cs_time_adjustment,
1396 : 0 : op_fft->fft.idft_shift, op_fft->fft.dft_shift,
1397 : 0 : op_fft->fft.ncs_reciprocal, op_fft->fft.power_shift,
1398 : 0 : op_fft->fft.fp16_exp_adjust, op_fft->fft.freq_resample_mode,
1399 : 0 : op_fft->fft.output_depadded_size, add0, add1, add2, add3);
1400 : : } else if (op_type == RTE_BBDEV_OP_MLDTS) {
1401 : : op_mldts = op;
1402 [ # # ]: 0 : if (op_mldts->mldts.qhy_input.data != NULL)
1403 : 0 : add0 = rte_pktmbuf_iova_offset(op_mldts->mldts.qhy_input.data, 0);
1404 [ # # ]: 0 : if (op_mldts->mldts.r_input.data != NULL)
1405 : 0 : add1 = rte_pktmbuf_iova_offset(op_mldts->mldts.r_input.data, 0);
1406 [ # # ]: 0 : if (op_mldts->mldts.output.data != NULL)
1407 : 0 : add2 = rte_pktmbuf_iova_offset(op_mldts->mldts.output.data, 0);
1408 : 0 : snprintf(str, len,
1409 : : "op %x st %x rbs %d lay %d rrep %d crep%d qm %d %d %d %d "
1410 : : "qhy %" PRIx64 " r %" PRIx64 " out %" PRIx64 "\n",
1411 : : op_mldts->mldts.op_flags, op_mldts->status,
1412 : 0 : op_mldts->mldts.num_rbs, op_mldts->mldts.num_layers,
1413 : 0 : op_mldts->mldts.r_rep, op_mldts->mldts.c_rep,
1414 : 0 : op_mldts->mldts.q_m[0], op_mldts->mldts.q_m[1],
1415 : 0 : op_mldts->mldts.q_m[2], op_mldts->mldts.q_m[3],
1416 : : add0, add1, add2);
1417 : :
1418 : : } else {
1419 : 0 : snprintf(str, len, "Invalid Operation type %d\n", op_type);
1420 : : }
1421 : :
1422 : : return str;
1423 : : }
|