return NULL;
}
+/**
+ * Verify and store value for devargs.
+ *
+ * @param[in] key
+ * Key argument to verify.
+ * @param[in] val
+ * Value associated with key.
+ * @param opaque
+ * User data.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+mlx5_common_args_check_handler(const char *key, const char *val, void *opaque)
+{
+ struct mlx5_common_dev_config *config = opaque;
+ signed long tmp;
+
+ errno = 0;
+ tmp = strtol(val, NULL, 0);
+ if (errno) {
+ rte_errno = errno;
+ DRV_LOG(WARNING, "%s: \"%s\" is an invalid integer.", key, val);
+ return -rte_errno;
+ }
+ if (strcmp(key, "tx_db_nc") == 0) {
+ if (tmp != MLX5_TXDB_CACHED &&
+ tmp != MLX5_TXDB_NCACHED &&
+ tmp != MLX5_TXDB_HEURISTIC) {
+ DRV_LOG(ERR, "Invalid Tx doorbell mapping parameter.");
+ rte_errno = EINVAL;
+ return -rte_errno;
+ }
+ config->dbnc = tmp;
+ } else if (strcmp(key, "mr_ext_memseg_en") == 0) {
+ config->mr_ext_memseg_en = !!tmp;
+ } else if (strcmp(key, "mr_mempool_reg_en") == 0) {
+ config->mr_mempool_reg_en = !!tmp;
+ } else if (strcmp(key, "sys_mem_en") == 0) {
+ config->sys_mem_en = !!tmp;
+ }
+ return 0;
+}
+
+/**
+ * Parse common device parameters.
+ *
+ * @param devargs
+ * Device arguments structure.
+ * @param config
+ * Pointer to device configuration structure.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+mlx5_common_config_get(struct rte_devargs *devargs,
+ struct mlx5_common_dev_config *config)
+{
+ struct rte_kvargs *kvlist;
+ int ret = 0;
+
+ /* Set defaults. */
+ config->mr_ext_memseg_en = 1;
+ config->mr_mempool_reg_en = 1;
+ config->sys_mem_en = 0;
+ config->dbnc = MLX5_ARG_UNSET;
+ if (devargs == NULL)
+ return 0;
+ kvlist = rte_kvargs_parse(devargs->args, NULL);
+ if (kvlist == NULL) {
+ rte_errno = EINVAL;
+ return -rte_errno;
+ }
+ ret = rte_kvargs_process(kvlist, NULL, mlx5_common_args_check_handler,
+ config);
+ if (ret)
+ ret = -rte_errno;
+ rte_kvargs_free(kvlist);
+ DRV_LOG(DEBUG, "mr_ext_memseg_en is %u.", config->mr_ext_memseg_en);
+ DRV_LOG(DEBUG, "mr_mempool_reg_en is %u.", config->mr_mempool_reg_en);
+ DRV_LOG(DEBUG, "sys_mem_en is %u.", config->sys_mem_en);
+ DRV_LOG(DEBUG, "Tx doorbell mapping parameter is %d.", config->dbnc);
+ return ret;
+}
+
static int
devargs_class_handler(__rte_unused const char *key,
const char *class_names, void *opaque)
static struct mlx5_common_device *
to_mlx5_device(const struct rte_device *rte_dev)
{
- struct mlx5_common_device *dev;
+ struct mlx5_common_device *cdev;
- TAILQ_FOREACH(dev, &devices_list, next) {
- if (rte_dev == dev->dev)
- return dev;
+ TAILQ_FOREACH(cdev, &devices_list, next) {
+ if (rte_dev == cdev->dev)
+ return cdev;
}
return NULL;
}
}
static void
-dev_release(struct mlx5_common_device *dev)
+mlx5_common_dev_release(struct mlx5_common_device *cdev)
+{
+ pthread_mutex_lock(&devices_list_lock);
+ TAILQ_REMOVE(&devices_list, cdev, next);
+ pthread_mutex_unlock(&devices_list_lock);
+ rte_free(cdev);
+}
+
+static struct mlx5_common_device *
+mlx5_common_dev_create(struct rte_device *eal_dev)
{
+ struct mlx5_common_device *cdev;
+ int ret;
+
+ cdev = rte_zmalloc("mlx5_common_device", sizeof(*cdev), 0);
+ if (!cdev) {
+ DRV_LOG(ERR, "Device allocation failure.");
+ rte_errno = ENOMEM;
+ return NULL;
+ }
+ cdev->dev = eal_dev;
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ goto exit;
+ /* Parse device parameters. */
+ ret = mlx5_common_config_get(eal_dev->devargs, &cdev->config);
+ if (ret < 0) {
+ DRV_LOG(ERR, "Failed to process device arguments: %s",
+ strerror(rte_errno));
+ rte_free(cdev);
+ return NULL;
+ }
+ mlx5_malloc_mem_select(cdev->config.sys_mem_en);
+exit:
pthread_mutex_lock(&devices_list_lock);
- TAILQ_REMOVE(&devices_list, dev, next);
+ TAILQ_INSERT_HEAD(&devices_list, cdev, next);
pthread_mutex_unlock(&devices_list_lock);
- rte_free(dev);
+ return cdev;
}
static int
-drivers_remove(struct mlx5_common_device *dev, uint32_t enabled_classes)
+drivers_remove(struct mlx5_common_device *cdev, uint32_t enabled_classes)
{
struct mlx5_class_driver *driver;
int local_ret = -ENODEV;
unsigned int i = 0;
int ret = 0;
- enabled_classes &= dev->classes_loaded;
+ enabled_classes &= cdev->classes_loaded;
while (enabled_classes) {
driver = driver_get(RTE_BIT64(i));
if (driver != NULL) {
- local_ret = driver->remove(dev);
+ local_ret = driver->remove(cdev);
if (local_ret == 0)
- dev->classes_loaded &= ~RTE_BIT64(i);
+ cdev->classes_loaded &= ~RTE_BIT64(i);
else if (ret == 0)
ret = local_ret;
}
}
static int
-drivers_probe(struct mlx5_common_device *dev, uint32_t user_classes)
+drivers_probe(struct mlx5_common_device *cdev, uint32_t user_classes)
{
struct mlx5_class_driver *driver;
uint32_t enabled_classes = 0;
TAILQ_FOREACH(driver, &drivers_list, next) {
if ((driver->drv_class & user_classes) == 0)
continue;
- if (!mlx5_bus_match(driver, dev->dev))
+ if (!mlx5_bus_match(driver, cdev->dev))
continue;
- already_loaded = dev->classes_loaded & driver->drv_class;
+ already_loaded = cdev->classes_loaded & driver->drv_class;
if (already_loaded && driver->probe_again == 0) {
DRV_LOG(ERR, "Device %s is already probed",
- dev->dev->name);
+ cdev->dev->name);
ret = -EEXIST;
goto probe_err;
}
- ret = driver->probe(dev);
+ ret = driver->probe(cdev);
if (ret < 0) {
DRV_LOG(ERR, "Failed to load driver %s",
driver->name);
}
enabled_classes |= driver->drv_class;
}
- dev->classes_loaded |= enabled_classes;
+ cdev->classes_loaded |= enabled_classes;
return 0;
probe_err:
/* Only unload drivers which are enabled which were enabled
* in this probe instance.
*/
- drivers_remove(dev, enabled_classes);
+ drivers_remove(cdev, enabled_classes);
return ret;
}
int
mlx5_common_dev_probe(struct rte_device *eal_dev)
{
- struct mlx5_common_device *dev;
+ struct mlx5_common_device *cdev;
uint32_t classes = 0;
bool new_device = false;
int ret;
if (classes == 0)
/* Default to net class. */
classes = MLX5_CLASS_ETH;
- dev = to_mlx5_device(eal_dev);
- if (!dev) {
- dev = rte_zmalloc("mlx5_common_device", sizeof(*dev), 0);
- if (!dev)
+ cdev = to_mlx5_device(eal_dev);
+ if (!cdev) {
+ cdev = mlx5_common_dev_create(eal_dev);
+ if (!cdev)
return -ENOMEM;
- dev->dev = eal_dev;
- pthread_mutex_lock(&devices_list_lock);
- TAILQ_INSERT_HEAD(&devices_list, dev, next);
- pthread_mutex_unlock(&devices_list_lock);
new_device = true;
}
/*
* For new device, the classes_loaded field is 0 and it check only
* the classes given as user device arguments.
*/
- ret = is_valid_class_combination(classes | dev->classes_loaded);
+ ret = is_valid_class_combination(classes | cdev->classes_loaded);
if (ret != 0) {
DRV_LOG(ERR, "Unsupported mlx5 classes combination.");
goto class_err;
}
- ret = drivers_probe(dev, classes);
+ ret = drivers_probe(cdev, classes);
if (ret)
goto class_err;
return 0;
class_err:
if (new_device)
- dev_release(dev);
+ mlx5_common_dev_release(cdev);
return ret;
}
int
mlx5_common_dev_remove(struct rte_device *eal_dev)
{
- struct mlx5_common_device *dev;
+ struct mlx5_common_device *cdev;
int ret;
- dev = to_mlx5_device(eal_dev);
- if (!dev)
+ cdev = to_mlx5_device(eal_dev);
+ if (!cdev)
return -ENODEV;
/* Matching device found, cleanup and unload drivers. */
- ret = drivers_remove(dev, dev->classes_loaded);
+ ret = drivers_remove(cdev, cdev->classes_loaded);
if (ret == 0)
- dev_release(dev);
+ mlx5_common_dev_release(cdev);
return ret;
}
* from devargs, locating target RDMA device and probing with it.
*/
+/*
+ * Device configuration structure.
+ *
+ * Merged configuration from:
+ *
+ * - Device capabilities,
+ * - User device parameters disabled features.
+ */
+struct mlx5_common_dev_config {
+ int dbnc; /* Skip doorbell register write barrier. */
+ unsigned int sys_mem_en:1; /* The default memory allocator. */
+ unsigned int mr_mempool_reg_en:1;
+ /* Allow/prevent implicit mempool memory registration. */
+ unsigned int mr_ext_memseg_en:1;
+ /* Whether memseg should be extended for MR creation. */
+};
+
struct mlx5_common_device {
struct rte_device *dev;
TAILQ_ENTRY(mlx5_common_device) next;
uint32_t classes_loaded;
+ struct mlx5_common_dev_config config; /* Device configuration. */
};
/**
* @param sys_mem_en
* Use system memory or not.
*/
-__rte_internal
void mlx5_malloc_mem_select(uint32_t sys_mem_en);
/**
mlx5_hlist_destroy;
mlx5_malloc;
- mlx5_malloc_mem_select;
mlx5_memory_stat_dump; # WINDOWS_NO_EXPORT
(const struct mlx5_mp_param *)mp_msg->param;
struct rte_eth_dev *dev;
struct mlx5_priv *priv;
+ struct mlx5_common_device *cdev;
struct mr_cache_entry entry;
uint32_t lkey;
int ret;
}
dev = &rte_eth_devices[param->port_id];
priv = dev->data->dev_private;
+ cdev = priv->sh->cdev;
switch (param->type) {
case MLX5_MP_REQ_CREATE_MR:
mp_init_msg(&priv->mp_id, &mp_res, param->type);
lkey = mlx5_mr_create_primary(priv->sh->pd,
&priv->sh->share_cache,
&entry, param->args.addr,
- priv->config.mr_ext_memseg_en);
+ cdev->config.mr_ext_memseg_en);
if (lkey == UINT32_MAX)
res->result = -rte_errno;
ret = rte_mp_reply(&mp_res, peer);
if (switch_info->master || switch_info->representor)
config->dv_xmeta_en = MLX5_XMETA_MODE_META16;
}
- mlx5_malloc_mem_select(config->sys_mem_en);
sh = mlx5_alloc_shared_dev_ctx(spawn, config);
if (!sh)
return NULL;
{
memset(config, 0, sizeof(*config));
config->mps = MLX5_ARG_UNSET;
- config->dbnc = MLX5_ARG_UNSET;
config->rx_vec_en = 1;
config->txq_inline_max = MLX5_ARG_UNSET;
config->txq_inline_min = MLX5_ARG_UNSET;
config->txq_inline_mpw = MLX5_ARG_UNSET;
config->txqs_inline = MLX5_ARG_UNSET;
config->vf_nl_en = 1;
- config->mr_ext_memseg_en = 1;
- config->mr_mempool_reg_en = 1;
config->mprq.max_memcpy_len = MLX5_MPRQ_MEMCPY_DEFAULT_LEN;
config->mprq.min_rxqs_num = MLX5_MPRQ_MIN_RXQS;
config->dv_esw_en = 1;
}
static int
-mlx5_config_doorbell_mapping_env(const struct mlx5_dev_config *config)
+mlx5_config_doorbell_mapping_env(const struct mlx5_common_dev_config *config)
{
char *env;
int value;
*
* @param[in] spawn
* Pointer to the IB device attributes (name, port, etc).
- * @param[out] config
- * Pointer to device configuration structure.
* @param[out] sh
* Pointer to shared context structure.
*
*/
int
mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
- const struct mlx5_dev_config *config,
struct mlx5_dev_ctx_shared *sh)
{
int dbmap_env;
* checks the variable at device creation and
* stores the result internally.
*/
- dbmap_env = mlx5_config_doorbell_mapping_env(config);
+ dbmap_env = mlx5_config_doorbell_mapping_env(&spawn->cdev->config);
/* Try to open IB device with DV first, then usual Verbs. */
errno = 0;
sh->ctx = mlx5_glue->dv_open_device(spawn->phys_dev);
*/
static int
mlx5_alloc_rxtx_uars(struct mlx5_dev_ctx_shared *sh,
- const struct mlx5_dev_config *config)
+ const struct mlx5_common_dev_config *config)
{
uint32_t uar_mapping, retry;
int err = 0;
int ret;
/* Check if we only need to track Rx mempool destruction. */
- if (!priv->config.mr_mempool_reg_en) {
+ if (!sh->cdev->config.mr_mempool_reg_en) {
ret = rte_mempool_event_callback_register
(mlx5_dev_ctx_shared_rx_mempool_event_cb, sh);
return ret == 0 || rte_errno == EEXIST ? 0 : ret;
sh->cdev = spawn->cdev;
if (spawn->bond_info)
sh->bond = *spawn->bond_info;
- err = mlx5_os_open_device(spawn, config, sh);
+ err = mlx5_os_open_device(spawn, sh);
if (!sh->ctx)
goto error;
err = mlx5_os_get_dev_attr(sh->ctx, &sh->device_attr);
err = ENOMEM;
goto error;
}
- err = mlx5_alloc_rxtx_uars(sh, config);
+ err = mlx5_alloc_rxtx_uars(sh, &sh->cdev->config);
if (err)
goto error;
MLX5_ASSERT(sh->tx_uar);
signed long tmp;
/* No-op, port representors are processed in mlx5_dev_spawn(). */
- if (!strcmp(MLX5_DRIVER_KEY, key) || !strcmp(MLX5_REPRESENTOR, key))
+ if (!strcmp(MLX5_DRIVER_KEY, key) || !strcmp(MLX5_REPRESENTOR, key) ||
+ !strcmp(MLX5_SYS_MEM_EN, key) || !strcmp(MLX5_TX_DB_NC, key) ||
+ !strcmp(MLX5_MR_MEMPOOL_REG_EN, key) ||
+ !strcmp(MLX5_MR_EXT_MEMSEG_EN, key))
return 0;
errno = 0;
tmp = strtol(val, NULL, 0);
DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key);
} else if (strcmp(MLX5_TXQ_MPW_EN, key) == 0) {
config->mps = !!tmp;
- } else if (strcmp(MLX5_TX_DB_NC, key) == 0) {
- if (tmp != MLX5_TXDB_CACHED &&
- tmp != MLX5_TXDB_NCACHED &&
- tmp != MLX5_TXDB_HEURISTIC) {
- DRV_LOG(ERR, "invalid Tx doorbell "
- "mapping parameter");
- rte_errno = EINVAL;
- return -rte_errno;
- }
- config->dbnc = tmp;
} else if (strcmp(MLX5_TXQ_MPW_HDR_DSEG_EN, key) == 0) {
DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key);
} else if (strcmp(MLX5_TXQ_MAX_INLINE_LEN, key) == 0) {
config->dv_miss_info = 1;
} else if (strcmp(MLX5_LACP_BY_USER, key) == 0) {
config->lacp_by_user = !!tmp;
- } else if (strcmp(MLX5_MR_EXT_MEMSEG_EN, key) == 0) {
- config->mr_ext_memseg_en = !!tmp;
} else if (strcmp(MLX5_MAX_DUMP_FILES_NUM, key) == 0) {
config->max_dump_files_num = tmp;
} else if (strcmp(MLX5_LRO_TIMEOUT_USEC, key) == 0) {
return -rte_errno;
}
config->reclaim_mode = tmp;
- } else if (strcmp(MLX5_SYS_MEM_EN, key) == 0) {
- config->sys_mem_en = !!tmp;
} else if (strcmp(MLX5_DECAP_EN, key) == 0) {
config->decap_en = !!tmp;
} else if (strcmp(MLX5_ALLOW_DUPLICATE_PATTERN, key) == 0) {
config->allow_duplicate_pattern = !!tmp;
- } else if (strcmp(MLX5_MR_MEMPOOL_REG_EN, key) == 0) {
- config->mr_mempool_reg_en = !!tmp;
} else {
DRV_LOG(WARNING, "%s: unknown parameter", key);
rte_errno = EINVAL;
unsigned int cqe_comp_fmt:3; /* CQE compression format. */
unsigned int tso:1; /* Whether TSO is supported. */
unsigned int rx_vec_en:1; /* Rx vector is enabled. */
- unsigned int mr_ext_memseg_en:1;
- /* Whether memseg should be extended for MR creation. */
unsigned int l3_vxlan_en:1; /* Enable L3 VXLAN flow creation. */
unsigned int vf_nl_en:1; /* Enable Netlink requests in VF mode. */
unsigned int dv_esw_en:1; /* Enable E-Switch DV flow. */
unsigned int dest_tir:1; /* Whether advanced DR API is available. */
unsigned int reclaim_mode:2; /* Memory reclaim mode. */
unsigned int rt_timestamp:1; /* realtime timestamp format. */
- unsigned int sys_mem_en:1; /* The default memory allocator. */
unsigned int decap_en:1; /* Whether decap will be used or not. */
unsigned int dv_miss_info:1; /* restore packet after partial hw miss */
unsigned int allow_duplicate_pattern:1;
/* Allow/Prevent the duplicate rules pattern. */
- unsigned int mr_mempool_reg_en:1;
- /* Allow/prevent implicit mempool memory registration. */
struct {
unsigned int enabled:1; /* Whether MPRQ is enabled. */
unsigned int stride_num_n; /* Number of strides. */
/* Rx queue count threshold to enable MPRQ. */
} mprq; /* Configurations for Multi-Packet RQ. */
int mps; /* Multi-packet send supported mode. */
- int dbnc; /* Skip doorbell register write barrier. */
unsigned int flow_prio; /* Number of flow priorities. */
enum modify_reg flow_mreg_c[MLX5_MREG_C_NUM];
/* Availibility of mreg_c's. */
int mlx5_os_get_dev_attr(void *ctx, struct mlx5_dev_attr *dev_attr);
void mlx5_os_free_shared_dr(struct mlx5_priv *priv);
int mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
- const struct mlx5_dev_config *config,
struct mlx5_dev_ctx_shared *sh);
int mlx5_os_get_pdn(void *pd, uint32_t *pdn);
int mlx5_os_net_probe(struct mlx5_common_device *cdev);
return mlx5_mr_addr2mr_bh(priv->sh->pd, &priv->mp_id,
&priv->sh->share_cache, mr_ctrl, addr,
- priv->config.mr_ext_memseg_en);
+ priv->sh->cdev->config.mr_ext_memseg_en);
}
/**
uintptr_t addr = (uintptr_t)mb->buf_addr;
uint32_t lkey;
- if (priv->config.mr_mempool_reg_en) {
+ if (priv->sh->cdev->config.mr_mempool_reg_en) {
struct rte_mempool *mp = NULL;
struct mlx5_mprq_buf *buf;
mlx5_mr_insert_cache(&sh->share_cache, mr);
rte_rwlock_write_unlock(&sh->share_cache.rwlock);
/* Insert to the local cache table */
- mlx5_mr_addr2mr_bh(sh->pd, &priv->mp_id, &sh->share_cache,
- mr_ctrl, addr, priv->config.mr_ext_memseg_en);
+ mlx5_mr_addr2mr_bh(sh->pd, &priv->mp_id, &sh->share_cache, mr_ctrl,
+ addr, priv->sh->cdev->config.mr_ext_memseg_en);
}
/**
static void
txq_uar_ncattr_init(struct mlx5_txq_ctrl *txq_ctrl, size_t page_size)
{
- struct mlx5_priv *priv = txq_ctrl->priv;
+ struct mlx5_common_device *cdev = txq_ctrl->priv->sh->cdev;
off_t cmd;
- txq_ctrl->txq.db_heu = priv->config.dbnc == MLX5_TXDB_HEURISTIC;
+ txq_ctrl->txq.db_heu = cdev->config.dbnc == MLX5_TXDB_HEURISTIC;
txq_ctrl->txq.db_nc = 0;
/* Check the doorbell register mapping type. */
cmd = txq_ctrl->uar_mmap_offset / page_size;
*
* @param[in] spawn
* Pointer to the device attributes (name, port, etc).
- * @param[out] config
- * Pointer to device configuration structure.
* @param[out] sh
* Pointer to shared context structure.
*
*/
int
mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
- const struct mlx5_dev_config *config,
struct mlx5_dev_ctx_shared *sh)
{
- RTE_SET_USED(config);
int err = 0;
struct mlx5_context *mlx5_ctx;
strerror(rte_errno));
goto error;
}
- mlx5_malloc_mem_select(config->sys_mem_en);
sh = mlx5_alloc_shared_dev_ctx(spawn, config);
if (!sh)
return NULL;
memset(&dev_config, 0, sizeof(struct mlx5_dev_config));
dev_config.vf = dev_config_vf;
dev_config.mps = 0;
- dev_config.dbnc = MLX5_ARG_UNSET;
dev_config.rx_vec_en = 1;
dev_config.txq_inline_max = MLX5_ARG_UNSET;
dev_config.txq_inline_min = MLX5_ARG_UNSET;
dev_config.txq_inline_mpw = MLX5_ARG_UNSET;
dev_config.txqs_inline = MLX5_ARG_UNSET;
dev_config.vf_nl_en = 0;
- dev_config.mr_ext_memseg_en = 1;
- dev_config.mr_mempool_reg_en = 1;
dev_config.mprq.max_memcpy_len = MLX5_MPRQ_MEMCPY_DEFAULT_LEN;
dev_config.mprq.min_rxqs_num = MLX5_MPRQ_MIN_RXQS;
dev_config.dv_esw_en = 0;