common/mlx5: add missing Verbs definitions on Windows
[dpdk.git] / drivers / common / mlx5 / mlx5_common.c
index 0693d03..a00ffcb 100644 (file)
 #include "mlx5_common_os.h"
 #include "mlx5_common_utils.h"
 #include "mlx5_malloc.h"
+#include "mlx5_common_pci.h"
 
 int mlx5_common_logtype;
 
 uint8_t haswell_broadwell_cpu;
 
-static int
-mlx5_class_check_handler(__rte_unused const char *key, const char *value,
-                        void *opaque)
-{
-       enum mlx5_class *ret = opaque;
-
-       if (strcmp(value, "vdpa") == 0) {
-               *ret = MLX5_CLASS_VDPA;
-       } else if (strcmp(value, "net") == 0) {
-               *ret = MLX5_CLASS_NET;
-       } else {
-               DRV_LOG(ERR, "Invalid mlx5 class %s. Maybe typo in device"
-                       " class argument setting?", value);
-               *ret = MLX5_CLASS_INVALID;
-       }
-       return 0;
-}
-
-enum mlx5_class
-mlx5_class_get(struct rte_devargs *devargs)
-{
-       struct rte_kvargs *kvlist;
-       const char *key = MLX5_CLASS_ARG_NAME;
-       enum mlx5_class ret = MLX5_CLASS_NET;
-
-       if (devargs == NULL)
-               return ret;
-       kvlist = rte_kvargs_parse(devargs->args, NULL);
-       if (kvlist == NULL)
-               return ret;
-       if (rte_kvargs_count(kvlist, key))
-               rte_kvargs_process(kvlist, key, mlx5_class_check_handler, &ret);
-       rte_kvargs_free(kvlist);
-       return ret;
-}
-
-
 /* In case this is an x86_64 intel processor to check if
  * we should use relaxed ordering.
  */
@@ -86,12 +50,22 @@ RTE_INIT_PRIO(mlx5_log_init, LOG)
                rte_log_set_level(mlx5_common_logtype, RTE_LOG_NOTICE);
 }
 
+static bool mlx5_common_initialized;
+
 /**
- * Initialization routine for run-time dependency on glue library.
+ * One time innitialization routine for run-time dependency on glue library
+ * for multiple PMDs. Each mlx5 PMD that depends on mlx5_common module,
+ * must invoke in its constructor.
  */
-RTE_INIT_PRIO(mlx5_glue_init, CLASS)
+void
+mlx5_common_init(void)
 {
+       if (mlx5_common_initialized)
+               return;
+
        mlx5_glue_constructor();
+       mlx5_common_pci_init();
+       mlx5_common_initialized = true;
 }
 
 /**
@@ -174,7 +148,7 @@ mlx5_alloc_dbr_page(void *ctx)
                return NULL;
        }
        /* Register allocated memory. */
