+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_devx_dbr_page *page = NULL;
+ uint32_t i, j;
+
+ LIST_FOREACH(page, &priv->dbrpgs, next)
+ if (page->dbr_count < MLX5_DBR_PER_PAGE)
+ break;
+ if (!page) { /* No page with free door-bell exists. */
+ page = mlx5_alloc_dbr_page(dev);
+ if (!page) /* Failed to allocate new page. */
+ return (-1);
+ LIST_INSERT_HEAD(&priv->dbrpgs, page, next);
+ }
+ /* Loop to find bitmap part with clear bit. */
+ for (i = 0;
+ i < MLX5_DBR_BITMAP_SIZE && page->dbr_bitmap[i] == UINT64_MAX;
+ i++)
+ ; /* Empty. */
+ /* Find the first clear bit. */
+ j = rte_bsf64(~page->dbr_bitmap[i]);
+ MLX5_ASSERT(i < (MLX5_DBR_PER_PAGE / 64));
+ page->dbr_bitmap[i] |= (1 << j);
+ page->dbr_count++;
+ *dbr_page = page;
+ return (((i * 64) + j) * sizeof(uint64_t));
+}
+
+/**
+ * Release a door-bell record.
+ *
+ * @param [in] dev
+ * Pointer to Ethernet device.
+ * @param [in] umem_id
+ * UMEM ID of page containing the door-bell record to release.
+ * @param [in] offset
+ * Offset of door-bell record in page.
+ *
+ * @return
+ * 0 on success, a negative error value otherwise.
+ */
+int32_t
+mlx5_release_dbr(struct rte_eth_dev *dev, uint32_t umem_id, uint64_t offset)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_devx_dbr_page *page = NULL;
+ int ret = 0;
+
+ LIST_FOREACH(page, &priv->dbrpgs, next)
+ /* Find the page this address belongs to. */
+ if (page->umem->umem_id == umem_id)
+ break;
+ if (!page)
+ return -EINVAL;
+ page->dbr_count--;
+ if (!page->dbr_count) {
+ /* Page not used, free it and remove from list. */
+ LIST_REMOVE(page, next);
+ if (page->umem)
+ ret = -mlx5_glue->devx_umem_dereg(page->umem);
+ rte_free(page);
+ } else {
+ /* Mark in bitmap that this door-bell is not in use. */
+ offset /= MLX5_DBR_SIZE;
+ int i = offset / 64;
+ int j = offset % 64;
+
+ page->dbr_bitmap[i] &= ~(1 << j);
+ }
+ return ret;
+}
+
+int
+rte_pmd_mlx5_get_dyn_flag_names(char *names[], unsigned int n)
+{
+ static const char *const dynf_names[] = {
+ RTE_PMD_MLX5_FINE_GRANULARITY_INLINE,
+ RTE_MBUF_DYNFLAG_METADATA_NAME
+ };
+ unsigned int i;
+
+ if (n < RTE_DIM(dynf_names))
+ return -ENOMEM;
+ for (i = 0; i < RTE_DIM(dynf_names); i++) {
+ if (names[i] == NULL)
+ return -EINVAL;
+ strcpy(names[i], dynf_names[i]);
+ }
+ return RTE_DIM(dynf_names);
+}
+
+/**
+ * Check sibling device configurations.
+ *
+ * Sibling devices sharing the Infiniband device context
+ * should have compatible configurations. This regards
+ * representors and bonding slaves.
+ *
+ * @param priv
+ * Private device descriptor.
+ * @param config
+ * Configuration of the device is going to be created.
+ *
+ * @return
+ * 0 on success, EINVAL otherwise
+ */
+static int
+mlx5_dev_check_sibling_config(struct mlx5_priv *priv,
+ struct mlx5_dev_config *config)
+{
+ struct mlx5_ibv_shared *sh = priv->sh;
+ struct mlx5_dev_config *sh_conf = NULL;
+ uint16_t port_id;
+
+ MLX5_ASSERT(sh);
+ /* Nothing to compare for the single/first device. */
+ if (sh->refcnt == 1)
+ return 0;
+ /* Find the device with shared context. */
+ MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) {
+ struct mlx5_priv *opriv =
+ rte_eth_devices[port_id].data->dev_private;
+
+ if (opriv && opriv != priv && opriv->sh == sh) {
+ sh_conf = &opriv->config;
+ break;
+ }
+ }
+ if (!sh_conf)
+ return 0;
+ if (sh_conf->dv_flow_en ^ config->dv_flow_en) {
+ DRV_LOG(ERR, "\"dv_flow_en\" configuration mismatch"
+ " for shared %s context", sh->ibdev_name);
+ rte_errno = EINVAL;
+ return rte_errno;
+ }
+ if (sh_conf->dv_xmeta_en ^ config->dv_xmeta_en) {
+ DRV_LOG(ERR, "\"dv_xmeta_en\" configuration mismatch"
+ " for shared %s context", sh->ibdev_name);
+ rte_errno = EINVAL;
+ return rte_errno;
+ }
+ return 0;
+}
+/**
+ * Spawn an Ethernet device from Verbs information.
+ *
+ * @param dpdk_dev
+ * Backing DPDK device.
+ * @param spawn
+ * Verbs device parameters (name, port, switch_info) to spawn.
+ * @param config
+ * Device configuration parameters.
+ *
+ * @return
+ * A valid Ethernet device object on success, NULL otherwise and rte_errno
+ * is set. The following errors are defined:
+ *
+ * EBUSY: device is not supposed to be spawned.
+ * EEXIST: device is already spawned
+ */
+static struct rte_eth_dev *
+mlx5_dev_spawn(struct rte_device *dpdk_dev,
+ struct mlx5_dev_spawn_data *spawn,
+ struct mlx5_dev_config config)
+{
+ const struct mlx5_switch_info *switch_info = &spawn->info;
+ struct mlx5_ibv_shared *sh = NULL;
+ struct ibv_port_attr port_attr;