X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5.c;h=0528ed35e206827b01122519f25c073241813abe;hb=62e3ccc2b94c625d4b3ce55044b135c4ab0793db;hp=237d05bc77a608163ab19ee215cdd21c1e951bf1;hpb=5382d28c2110ceac10051e32a0be97bb59b82555;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index 237d05bc77..0528ed35e2 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -32,11 +32,11 @@ #include #include #include -#include #include #include #include #include +#include #include "mlx5.h" #include "mlx5_utils.h" @@ -68,9 +68,18 @@ /* Device parameter to set the minimum number of Rx queues to enable MPRQ. */ #define MLX5_RXQS_MIN_MPRQ "rxqs_min_mprq" -/* Device parameter to configure inline send. */ +/* Device parameter to configure inline send. Deprecated, ignored.*/ #define MLX5_TXQ_INLINE "txq_inline" +/* Device parameter to limit packet size to inline with ordinary SEND. */ +#define MLX5_TXQ_INLINE_MAX "txq_inline_max" + +/* Device parameter to configure minimal data size to inline. */ +#define MLX5_TXQ_INLINE_MIN "txq_inline_min" + +/* Device parameter to limit packet size to inline with Enhanced MPW. */ +#define MLX5_TXQ_INLINE_MPW "txq_inline_mpw" + /* * Device parameter to configure the number of TX queues threshold for * enabling inline send. @@ -79,20 +88,29 @@ /* * Device parameter to configure the number of TX queues threshold for - * enabling vectorized Tx. + * enabling vectorized Tx, deprecated, ignored (no vectorized Tx routines). */ #define MLX5_TXQS_MAX_VEC "txqs_max_vec" /* Device parameter to enable multi-packet send WQEs. */ #define MLX5_TXQ_MPW_EN "txq_mpw_en" -/* Device parameter to include 2 dsegs in the title WQEBB. */ +/* + * Device parameter to include 2 dsegs in the title WQEBB. + * Deprecated, ignored. + */ #define MLX5_TXQ_MPW_HDR_DSEG_EN "txq_mpw_hdr_dseg_en" -/* Device parameter to limit the size of inlining packet. */ +/* + * Device parameter to limit the size of inlining packet. + * Deprecated, ignored. + */ #define MLX5_TXQ_MAX_INLINE_LEN "txq_max_inline_len" -/* Device parameter to enable hardware Tx vector. */ +/* + * Device parameter to enable hardware Tx vector. + * Deprecated, ignored (no vectorized Tx routines anymore). + */ #define MLX5_TX_VEC_EN "tx_vec_en" /* Device parameter to enable hardware Rx vector. */ @@ -119,6 +137,9 @@ /* Device parameter to configure the maximum number of dump files per queue. */ #define MLX5_MAX_DUMP_FILES_NUM "max_dump_files_num" +/* Configure timeout of LRO session (in microseconds). */ +#define MLX5_LRO_TIMEOUT_USEC "lro_timeout_usec" + #ifndef HAVE_IBV_MLX5_MOD_MPW #define MLX5DV_CONTEXT_FLAGS_MPW_ALLOWED (1 << 2) #define MLX5DV_CONTEXT_FLAGS_ENHANCED_MPW (1 << 3) @@ -201,7 +222,15 @@ mlx5_flow_counters_mng_close(struct mlx5_ibv_shared *sh) struct mlx5_counter_stats_mem_mng *mng; uint8_t i; int j; + int retries = 1024; + rte_errno = 0; + while (--retries) { + rte_eal_alarm_cancel(mlx5_flow_query_alarm, sh); + if (rte_errno != EINPROGRESS) + break; + rte_pause(); + } for (i = 0; i < RTE_DIM(sh->cmng.ccont); ++i) { struct mlx5_flow_counter_pool *pool; uint32_t batch = !!(i % 2); @@ -239,6 +268,37 @@ mlx5_flow_counters_mng_close(struct mlx5_ibv_shared *sh) memset(&sh->cmng, 0, sizeof(sh->cmng)); } +/** + * Extract pdn of PD object using DV API. + * + * @param[in] pd + * Pointer to the verbs PD object. + * @param[out] pdn + * Pointer to the PD object number variable. + * + * @return + * 0 on success, error value otherwise. + */ +#ifdef HAVE_IBV_FLOW_DV_SUPPORT +static int +mlx5_get_pdn(struct ibv_pd *pd __rte_unused, uint32_t *pdn __rte_unused) +{ + struct mlx5dv_obj obj; + struct mlx5dv_pd pd_info; + int ret = 0; + + obj.pd.in = pd; + obj.pd.out = &pd_info; + ret = mlx5_glue->dv_init_obj(&obj, MLX5DV_OBJ_PD); + if (ret) { + DRV_LOG(DEBUG, "Fail to get PD object info"); + return ret; + } + *pdn = pd_info.pdn; + return 0; +} +#endif /* HAVE_IBV_FLOW_DV_SUPPORT */ + /** * Allocate shared IB device context. If there is multiport device the * master and representors will share this context, if there is single @@ -327,6 +387,13 @@ mlx5_alloc_shared_ibctx(const struct mlx5_dev_spawn_data *spawn) err = ENOMEM; goto error; } +#ifdef HAVE_IBV_FLOW_DV_SUPPORT + err = mlx5_get_pdn(sh->pd, &sh->pdn); + if (err) { + DRV_LOG(ERR, "Fail to extract pdn from PD"); + goto error; + } +#endif /* HAVE_IBV_FLOW_DV_SUPPORT */ /* * Once the device is added to the list of memory event * callback, its global MR cache table cannot be expanded @@ -344,6 +411,12 @@ mlx5_alloc_shared_ibctx(const struct mlx5_dev_spawn_data *spawn) goto error; } mlx5_flow_counters_mng_init(sh); + /* Add device to memory callback list. */ + rte_rwlock_write_lock(&mlx5_shared_data->mem_event_rwlock); + LIST_INSERT_HEAD(&mlx5_shared_data->mem_event_cb_list, + sh, mem_event_cb); + rte_rwlock_write_unlock(&mlx5_shared_data->mem_event_rwlock); + /* Add context to the global device list. */ LIST_INSERT_HEAD(&mlx5_ibv_list, sh, next); exit: pthread_mutex_unlock(&mlx5_ibv_list_mutex); @@ -393,6 +466,11 @@ mlx5_free_shared_ibctx(struct mlx5_ibv_shared *sh) goto exit; /* Release created Memory Regions. */ mlx5_mr_release(sh); + /* Remove from memory callback device list. */ + rte_rwlock_write_lock(&mlx5_shared_data->mem_event_rwlock); + LIST_REMOVE(sh, mem_event_cb); + rte_rwlock_write_unlock(&mlx5_shared_data->mem_event_rwlock); + /* Remove context from the global device list. */ LIST_REMOVE(sh, next); /* * Ensure there is no async event handler installed. @@ -470,6 +548,7 @@ mlx5_alloc_shared_dr(struct mlx5_priv *priv) sh->esw_drop_action = mlx5_glue->dr_create_flow_action_drop(); } #endif + sh->pop_vlan_action = mlx5_glue->dr_create_flow_action_pop_vlan(); sh->dv_refcnt++; priv->dr_shared = 1; return 0; @@ -492,6 +571,10 @@ error: mlx5_glue->destroy_flow_action(sh->esw_drop_action); sh->esw_drop_action = NULL; } + if (sh->pop_vlan_action) { + mlx5_glue->destroy_flow_action(sh->pop_vlan_action); + sh->pop_vlan_action = NULL; + } return err; #else (void)priv; @@ -537,6 +620,10 @@ mlx5_free_shared_dr(struct mlx5_priv *priv) sh->esw_drop_action = NULL; } #endif + if (sh->pop_vlan_action) { + mlx5_glue->destroy_flow_action(sh->pop_vlan_action); + sh->pop_vlan_action = NULL; + } pthread_mutex_destroy(&sh->dv_mutex); #else (void)priv; @@ -665,6 +752,31 @@ mlx5_free_verbs_buf(void *ptr, void *data __rte_unused) rte_free(ptr); } +/** + * DPDK callback to add udp tunnel port + * + * @param[in] dev + * A pointer to eth_dev + * @param[in] udp_tunnel + * A pointer to udp tunnel + * + * @return + * 0 on valid udp ports and tunnels, -ENOTSUP otherwise. + */ +int +mlx5_udp_tunnel_port_add(struct rte_eth_dev *dev __rte_unused, + struct rte_eth_udp_tunnel *udp_tunnel) +{ + assert(udp_tunnel != NULL); + if (udp_tunnel->prot_type == RTE_TUNNEL_TYPE_VXLAN && + udp_tunnel->udp_port == 4789) + return 0; + if (udp_tunnel->prot_type == RTE_TUNNEL_TYPE_VXLAN_GPE && + udp_tunnel->udp_port == 4790) + return 0; + return -ENOTSUP; +} + /** * Initialize process private data structure. * @@ -759,11 +871,6 @@ mlx5_dev_close(struct rte_eth_dev *dev) } mlx5_proc_priv_uninit(dev); mlx5_mprq_free_mp(dev); - /* Remove from memory callback device list. */ - rte_rwlock_write_lock(&mlx5_shared_data->mem_event_rwlock); - assert(priv->sh); - LIST_REMOVE(priv->sh, mem_event_cb); - rte_rwlock_write_unlock(&mlx5_shared_data->mem_event_rwlock); mlx5_free_shared_dr(priv); if (priv->rss_conf.rss_key != NULL) rte_free(priv->rss_conf.rss_key); @@ -775,6 +882,8 @@ mlx5_dev_close(struct rte_eth_dev *dev) close(priv->nl_socket_route); if (priv->nl_socket_rdma >= 0) close(priv->nl_socket_rdma); + if (priv->vmwa_context) + mlx5_vlan_vmwa_exit(priv->vmwa_context); if (priv->sh) { /* * Free the shared context in last turn, because the cleanup @@ -785,17 +894,17 @@ mlx5_dev_close(struct rte_eth_dev *dev) mlx5_free_shared_ibctx(priv->sh); priv->sh = NULL; } - ret = mlx5_hrxq_ibv_verify(dev); + ret = mlx5_hrxq_verify(dev); if (ret) DRV_LOG(WARNING, "port %u some hash Rx queue still remain", dev->data->port_id); - ret = mlx5_ind_table_ibv_verify(dev); + ret = mlx5_ind_table_obj_verify(dev); if (ret) DRV_LOG(WARNING, "port %u some indirection table still remain", dev->data->port_id); - ret = mlx5_rxq_ibv_verify(dev); + ret = mlx5_rxq_obj_verify(dev); if (ret) - DRV_LOG(WARNING, "port %u some Verbs Rx queue still remain", + DRV_LOG(WARNING, "port %u some Rx queue objects still remain", dev->data->port_id); ret = mlx5_rxq_verify(dev); if (ret) @@ -886,6 +995,9 @@ const struct eth_dev_ops mlx5_dev_ops = { .rx_queue_intr_enable = mlx5_rx_intr_enable, .rx_queue_intr_disable = mlx5_rx_intr_disable, .is_removed = mlx5_is_removed, + .udp_tunnel_port_add = mlx5_udp_tunnel_port_add, + .get_module_info = mlx5_get_module_info, + .get_module_eeprom = mlx5_get_module_eeprom, }; /* Available operations from secondary process. */ @@ -899,6 +1011,8 @@ static const struct eth_dev_ops mlx5_dev_sec_ops = { .dev_infos_get = mlx5_dev_infos_get, .rx_descriptor_status = mlx5_rx_descriptor_status, .tx_descriptor_status = mlx5_tx_descriptor_status, + .get_module_info = mlx5_get_module_info, + .get_module_eeprom = mlx5_get_module_eeprom, }; /* Available operations in flow isolated mode. */ @@ -942,6 +1056,8 @@ const struct eth_dev_ops mlx5_dev_ops_isolate = { .rx_queue_intr_enable = mlx5_rx_intr_enable, .rx_queue_intr_disable = mlx5_rx_intr_disable, .is_removed = mlx5_is_removed, + .get_module_info = mlx5_get_module_info, + .get_module_eeprom = mlx5_get_module_eeprom, }; /** @@ -988,19 +1104,29 @@ mlx5_args_check(const char *key, const char *val, void *opaque) } else if (strcmp(MLX5_RXQS_MIN_MPRQ, key) == 0) { config->mprq.min_rxqs_num = tmp; } else if (strcmp(MLX5_TXQ_INLINE, key) == 0) { - config->txq_inline = tmp; + DRV_LOG(WARNING, "%s: deprecated parameter," + " converted to txq_inline_max", key); + config->txq_inline_max = tmp; + } else if (strcmp(MLX5_TXQ_INLINE_MAX, key) == 0) { + config->txq_inline_max = tmp; + } else if (strcmp(MLX5_TXQ_INLINE_MIN, key) == 0) { + config->txq_inline_min = tmp; + } else if (strcmp(MLX5_TXQ_INLINE_MPW, key) == 0) { + config->txq_inline_mpw = tmp; } else if (strcmp(MLX5_TXQS_MIN_INLINE, key) == 0) { config->txqs_inline = tmp; } else if (strcmp(MLX5_TXQS_MAX_VEC, key) == 0) { - config->txqs_vec = tmp; + DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key); } else if (strcmp(MLX5_TXQ_MPW_EN, key) == 0) { config->mps = !!tmp; } else if (strcmp(MLX5_TXQ_MPW_HDR_DSEG_EN, key) == 0) { - config->mpw_hdr_dseg = !!tmp; + DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key); } else if (strcmp(MLX5_TXQ_MAX_INLINE_LEN, key) == 0) { - config->inline_max_packet_sz = tmp; + DRV_LOG(WARNING, "%s: deprecated parameter," + " converted to txq_inline_mpw", key); + config->txq_inline_mpw = tmp; } else if (strcmp(MLX5_TX_VEC_EN, key) == 0) { - config->tx_vec_en = !!tmp; + DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key); } else if (strcmp(MLX5_RX_VEC_EN, key) == 0) { config->rx_vec_en = !!tmp; } else if (strcmp(MLX5_L3_VXLAN_EN, key) == 0) { @@ -1015,6 +1141,8 @@ mlx5_args_check(const char *key, const char *val, void *opaque) 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) { + config->lro.timeout = tmp; } else { DRV_LOG(WARNING, "%s: unknown parameter", key); rte_errno = EINVAL; @@ -1046,6 +1174,9 @@ mlx5_args(struct mlx5_dev_config *config, struct rte_devargs *devargs) MLX5_RX_MPRQ_MAX_MEMCPY_LEN, MLX5_RXQS_MIN_MPRQ, MLX5_TXQ_INLINE, + MLX5_TXQ_INLINE_MIN, + MLX5_TXQ_INLINE_MAX, + MLX5_TXQ_INLINE_MPW, MLX5_TXQS_MIN_INLINE, MLX5_TXQS_MAX_VEC, MLX5_TXQ_MPW_EN, @@ -1060,6 +1191,7 @@ mlx5_args(struct mlx5_dev_config *config, struct rte_devargs *devargs) MLX5_MR_EXT_MEMSEG_EN, MLX5_REPRESENTOR, MLX5_MAX_DUMP_FILES_NUM, + MLX5_LRO_TIMEOUT_USEC, NULL, }; struct rte_kvargs *kvlist; @@ -1144,6 +1276,246 @@ out: return ret; } +/** + * Configures the minimal amount of data to inline into WQE + * while sending packets. + * + * - the txq_inline_min has the maximal priority, if this + * key is specified in devargs + * - if DevX is enabled the inline mode is queried from the + * device (HCA attributes and NIC vport context if needed). + * - otherwise L2 mode (18 bytes) is assumed for ConnectX-4/4LX + * and none (0 bytes) for other NICs + * + * @param spawn + * Verbs device parameters (name, port, switch_info) to spawn. + * @param config + * Device configuration parameters. + */ +static void +mlx5_set_min_inline(struct mlx5_dev_spawn_data *spawn, + struct mlx5_dev_config *config) +{ + if (config->txq_inline_min != MLX5_ARG_UNSET) { + /* Application defines size of inlined data explicitly. */ + switch (spawn->pci_dev->id.device_id) { + case PCI_DEVICE_ID_MELLANOX_CONNECTX4: + case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF: + if (config->txq_inline_min < + (int)MLX5_INLINE_HSIZE_L2) { + DRV_LOG(DEBUG, + "txq_inline_mix aligned to minimal" + " ConnectX-4 required value %d", + (int)MLX5_INLINE_HSIZE_L2); + config->txq_inline_min = MLX5_INLINE_HSIZE_L2; + } + break; + } + goto exit; + } + if (config->hca_attr.eth_net_offloads) { + /* We have DevX enabled, inline mode queried successfully. */ + switch (config->hca_attr.wqe_inline_mode) { + case MLX5_CAP_INLINE_MODE_L2: + /* outer L2 header must be inlined. */ + config->txq_inline_min = MLX5_INLINE_HSIZE_L2; + goto exit; + case MLX5_CAP_INLINE_MODE_NOT_REQUIRED: + /* No inline data are required by NIC. */ + config->txq_inline_min = MLX5_INLINE_HSIZE_NONE; + config->hw_vlan_insert = + config->hca_attr.wqe_vlan_insert; + DRV_LOG(DEBUG, "Tx VLAN insertion is supported"); + goto exit; + case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT: + /* inline mode is defined by NIC vport context. */ + if (!config->hca_attr.eth_virt) + break; + switch (config->hca_attr.vport_inline_mode) { + case MLX5_INLINE_MODE_NONE: + config->txq_inline_min = + MLX5_INLINE_HSIZE_NONE; + goto exit; + case MLX5_INLINE_MODE_L2: + config->txq_inline_min = + MLX5_INLINE_HSIZE_L2; + goto exit; + case MLX5_INLINE_MODE_IP: + config->txq_inline_min = + MLX5_INLINE_HSIZE_L3; + goto exit; + case MLX5_INLINE_MODE_TCP_UDP: + config->txq_inline_min = + MLX5_INLINE_HSIZE_L4; + goto exit; + case MLX5_INLINE_MODE_INNER_L2: + config->txq_inline_min = + MLX5_INLINE_HSIZE_INNER_L2; + goto exit; + case MLX5_INLINE_MODE_INNER_IP: + config->txq_inline_min = + MLX5_INLINE_HSIZE_INNER_L3; + goto exit; + case MLX5_INLINE_MODE_INNER_TCP_UDP: + config->txq_inline_min = + MLX5_INLINE_HSIZE_INNER_L4; + goto exit; + } + } + } + /* + * We get here if we are unable to deduce + * inline data size with DevX. Try PCI ID + * to determine old NICs. + */ + switch (spawn->pci_dev->id.device_id) { + case PCI_DEVICE_ID_MELLANOX_CONNECTX4: + case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF: + case PCI_DEVICE_ID_MELLANOX_CONNECTX4LX: + case PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF: + config->txq_inline_min = MLX5_INLINE_HSIZE_L2; + config->hw_vlan_insert = 0; + break; + case PCI_DEVICE_ID_MELLANOX_CONNECTX5: + case PCI_DEVICE_ID_MELLANOX_CONNECTX5VF: + case PCI_DEVICE_ID_MELLANOX_CONNECTX5EX: + case PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF: + /* + * These NICs support VLAN insertion from WQE and + * report the wqe_vlan_insert flag. But there is the bug + * and PFC control may be broken, so disable feature. + */ + config->hw_vlan_insert = 0; + config->txq_inline_min = MLX5_INLINE_HSIZE_NONE; + break; + default: + config->txq_inline_min = MLX5_INLINE_HSIZE_NONE; + break; + } +exit: + DRV_LOG(DEBUG, "min tx inline configured: %d", config->txq_inline_min); +} + +/** + * Allocate page of door-bells and register it using DevX API. + * + * @param [in] dev + * Pointer to Ethernet device. + * + * @return + * Pointer to new page on success, NULL otherwise. + */ +static struct mlx5_devx_dbr_page * +mlx5_alloc_dbr_page(struct rte_eth_dev *dev) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_devx_dbr_page *page; + + /* Allocate space for door-bell page and management data. */ + page = rte_calloc_socket(__func__, 1, sizeof(struct mlx5_devx_dbr_page), + RTE_CACHE_LINE_SIZE, dev->device->numa_node); + if (!page) { + DRV_LOG(ERR, "port %u cannot allocate dbr page", + dev->data->port_id); + return NULL; + } + /* Register allocated memory. */ + page->umem = mlx5_glue->devx_umem_reg(priv->sh->ctx, page->dbrs, + MLX5_DBR_PAGE_SIZE, 0); + if (!page->umem) { + DRV_LOG(ERR, "port %u cannot umem reg dbr page", + dev->data->port_id); + rte_free(page); + return NULL; + } + return page; +} + +/** + * Find the next available door-bell, allocate new page if needed. + * + * @param [in] dev + * Pointer to Ethernet device. + * @param [out] dbr_page + * Door-bell page containing the page data. + * + * @return + * Door-bell address offset on success, a negative error value otherwise. + */ +int64_t +mlx5_get_dbr(struct rte_eth_dev *dev, struct mlx5_devx_dbr_page **dbr_page) +{ + 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]); + 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; +} + /** * Spawn an Ethernet device from Verbs information. * @@ -1256,6 +1628,9 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev, if (!sh) return NULL; config.devx = sh->devx; +#ifdef HAVE_MLX5DV_DR_ACTION_DEST_DEVX_TIR + config.dest_tir = 1; +#endif #ifdef HAVE_IBV_MLX5_MOD_SWP dv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_SWP; #endif @@ -1513,6 +1888,36 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev, } else if (config.cqe_pad) { DRV_LOG(INFO, "Rx CQE padding is enabled"); } + if (config.devx) { + priv->counter_fallback = 0; + err = mlx5_devx_cmd_query_hca_attr(sh->ctx, &config.hca_attr); + if (err) { + err = -err; + goto error; + } + if (!config.hca_attr.flow_counters_dump) + priv->counter_fallback = 1; +#ifndef HAVE_IBV_DEVX_ASYNC + priv->counter_fallback = 1; +#endif + if (priv->counter_fallback) + DRV_LOG(INFO, "Use fall-back DV counter management\n"); + /* Check for LRO support. */ + if (config.dest_tir && config.hca_attr.lro_cap) { + /* TBD check tunnel lro caps. */ + config.lro.supported = config.hca_attr.lro_cap; + DRV_LOG(DEBUG, "Device supports LRO"); + /* + * If LRO timeout is not configured by application, + * use the minimal supported value. + */ + if (!config.lro.timeout) + config.lro.timeout = + config.hca_attr.lro_timer_supported_periods[0]; + DRV_LOG(DEBUG, "LRO session timeout set to %d usec", + config.lro.timeout); + } + } if (config.mprq.enabled && mprq) { if (config.mprq.stride_num_n > mprq_max_stride_num_n || config.mprq.stride_num_n < mprq_min_stride_num_n) { @@ -1545,6 +1950,13 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev, eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR; eth_dev->data->representor_id = priv->representor_id; } + /* + * Store associated network device interface index. This index + * is permanent throughout the lifetime of device. So, we may store + * the ifindex here and use the cached value further. + */ + assert(spawn->ifindex); + priv->if_index = spawn->ifindex; eth_dev->data->dev_private = priv; priv->dev_data = eth_dev->data; eth_dev->data->mac_addrs = priv->mac; @@ -1613,15 +2025,6 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev, * Verbs context returned by ibv_open_device(). */ mlx5_link_update(eth_dev, 0); -#ifdef HAVE_IBV_DEVX_OBJ - if (config.devx) { - err = mlx5_devx_cmd_query_hca_attr(sh->ctx, &config.hca_attr); - if (err) { - err = -err; - goto error; - } - } -#endif #ifdef HAVE_MLX5DV_DR_ESWITCH if (!(config.hca_attr.eswitch_manager && config.dv_flow_en && (switch_info->representor || switch_info->master))) @@ -1629,8 +2032,12 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev, #else config.dv_esw_en = 0; #endif + /* Detect minimal data bytes to inline. */ + mlx5_set_min_inline(spawn, &config); /* Store device configuration on private structure. */ priv->config = config; + /* Create context for virtual machine VLAN workaround. */ + priv->vmwa_context = mlx5_vlan_vmwa_init(eth_dev, spawn->ifindex); if (config.dv_flow_en) { err = mlx5_alloc_shared_dr(priv); if (err) @@ -1643,11 +2050,6 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev, goto error; } priv->config.flow_prio = err; - /* Add device to memory callback list. */ - rte_rwlock_write_lock(&mlx5_shared_data->mem_event_rwlock); - LIST_INSERT_HEAD(&mlx5_shared_data->mem_event_cb_list, - sh, mem_event_cb); - rte_rwlock_write_unlock(&mlx5_shared_data->mem_event_rwlock); return eth_dev; error: if (priv) { @@ -1657,6 +2059,8 @@ error: close(priv->nl_socket_route); if (priv->nl_socket_rdma >= 0) close(priv->nl_socket_rdma); + if (priv->vmwa_context) + mlx5_vlan_vmwa_exit(priv->vmwa_context); if (own_domain_id) claim_zero(rte_eth_switch_domain_free(priv->domain_id)); rte_free(priv); @@ -1999,12 +2403,11 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, dev_config = (struct mlx5_dev_config){ .hw_padding = 0, .mps = MLX5_ARG_UNSET, - .tx_vec_en = 1, .rx_vec_en = 1, - .txq_inline = MLX5_ARG_UNSET, + .txq_inline_max = MLX5_ARG_UNSET, + .txq_inline_min = MLX5_ARG_UNSET, + .txq_inline_mpw = MLX5_ARG_UNSET, .txqs_inline = MLX5_ARG_UNSET, - .txqs_vec = MLX5_ARG_UNSET, - .inline_max_packet_sz = MLX5_ARG_UNSET, .vf_nl_en = 1, .mr_ext_memseg_en = 1, .mprq = { @@ -2017,9 +2420,6 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, }; /* Device specific configuration. */ switch (pci_dev->id.device_id) { - case PCI_DEVICE_ID_MELLANOX_CONNECTX5BF: - dev_config.txqs_vec = MLX5_VPMD_MAX_TXQS_BLUEFIELD; - break; case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF: case PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF: case PCI_DEVICE_ID_MELLANOX_CONNECTX5VF: @@ -2029,9 +2429,6 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, default: break; } - /* Set architecture-dependent default value if unset. */ - if (dev_config.txqs_vec == MLX5_ARG_UNSET) - dev_config.txqs_vec = MLX5_VPMD_MAX_TXQS; for (i = 0; i != ns; ++i) { uint32_t restore;