common/mlx5: share device context object
[dpdk.git] / drivers / common / mlx5 / linux / mlx5_common_os.c
index ea0b71e..1589212 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "mlx5_common.h"
 #include "mlx5_common_log.h"
+#include "mlx5_common_defs.h"
 #include "mlx5_common_os.h"
 #include "mlx5_glue.h"
 
 const struct mlx5_glue *mlx5_glue;
 #endif
 
-/**
- * Get PCI information by sysfs device path.
- *
- * @param dev_path
- *   Pointer to device sysfs folder name.
- * @param[out] pci_addr
- *   PCI bus address output buffer.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
 int
-mlx5_dev_to_pci_addr(const char *dev_path,
-                    struct rte_pci_addr *pci_addr)
+mlx5_get_pci_addr(const char *dev_path, struct rte_pci_addr *pci_addr)
 {
        FILE *file;
        char line[32];
@@ -159,17 +148,6 @@ mlx5_translate_port_name(const char *port_name_in,
        port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN;
 }
 
-/**
- * Get kernel interface name from IB device path.
- *
- * @param[in] ibdev_path
- *   Pointer to IB device path.
- * @param[out] ifname
- *   Interface name output buffer.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
 int
 mlx5_get_ifname_sysfs(const char *ibdev_path, char *ifname)
 {
@@ -425,7 +403,7 @@ glue_error:
 }
 
 struct ibv_device *
-mlx5_os_get_ibv_device(struct rte_pci_addr *addr)
+mlx5_os_get_ibv_device(const struct rte_pci_addr *addr)
 {
        int n;
        struct ibv_device **ibv_list = mlx5_glue->get_device_list(&n);
@@ -439,15 +417,107 @@ mlx5_os_get_ibv_device(struct rte_pci_addr *addr)
                struct rte_pci_addr paddr;
 
                DRV_LOG(DEBUG, "Checking device \"%s\"..", ibv_list[n]->name);
-               if (mlx5_dev_to_pci_addr(ibv_list[n]->ibdev_path, &paddr) != 0)
+               if (mlx5_get_pci_addr(ibv_list[n]->ibdev_path, &paddr) != 0)
                        continue;
                if (rte_pci_addr_cmp(addr, &paddr) != 0)
                        continue;
                ibv_match = ibv_list[n];
                break;
        }
-       if (ibv_match == NULL)
+       if (ibv_match == NULL) {
+               DRV_LOG(WARNING,
+                       "No Verbs device matches PCI device " PCI_PRI_FMT ","
+                       " are kernel drivers loaded?",
+                       addr->domain, addr->bus, addr->devid, addr->function);
                rte_errno = ENOENT;
+       }
        mlx5_glue->free_device_list(ibv_list);
        return ibv_match;
 }
+
+static int
+mlx5_config_doorbell_mapping_env(int dbnc)
+{
+       char *env;
+       int value;
+
+       MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
+       /* Get environment variable to store. */
+       env = getenv(MLX5_SHUT_UP_BF);
+       value = env ? !!strcmp(env, "0") : MLX5_ARG_UNSET;
+       if (dbnc == MLX5_ARG_UNSET)
+               setenv(MLX5_SHUT_UP_BF, MLX5_SHUT_UP_BF_DEFAULT, 1);
+       else
+               setenv(MLX5_SHUT_UP_BF,
+                      dbnc == MLX5_TXDB_NCACHED ? "1" : "0", 1);
+       return value;
+}
+
+static void
+mlx5_restore_doorbell_mapping_env(int value)
+{
+       MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
+       /* Restore the original environment variable state. */
+       if (value == MLX5_ARG_UNSET)
+               unsetenv(MLX5_SHUT_UP_BF);
+       else
+               setenv(MLX5_SHUT_UP_BF, value ? "1" : "0", 1);
+}
+
+/**
+ * Function API to open IB device.
+ *
+ *
+ * @param cdev
+ *   Pointer to the mlx5 device.
+ * @param classes
+ *   Chosen classes come from device arguments.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_os_open_device(struct mlx5_common_device *cdev, uint32_t classes)
+{
+       struct ibv_device *ibv;
+       struct ibv_context *ctx = NULL;
+       int dbmap_env;
+
+       ibv = mlx5_os_get_ibv_dev(cdev->dev);
+       if (!ibv)
+               return -rte_errno;
+       DRV_LOG(INFO, "Dev information matches for device \"%s\".", ibv->name);
+       /*
+        * Configure environment variable "MLX5_BF_SHUT_UP" before the device
+        * creation. The rdma_core library checks the variable at device
+        * creation and stores the result internally.
+        */
+       dbmap_env = mlx5_config_doorbell_mapping_env(cdev->config.dbnc);
+       /* Try to open IB device with DV first, then usual Verbs. */
+       errno = 0;
+       ctx = mlx5_glue->dv_open_device(ibv);
+       if (ctx) {
+               cdev->config.devx = 1;
+               DRV_LOG(DEBUG, "DevX is supported.");
+       } else if (classes == MLX5_CLASS_ETH) {
+               /* The environment variable is still configured. */
+               ctx = mlx5_glue->open_device(ibv);
+               if (ctx == NULL)
+                       goto error;
+               DRV_LOG(DEBUG, "DevX is NOT supported.");
+       } else {
+               goto error;
+       }
+       /* The device is created, no need for environment. */
+       mlx5_restore_doorbell_mapping_env(dbmap_env);
+       /* Hint libmlx5 to use PMD allocator for data plane resources */
+       mlx5_set_context_attr(cdev->dev, ctx);
+       cdev->ctx = ctx;
+       return 0;
+error:
+       rte_errno = errno ? errno : ENODEV;
+       /* The device creation is failed, no need for environment. */
+       mlx5_restore_doorbell_mapping_env(dbmap_env);
+       DRV_LOG(ERR, "Failed to open IB device \"%s\".", ibv->name);
+       return -rte_errno;
+}