#include <rte_log.h>
#include <rte_errno.h>
#include <rte_bus_pci.h>
-#ifdef PEDANTIC
-#pragma GCC diagnostic ignored "-Wpedantic"
-#endif
-#include <rte_vdpa.h>
-#ifdef PEDANTIC
-#pragma GCC diagnostic error "-Wpedantic"
-#endif
#include <mlx5_glue.h>
#include <mlx5_common.h>
#include <mlx5_devx_cmds.h>
+#include <mlx5_prm.h>
#include "mlx5_vdpa_utils.h"
+#include "mlx5_vdpa.h"
-struct mlx5_vdpa_priv {
- TAILQ_ENTRY(mlx5_vdpa_priv) next;
- int id; /* vDPA device id. */
- struct ibv_context *ctx; /* Device context. */
- struct rte_vdpa_dev_addr dev_addr;
- struct mlx5_hca_vdpa_attr caps;
-};
+#define MLX5_VDPA_DEFAULT_FEATURES ((1ULL << VHOST_USER_F_PROTOCOL_FEATURES) | \
+ (1ULL << VIRTIO_F_ANY_LAYOUT) | \
+ (1ULL << VIRTIO_NET_F_MQ) | \
+ (1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) | \
+ (1ULL << VIRTIO_F_ORDER_PLATFORM) | \
+ (1ULL << VHOST_F_LOG_ALL))
+
+#define MLX5_VDPA_PROTOCOL_FEATURES \
+ ((1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_MQ))
TAILQ_HEAD(mlx5_vdpa_privs, mlx5_vdpa_priv) priv_list =
TAILQ_HEAD_INITIALIZER(priv_list);
return 0;
}
+static int
+mlx5_vdpa_get_vdpa_features(int did, uint64_t *features)
+{
+ struct mlx5_vdpa_priv *priv = mlx5_vdpa_find_priv_resource_by_did(did);
+
+ if (priv == NULL) {
+ DRV_LOG(ERR, "Invalid device id: %d.", did);
+ return -1;
+ }
+ *features = MLX5_VDPA_DEFAULT_FEATURES;
+ if (priv->caps.virtio_queue_type & (1 << MLX5_VIRTQ_TYPE_PACKED))
+ *features |= (1ULL << VIRTIO_F_RING_PACKED);
+ if (priv->caps.tso_ipv4)
+ *features |= (1ULL << VIRTIO_NET_F_HOST_TSO4);
+ if (priv->caps.tso_ipv6)
+ *features |= (1ULL << VIRTIO_NET_F_HOST_TSO6);
+ if (priv->caps.tx_csum)
+ *features |= (1ULL << VIRTIO_NET_F_CSUM);
+ if (priv->caps.rx_csum)
+ *features |= (1ULL << VIRTIO_NET_F_GUEST_CSUM);
+ if (priv->caps.virtio_version_1_0)
+ *features |= (1ULL << VIRTIO_F_VERSION_1);
+ return 0;
+}
+
+static int
+mlx5_vdpa_get_protocol_features(int did, uint64_t *features)
+{
+ struct mlx5_vdpa_priv *priv = mlx5_vdpa_find_priv_resource_by_did(did);
+
+ if (priv == NULL) {
+ DRV_LOG(ERR, "Invalid device id: %d.", did);
+ return -1;
+ }
+ *features = MLX5_VDPA_PROTOCOL_FEATURES;
+ return 0;
+}
+
+static int
+mlx5_vdpa_set_vring_state(int vid, int vring, int state)
+{
+ int did = rte_vhost_get_vdpa_device_id(vid);
+ struct mlx5_vdpa_priv *priv = mlx5_vdpa_find_priv_resource_by_did(did);
+ struct mlx5_vdpa_virtq *virtq = NULL;
+
+ if (priv == NULL) {
+ DRV_LOG(ERR, "Invalid device id: %d.", did);
+ return -EINVAL;
+ }
+ SLIST_FOREACH(virtq, &priv->virtq_list, next)
+ if (virtq->index == vring)
+ break;
+ if (!virtq) {
+ DRV_LOG(ERR, "Invalid or unconfigured vring id: %d.", vring);
+ return -EINVAL;
+ }
+ return mlx5_vdpa_virtq_enable(virtq, state);
+}
+
+static int
+mlx5_vdpa_features_set(int vid)
+{
+ int did = rte_vhost_get_vdpa_device_id(vid);
+ struct mlx5_vdpa_priv *priv = mlx5_vdpa_find_priv_resource_by_did(did);
+ uint64_t log_base, log_size;
+ uint64_t features;
+ int ret;
+
+ if (priv == NULL) {
+ DRV_LOG(ERR, "Invalid device id: %d.", did);
+ return -EINVAL;
+ }
+ ret = rte_vhost_get_negotiated_features(vid, &features);
+ if (ret) {
+ DRV_LOG(ERR, "Failed to get negotiated features.");
+ return ret;
+ }
+ if (RTE_VHOST_NEED_LOG(features)) {
+ ret = rte_vhost_get_log_base(vid, &log_base, &log_size);
+ if (ret) {
+ DRV_LOG(ERR, "Failed to get log base.");
+ return ret;
+ }
+ ret = mlx5_vdpa_dirty_bitmap_set(priv, log_base, log_size);
+ if (ret) {
+ DRV_LOG(ERR, "Failed to set dirty bitmap.");
+ return ret;
+ }
+ DRV_LOG(INFO, "mlx5 vdpa: enabling dirty logging...");
+ ret = mlx5_vdpa_logging_enable(priv, 1);
+ if (ret) {
+ DRV_LOG(ERR, "Failed t enable dirty logging.");
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int
+mlx5_vdpa_dev_close(int vid)
+{
+ int did = rte_vhost_get_vdpa_device_id(vid);
+ struct mlx5_vdpa_priv *priv = mlx5_vdpa_find_priv_resource_by_did(did);
+ int ret = 0;
+
+ if (priv == NULL) {
+ DRV_LOG(ERR, "Invalid device id: %d.", did);
+ return -1;
+ }
+ if (priv->configured)
+ ret |= mlx5_vdpa_lm_log(priv);
+ mlx5_vdpa_cqe_event_unset(priv);
+ ret |= mlx5_vdpa_steer_unset(priv);
+ mlx5_vdpa_virtqs_release(priv);
+ mlx5_vdpa_event_qp_global_release(priv);
+ mlx5_vdpa_mem_dereg(priv);
+ priv->configured = 0;
+ priv->vid = 0;
+ return ret;
+}
+
+static int
+mlx5_vdpa_dev_config(int vid)
+{
+ int did = rte_vhost_get_vdpa_device_id(vid);
+ struct mlx5_vdpa_priv *priv = mlx5_vdpa_find_priv_resource_by_did(did);
+
+ if (priv == NULL) {
+ DRV_LOG(ERR, "Invalid device id: %d.", did);
+ return -EINVAL;
+ }
+ if (priv->configured && mlx5_vdpa_dev_close(vid)) {
+ DRV_LOG(ERR, "Failed to reconfigure vid %d.", vid);
+ return -1;
+ }
+ priv->vid = vid;
+ if (mlx5_vdpa_mem_register(priv) || mlx5_vdpa_virtqs_prepare(priv) ||
+ mlx5_vdpa_steer_setup(priv) || mlx5_vdpa_cqe_event_setup(priv)) {
+ mlx5_vdpa_dev_close(vid);
+ return -1;
+ }
+ priv->configured = 1;
+ return 0;
+}
+
static struct rte_vdpa_dev_ops mlx5_vdpa_ops = {
.get_queue_num = mlx5_vdpa_get_queue_num,
- .get_features = NULL,
- .get_protocol_features = NULL,
- .dev_conf = NULL,
- .dev_close = NULL,
- .set_vring_state = NULL,
- .set_features = NULL,
+ .get_features = mlx5_vdpa_get_vdpa_features,
+ .get_protocol_features = mlx5_vdpa_get_protocol_features,
+ .dev_conf = mlx5_vdpa_dev_config,
+ .dev_close = mlx5_vdpa_dev_close,
+ .set_vring_state = mlx5_vdpa_set_vring_state,
+ .set_features = mlx5_vdpa_features_set,
.migration_done = NULL,
.get_vfio_group_fd = NULL,
.get_vfio_device_fd = NULL,
goto error;
}
priv->caps = attr.vdpa;
+ priv->log_max_rqt_size = attr.log_max_rqt_size;
}
priv->ctx = ctx;
priv->dev_addr.pci_addr = pci_dev->addr;
rte_errno = rte_errno ? rte_errno : EINVAL;
goto error;
}
+ SLIST_INIT(&priv->mr_list);
+ SLIST_INIT(&priv->virtq_list);
pthread_mutex_lock(&priv_list_lock);
TAILQ_INSERT_TAIL(&priv_list, priv, next);
pthread_mutex_unlock(&priv_list_lock);
break;
}
}
- if (found) {
+ if (found)
TAILQ_REMOVE(&priv_list, priv, next);
+ pthread_mutex_unlock(&priv_list_lock);
+ if (found) {
+ if (priv->configured)
+ mlx5_vdpa_dev_close(priv->vid);
mlx5_glue->close_device(priv->ctx);
rte_free(priv);
}
- pthread_mutex_unlock(&priv_list_lock);
return 0;
}