1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2019 Mellanox Technologies, Ltd 3 */ 4 5 #include <unistd.h> 6 #include <string.h> 7 #include <stdio.h> 8 #include <pthread.h> 9 10 #include <rte_errno.h> 11 #include <rte_mempool.h> 12 #include <rte_class.h> 13 #include <rte_malloc.h> 14 #include <rte_eal_paging.h> 15 16 #include "mlx5_common.h" 17 #include "mlx5_common_os.h" 18 #include "mlx5_common_mp.h" 19 #include "mlx5_common_log.h" 20 #include "mlx5_common_defs.h" 21 #include "mlx5_common_private.h" 22 23 uint8_t haswell_broadwell_cpu; 24 25 /* Driver type key for new device global syntax. */ 26 #define MLX5_DRIVER_KEY "driver" 27 28 /* Device parameter to get file descriptor for import device. */ 29 #define MLX5_DEVICE_FD "cmd_fd" 30 31 /* Device parameter to get PD number for import Protection Domain. */ 32 #define MLX5_PD_HANDLE "pd_handle" 33 34 /* Enable extending memsegs when creating a MR. */ 35 #define MLX5_MR_EXT_MEMSEG_EN "mr_ext_memseg_en" 36 37 /* Device parameter to configure implicit registration of mempool memory. */ 38 #define MLX5_MR_MEMPOOL_REG_EN "mr_mempool_reg_en" 39 40 /* The default memory allocator used in PMD. */ 41 #define MLX5_SYS_MEM_EN "sys_mem_en" 42 43 /* 44 * Device parameter to force doorbell register mapping 45 * to non-cached region eliminating the extra write memory barrier. 46 * Deprecated, ignored (Name changed to sq_db_nc). 47 */ 48 #define MLX5_TX_DB_NC "tx_db_nc" 49 50 /* 51 * Device parameter to force doorbell register mapping 52 * to non-cached region eliminating the extra write memory barrier. 53 */ 54 #define MLX5_SQ_DB_NC "sq_db_nc" 55 56 /* In case this is an x86_64 intel processor to check if 57 * we should use relaxed ordering. 58 */ 59 #ifdef RTE_ARCH_X86_64 60 /** 61 * This function returns processor identification and feature information 62 * into the registers. 63 * 64 * @param eax, ebx, ecx, edx 65 * Pointers to the registers that will hold cpu information. 66 * @param level 67 * The main category of information returned. 68 */ 69 static inline void mlx5_cpu_id(unsigned int level, 70 unsigned int *eax, unsigned int *ebx, 71 unsigned int *ecx, unsigned int *edx) 72 { 73 __asm__("cpuid\n\t" 74 : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) 75 : "0" (level)); 76 } 77 #endif 78 79 RTE_LOG_REGISTER_DEFAULT(mlx5_common_logtype, NOTICE) 80 81 /* Head of list of drivers. */ 82 static TAILQ_HEAD(mlx5_drivers, mlx5_class_driver) drivers_list = 83 TAILQ_HEAD_INITIALIZER(drivers_list); 84 85 /* Head of devices. */ 86 static TAILQ_HEAD(mlx5_devices, mlx5_common_device) devices_list = 87 TAILQ_HEAD_INITIALIZER(devices_list); 88 static pthread_mutex_t devices_list_lock; 89 90 static const struct { 91 const char *name; 92 unsigned int drv_class; 93 } mlx5_classes[] = { 94 { .name = "vdpa", .drv_class = MLX5_CLASS_VDPA }, 95 { .name = "eth", .drv_class = MLX5_CLASS_ETH }, 96 /* Keep class "net" for backward compatibility. */ 97 { .name = "net", .drv_class = MLX5_CLASS_ETH }, 98 { .name = "regex", .drv_class = MLX5_CLASS_REGEX }, 99 { .name = "compress", .drv_class = MLX5_CLASS_COMPRESS }, 100 { .name = "crypto", .drv_class = MLX5_CLASS_CRYPTO }, 101 }; 102 103 static int 104 class_name_to_value(const char *class_name) 105 { 106 unsigned int i; 107 108 for (i = 0; i < RTE_DIM(mlx5_classes); i++) { 109 if (strcmp(class_name, mlx5_classes[i].name) == 0) 110 return mlx5_classes[i].drv_class; 111 } 112 return -EINVAL; 113 } 114 115 static struct mlx5_class_driver * 116 driver_get(uint32_t class) 117 { 118 struct mlx5_class_driver *driver; 119 120 TAILQ_FOREACH(driver, &drivers_list, next) { 121 if ((uint32_t)driver->drv_class == class) 122 return driver; 123 } 124 return NULL; 125 } 126 127 int 128 mlx5_kvargs_process(struct mlx5_kvargs_ctrl *mkvlist, const char *const keys[], 129 arg_handler_t handler, void *opaque_arg) 130 { 131 const struct rte_kvargs_pair *pair; 132 uint32_t i, j; 133 134 MLX5_ASSERT(mkvlist && mkvlist->kvlist); 135 /* Process parameters. */ 136 for (i = 0; i < mkvlist->kvlist->count; i++) { 137 pair = &mkvlist->kvlist->pairs[i]; 138 for (j = 0; keys[j] != NULL; ++j) { 139 if (strcmp(pair->key, keys[j]) != 0) 140 continue; 141 if ((*handler)(pair->key, pair->value, opaque_arg) < 0) 142 return -1; 143 mkvlist->is_used[i] = true; 144 break; 145 } 146 } 147 return 0; 148 } 149 150 /** 151 * Prepare a mlx5 kvargs control. 152 * 153 * @param[out] mkvlist 154 * Pointer to mlx5 kvargs control. 155 * @param[in] devargs 156 * The input string containing the key/value associations. 157 * 158 * @return 159 * 0 on success, a negative errno value otherwise and rte_errno is set. 160 */ 161 static int 162 mlx5_kvargs_prepare(struct mlx5_kvargs_ctrl *mkvlist, 163 const struct rte_devargs *devargs) 164 { 165 struct rte_kvargs *kvlist; 166 uint32_t i; 167 168 if (mkvlist == NULL) 169 return 0; 170 MLX5_ASSERT(devargs != NULL && devargs->args != NULL); 171 kvlist = rte_kvargs_parse(devargs->args, NULL); 172 if (kvlist == NULL) { 173 rte_errno = EINVAL; 174 return -rte_errno; 175 } 176 /* 177 * rte_kvargs_parse enable key without value, in mlx5 PMDs we disable 178 * this syntax. 179 */ 180 for (i = 0; i < kvlist->count; i++) { 181 const struct rte_kvargs_pair *pair = &kvlist->pairs[i]; 182 if (pair->value == NULL || *(pair->value) == '\0') { 183 DRV_LOG(ERR, "Key %s is missing value.", pair->key); 184 rte_kvargs_free(kvlist); 185 rte_errno = EINVAL; 186 return -rte_errno; 187 } 188 } 189 /* Makes sure all devargs used array is false. */ 190 memset(mkvlist, 0, sizeof(*mkvlist)); 191 mkvlist->kvlist = kvlist; 192 DRV_LOG(DEBUG, "Parse successfully %u devargs.", 193 mkvlist->kvlist->count); 194 return 0; 195 } 196 197 /** 198 * Release a mlx5 kvargs control. 199 * 200 * @param[out] mkvlist 201 * Pointer to mlx5 kvargs control. 202 */ 203 static void 204 mlx5_kvargs_release(struct mlx5_kvargs_ctrl *mkvlist) 205 { 206 if (mkvlist == NULL) 207 return; 208 rte_kvargs_free(mkvlist->kvlist); 209 memset(mkvlist, 0, sizeof(*mkvlist)); 210 } 211 212 /** 213 * Validate device arguments list. 214 * It report about the first unknown parameter. 215 * 216 * @param[in] mkvlist 217 * Pointer to mlx5 kvargs control. 218 * 219 * @return 220 * 0 on success, a negative errno value otherwise and rte_errno is set. 221 */ 222 static int 223 mlx5_kvargs_validate(struct mlx5_kvargs_ctrl *mkvlist) 224 { 225 uint32_t i; 226 227 /* Secondary process should not handle devargs. */ 228 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 229 return 0; 230 if (mkvlist == NULL) 231 return 0; 232 for (i = 0; i < mkvlist->kvlist->count; i++) { 233 if (mkvlist->is_used[i] == 0) { 234 DRV_LOG(ERR, "Key \"%s\" " 235 "is unknown for the provided classes.", 236 mkvlist->kvlist->pairs[i].key); 237 rte_errno = EINVAL; 238 return -rte_errno; 239 } 240 } 241 return 0; 242 } 243 244 /** 245 * Verify and store value for devargs. 246 * 247 * @param[in] key 248 * Key argument to verify. 249 * @param[in] val 250 * Value associated with key. 251 * @param opaque 252 * User data. 253 * 254 * @return 255 * 0 on success, a negative errno value otherwise and rte_errno is set. 256 */ 257 static int 258 mlx5_common_args_check_handler(const char *key, const char *val, void *opaque) 259 { 260 struct mlx5_common_dev_config *config = opaque; 261 signed long tmp; 262 263 if (strcmp(MLX5_DRIVER_KEY, key) == 0 || 264 strcmp(RTE_DEVARGS_KEY_CLASS, key) == 0) 265 return 0; 266 errno = 0; 267 tmp = strtol(val, NULL, 0); 268 if (errno) { 269 rte_errno = errno; 270 DRV_LOG(WARNING, "%s: \"%s\" is an invalid integer.", key, val); 271 return -rte_errno; 272 } 273 if (strcmp(key, MLX5_TX_DB_NC) == 0) 274 DRV_LOG(WARNING, 275 "%s: deprecated parameter, converted to queue_db_nc", 276 key); 277 if (strcmp(key, MLX5_SQ_DB_NC) == 0 || 278 strcmp(key, MLX5_TX_DB_NC) == 0) { 279 if (tmp != MLX5_SQ_DB_CACHED && 280 tmp != MLX5_SQ_DB_NCACHED && 281 tmp != MLX5_SQ_DB_HEURISTIC) { 282 DRV_LOG(ERR, 283 "Invalid Send Queue doorbell mapping parameter."); 284 rte_errno = EINVAL; 285 return -rte_errno; 286 } 287 config->dbnc = tmp; 288 } else if (strcmp(key, MLX5_MR_EXT_MEMSEG_EN) == 0) { 289 config->mr_ext_memseg_en = !!tmp; 290 } else if (strcmp(key, MLX5_MR_MEMPOOL_REG_EN) == 0) { 291 config->mr_mempool_reg_en = !!tmp; 292 } else if (strcmp(key, MLX5_SYS_MEM_EN) == 0) { 293 config->sys_mem_en = !!tmp; 294 } else if (strcmp(key, MLX5_DEVICE_FD) == 0) { 295 config->device_fd = tmp; 296 } else if (strcmp(key, MLX5_PD_HANDLE) == 0) { 297 config->pd_handle = tmp; 298 } 299 return 0; 300 } 301 302 /** 303 * Parse common device parameters. 304 * 305 * @param devargs 306 * Device arguments structure. 307 * @param config 308 * Pointer to device configuration structure. 309 * 310 * @return 311 * 0 on success, a negative errno value otherwise and rte_errno is set. 312 */ 313 static int 314 mlx5_common_config_get(struct mlx5_kvargs_ctrl *mkvlist, 315 struct mlx5_common_dev_config *config) 316 { 317 const char **params = (const char *[]){ 318 RTE_DEVARGS_KEY_CLASS, 319 MLX5_DRIVER_KEY, 320 MLX5_TX_DB_NC, 321 MLX5_SQ_DB_NC, 322 MLX5_MR_EXT_MEMSEG_EN, 323 MLX5_SYS_MEM_EN, 324 MLX5_MR_MEMPOOL_REG_EN, 325 MLX5_DEVICE_FD, 326 MLX5_PD_HANDLE, 327 NULL, 328 }; 329 int ret = 0; 330 331 /* Set defaults. */ 332 config->mr_ext_memseg_en = 1; 333 config->mr_mempool_reg_en = 1; 334 config->sys_mem_en = 0; 335 config->dbnc = MLX5_ARG_UNSET; 336 config->device_fd = MLX5_ARG_UNSET; 337 config->pd_handle = MLX5_ARG_UNSET; 338 if (mkvlist == NULL) 339 return 0; 340 /* Process common parameters. */ 341 ret = mlx5_kvargs_process(mkvlist, params, 342 mlx5_common_args_check_handler, config); 343 if (ret) { 344 rte_errno = EINVAL; 345 return -rte_errno; 346 } 347 /* Validate user arguments for remote PD and CTX if it is given. */ 348 ret = mlx5_os_remote_pd_and_ctx_validate(config); 349 if (ret) 350 return ret; 351 DRV_LOG(DEBUG, "mr_ext_memseg_en is %u.", config->mr_ext_memseg_en); 352 DRV_LOG(DEBUG, "mr_mempool_reg_en is %u.", config->mr_mempool_reg_en); 353 DRV_LOG(DEBUG, "sys_mem_en is %u.", config->sys_mem_en); 354 DRV_LOG(DEBUG, "Send Queue doorbell mapping parameter is %d.", 355 config->dbnc); 356 return ret; 357 } 358 359 static int 360 devargs_class_handler(__rte_unused const char *key, 361 const char *class_names, void *opaque) 362 { 363 int *ret = opaque; 364 int class_val; 365 char *scratch; 366 char *found; 367 char *refstr = NULL; 368 369 *ret = 0; 370 scratch = strdup(class_names); 371 if (scratch == NULL) { 372 *ret = -ENOMEM; 373 return *ret; 374 } 375 found = strtok_r(scratch, ":", &refstr); 376 if (found == NULL) 377 /* Empty string. */ 378 goto err; 379 do { 380 /* Extract each individual class name. Multiple 381 * classes can be supplied as class=net:regex:foo:bar. 382 */ 383 class_val = class_name_to_value(found); 384 /* Check if its a valid class. */ 385 if (class_val < 0) { 386 *ret = -EINVAL; 387 goto err; 388 } 389 *ret |= class_val; 390 found = strtok_r(NULL, ":", &refstr); 391 } while (found != NULL); 392 err: 393 free(scratch); 394 if (*ret < 0) 395 DRV_LOG(ERR, "Invalid mlx5 class options: %s.\n", class_names); 396 return *ret; 397 } 398 399 static int 400 parse_class_options(const struct rte_devargs *devargs, 401 struct mlx5_kvargs_ctrl *mkvlist) 402 { 403 int ret = 0; 404 405 if (mkvlist == NULL) 406 return 0; 407 MLX5_ASSERT(devargs != NULL); 408 if (devargs->cls != NULL && devargs->cls->name != NULL) 409 /* Global syntax, only one class type. */ 410 return class_name_to_value(devargs->cls->name); 411 /* Legacy devargs support multiple classes. */ 412 rte_kvargs_process(mkvlist->kvlist, RTE_DEVARGS_KEY_CLASS, 413 devargs_class_handler, &ret); 414 return ret; 415 } 416 417 static const unsigned int mlx5_class_invalid_combinations[] = { 418 MLX5_CLASS_ETH | MLX5_CLASS_VDPA, 419 /* New class combination should be added here. */ 420 }; 421 422 static int 423 is_valid_class_combination(uint32_t user_classes) 424 { 425 unsigned int i; 426 427 /* Verify if user specified unsupported combination. */ 428 for (i = 0; i < RTE_DIM(mlx5_class_invalid_combinations); i++) { 429 if ((mlx5_class_invalid_combinations[i] & user_classes) == 430 mlx5_class_invalid_combinations[i]) 431 return -EINVAL; 432 } 433 /* Not found any invalid class combination. */ 434 return 0; 435 } 436 437 static bool 438 mlx5_bus_match(const struct mlx5_class_driver *drv, 439 const struct rte_device *dev) 440 { 441 if (mlx5_dev_is_pci(dev)) 442 return mlx5_dev_pci_match(drv, dev); 443 return true; 444 } 445 446 static struct mlx5_common_device * 447 to_mlx5_device(const struct rte_device *rte_dev) 448 { 449 struct mlx5_common_device *cdev; 450 451 TAILQ_FOREACH(cdev, &devices_list, next) { 452 if (rte_dev == cdev->dev) 453 return cdev; 454 } 455 return NULL; 456 } 457 458 int 459 mlx5_dev_to_pci_str(const struct rte_device *dev, char *addr, size_t size) 460 { 461 struct rte_pci_addr pci_addr = { 0 }; 462 int ret; 463 464 if (mlx5_dev_is_pci(dev)) { 465 /* Input might be <BDF>, format PCI address to <DBDF>. */ 466 ret = rte_pci_addr_parse(dev->name, &pci_addr); 467 if (ret != 0) 468 return -ENODEV; 469 rte_pci_device_name(&pci_addr, addr, size); 470 return 0; 471 } 472 #ifdef RTE_EXEC_ENV_LINUX 473 return mlx5_auxiliary_get_pci_str(RTE_DEV_TO_AUXILIARY_CONST(dev), 474 addr, size); 475 #else 476 rte_errno = ENODEV; 477 return -rte_errno; 478 #endif 479 } 480 481 /** 482 * Register the mempool for the protection domain. 483 * 484 * @param cdev 485 * Pointer to the mlx5 common device. 486 * @param mp 487 * Mempool being registered. 488 * 489 * @return 490 * 0 on success, (-1) on failure and rte_errno is set. 491 */ 492 static int 493 mlx5_dev_mempool_register(struct mlx5_common_device *cdev, 494 struct rte_mempool *mp, bool is_extmem) 495 { 496 return mlx5_mr_mempool_register(cdev, mp, is_extmem); 497 } 498 499 /** 500 * Unregister the mempool from the protection domain. 501 * 502 * @param cdev 503 * Pointer to the mlx5 common device. 504 * @param mp 505 * Mempool being unregistered. 506 */ 507 void 508 mlx5_dev_mempool_unregister(struct mlx5_common_device *cdev, 509 struct rte_mempool *mp) 510 { 511 if (mlx5_mr_mempool_unregister(cdev, mp) < 0) 512 DRV_LOG(WARNING, "Failed to unregister mempool %s for PD %p: %s", 513 mp->name, cdev->pd, rte_strerror(rte_errno)); 514 } 515 516 /** 517 * rte_mempool_walk() callback to register mempools for the protection domain. 518 * 519 * @param mp 520 * The mempool being walked. 521 * @param arg 522 * Pointer to the device shared context. 523 */ 524 static void 525 mlx5_dev_mempool_register_cb(struct rte_mempool *mp, void *arg) 526 { 527 struct mlx5_common_device *cdev = arg; 528 int ret; 529 530 ret = mlx5_dev_mempool_register(cdev, mp, false); 531 if (ret < 0 && rte_errno != EEXIST) 532 DRV_LOG(ERR, 533 "Failed to register existing mempool %s for PD %p: %s", 534 mp->name, cdev->pd, rte_strerror(rte_errno)); 535 } 536 537 /** 538 * rte_mempool_walk() callback to unregister mempools 539 * from the protection domain. 540 * 541 * @param mp 542 * The mempool being walked. 543 * @param arg 544 * Pointer to the device shared context. 545 */ 546 static void 547 mlx5_dev_mempool_unregister_cb(struct rte_mempool *mp, void *arg) 548 { 549 mlx5_dev_mempool_unregister((struct mlx5_common_device *)arg, mp); 550 } 551 552 /** 553 * Mempool life cycle callback for mlx5 common devices. 554 * 555 * @param event 556 * Mempool life cycle event. 557 * @param mp 558 * Associated mempool. 559 * @param arg 560 * Pointer to a device shared context. 561 */ 562 static void 563 mlx5_dev_mempool_event_cb(enum rte_mempool_event event, struct rte_mempool *mp, 564 void *arg) 565 { 566 struct mlx5_common_device *cdev = arg; 567 568 switch (event) { 569 case RTE_MEMPOOL_EVENT_READY: 570 if (mlx5_dev_mempool_register(cdev, mp, false) < 0) 571 DRV_LOG(ERR, 572 "Failed to register new mempool %s for PD %p: %s", 573 mp->name, cdev->pd, rte_strerror(rte_errno)); 574 break; 575 case RTE_MEMPOOL_EVENT_DESTROY: 576 mlx5_dev_mempool_unregister(cdev, mp); 577 break; 578 } 579 } 580 581 /** 582 * Primary and secondary processes share the `cdev` pointer. 583 * Callbacks addresses are local in each process. 584 * Therefore, each process can register private callbacks. 585 */ 586 int 587 mlx5_dev_mempool_subscribe(struct mlx5_common_device *cdev) 588 { 589 int ret = 0; 590 591 if (!cdev->config.mr_mempool_reg_en) 592 return 0; 593 rte_rwlock_write_lock(&cdev->mr_scache.mprwlock); 594 /* Callback for this device may be already registered. */ 595 ret = rte_mempool_event_callback_register(mlx5_dev_mempool_event_cb, 596 cdev); 597 /* Register mempools only once for this device. */ 598 if (ret == 0 && rte_eal_process_type() == RTE_PROC_PRIMARY) { 599 rte_mempool_walk(mlx5_dev_mempool_register_cb, cdev); 600 goto exit; 601 } 602 if (ret != 0 && rte_errno == EEXIST) 603 ret = 0; 604 exit: 605 rte_rwlock_write_unlock(&cdev->mr_scache.mprwlock); 606 return ret; 607 } 608 609 static void 610 mlx5_dev_mempool_unsubscribe(struct mlx5_common_device *cdev) 611 { 612 int ret; 613 614 MLX5_ASSERT(cdev->dev != NULL); 615 if (!cdev->config.mr_mempool_reg_en) 616 return; 617 /* Stop watching for mempool events and unregister all mempools. */ 618 ret = rte_mempool_event_callback_unregister(mlx5_dev_mempool_event_cb, 619 cdev); 620 if (ret == 0) 621 rte_mempool_walk(mlx5_dev_mempool_unregister_cb, cdev); 622 } 623 624 /** 625 * Callback for memory event. 626 * 627 * @param event_type 628 * Memory event type. 629 * @param addr 630 * Address of memory. 631 * @param len 632 * Size of memory. 633 */ 634 static void 635 mlx5_mr_mem_event_cb(enum rte_mem_event event_type, const void *addr, 636 size_t len, void *arg __rte_unused) 637 { 638 struct mlx5_common_device *cdev; 639 640 /* Must be called from the primary process. */ 641 MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 642 switch (event_type) { 643 case RTE_MEM_EVENT_FREE: 644 pthread_mutex_lock(&devices_list_lock); 645 /* Iterate all the existing mlx5 devices. */ 646 TAILQ_FOREACH(cdev, &devices_list, next) 647 mlx5_free_mr_by_addr(&cdev->mr_scache, 648 mlx5_os_get_ctx_device_name 649 (cdev->ctx), 650 addr, len); 651 pthread_mutex_unlock(&devices_list_lock); 652 break; 653 case RTE_MEM_EVENT_ALLOC: 654 default: 655 break; 656 } 657 } 658 659 /** 660 * Uninitialize all HW global of device context. 661 * 662 * @param cdev 663 * Pointer to mlx5 device structure. 664 * 665 * @return 666 * 0 on success, a negative errno value otherwise and rte_errno is set. 667 */ 668 static void 669 mlx5_dev_hw_global_release(struct mlx5_common_device *cdev) 670 { 671 if (cdev->pd != NULL) { 672 claim_zero(mlx5_os_pd_release(cdev)); 673 cdev->pd = NULL; 674 } 675 if (cdev->ctx != NULL) { 676 claim_zero(mlx5_glue->close_device(cdev->ctx)); 677 cdev->ctx = NULL; 678 } 679 } 680 681 /** 682 * Initialize all HW global of device context. 683 * 684 * @param cdev 685 * Pointer to mlx5 device structure. 686 * @param classes 687 * Chosen classes come from user device arguments. 688 * 689 * @return 690 * 0 on success, a negative errno value otherwise and rte_errno is set. 691 */ 692 static int 693 mlx5_dev_hw_global_prepare(struct mlx5_common_device *cdev, uint32_t classes) 694 { 695 int ret; 696 697 /* Create context device */ 698 ret = mlx5_os_open_device(cdev, classes); 699 if (ret < 0) 700 return ret; 701 /* 702 * When CTX is created by Verbs, query HCA attribute is unsupported. 703 * When CTX is imported, we cannot know if it is created by DevX or 704 * Verbs. So, we use query HCA attribute function to check it. 705 */ 706 if (cdev->config.devx || cdev->config.device_fd != MLX5_ARG_UNSET) { 707 /* Query HCA attributes. */ 708 ret = mlx5_devx_cmd_query_hca_attr(cdev->ctx, 709 &cdev->config.hca_attr); 710 if (ret) { 711 DRV_LOG(ERR, "Unable to read HCA caps in DevX mode."); 712 rte_errno = ENOTSUP; 713 goto error; 714 } 715 cdev->config.devx = 1; 716 } 717 DRV_LOG(DEBUG, "DevX is %ssupported.", cdev->config.devx ? "" : "NOT "); 718 /* Prepare Protection Domain object and extract its pdn. */ 719 ret = mlx5_os_pd_prepare(cdev); 720 if (ret) 721 goto error; 722 return 0; 723 error: 724 mlx5_dev_hw_global_release(cdev); 725 return ret; 726 } 727 728 static void 729 mlx5_common_dev_release(struct mlx5_common_device *cdev) 730 { 731 pthread_mutex_lock(&devices_list_lock); 732 TAILQ_REMOVE(&devices_list, cdev, next); 733 pthread_mutex_unlock(&devices_list_lock); 734 if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 735 if (TAILQ_EMPTY(&devices_list)) 736 rte_mem_event_callback_unregister("MLX5_MEM_EVENT_CB", 737 NULL); 738 mlx5_dev_mempool_unsubscribe(cdev); 739 mlx5_mr_release_cache(&cdev->mr_scache); 740 mlx5_dev_hw_global_release(cdev); 741 } 742 rte_free(cdev); 743 } 744 745 static struct mlx5_common_device * 746 mlx5_common_dev_create(struct rte_device *eal_dev, uint32_t classes, 747 struct mlx5_kvargs_ctrl *mkvlist) 748 { 749 struct mlx5_common_device *cdev; 750 int ret; 751 752 cdev = rte_zmalloc("mlx5_common_device", sizeof(*cdev), 0); 753 if (!cdev) { 754 DRV_LOG(ERR, "Device allocation failure."); 755 rte_errno = ENOMEM; 756 return NULL; 757 } 758 cdev->dev = eal_dev; 759 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 760 goto exit; 761 /* Parse device parameters. */ 762 ret = mlx5_common_config_get(mkvlist, &cdev->config); 763 if (ret < 0) { 764 DRV_LOG(ERR, "Failed to process device arguments: %s", 765 strerror(rte_errno)); 766 rte_free(cdev); 767 return NULL; 768 } 769 mlx5_malloc_mem_select(cdev->config.sys_mem_en); 770 /* Initialize all HW global of device context. */ 771 ret = mlx5_dev_hw_global_prepare(cdev, classes); 772 if (ret) { 773 DRV_LOG(ERR, "Failed to initialize device context."); 774 rte_free(cdev); 775 return NULL; 776 } 777 /* Initialize global MR cache resources and update its functions. */ 778 ret = mlx5_mr_create_cache(&cdev->mr_scache, eal_dev->numa_node); 779 if (ret) { 780 DRV_LOG(ERR, "Failed to initialize global MR share cache."); 781 mlx5_dev_hw_global_release(cdev); 782 rte_free(cdev); 783 return NULL; 784 } 785 /* Register callback function for global shared MR cache management. */ 786 if (TAILQ_EMPTY(&devices_list)) 787 rte_mem_event_callback_register("MLX5_MEM_EVENT_CB", 788 mlx5_mr_mem_event_cb, NULL); 789 exit: 790 pthread_mutex_lock(&devices_list_lock); 791 TAILQ_INSERT_HEAD(&devices_list, cdev, next); 792 pthread_mutex_unlock(&devices_list_lock); 793 return cdev; 794 } 795 796 /** 797 * Validate common devargs when probing again. 798 * 799 * When common device probing again, it cannot change its configurations. 800 * If user ask non compatible configurations in devargs, it is error. 801 * This function checks the match between: 802 * - Common device configurations requested by probe again devargs. 803 * - Existing common device configurations. 804 * 805 * @param cdev 806 * Pointer to mlx5 device structure. 807 * @param mkvlist 808 * Pointer to mlx5 kvargs control, can be NULL if there is no devargs. 809 * 810 * @return 811 * 0 on success, a negative errno value otherwise and rte_errno is set. 812 */ 813 static int 814 mlx5_common_probe_again_args_validate(struct mlx5_common_device *cdev, 815 struct mlx5_kvargs_ctrl *mkvlist) 816 { 817 struct mlx5_common_dev_config *config; 818 int ret; 819 820 /* Secondary process should not handle devargs. */ 821 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 822 return 0; 823 /* Probe again doesn't have to generate devargs. */ 824 if (mkvlist == NULL) 825 return 0; 826 config = mlx5_malloc(MLX5_MEM_ZERO | MLX5_MEM_RTE, 827 sizeof(struct mlx5_common_dev_config), 828 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 829 if (config == NULL) { 830 rte_errno = -ENOMEM; 831 return -rte_errno; 832 } 833 /* 834 * Creates a temporary common configure structure according to new 835 * devargs attached in probing again. 836 */ 837 ret = mlx5_common_config_get(mkvlist, config); 838 if (ret) { 839 DRV_LOG(ERR, "Failed to process device configure: %s", 840 strerror(rte_errno)); 841 mlx5_free(config); 842 return ret; 843 } 844 /* 845 * Checks the match between the temporary structure and the existing 846 * common device structure. 847 */ 848 if (cdev->config.mr_ext_memseg_en != config->mr_ext_memseg_en) { 849 DRV_LOG(ERR, "\"" MLX5_MR_EXT_MEMSEG_EN "\" " 850 "configuration mismatch for device %s.", 851 cdev->dev->name); 852 goto error; 853 } 854 if (cdev->config.mr_mempool_reg_en != config->mr_mempool_reg_en) { 855 DRV_LOG(ERR, "\"" MLX5_MR_MEMPOOL_REG_EN "\" " 856 "configuration mismatch for device %s.", 857 cdev->dev->name); 858 goto error; 859 } 860 if (cdev->config.device_fd != config->device_fd) { 861 DRV_LOG(ERR, "\"" MLX5_DEVICE_FD "\" " 862 "configuration mismatch for device %s.", 863 cdev->dev->name); 864 goto error; 865 } 866 if (cdev->config.pd_handle != config->pd_handle) { 867 DRV_LOG(ERR, "\"" MLX5_PD_HANDLE "\" " 868 "configuration mismatch for device %s.", 869 cdev->dev->name); 870 goto error; 871 } 872 if (cdev->config.sys_mem_en != config->sys_mem_en) { 873 DRV_LOG(ERR, "\"" MLX5_SYS_MEM_EN "\" " 874 "configuration mismatch for device %s.", 875 cdev->dev->name); 876 goto error; 877 } 878 if (cdev->config.dbnc != config->dbnc) { 879 DRV_LOG(ERR, "\"" MLX5_SQ_DB_NC "\" " 880 "configuration mismatch for device %s.", 881 cdev->dev->name); 882 goto error; 883 } 884 mlx5_free(config); 885 return 0; 886 error: 887 mlx5_free(config); 888 rte_errno = EINVAL; 889 return -rte_errno; 890 } 891 892 static int 893 drivers_remove(struct mlx5_common_device *cdev, uint32_t enabled_classes) 894 { 895 struct mlx5_class_driver *driver; 896 int local_ret = -ENODEV; 897 unsigned int i = 0; 898 int ret = 0; 899 900 while (enabled_classes) { 901 driver = driver_get(RTE_BIT64(i)); 902 if (driver != NULL) { 903 local_ret = driver->remove(cdev); 904 if (local_ret == 0) 905 cdev->classes_loaded &= ~RTE_BIT64(i); 906 else if (ret == 0) 907 ret = local_ret; 908 } 909 enabled_classes &= ~RTE_BIT64(i); 910 i++; 911 } 912 if (local_ret != 0 && ret == 0) 913 ret = local_ret; 914 return ret; 915 } 916 917 static int 918 drivers_probe(struct mlx5_common_device *cdev, uint32_t user_classes, 919 struct mlx5_kvargs_ctrl *mkvlist) 920 { 921 struct mlx5_class_driver *driver; 922 uint32_t enabled_classes = 0; 923 bool already_loaded; 924 int ret = -EINVAL; 925 926 TAILQ_FOREACH(driver, &drivers_list, next) { 927 if ((driver->drv_class & user_classes) == 0) 928 continue; 929 if (!mlx5_bus_match(driver, cdev->dev)) 930 continue; 931 already_loaded = cdev->classes_loaded & driver->drv_class; 932 if (already_loaded && driver->probe_again == 0) { 933 DRV_LOG(ERR, "Device %s is already probed", 934 cdev->dev->name); 935 ret = -EEXIST; 936 goto probe_err; 937 } 938 ret = driver->probe(cdev, mkvlist); 939 if (ret < 0) { 940 DRV_LOG(ERR, "Failed to load driver %s", 941 driver->name); 942 goto probe_err; 943 } 944 enabled_classes |= driver->drv_class; 945 } 946 if (!ret) { 947 cdev->classes_loaded |= enabled_classes; 948 return 0; 949 } 950 probe_err: 951 /* 952 * Need to remove only drivers which were not probed before this probe 953 * instance, but have already been probed before this failure. 954 */ 955 enabled_classes &= ~cdev->classes_loaded; 956 drivers_remove(cdev, enabled_classes); 957 return ret; 958 } 959 960 int 961 mlx5_common_dev_probe(struct rte_device *eal_dev) 962 { 963 struct mlx5_common_device *cdev; 964 struct mlx5_kvargs_ctrl mkvlist; 965 struct mlx5_kvargs_ctrl *mkvlist_p = NULL; 966 uint32_t classes = 0; 967 bool new_device = false; 968 int ret; 969 970 DRV_LOG(INFO, "probe device \"%s\".", eal_dev->name); 971 if (eal_dev->devargs != NULL && eal_dev->devargs->args != NULL) 972 mkvlist_p = &mkvlist; 973 ret = mlx5_kvargs_prepare(mkvlist_p, eal_dev->devargs); 974 if (ret < 0) { 975 DRV_LOG(ERR, "Unsupported device arguments: %s", 976 eal_dev->devargs->args); 977 return ret; 978 } 979 ret = parse_class_options(eal_dev->devargs, mkvlist_p); 980 if (ret < 0) { 981 DRV_LOG(ERR, "Unsupported mlx5 class type: %s", 982 eal_dev->devargs->args); 983 goto class_err; 984 } 985 classes = ret; 986 if (classes == 0) 987 /* Default to net class. */ 988 classes = MLX5_CLASS_ETH; 989 /* 990 * MLX5 common driver supports probing again in two scenarios: 991 * - Add new driver under existing common device (regardless of the 992 * driver's own support in probing again). 993 * - Transfer the probing again support of the drivers themselves. 994 * 995 * In both scenarios it uses in the existing device. here it looks for 996 * device that match to rte device, if it exists, the request classes 997 * were probed with this device. 998 */ 999 cdev = to_mlx5_device(eal_dev); 1000 if (!cdev) { 1001 /* It isn't probing again, creates a new device. */ 1002 cdev = mlx5_common_dev_create(eal_dev, classes, mkvlist_p); 1003 if (!cdev) { 1004 ret = -ENOMEM; 1005 goto class_err; 1006 } 1007 new_device = true; 1008 } else { 1009 /* It is probing again, validate common devargs match. */ 1010 ret = mlx5_common_probe_again_args_validate(cdev, mkvlist_p); 1011 if (ret) { 1012 DRV_LOG(ERR, 1013 "Probe again parameters aren't compatible : %s", 1014 strerror(rte_errno)); 1015 goto class_err; 1016 } 1017 } 1018 /* 1019 * Validate combination here. 1020 * For new device, the classes_loaded field is 0 and it check only 1021 * the classes given as user device arguments. 1022 */ 1023 ret = is_valid_class_combination(classes | cdev->classes_loaded); 1024 if (ret != 0) { 1025 DRV_LOG(ERR, "Unsupported mlx5 classes combination."); 1026 goto class_err; 1027 } 1028 ret = drivers_probe(cdev, classes, mkvlist_p); 1029 if (ret) 1030 goto class_err; 1031 /* 1032 * Validate that all devargs have been used, unused key -> unknown Key. 1033 * When probe again validate is failed, the added drivers aren't removed 1034 * here but when device is released. 1035 */ 1036 ret = mlx5_kvargs_validate(mkvlist_p); 1037 if (ret) 1038 goto class_err; 1039 mlx5_kvargs_release(mkvlist_p); 1040 return 0; 1041 class_err: 1042 if (new_device) { 1043 /* 1044 * For new device, classes_loaded is always 0 before 1045 * drivers_probe function. 1046 */ 1047 if (cdev->classes_loaded) 1048 drivers_remove(cdev, cdev->classes_loaded); 1049 mlx5_common_dev_release(cdev); 1050 } 1051 mlx5_kvargs_release(mkvlist_p); 1052 return ret; 1053 } 1054 1055 int 1056 mlx5_common_dev_remove(struct rte_device *eal_dev) 1057 { 1058 struct mlx5_common_device *cdev; 1059 int ret; 1060 1061 cdev = to_mlx5_device(eal_dev); 1062 if (!cdev) 1063 return -ENODEV; 1064 /* Matching device found, cleanup and unload drivers. */ 1065 ret = drivers_remove(cdev, cdev->classes_loaded); 1066 if (ret == 0) 1067 mlx5_common_dev_release(cdev); 1068 return ret; 1069 } 1070 1071 /** 1072 * Callback to DMA map external memory to a device. 1073 * 1074 * @param rte_dev 1075 * Pointer to the generic device. 1076 * @param addr 1077 * Starting virtual address of memory to be mapped. 1078 * @param iova 1079 * Starting IOVA address of memory to be mapped. 1080 * @param len 1081 * Length of memory segment being mapped. 1082 * 1083 * @return 1084 * 0 on success, negative value on error. 1085 */ 1086 int 1087 mlx5_common_dev_dma_map(struct rte_device *rte_dev, void *addr, 1088 uint64_t iova __rte_unused, size_t len) 1089 { 1090 struct mlx5_common_device *dev; 1091 struct mlx5_mr_btree *bt; 1092 struct mlx5_mr *mr; 1093 1094 dev = to_mlx5_device(rte_dev); 1095 if (!dev) { 1096 DRV_LOG(WARNING, 1097 "Unable to find matching mlx5 device to device %s", 1098 rte_dev->name); 1099 rte_errno = ENODEV; 1100 return -1; 1101 } 1102 mr = mlx5_create_mr_ext(dev->pd, (uintptr_t)addr, len, 1103 SOCKET_ID_ANY, dev->mr_scache.reg_mr_cb); 1104 if (!mr) { 1105 DRV_LOG(WARNING, "Device %s unable to DMA map", rte_dev->name); 1106 rte_errno = EINVAL; 1107 return -1; 1108 } 1109 try_insert: 1110 rte_rwlock_write_lock(&dev->mr_scache.rwlock); 1111 bt = &dev->mr_scache.cache; 1112 if (bt->len == bt->size) { 1113 uint32_t size; 1114 int ret; 1115 1116 size = bt->size + 1; 1117 MLX5_ASSERT(size > bt->size); 1118 /* 1119 * Avoid deadlock (numbers show the sequence of events): 1120 * mlx5_mr_create_primary(): 1121 * 1) take EAL memory lock 1122 * 3) take MR lock 1123 * this function: 1124 * 2) take MR lock 1125 * 4) take EAL memory lock while allocating the new cache 1126 * Releasing the MR lock before step 4 1127 * allows another thread to execute step 3. 1128 */ 1129 rte_rwlock_write_unlock(&dev->mr_scache.rwlock); 1130 ret = mlx5_mr_expand_cache(&dev->mr_scache, size, 1131 rte_dev->numa_node); 1132 if (ret < 0) { 1133 mlx5_mr_free(mr, dev->mr_scache.dereg_mr_cb); 1134 rte_errno = ret; 1135 return -1; 1136 } 1137 goto try_insert; 1138 } 1139 LIST_INSERT_HEAD(&dev->mr_scache.mr_list, mr, mr); 1140 /* Insert to the global cache table. */ 1141 mlx5_mr_insert_cache(&dev->mr_scache, mr); 1142 rte_rwlock_write_unlock(&dev->mr_scache.rwlock); 1143 return 0; 1144 } 1145 1146 /** 1147 * Callback to DMA unmap external memory to a device. 1148 * 1149 * @param rte_dev 1150 * Pointer to the generic device. 1151 * @param addr 1152 * Starting virtual address of memory to be unmapped. 1153 * @param iova 1154 * Starting IOVA address of memory to be unmapped. 1155 * @param len 1156 * Length of memory segment being unmapped. 1157 * 1158 * @return 1159 * 0 on success, negative value on error. 1160 */ 1161 int 1162 mlx5_common_dev_dma_unmap(struct rte_device *rte_dev, void *addr, 1163 uint64_t iova __rte_unused, size_t len __rte_unused) 1164 { 1165 struct mlx5_common_device *dev; 1166 struct mr_cache_entry entry; 1167 struct mlx5_mr *mr; 1168 1169 dev = to_mlx5_device(rte_dev); 1170 if (!dev) { 1171 DRV_LOG(WARNING, 1172 "Unable to find matching mlx5 device to device %s.", 1173 rte_dev->name); 1174 rte_errno = ENODEV; 1175 return -1; 1176 } 1177 rte_rwlock_read_lock(&dev->mr_scache.rwlock); 1178 mr = mlx5_mr_lookup_list(&dev->mr_scache, &entry, (uintptr_t)addr); 1179 if (!mr) { 1180 rte_rwlock_read_unlock(&dev->mr_scache.rwlock); 1181 DRV_LOG(WARNING, 1182 "Address 0x%" PRIxPTR " wasn't registered to device %s", 1183 (uintptr_t)addr, rte_dev->name); 1184 rte_errno = EINVAL; 1185 return -1; 1186 } 1187 LIST_REMOVE(mr, mr); 1188 DRV_LOG(DEBUG, "MR(%p) is removed from list.", (void *)mr); 1189 mlx5_mr_free(mr, dev->mr_scache.dereg_mr_cb); 1190 mlx5_mr_rebuild_cache(&dev->mr_scache); 1191 /* 1192 * No explicit wmb is needed after updating dev_gen due to 1193 * store-release ordering in unlock that provides the 1194 * implicit barrier at the software visible level. 1195 */ 1196 ++dev->mr_scache.dev_gen; 1197 DRV_LOG(DEBUG, "Broadcasting local cache flush, gen=%d.", 1198 dev->mr_scache.dev_gen); 1199 rte_rwlock_read_unlock(&dev->mr_scache.rwlock); 1200 return 0; 1201 } 1202 1203 void 1204 mlx5_class_driver_register(struct mlx5_class_driver *driver) 1205 { 1206 mlx5_common_driver_on_register_pci(driver); 1207 TAILQ_INSERT_TAIL(&drivers_list, driver, next); 1208 } 1209 1210 static void mlx5_common_driver_init(void) 1211 { 1212 mlx5_common_pci_init(); 1213 #ifdef RTE_EXEC_ENV_LINUX 1214 mlx5_common_auxiliary_init(); 1215 #endif 1216 } 1217 1218 static bool mlx5_common_initialized; 1219 1220 /** 1221 * One time initialization routine for run-time dependency on glue library 1222 * for multiple PMDs. Each mlx5 PMD that depends on mlx5_common module, 1223 * must invoke in its constructor. 1224 */ 1225 void 1226 mlx5_common_init(void) 1227 { 1228 if (mlx5_common_initialized) 1229 return; 1230 1231 pthread_mutex_init(&devices_list_lock, NULL); 1232 mlx5_glue_constructor(); 1233 mlx5_common_driver_init(); 1234 mlx5_common_initialized = true; 1235 } 1236 1237 /** 1238 * This function is responsible of initializing the variable 1239 * haswell_broadwell_cpu by checking if the cpu is intel 1240 * and reading the data returned from mlx5_cpu_id(). 1241 * since haswell and broadwell cpus don't have improved performance 1242 * when using relaxed ordering we want to check the cpu type before 1243 * before deciding whether to enable RO or not. 1244 * if the cpu is haswell or broadwell the variable will be set to 1 1245 * otherwise it will be 0. 1246 */ 1247 RTE_INIT_PRIO(mlx5_is_haswell_broadwell_cpu, LOG) 1248 { 1249 #ifdef RTE_ARCH_X86_64 1250 unsigned int broadwell_models[4] = {0x3d, 0x47, 0x4F, 0x56}; 1251 unsigned int haswell_models[4] = {0x3c, 0x3f, 0x45, 0x46}; 1252 unsigned int i, model, family, brand_id, vendor; 1253 unsigned int signature_intel_ebx = 0x756e6547; 1254 unsigned int extended_model; 1255 unsigned int eax = 0; 1256 unsigned int ebx = 0; 1257 unsigned int ecx = 0; 1258 unsigned int edx = 0; 1259 int max_level; 1260 1261 mlx5_cpu_id(0, &eax, &ebx, &ecx, &edx); 1262 vendor = ebx; 1263 max_level = eax; 1264 if (max_level < 1) { 1265 haswell_broadwell_cpu = 0; 1266 return; 1267 } 1268 mlx5_cpu_id(1, &eax, &ebx, &ecx, &edx); 1269 model = (eax >> 4) & 0x0f; 1270 family = (eax >> 8) & 0x0f; 1271 brand_id = ebx & 0xff; 1272 extended_model = (eax >> 12) & 0xf0; 1273 /* Check if the processor is Haswell or Broadwell */ 1274 if (vendor == signature_intel_ebx) { 1275 if (family == 0x06) 1276 model += extended_model; 1277 if (brand_id == 0 && family == 0x6) { 1278 for (i = 0; i < RTE_DIM(broadwell_models); i++) 1279 if (model == broadwell_models[i]) { 1280 haswell_broadwell_cpu = 1; 1281 return; 1282 } 1283 for (i = 0; i < RTE_DIM(haswell_models); i++) 1284 if (model == haswell_models[i]) { 1285 haswell_broadwell_cpu = 1; 1286 return; 1287 } 1288 } 1289 } 1290 #endif 1291 haswell_broadwell_cpu = 0; 1292 } 1293 1294 /** 1295 * Allocate the User Access Region with DevX on specified device. 1296 * This routine handles the following UAR allocation issues: 1297 * 1298 * - Try to allocate the UAR with the most appropriate memory mapping 1299 * type from the ones supported by the host. 1300 * 1301 * - Try to allocate the UAR with non-NULL base address OFED 5.0.x and 1302 * Upstream rdma_core before v29 returned the NULL as UAR base address 1303 * if UAR was not the first object in the UAR page. 1304 * It caused the PMD failure and we should try to get another UAR till 1305 * we get the first one with non-NULL base address returned. 1306 * 1307 * @param [in] cdev 1308 * Pointer to mlx5 device structure to perform allocation on its context. 1309 * 1310 * @return 1311 * UAR object pointer on success, NULL otherwise and rte_errno is set. 1312 */ 1313 static void * 1314 mlx5_devx_alloc_uar(struct mlx5_common_device *cdev) 1315 { 1316 void *uar; 1317 uint32_t retry, uar_mapping; 1318 void *base_addr; 1319 1320 for (retry = 0; retry < MLX5_ALLOC_UAR_RETRY; ++retry) { 1321 #ifdef MLX5DV_UAR_ALLOC_TYPE_NC 1322 /* Control the mapping type according to the settings. */ 1323 uar_mapping = (cdev->config.dbnc == MLX5_SQ_DB_NCACHED) ? 1324 MLX5DV_UAR_ALLOC_TYPE_NC : MLX5DV_UAR_ALLOC_TYPE_BF; 1325 #else 1326 /* 1327 * It seems we have no way to control the memory mapping type 1328 * for the UAR, the default "Write-Combining" type is supposed. 1329 */ 1330 uar_mapping = 0; 1331 #endif 1332 uar = mlx5_glue->devx_alloc_uar(cdev->ctx, uar_mapping); 1333 #ifdef MLX5DV_UAR_ALLOC_TYPE_NC 1334 if (!uar && uar_mapping == MLX5DV_UAR_ALLOC_TYPE_BF) { 1335 /* 1336 * In some environments like virtual machine the 1337 * Write Combining mapped might be not supported and 1338 * UAR allocation fails. We tried "Non-Cached" mapping 1339 * for the case. 1340 */ 1341 DRV_LOG(DEBUG, "Failed to allocate DevX UAR (BF)"); 1342 uar_mapping = MLX5DV_UAR_ALLOC_TYPE_NC; 1343 uar = mlx5_glue->devx_alloc_uar(cdev->ctx, uar_mapping); 1344 } else if (!uar && uar_mapping == MLX5DV_UAR_ALLOC_TYPE_NC) { 1345 /* 1346 * If Verbs/kernel does not support "Non-Cached" 1347 * try the "Write-Combining". 1348 */ 1349 DRV_LOG(DEBUG, "Failed to allocate DevX UAR (NC)"); 1350 uar_mapping = MLX5DV_UAR_ALLOC_TYPE_BF; 1351 uar = mlx5_glue->devx_alloc_uar(cdev->ctx, uar_mapping); 1352 } 1353 #endif 1354 if (!uar) { 1355 DRV_LOG(ERR, "Failed to allocate DevX UAR (BF/NC)"); 1356 rte_errno = ENOMEM; 1357 goto exit; 1358 } 1359 base_addr = mlx5_os_get_devx_uar_base_addr(uar); 1360 if (base_addr) 1361 break; 1362 /* 1363 * The UARs are allocated by rdma_core within the 1364 * IB device context, on context closure all UARs 1365 * will be freed, should be no memory/object leakage. 1366 */ 1367 DRV_LOG(DEBUG, "Retrying to allocate DevX UAR"); 1368 uar = NULL; 1369 } 1370 /* Check whether we finally succeeded with valid UAR allocation. */ 1371 if (!uar) { 1372 DRV_LOG(ERR, "Failed to allocate DevX UAR (NULL base)"); 1373 rte_errno = ENOMEM; 1374 } 1375 /* 1376 * Return void * instead of struct mlx5dv_devx_uar * 1377 * is for compatibility with older rdma-core library headers. 1378 */ 1379 exit: 1380 return uar; 1381 } 1382 1383 void 1384 mlx5_devx_uar_release(struct mlx5_uar *uar) 1385 { 1386 if (uar->obj != NULL) 1387 mlx5_glue->devx_free_uar(uar->obj); 1388 memset(uar, 0, sizeof(*uar)); 1389 } 1390 1391 int 1392 mlx5_devx_uar_prepare(struct mlx5_common_device *cdev, struct mlx5_uar *uar) 1393 { 1394 off_t uar_mmap_offset; 1395 const size_t page_size = rte_mem_page_size(); 1396 void *base_addr; 1397 void *uar_obj; 1398 1399 if (page_size == (size_t)-1) { 1400 DRV_LOG(ERR, "Failed to get mem page size"); 1401 rte_errno = ENOMEM; 1402 return -1; 1403 } 1404 uar_obj = mlx5_devx_alloc_uar(cdev); 1405 if (uar_obj == NULL || mlx5_os_get_devx_uar_reg_addr(uar_obj) == NULL) { 1406 rte_errno = errno; 1407 DRV_LOG(ERR, "Failed to allocate UAR."); 1408 return -1; 1409 } 1410 uar->obj = uar_obj; 1411 uar_mmap_offset = mlx5_os_get_devx_uar_mmap_offset(uar_obj); 1412 base_addr = mlx5_os_get_devx_uar_base_addr(uar_obj); 1413 uar->dbnc = mlx5_db_map_type_get(uar_mmap_offset, page_size); 1414 uar->bf_db.db = mlx5_os_get_devx_uar_reg_addr(uar_obj); 1415 uar->cq_db.db = RTE_PTR_ADD(base_addr, MLX5_CQ_DOORBELL); 1416 #ifndef RTE_ARCH_64 1417 rte_spinlock_init(&uar->bf_sl); 1418 rte_spinlock_init(&uar->cq_sl); 1419 uar->bf_db.sl_p = &uar->bf_sl; 1420 uar->cq_db.sl_p = &uar->cq_sl; 1421 #endif /* RTE_ARCH_64 */ 1422 return 0; 1423 } 1424 1425 RTE_PMD_EXPORT_NAME(mlx5_common_driver, __COUNTER__); 1426