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