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