-       page->umem = mlx5_glue->devx_umem_reg(ctx, page->dbrs,
+       page->umem = mlx5_os_umem_reg(ctx, page->dbrs,
                                              MLX5_DBR_PAGE_SIZE, 0);
        if (!page->umem) {
                DRV_LOG(ERR, "cannot umem reg dbr page");
@@ -224,7 +198,7 @@ mlx5_get_dbr(void *ctx,  struct mlx5_dbr_page_list *head,
        page->dbr_bitmap[i] |= (UINT64_C(1) << j);
        page->dbr_count++;
        *dbr_page = page;
-       return (((i * 64) + j) * sizeof(uint64_t));
+       return (i * CHAR_BIT * sizeof(uint64_t) + j) * MLX5_DBR_SIZE;
 }
 
 /**
@@ -258,7 +232,7 @@ mlx5_release_dbr(struct mlx5_dbr_page_list *head, uint32_t umem_id,
                /* Page not used, free it and remove from list. */
                LIST_REMOVE(page, next);
                if (page->umem)
-                       ret = -mlx5_glue->devx_umem_dereg(page->umem);
+                       ret = -mlx5_os_umem_dereg(page->umem);
                mlx5_free(page);
        } else {
                /* Mark in bitmap that this door-bell is not in use. */
@@ -270,3 +244,102 @@ mlx5_release_dbr(struct mlx5_dbr_page_list *head, uint32_t umem_id,
        }
        return ret;
 }
+
+/**
+ * Allocate the User Access Region with DevX on specified device.
+ *
+ * @param [in] ctx
+ *   Infiniband device context to perform allocation on.
+ * @param [in] mapping
+ *   MLX5DV_UAR_ALLOC_TYPE_BF - allocate as cached memory with write-combining
+ *                             attributes (if supported by the host), the
+ *                             writes to the UAR registers must be followed
+ *                             by write memory barrier.
+ *   MLX5DV_UAR_ALLOC_TYPE_NC - allocate as non-cached nenory, all writes are
+ *                             promoted to the registers immediately, no
+ *                             memory barriers needed.
+ *   mapping < 0 - the first attempt is performed with MLX5DV_UAR_ALLOC_TYPE_BF,
+ *                if this fails the next attempt with MLX5DV_UAR_ALLOC_TYPE_NC
+ *                is performed. The drivers specifying negative values should
+ *                always provide the write memory barrier operation after UAR
+ *                register writings.
+ * If there is no definitions for the MLX5DV_UAR_ALLOC_TYPE_xx (older rdma
+ * library headers), the caller can specify 0.
+ *
+ * @return
+ *   UAR object pointer on success, NULL otherwise and rte_errno is set.
+ */
+void *
+mlx5_devx_alloc_uar(void *ctx, int mapping)
+{
+       void *uar;
+       uint32_t retry, uar_mapping;
+       void *base_addr;
+
+       for (retry = 0; retry < MLX5_ALLOC_UAR_RETRY; ++retry) {
+#ifdef MLX5DV_UAR_ALLOC_TYPE_NC
+               /* Control the mapping type according to the settings. */
+               uar_mapping = (mapping < 0) ?
+                             MLX5DV_UAR_ALLOC_TYPE_NC : mapping;
+#else
+               /*
+                * It seems we have no way to control the memory mapping type
+                * for the UAR, the default "Write-Combining" type is supposed.
+                */
+               uar_mapping = 0;
+               RTE_SET_USED(mapping);
+#endif
+               uar = mlx5_glue->devx_alloc_uar(ctx, uar_mapping);
+#ifdef MLX5DV_UAR_ALLOC_TYPE_NC
+               if (!uar &&
+                   mapping < 0 &&
+                   uar_mapping == MLX5DV_UAR_ALLOC_TYPE_BF) {
+                       /*
+                        * In some environments like virtual machine the
+                        * Write Combining mapped might be not supported and
+                        * UAR allocation fails. We tried "Non-Cached" mapping
+                        * for the case.
+                        */
+                       DRV_LOG(WARNING, "Failed to allocate DevX UAR (BF)");
+                       uar_mapping = MLX5DV_UAR_ALLOC_TYPE_NC;
+                       uar = mlx5_glue->devx_alloc_uar(ctx, uar_mapping);
+               } else if (!uar &&
+                          mapping < 0 &&
+                          uar_mapping == MLX5DV_UAR_ALLOC_TYPE_NC) {
+                       /*
+                        * If Verbs/kernel does not support "Non-Cached"
+                        * try the "Write-Combining".
+                        */
+                       DRV_LOG(WARNING, "Failed to allocate DevX UAR (NC)");
+                       uar_mapping = MLX5DV_UAR_ALLOC_TYPE_BF;
+                       uar = mlx5_glue->devx_alloc_uar(ctx, uar_mapping);
+               }
+#endif
+               if (!uar) {
+                       DRV_LOG(ERR, "Failed to allocate DevX UAR (BF/NC)");
+                       rte_errno = ENOMEM;
+                       goto exit;
+               }
+               base_addr = mlx5_os_get_devx_uar_base_addr(uar);
+               if (base_addr)
+                       break;
+               /*
+                * The UARs are allocated by rdma_core within the
+                * IB device context, on context closure all UARs
+                * will be freed, should be no memory/object leakage.
+                */
+               DRV_LOG(WARNING, "Retrying to allocate DevX UAR");
+               uar = NULL;
+       }
+       /* Check whether we finally succeeded with valid UAR allocation. */
+       if (!uar) {
+               DRV_LOG(ERR, "Failed to allocate DevX UAR (NULL base)");
+               rte_errno = ENOMEM;
+       }
+       /*
+        * Return void * instead of struct mlx5dv_devx_uar *
+        * is for compatibility with older rdma-core library headers.
+        */
+exit:
+       return uar;
+}