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 9 #include <rte_compat.h> 10 #include <rte_common.h> 11 #include <rte_errno.h> 12 #include <rte_log.h> 13 #include <rte_debug.h> 14 #include <rte_eal.h> 15 #include <rte_malloc.h> 16 #include <rte_mempool.h> 17 #include <rte_memzone.h> 18 #include <rte_lcore.h> 19 #include <rte_dev.h> 20 #include <rte_spinlock.h> 21 #include <rte_tailq.h> 22 #include <rte_interrupts.h> 23 24 #include "rte_bbdev_op.h" 25 #include "rte_bbdev.h" 26 #include "rte_bbdev_pmd.h" 27 28 #define DEV_NAME "BBDEV" 29 30 31 /* BBDev library logging ID */ 32 static int bbdev_logtype; 33 34 /* Helper macro for logging */ 35 #define rte_bbdev_log(level, fmt, ...) \ 36 rte_log(RTE_LOG_ ## level, bbdev_logtype, fmt "\n", ##__VA_ARGS__) 37 38 #define rte_bbdev_log_debug(fmt, ...) \ 39 rte_bbdev_log(DEBUG, RTE_STR(__LINE__) ":%s() " fmt, __func__, \ 40 ##__VA_ARGS__) 41 42 /* Helper macro to check dev_id is valid */ 43 #define VALID_DEV_OR_RET_ERR(dev, dev_id) do { \ 44 if (dev == NULL) { \ 45 rte_bbdev_log(ERR, "device %u is invalid", dev_id); \ 46 return -ENODEV; \ 47 } \ 48 } while (0) 49 50 /* Helper macro to check dev_ops is valid */ 51 #define VALID_DEV_OPS_OR_RET_ERR(dev, dev_id) do { \ 52 if (dev->dev_ops == NULL) { \ 53 rte_bbdev_log(ERR, "NULL dev_ops structure in device %u", \ 54 dev_id); \ 55 return -ENODEV; \ 56 } \ 57 } while (0) 58 59 /* Helper macro to check that driver implements required function pointer */ 60 #define VALID_FUNC_OR_RET_ERR(func, dev_id) do { \ 61 if (func == NULL) { \ 62 rte_bbdev_log(ERR, "device %u does not support %s", \ 63 dev_id, #func); \ 64 return -ENOTSUP; \ 65 } \ 66 } while (0) 67 68 /* Helper macro to check that queue is valid */ 69 #define VALID_QUEUE_OR_RET_ERR(queue_id, dev) do { \ 70 if (queue_id >= dev->data->num_queues) { \ 71 rte_bbdev_log(ERR, "Invalid queue_id %u for device %u", \ 72 queue_id, dev->data->dev_id); \ 73 return -ERANGE; \ 74 } \ 75 } while (0) 76 77 /* List of callback functions registered by an application */ 78 struct rte_bbdev_callback { 79 TAILQ_ENTRY(rte_bbdev_callback) next; /* Callbacks list */ 80 rte_bbdev_cb_fn cb_fn; /* Callback address */ 81 void *cb_arg; /* Parameter for callback */ 82 void *ret_param; /* Return parameter */ 83 enum rte_bbdev_event_type event; /* Interrupt event type */ 84 uint32_t active; /* Callback is executing */ 85 }; 86 87 /* spinlock for bbdev device callbacks */ 88 static rte_spinlock_t rte_bbdev_cb_lock = RTE_SPINLOCK_INITIALIZER; 89 90 /* 91 * Global array of all devices. This is not static because it's used by the 92 * inline enqueue and dequeue functions 93 */ 94 struct rte_bbdev rte_bbdev_devices[RTE_BBDEV_MAX_DEVS]; 95 96 /* Global array with rte_bbdev_data structures */ 97 static struct rte_bbdev_data *rte_bbdev_data; 98 99 /* Memzone name for global bbdev data pool */ 100 static const char *MZ_RTE_BBDEV_DATA = "rte_bbdev_data"; 101 102 /* Number of currently valid devices */ 103 static uint16_t num_devs; 104 105 /* Return pointer to device structure, with validity check */ 106 static struct rte_bbdev * 107 get_dev(uint16_t dev_id) 108 { 109 if (rte_bbdev_is_valid(dev_id)) 110 return &rte_bbdev_devices[dev_id]; 111 return NULL; 112 } 113 114 /* Allocate global data array */ 115 static int 116 rte_bbdev_data_alloc(void) 117 { 118 const unsigned int flags = 0; 119 const struct rte_memzone *mz; 120 121 if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 122 mz = rte_memzone_reserve(MZ_RTE_BBDEV_DATA, 123 RTE_BBDEV_MAX_DEVS * sizeof(*rte_bbdev_data), 124 rte_socket_id(), flags); 125 } else 126 mz = rte_memzone_lookup(MZ_RTE_BBDEV_DATA); 127 if (mz == NULL) { 128 rte_bbdev_log(CRIT, 129 "Cannot allocate memzone for bbdev port data"); 130 return -ENOMEM; 131 } 132 133 rte_bbdev_data = mz->addr; 134 if (rte_eal_process_type() == RTE_PROC_PRIMARY) 135 memset(rte_bbdev_data, 0, 136 RTE_BBDEV_MAX_DEVS * sizeof(*rte_bbdev_data)); 137 return 0; 138 } 139 140 /* 141 * Find data alocated for the device or if not found return first unused bbdev 142 * data. If all structures are in use and none is used by the device return 143 * NULL. 144 */ 145 static struct rte_bbdev_data * 146 find_bbdev_data(const char *name) 147 { 148 uint16_t data_id; 149 150 for (data_id = 0; data_id < RTE_BBDEV_MAX_DEVS; ++data_id) { 151 if (strlen(rte_bbdev_data[data_id].name) == 0) { 152 memset(&rte_bbdev_data[data_id], 0, 153 sizeof(struct rte_bbdev_data)); 154 return &rte_bbdev_data[data_id]; 155 } else if (strncmp(rte_bbdev_data[data_id].name, name, 156 RTE_BBDEV_NAME_MAX_LEN) == 0) 157 return &rte_bbdev_data[data_id]; 158 } 159 160 return NULL; 161 } 162 163 /* Find lowest device id with no attached device */ 164 static uint16_t 165 find_free_dev_id(void) 166 { 167 uint16_t i; 168 for (i = 0; i < RTE_BBDEV_MAX_DEVS; i++) { 169 if (rte_bbdev_devices[i].state == RTE_BBDEV_UNUSED) 170 return i; 171 } 172 return RTE_BBDEV_MAX_DEVS; 173 } 174 175 struct rte_bbdev * __rte_experimental 176 rte_bbdev_allocate(const char *name) 177 { 178 int ret; 179 struct rte_bbdev *bbdev; 180 uint16_t dev_id; 181 182 if (name == NULL) { 183 rte_bbdev_log(ERR, "Invalid null device name"); 184 return NULL; 185 } 186 187 if (rte_bbdev_get_named_dev(name) != NULL) { 188 rte_bbdev_log(ERR, "Device \"%s\" is already allocated", name); 189 return NULL; 190 } 191 192 dev_id = find_free_dev_id(); 193 if (dev_id == RTE_BBDEV_MAX_DEVS) { 194 rte_bbdev_log(ERR, "Reached maximum number of devices"); 195 return NULL; 196 } 197 198 bbdev = &rte_bbdev_devices[dev_id]; 199 200 if (rte_bbdev_data == NULL) { 201 ret = rte_bbdev_data_alloc(); 202 if (ret != 0) 203 return NULL; 204 } 205 206 bbdev->data = find_bbdev_data(name); 207 if (bbdev->data == NULL) { 208 rte_bbdev_log(ERR, 209 "Max BBDevs already allocated in multi-process environment!"); 210 return NULL; 211 } 212 213 rte_atomic16_inc(&bbdev->data->process_cnt); 214 bbdev->data->dev_id = dev_id; 215 bbdev->state = RTE_BBDEV_INITIALIZED; 216 217 ret = snprintf(bbdev->data->name, RTE_BBDEV_NAME_MAX_LEN, "%s", name); 218 if ((ret < 0) || (ret >= RTE_BBDEV_NAME_MAX_LEN)) { 219 rte_bbdev_log(ERR, "Copying device name \"%s\" failed", name); 220 return NULL; 221 } 222 223 /* init user callbacks */ 224 TAILQ_INIT(&(bbdev->list_cbs)); 225 226 num_devs++; 227 228 rte_bbdev_log_debug("Initialised device %s (id = %u). Num devices = %u", 229 name, dev_id, num_devs); 230 231 return bbdev; 232 } 233 234 int __rte_experimental 235 rte_bbdev_release(struct rte_bbdev *bbdev) 236 { 237 uint16_t dev_id; 238 struct rte_bbdev_callback *cb, *next; 239 240 if (bbdev == NULL) { 241 rte_bbdev_log(ERR, "NULL bbdev"); 242 return -ENODEV; 243 } 244 dev_id = bbdev->data->dev_id; 245 246 /* free all callbacks from the device's list */ 247 for (cb = TAILQ_FIRST(&bbdev->list_cbs); cb != NULL; cb = next) { 248 249 next = TAILQ_NEXT(cb, next); 250 TAILQ_REMOVE(&(bbdev->list_cbs), cb, next); 251 rte_free(cb); 252 } 253 254 /* clear shared BBDev Data if no process is using the device anymore */ 255 if (rte_atomic16_dec_and_test(&bbdev->data->process_cnt)) 256 memset(bbdev->data, 0, sizeof(*bbdev->data)); 257 258 memset(bbdev, 0, sizeof(*bbdev)); 259 num_devs--; 260 bbdev->state = RTE_BBDEV_UNUSED; 261 262 rte_bbdev_log_debug( 263 "Un-initialised device id = %u. Num devices = %u", 264 dev_id, num_devs); 265 return 0; 266 } 267 268 struct rte_bbdev * __rte_experimental 269 rte_bbdev_get_named_dev(const char *name) 270 { 271 unsigned int i; 272 273 if (name == NULL) { 274 rte_bbdev_log(ERR, "NULL driver name"); 275 return NULL; 276 } 277 278 for (i = 0; i < RTE_BBDEV_MAX_DEVS; i++) { 279 struct rte_bbdev *dev = get_dev(i); 280 if (dev && (strncmp(dev->data->name, 281 name, RTE_BBDEV_NAME_MAX_LEN) == 0)) 282 return dev; 283 } 284 285 return NULL; 286 } 287 288 uint16_t __rte_experimental 289 rte_bbdev_count(void) 290 { 291 return num_devs; 292 } 293 294 bool __rte_experimental 295 rte_bbdev_is_valid(uint16_t dev_id) 296 { 297 if ((dev_id < RTE_BBDEV_MAX_DEVS) && 298 rte_bbdev_devices[dev_id].state == RTE_BBDEV_INITIALIZED) 299 return true; 300 return false; 301 } 302 303 uint16_t __rte_experimental 304 rte_bbdev_find_next(uint16_t dev_id) 305 { 306 dev_id++; 307 for (; dev_id < RTE_BBDEV_MAX_DEVS; dev_id++) 308 if (rte_bbdev_is_valid(dev_id)) 309 break; 310 return dev_id; 311 } 312 313 int __rte_experimental 314 rte_bbdev_setup_queues(uint16_t dev_id, uint16_t num_queues, int socket_id) 315 { 316 unsigned int i; 317 int ret; 318 struct rte_bbdev_driver_info dev_info; 319 struct rte_bbdev *dev = get_dev(dev_id); 320 VALID_DEV_OR_RET_ERR(dev, dev_id); 321 322 VALID_DEV_OPS_OR_RET_ERR(dev, dev_id); 323 324 if (dev->data->started) { 325 rte_bbdev_log(ERR, 326 "Device %u cannot be configured when started", 327 dev_id); 328 return -EBUSY; 329 } 330 331 /* Get device driver information to get max number of queues */ 332 VALID_FUNC_OR_RET_ERR(dev->dev_ops->info_get, dev_id); 333 memset(&dev_info, 0, sizeof(dev_info)); 334 dev->dev_ops->info_get(dev, &dev_info); 335 336 if ((num_queues == 0) || (num_queues > dev_info.max_num_queues)) { 337 rte_bbdev_log(ERR, 338 "Device %u supports 0 < N <= %u queues, not %u", 339 dev_id, dev_info.max_num_queues, num_queues); 340 return -EINVAL; 341 } 342 343 /* If re-configuration, get driver to free existing internal memory */ 344 if (dev->data->queues != NULL) { 345 VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_release, dev_id); 346 for (i = 0; i < dev->data->num_queues; i++) { 347 int ret = dev->dev_ops->queue_release(dev, i); 348 if (ret < 0) { 349 rte_bbdev_log(ERR, 350 "Device %u queue %u release failed", 351 dev_id, i); 352 return ret; 353 } 354 } 355 /* Call optional device close */ 356 if (dev->dev_ops->close) { 357 ret = dev->dev_ops->close(dev); 358 if (ret < 0) { 359 rte_bbdev_log(ERR, 360 "Device %u couldn't be closed", 361 dev_id); 362 return ret; 363 } 364 } 365 rte_free(dev->data->queues); 366 } 367 368 /* Allocate queue pointers */ 369 dev->data->queues = rte_calloc_socket(DEV_NAME, num_queues, 370 sizeof(dev->data->queues[0]), RTE_CACHE_LINE_SIZE, 371 dev->data->socket_id); 372 if (dev->data->queues == NULL) { 373 rte_bbdev_log(ERR, 374 "calloc of %u queues for device %u on socket %i failed", 375 num_queues, dev_id, dev->data->socket_id); 376 return -ENOMEM; 377 } 378 379 dev->data->num_queues = num_queues; 380 381 /* Call optional device configuration */ 382 if (dev->dev_ops->setup_queues) { 383 ret = dev->dev_ops->setup_queues(dev, num_queues, socket_id); 384 if (ret < 0) { 385 rte_bbdev_log(ERR, 386 "Device %u memory configuration failed", 387 dev_id); 388 goto error; 389 } 390 } 391 392 rte_bbdev_log_debug("Device %u set up with %u queues", dev_id, 393 num_queues); 394 return 0; 395 396 error: 397 dev->data->num_queues = 0; 398 rte_free(dev->data->queues); 399 dev->data->queues = NULL; 400 return ret; 401 } 402 403 int __rte_experimental 404 rte_bbdev_intr_enable(uint16_t dev_id) 405 { 406 int ret; 407 struct rte_bbdev *dev = get_dev(dev_id); 408 VALID_DEV_OR_RET_ERR(dev, dev_id); 409 410 VALID_DEV_OPS_OR_RET_ERR(dev, dev_id); 411 412 if (dev->data->started) { 413 rte_bbdev_log(ERR, 414 "Device %u cannot be configured when started", 415 dev_id); 416 return -EBUSY; 417 } 418 419 if (dev->dev_ops->intr_enable) { 420 ret = dev->dev_ops->intr_enable(dev); 421 if (ret < 0) { 422 rte_bbdev_log(ERR, 423 "Device %u interrupts configuration failed", 424 dev_id); 425 return ret; 426 } 427 rte_bbdev_log_debug("Enabled interrupts for dev %u", dev_id); 428 return 0; 429 } 430 431 rte_bbdev_log(ERR, "Device %u doesn't support interrupts", dev_id); 432 return -ENOTSUP; 433 } 434 435 int __rte_experimental 436 rte_bbdev_queue_configure(uint16_t dev_id, uint16_t queue_id, 437 const struct rte_bbdev_queue_conf *conf) 438 { 439 int ret = 0; 440 struct rte_bbdev_driver_info dev_info; 441 struct rte_bbdev *dev = get_dev(dev_id); 442 const struct rte_bbdev_op_cap *p; 443 struct rte_bbdev_queue_conf *stored_conf; 444 const char *op_type_str; 445 VALID_DEV_OR_RET_ERR(dev, dev_id); 446 447 VALID_DEV_OPS_OR_RET_ERR(dev, dev_id); 448 449 VALID_QUEUE_OR_RET_ERR(queue_id, dev); 450 451 if (dev->data->queues[queue_id].started || dev->data->started) { 452 rte_bbdev_log(ERR, 453 "Queue %u of device %u cannot be configured when started", 454 queue_id, dev_id); 455 return -EBUSY; 456 } 457 458 VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_release, dev_id); 459 VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_setup, dev_id); 460 461 /* Get device driver information to verify config is valid */ 462 VALID_FUNC_OR_RET_ERR(dev->dev_ops->info_get, dev_id); 463 memset(&dev_info, 0, sizeof(dev_info)); 464 dev->dev_ops->info_get(dev, &dev_info); 465 466 /* Check configuration is valid */ 467 if (conf != NULL) { 468 if ((conf->op_type == RTE_BBDEV_OP_NONE) && 469 (dev_info.capabilities[0].type == 470 RTE_BBDEV_OP_NONE)) { 471 ret = 1; 472 } else { 473 for (p = dev_info.capabilities; 474 p->type != RTE_BBDEV_OP_NONE; p++) { 475 if (conf->op_type == p->type) { 476 ret = 1; 477 break; 478 } 479 } 480 } 481 if (ret == 0) { 482 rte_bbdev_log(ERR, "Invalid operation type"); 483 return -EINVAL; 484 } 485 if (conf->queue_size > dev_info.queue_size_lim) { 486 rte_bbdev_log(ERR, 487 "Size (%u) of queue %u of device %u must be: <= %u", 488 conf->queue_size, queue_id, dev_id, 489 dev_info.queue_size_lim); 490 return -EINVAL; 491 } 492 if (!rte_is_power_of_2(conf->queue_size)) { 493 rte_bbdev_log(ERR, 494 "Size (%u) of queue %u of device %u must be a power of 2", 495 conf->queue_size, queue_id, dev_id); 496 return -EINVAL; 497 } 498 if (conf->op_type == RTE_BBDEV_OP_TURBO_DEC && 499 conf->priority > dev_info.max_ul_queue_priority) { 500 rte_bbdev_log(ERR, 501 "Priority (%u) of queue %u of bdev %u must be <= %u", 502 conf->priority, queue_id, dev_id, 503 dev_info.max_ul_queue_priority); 504 return -EINVAL; 505 } 506 if (conf->op_type == RTE_BBDEV_OP_TURBO_ENC && 507 conf->priority > dev_info.max_dl_queue_priority) { 508 rte_bbdev_log(ERR, 509 "Priority (%u) of queue %u of bdev %u must be <= %u", 510 conf->priority, queue_id, dev_id, 511 dev_info.max_dl_queue_priority); 512 return -EINVAL; 513 } 514 } 515 516 /* Release existing queue (in case of queue reconfiguration) */ 517 if (dev->data->queues[queue_id].queue_private != NULL) { 518 ret = dev->dev_ops->queue_release(dev, queue_id); 519 if (ret < 0) { 520 rte_bbdev_log(ERR, "Device %u queue %u release failed", 521 dev_id, queue_id); 522 return ret; 523 } 524 } 525 526 /* Get driver to setup the queue */ 527 ret = dev->dev_ops->queue_setup(dev, queue_id, (conf != NULL) ? 528 conf : &dev_info.default_queue_conf); 529 if (ret < 0) { 530 rte_bbdev_log(ERR, 531 "Device %u queue %u setup failed", dev_id, 532 queue_id); 533 return ret; 534 } 535 536 /* Store configuration */ 537 stored_conf = &dev->data->queues[queue_id].conf; 538 memcpy(stored_conf, 539 (conf != NULL) ? conf : &dev_info.default_queue_conf, 540 sizeof(*stored_conf)); 541 542 op_type_str = rte_bbdev_op_type_str(stored_conf->op_type); 543 if (op_type_str == NULL) 544 return -EINVAL; 545 546 rte_bbdev_log_debug("Configured dev%uq%u (size=%u, type=%s, prio=%u)", 547 dev_id, queue_id, stored_conf->queue_size, op_type_str, 548 stored_conf->priority); 549 550 return 0; 551 } 552 553 int __rte_experimental 554 rte_bbdev_start(uint16_t dev_id) 555 { 556 int i; 557 struct rte_bbdev *dev = get_dev(dev_id); 558 VALID_DEV_OR_RET_ERR(dev, dev_id); 559 560 VALID_DEV_OPS_OR_RET_ERR(dev, dev_id); 561 562 if (dev->data->started) { 563 rte_bbdev_log_debug("Device %u is already started", dev_id); 564 return 0; 565 } 566 567 if (dev->dev_ops->start) { 568 int ret = dev->dev_ops->start(dev); 569 if (ret < 0) { 570 rte_bbdev_log(ERR, "Device %u start failed", dev_id); 571 return ret; 572 } 573 } 574 575 /* Store new state */ 576 for (i = 0; i < dev->data->num_queues; i++) 577 if (!dev->data->queues[i].conf.deferred_start) 578 dev->data->queues[i].started = true; 579 dev->data->started = true; 580 581 rte_bbdev_log_debug("Started device %u", dev_id); 582 return 0; 583 } 584 585 int __rte_experimental 586 rte_bbdev_stop(uint16_t dev_id) 587 { 588 struct rte_bbdev *dev = get_dev(dev_id); 589 VALID_DEV_OR_RET_ERR(dev, dev_id); 590 591 VALID_DEV_OPS_OR_RET_ERR(dev, dev_id); 592 593 if (!dev->data->started) { 594 rte_bbdev_log_debug("Device %u is already stopped", dev_id); 595 return 0; 596 } 597 598 if (dev->dev_ops->stop) 599 dev->dev_ops->stop(dev); 600 dev->data->started = false; 601 602 rte_bbdev_log_debug("Stopped device %u", dev_id); 603 return 0; 604 } 605 606 int __rte_experimental 607 rte_bbdev_close(uint16_t dev_id) 608 { 609 int ret; 610 uint16_t i; 611 struct rte_bbdev *dev = get_dev(dev_id); 612 VALID_DEV_OR_RET_ERR(dev, dev_id); 613 614 VALID_DEV_OPS_OR_RET_ERR(dev, dev_id); 615 616 if (dev->data->started) { 617 ret = rte_bbdev_stop(dev_id); 618 if (ret < 0) { 619 rte_bbdev_log(ERR, "Device %u stop failed", dev_id); 620 return ret; 621 } 622 } 623 624 /* Free memory used by queues */ 625 for (i = 0; i < dev->data->num_queues; i++) { 626 ret = dev->dev_ops->queue_release(dev, i); 627 if (ret < 0) { 628 rte_bbdev_log(ERR, "Device %u queue %u release failed", 629 dev_id, i); 630 return ret; 631 } 632 } 633 rte_free(dev->data->queues); 634 635 if (dev->dev_ops->close) { 636 ret = dev->dev_ops->close(dev); 637 if (ret < 0) { 638 rte_bbdev_log(ERR, "Device %u close failed", dev_id); 639 return ret; 640 } 641 } 642 643 /* Clear configuration */ 644 dev->data->queues = NULL; 645 dev->data->num_queues = 0; 646 647 rte_bbdev_log_debug("Closed device %u", dev_id); 648 return 0; 649 } 650 651 int __rte_experimental 652 rte_bbdev_queue_start(uint16_t dev_id, uint16_t queue_id) 653 { 654 struct rte_bbdev *dev = get_dev(dev_id); 655 VALID_DEV_OR_RET_ERR(dev, dev_id); 656 657 VALID_DEV_OPS_OR_RET_ERR(dev, dev_id); 658 659 VALID_QUEUE_OR_RET_ERR(queue_id, dev); 660 661 if (dev->data->queues[queue_id].started) { 662 rte_bbdev_log_debug("Queue %u of device %u already started", 663 queue_id, dev_id); 664 return 0; 665 } 666 667 if (dev->dev_ops->queue_start) { 668 int ret = dev->dev_ops->queue_start(dev, queue_id); 669 if (ret < 0) { 670 rte_bbdev_log(ERR, "Device %u queue %u start failed", 671 dev_id, queue_id); 672 return ret; 673 } 674 } 675 dev->data->queues[queue_id].started = true; 676 677 rte_bbdev_log_debug("Started queue %u of device %u", queue_id, dev_id); 678 return 0; 679 } 680 681 int __rte_experimental 682 rte_bbdev_queue_stop(uint16_t dev_id, uint16_t queue_id) 683 { 684 struct rte_bbdev *dev = get_dev(dev_id); 685 VALID_DEV_OR_RET_ERR(dev, dev_id); 686 687 VALID_DEV_OPS_OR_RET_ERR(dev, dev_id); 688 689 VALID_QUEUE_OR_RET_ERR(queue_id, dev); 690 691 if (!dev->data->queues[queue_id].started) { 692 rte_bbdev_log_debug("Queue %u of device %u already stopped", 693 queue_id, dev_id); 694 return 0; 695 } 696 697 if (dev->dev_ops->queue_stop) { 698 int ret = dev->dev_ops->queue_stop(dev, queue_id); 699 if (ret < 0) { 700 rte_bbdev_log(ERR, "Device %u queue %u stop failed", 701 dev_id, queue_id); 702 return ret; 703 } 704 } 705 dev->data->queues[queue_id].started = false; 706 707 rte_bbdev_log_debug("Stopped queue %u of device %u", queue_id, dev_id); 708 return 0; 709 } 710 711 /* Get device statistics */ 712 static void 713 get_stats_from_queues(struct rte_bbdev *dev, struct rte_bbdev_stats *stats) 714 { 715 unsigned int q_id; 716 for (q_id = 0; q_id < dev->data->num_queues; q_id++) { 717 struct rte_bbdev_stats *q_stats = 718 &dev->data->queues[q_id].queue_stats; 719 720 stats->enqueued_count += q_stats->enqueued_count; 721 stats->dequeued_count += q_stats->dequeued_count; 722 stats->enqueue_err_count += q_stats->enqueue_err_count; 723 stats->dequeue_err_count += q_stats->dequeue_err_count; 724 } 725 rte_bbdev_log_debug("Got stats on %u", dev->data->dev_id); 726 } 727 728 static void 729 reset_stats_in_queues(struct rte_bbdev *dev) 730 { 731 unsigned int q_id; 732 for (q_id = 0; q_id < dev->data->num_queues; q_id++) { 733 struct rte_bbdev_stats *q_stats = 734 &dev->data->queues[q_id].queue_stats; 735 736 memset(q_stats, 0, sizeof(*q_stats)); 737 } 738 rte_bbdev_log_debug("Reset stats on %u", dev->data->dev_id); 739 } 740 741 int __rte_experimental 742 rte_bbdev_stats_get(uint16_t dev_id, struct rte_bbdev_stats *stats) 743 { 744 struct rte_bbdev *dev = get_dev(dev_id); 745 VALID_DEV_OR_RET_ERR(dev, dev_id); 746 747 VALID_DEV_OPS_OR_RET_ERR(dev, dev_id); 748 749 if (stats == NULL) { 750 rte_bbdev_log(ERR, "NULL stats structure"); 751 return -EINVAL; 752 } 753 754 memset(stats, 0, sizeof(*stats)); 755 if (dev->dev_ops->stats_get != NULL) 756 dev->dev_ops->stats_get(dev, stats); 757 else 758 get_stats_from_queues(dev, stats); 759 760 rte_bbdev_log_debug("Retrieved stats of device %u", dev_id); 761 return 0; 762 } 763 764 int __rte_experimental 765 rte_bbdev_stats_reset(uint16_t dev_id) 766 { 767 struct rte_bbdev *dev = get_dev(dev_id); 768 VALID_DEV_OR_RET_ERR(dev, dev_id); 769 770 VALID_DEV_OPS_OR_RET_ERR(dev, dev_id); 771 772 if (dev->dev_ops->stats_reset != NULL) 773 dev->dev_ops->stats_reset(dev); 774 else 775 reset_stats_in_queues(dev); 776 777 rte_bbdev_log_debug("Reset stats of device %u", dev_id); 778 return 0; 779 } 780 781 int __rte_experimental 782 rte_bbdev_info_get(uint16_t dev_id, struct rte_bbdev_info *dev_info) 783 { 784 struct rte_bbdev *dev = get_dev(dev_id); 785 VALID_DEV_OR_RET_ERR(dev, dev_id); 786 787 VALID_FUNC_OR_RET_ERR(dev->dev_ops->info_get, dev_id); 788 789 if (dev_info == NULL) { 790 rte_bbdev_log(ERR, "NULL dev info structure"); 791 return -EINVAL; 792 } 793 794 /* Copy data maintained by device interface layer */ 795 memset(dev_info, 0, sizeof(*dev_info)); 796 dev_info->dev_name = dev->data->name; 797 dev_info->num_queues = dev->data->num_queues; 798 dev_info->bus = rte_bus_find_by_device(dev->device); 799 dev_info->socket_id = dev->data->socket_id; 800 dev_info->started = dev->data->started; 801 802 /* Copy data maintained by device driver layer */ 803 dev->dev_ops->info_get(dev, &dev_info->drv); 804 805 rte_bbdev_log_debug("Retrieved info of device %u", dev_id); 806 return 0; 807 } 808 809 int __rte_experimental 810 rte_bbdev_queue_info_get(uint16_t dev_id, uint16_t queue_id, 811 struct rte_bbdev_queue_info *queue_info) 812 { 813 struct rte_bbdev *dev = get_dev(dev_id); 814 VALID_DEV_OR_RET_ERR(dev, dev_id); 815 816 VALID_QUEUE_OR_RET_ERR(queue_id, dev); 817 818 if (queue_info == NULL) { 819 rte_bbdev_log(ERR, "NULL queue info structure"); 820 return -EINVAL; 821 } 822 823 /* Copy data to output */ 824 memset(queue_info, 0, sizeof(*queue_info)); 825 queue_info->conf = dev->data->queues[queue_id].conf; 826 queue_info->started = dev->data->queues[queue_id].started; 827 828 rte_bbdev_log_debug("Retrieved info of queue %u of device %u", 829 queue_id, dev_id); 830 return 0; 831 } 832 833 /* Calculate size needed to store bbdev_op, depending on type */ 834 static unsigned int 835 get_bbdev_op_size(enum rte_bbdev_op_type type) 836 { 837 unsigned int result = 0; 838 switch (type) { 839 case RTE_BBDEV_OP_NONE: 840 result = RTE_MAX(sizeof(struct rte_bbdev_dec_op), 841 sizeof(struct rte_bbdev_enc_op)); 842 break; 843 case RTE_BBDEV_OP_TURBO_DEC: 844 result = sizeof(struct rte_bbdev_dec_op); 845 break; 846 case RTE_BBDEV_OP_TURBO_ENC: 847 result = sizeof(struct rte_bbdev_enc_op); 848 break; 849 default: 850 break; 851 } 852 853 return result; 854 } 855 856 /* Initialise a bbdev_op structure */ 857 static void 858 bbdev_op_init(struct rte_mempool *mempool, void *arg, void *element, 859 __rte_unused unsigned int n) 860 { 861 enum rte_bbdev_op_type type = *(enum rte_bbdev_op_type *)arg; 862 863 if (type == RTE_BBDEV_OP_TURBO_DEC) { 864 struct rte_bbdev_dec_op *op = element; 865 memset(op, 0, mempool->elt_size); 866 op->mempool = mempool; 867 } else if (type == RTE_BBDEV_OP_TURBO_ENC) { 868 struct rte_bbdev_enc_op *op = element; 869 memset(op, 0, mempool->elt_size); 870 op->mempool = mempool; 871 } 872 } 873 874 struct rte_mempool * __rte_experimental 875 rte_bbdev_op_pool_create(const char *name, enum rte_bbdev_op_type type, 876 unsigned int num_elements, unsigned int cache_size, 877 int socket_id) 878 { 879 struct rte_bbdev_op_pool_private *priv; 880 struct rte_mempool *mp; 881 const char *op_type_str; 882 883 if (name == NULL) { 884 rte_bbdev_log(ERR, "NULL name for op pool"); 885 return NULL; 886 } 887 888 if (type >= RTE_BBDEV_OP_TYPE_COUNT) { 889 rte_bbdev_log(ERR, 890 "Invalid op type (%u), should be less than %u", 891 type, RTE_BBDEV_OP_TYPE_COUNT); 892 return NULL; 893 } 894 895 mp = rte_mempool_create(name, num_elements, get_bbdev_op_size(type), 896 cache_size, sizeof(struct rte_bbdev_op_pool_private), 897 NULL, NULL, bbdev_op_init, &type, socket_id, 0); 898 if (mp == NULL) { 899 rte_bbdev_log(ERR, 900 "Failed to create op pool %s (num ops=%u, op size=%u) with error: %s", 901 name, num_elements, get_bbdev_op_size(type), 902 rte_strerror(rte_errno)); 903 return NULL; 904 } 905 906 op_type_str = rte_bbdev_op_type_str(type); 907 if (op_type_str == NULL) 908 return NULL; 909 910 rte_bbdev_log_debug( 911 "Op pool %s created for %u ops (type=%s, cache=%u, socket=%u, size=%u)", 912 name, num_elements, op_type_str, cache_size, socket_id, 913 get_bbdev_op_size(type)); 914 915 priv = (struct rte_bbdev_op_pool_private *)rte_mempool_get_priv(mp); 916 priv->type = type; 917 918 return mp; 919 } 920 921 int __rte_experimental 922 rte_bbdev_callback_register(uint16_t dev_id, enum rte_bbdev_event_type event, 923 rte_bbdev_cb_fn cb_fn, void *cb_arg) 924 { 925 struct rte_bbdev_callback *user_cb; 926 struct rte_bbdev *dev = get_dev(dev_id); 927 VALID_DEV_OR_RET_ERR(dev, dev_id); 928 929 if (event >= RTE_BBDEV_EVENT_MAX) { 930 rte_bbdev_log(ERR, 931 "Invalid event type (%u), should be less than %u", 932 event, RTE_BBDEV_EVENT_MAX); 933 return -EINVAL; 934 } 935 936 if (cb_fn == NULL) { 937 rte_bbdev_log(ERR, "NULL callback function"); 938 return -EINVAL; 939 } 940 941 rte_spinlock_lock(&rte_bbdev_cb_lock); 942 943 TAILQ_FOREACH(user_cb, &(dev->list_cbs), next) { 944 if (user_cb->cb_fn == cb_fn && 945 user_cb->cb_arg == cb_arg && 946 user_cb->event == event) 947 break; 948 } 949 950 /* create a new callback. */ 951 if (user_cb == NULL) { 952 user_cb = rte_zmalloc("INTR_USER_CALLBACK", 953 sizeof(struct rte_bbdev_callback), 0); 954 if (user_cb != NULL) { 955 user_cb->cb_fn = cb_fn; 956 user_cb->cb_arg = cb_arg; 957 user_cb->event = event; 958 TAILQ_INSERT_TAIL(&(dev->list_cbs), user_cb, next); 959 } 960 } 961 962 rte_spinlock_unlock(&rte_bbdev_cb_lock); 963 return (user_cb == NULL) ? -ENOMEM : 0; 964 } 965 966 int __rte_experimental 967 rte_bbdev_callback_unregister(uint16_t dev_id, enum rte_bbdev_event_type event, 968 rte_bbdev_cb_fn cb_fn, void *cb_arg) 969 { 970 int ret = 0; 971 struct rte_bbdev_callback *cb, *next; 972 struct rte_bbdev *dev = get_dev(dev_id); 973 VALID_DEV_OR_RET_ERR(dev, dev_id); 974 975 if (event >= RTE_BBDEV_EVENT_MAX) { 976 rte_bbdev_log(ERR, 977 "Invalid event type (%u), should be less than %u", 978 event, RTE_BBDEV_EVENT_MAX); 979 return -EINVAL; 980 } 981 982 if (cb_fn == NULL) { 983 rte_bbdev_log(ERR, 984 "NULL callback function cannot be unregistered"); 985 return -EINVAL; 986 } 987 988 dev = &rte_bbdev_devices[dev_id]; 989 rte_spinlock_lock(&rte_bbdev_cb_lock); 990 991 for (cb = TAILQ_FIRST(&dev->list_cbs); cb != NULL; cb = next) { 992 993 next = TAILQ_NEXT(cb, next); 994 995 if (cb->cb_fn != cb_fn || cb->event != event || 996 (cb_arg != (void *)-1 && cb->cb_arg != cb_arg)) 997 continue; 998 999 /* If this callback is not executing right now, remove it. */ 1000 if (cb->active == 0) { 1001 TAILQ_REMOVE(&(dev->list_cbs), cb, next); 1002 rte_free(cb); 1003 } else 1004 ret = -EAGAIN; 1005 } 1006 1007 rte_spinlock_unlock(&rte_bbdev_cb_lock); 1008 return ret; 1009 } 1010 1011 void __rte_experimental 1012 rte_bbdev_pmd_callback_process(struct rte_bbdev *dev, 1013 enum rte_bbdev_event_type event, void *ret_param) 1014 { 1015 struct rte_bbdev_callback *cb_lst; 1016 struct rte_bbdev_callback dev_cb; 1017 1018 if (dev == NULL) { 1019 rte_bbdev_log(ERR, "NULL device"); 1020 return; 1021 } 1022 1023 if (dev->data == NULL) { 1024 rte_bbdev_log(ERR, "NULL data structure"); 1025 return; 1026 } 1027 1028 if (event >= RTE_BBDEV_EVENT_MAX) { 1029 rte_bbdev_log(ERR, 1030 "Invalid event type (%u), should be less than %u", 1031 event, RTE_BBDEV_EVENT_MAX); 1032 return; 1033 } 1034 1035 rte_spinlock_lock(&rte_bbdev_cb_lock); 1036 TAILQ_FOREACH(cb_lst, &(dev->list_cbs), next) { 1037 if (cb_lst->cb_fn == NULL || cb_lst->event != event) 1038 continue; 1039 dev_cb = *cb_lst; 1040 cb_lst->active = 1; 1041 if (ret_param != NULL) 1042 dev_cb.ret_param = ret_param; 1043 1044 rte_spinlock_unlock(&rte_bbdev_cb_lock); 1045 dev_cb.cb_fn(dev->data->dev_id, dev_cb.event, 1046 dev_cb.cb_arg, dev_cb.ret_param); 1047 rte_spinlock_lock(&rte_bbdev_cb_lock); 1048 cb_lst->active = 0; 1049 } 1050 rte_spinlock_unlock(&rte_bbdev_cb_lock); 1051 } 1052 1053 int __rte_experimental 1054 rte_bbdev_queue_intr_enable(uint16_t dev_id, uint16_t queue_id) 1055 { 1056 struct rte_bbdev *dev = get_dev(dev_id); 1057 VALID_DEV_OR_RET_ERR(dev, dev_id); 1058 VALID_QUEUE_OR_RET_ERR(queue_id, dev); 1059 VALID_DEV_OPS_OR_RET_ERR(dev, dev_id); 1060 VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_intr_enable, dev_id); 1061 return dev->dev_ops->queue_intr_enable(dev, queue_id); 1062 } 1063 1064 int __rte_experimental 1065 rte_bbdev_queue_intr_disable(uint16_t dev_id, uint16_t queue_id) 1066 { 1067 struct rte_bbdev *dev = get_dev(dev_id); 1068 VALID_DEV_OR_RET_ERR(dev, dev_id); 1069 VALID_QUEUE_OR_RET_ERR(queue_id, dev); 1070 VALID_DEV_OPS_OR_RET_ERR(dev, dev_id); 1071 VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_intr_disable, dev_id); 1072 return dev->dev_ops->queue_intr_disable(dev, queue_id); 1073 } 1074 1075 int __rte_experimental 1076 rte_bbdev_queue_intr_ctl(uint16_t dev_id, uint16_t queue_id, int epfd, int op, 1077 void *data) 1078 { 1079 uint32_t vec; 1080 struct rte_bbdev *dev = get_dev(dev_id); 1081 struct rte_intr_handle *intr_handle; 1082 int ret; 1083 1084 VALID_DEV_OR_RET_ERR(dev, dev_id); 1085 VALID_QUEUE_OR_RET_ERR(queue_id, dev); 1086 1087 intr_handle = dev->intr_handle; 1088 if (!intr_handle || !intr_handle->intr_vec) { 1089 rte_bbdev_log(ERR, "Device %u intr handle unset\n", dev_id); 1090 return -ENOTSUP; 1091 } 1092 1093 if (queue_id >= RTE_MAX_RXTX_INTR_VEC_ID) { 1094 rte_bbdev_log(ERR, "Device %u queue_id %u is too big\n", 1095 dev_id, queue_id); 1096 return -ENOTSUP; 1097 } 1098 1099 vec = intr_handle->intr_vec[queue_id]; 1100 ret = rte_intr_rx_ctl(intr_handle, epfd, op, vec, data); 1101 if (ret && (ret != -EEXIST)) { 1102 rte_bbdev_log(ERR, 1103 "dev %u q %u int ctl error op %d epfd %d vec %u\n", 1104 dev_id, queue_id, op, epfd, vec); 1105 return ret; 1106 } 1107 1108 return 0; 1109 } 1110 1111 1112 const char * __rte_experimental 1113 rte_bbdev_op_type_str(enum rte_bbdev_op_type op_type) 1114 { 1115 static const char * const op_types[] = { 1116 "RTE_BBDEV_OP_NONE", 1117 "RTE_BBDEV_OP_TURBO_DEC", 1118 "RTE_BBDEV_OP_TURBO_ENC", 1119 }; 1120 1121 if (op_type < RTE_BBDEV_OP_TYPE_COUNT) 1122 return op_types[op_type]; 1123 1124 rte_bbdev_log(ERR, "Invalid operation type"); 1125 return NULL; 1126 } 1127 1128 RTE_INIT(rte_bbdev_init_log) 1129 { 1130 bbdev_logtype = rte_log_register("lib.bbdev"); 1131 if (bbdev_logtype >= 0) 1132 rte_log_set_level(bbdev_logtype, RTE_LOG_NOTICE); 1133 } 1134