vdpa/mlx5: support queue update
Last changes in vDPA device management by vhost library may cause queue ready state update after the device configuration. So, there is chance that some queue configuration information will be known only after the device was configured. Add support to reconfigure a queue after the device configuration according to the queue state update and the configuration changes. Adjust the host notifier and the guest notification configuration to be per queue and to be applied in the enablement process. Signed-off-by: Matan Azrad <matan@mellanox.com> Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
This commit is contained in:
parent
b213af9aa4
commit
c47d6e8333
@ -145,31 +145,6 @@ mlx5_vdpa_set_vring_state(int vid, int vring, int state)
|
||||
return mlx5_vdpa_virtq_enable(priv, vring, state);
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5_vdpa_direct_db_prepare(struct mlx5_vdpa_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (priv->direct_notifier) {
|
||||
ret = rte_vhost_host_notifier_ctrl(priv->vid,
|
||||
RTE_VHOST_QUEUE_ALL, false);
|
||||
if (ret != 0) {
|
||||
DRV_LOG(INFO, "Direct HW notifier FD cannot be "
|
||||
"destroyed for device %d: %d.", priv->vid, ret);
|
||||
return -1;
|
||||
}
|
||||
priv->direct_notifier = 0;
|
||||
}
|
||||
ret = rte_vhost_host_notifier_ctrl(priv->vid, RTE_VHOST_QUEUE_ALL,
|
||||
true);
|
||||
if (ret != 0)
|
||||
DRV_LOG(INFO, "Direct HW notifier FD cannot be configured for"
|
||||
" device %d: %d.", priv->vid, ret);
|
||||
else
|
||||
priv->direct_notifier = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5_vdpa_features_set(int vid)
|
||||
{
|
||||
@ -339,7 +314,6 @@ mlx5_vdpa_dev_config(int vid)
|
||||
DRV_LOG(WARNING, "MTU cannot be set on device %s.",
|
||||
vdev->device->name);
|
||||
if (mlx5_vdpa_pd_create(priv) || mlx5_vdpa_mem_register(priv) ||
|
||||
mlx5_vdpa_direct_db_prepare(priv) ||
|
||||
mlx5_vdpa_virtqs_prepare(priv) || mlx5_vdpa_steer_setup(priv) ||
|
||||
mlx5_vdpa_cqe_event_setup(priv)) {
|
||||
mlx5_vdpa_dev_close(vid);
|
||||
|
@ -74,11 +74,18 @@ struct mlx5_vdpa_query_mr {
|
||||
int is_indirect;
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_VDPA_NOTIFIER_STATE_DISABLED,
|
||||
MLX5_VDPA_NOTIFIER_STATE_ENABLED,
|
||||
MLX5_VDPA_NOTIFIER_STATE_ERR
|
||||
};
|
||||
|
||||
struct mlx5_vdpa_virtq {
|
||||
SLIST_ENTRY(mlx5_vdpa_virtq) next;
|
||||
uint8_t enable;
|
||||
uint16_t index;
|
||||
uint16_t vq_size;
|
||||
uint8_t notifier_state;
|
||||
struct mlx5_vdpa_priv *priv;
|
||||
struct mlx5_devx_obj *virtq;
|
||||
struct mlx5_devx_obj *counters;
|
||||
@ -113,7 +120,6 @@ enum {
|
||||
struct mlx5_vdpa_priv {
|
||||
TAILQ_ENTRY(mlx5_vdpa_priv) next;
|
||||
uint8_t configured;
|
||||
uint8_t direct_notifier; /* Whether direct notifier is on or off. */
|
||||
uint64_t last_traffic_tic;
|
||||
pthread_t timer_tid;
|
||||
pthread_mutex_t timer_lock;
|
||||
|
@ -36,6 +36,17 @@ mlx5_vdpa_virtq_handler(void *cb_arg)
|
||||
break;
|
||||
} while (1);
|
||||
rte_write32(virtq->index, priv->virtq_db_addr);
|
||||
if (virtq->notifier_state == MLX5_VDPA_NOTIFIER_STATE_DISABLED) {
|
||||
if (rte_vhost_host_notifier_ctrl(priv->vid, virtq->index, true))
|
||||
virtq->notifier_state = MLX5_VDPA_NOTIFIER_STATE_ERR;
|
||||
else
|
||||
virtq->notifier_state =
|
||||
MLX5_VDPA_NOTIFIER_STATE_ENABLED;
|
||||
DRV_LOG(INFO, "Virtq %u notifier state is %s.", virtq->index,
|
||||
virtq->notifier_state ==
|
||||
MLX5_VDPA_NOTIFIER_STATE_ENABLED ? "enabled" :
|
||||
"disabled");
|
||||
}
|
||||
DRV_LOG(DEBUG, "Ring virtq %u doorbell.", virtq->index);
|
||||
}
|
||||
|
||||
@ -79,6 +90,7 @@ mlx5_vdpa_virtq_unset(struct mlx5_vdpa_virtq *virtq)
|
||||
memset(&virtq->reset, 0, sizeof(virtq->reset));
|
||||
if (virtq->eqp.fw_qp)
|
||||
mlx5_vdpa_event_qp_destroy(&virtq->eqp);
|
||||
virtq->notifier_state = MLX5_VDPA_NOTIFIER_STATE_DISABLED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -87,10 +99,8 @@ mlx5_vdpa_virtqs_release(struct mlx5_vdpa_priv *priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->nr_virtqs; i++) {
|
||||
for (i = 0; i < priv->nr_virtqs; i++)
|
||||
mlx5_vdpa_virtq_unset(&priv->virtqs[i]);
|
||||
priv->virtqs[i].enable = 0;
|
||||
}
|
||||
if (priv->tis) {
|
||||
claim_zero(mlx5_devx_cmd_destroy(priv->tis));
|
||||
priv->tis = NULL;
|
||||
@ -143,6 +153,7 @@ mlx5_vdpa_virtq_stop(struct mlx5_vdpa_priv *priv, int index)
|
||||
DRV_LOG(ERR, "Failed to set virtq %d base.", index);
|
||||
return -1;
|
||||
}
|
||||
DRV_LOG(DEBUG, "vid %u virtq %u was stopped.", priv->vid, index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -289,6 +300,7 @@ mlx5_vdpa_virtq_setup(struct mlx5_vdpa_priv *priv, int index)
|
||||
virtq->priv = priv;
|
||||
if (!virtq->virtq)
|
||||
goto error;
|
||||
claim_zero(rte_vhost_enable_guest_notification(priv->vid, index, 1));
|
||||
if (mlx5_vdpa_virtq_modify(virtq, 1))
|
||||
goto error;
|
||||
virtq->priv = priv;
|
||||
@ -297,10 +309,6 @@ mlx5_vdpa_virtq_setup(struct mlx5_vdpa_priv *priv, int index)
|
||||
virtq->intr_handle.fd = vq.kickfd;
|
||||
if (virtq->intr_handle.fd == -1) {
|
||||
DRV_LOG(WARNING, "Virtq %d kickfd is invalid.", index);
|
||||
if (!priv->direct_notifier) {
|
||||
DRV_LOG(ERR, "Virtq %d cannot be notified.", index);
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
virtq->intr_handle.type = RTE_INTR_HANDLE_EXT;
|
||||
if (rte_intr_callback_register(&virtq->intr_handle,
|
||||
@ -315,6 +323,8 @@ mlx5_vdpa_virtq_setup(struct mlx5_vdpa_priv *priv, int index)
|
||||
virtq->intr_handle.fd, index);
|
||||
}
|
||||
}
|
||||
DRV_LOG(DEBUG, "vid %u virtq %u was created successfully.", priv->vid,
|
||||
index);
|
||||
return 0;
|
||||
error:
|
||||
mlx5_vdpa_virtq_unset(virtq);
|
||||
@ -418,18 +428,35 @@ mlx5_vdpa_virtqs_prepare(struct mlx5_vdpa_priv *priv)
|
||||
goto error;
|
||||
}
|
||||
priv->nr_virtqs = nr_vring;
|
||||
for (i = 0; i < nr_vring; i++) {
|
||||
claim_zero(rte_vhost_enable_guest_notification(priv->vid, i,
|
||||
1));
|
||||
if (mlx5_vdpa_virtq_setup(priv, i))
|
||||
for (i = 0; i < nr_vring; i++)
|
||||
if (priv->virtqs[i].enable && mlx5_vdpa_virtq_setup(priv, i))
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
mlx5_vdpa_virtqs_release(priv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5_vdpa_virtq_is_modified(struct mlx5_vdpa_priv *priv,
|
||||
struct mlx5_vdpa_virtq *virtq)
|
||||
{
|
||||
struct rte_vhost_vring vq;
|
||||
int ret = rte_vhost_get_vhost_vring(priv->vid, virtq->index, &vq);
|
||||
|
||||
if (ret)
|
||||
return -1;
|
||||
if (vq.size != virtq->vq_size || vq.kickfd != virtq->intr_handle.fd)
|
||||
return 1;
|
||||
if (virtq->eqp.cq.cq) {
|
||||
if (vq.callfd != virtq->eqp.cq.callfd)
|
||||
return 1;
|
||||
} else if (vq.callfd != -1) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mlx5_vdpa_virtq_enable(struct mlx5_vdpa_priv *priv, int index, int enable)
|
||||
{
|
||||
@ -438,26 +465,33 @@ mlx5_vdpa_virtq_enable(struct mlx5_vdpa_priv *priv, int index, int enable)
|
||||
|
||||
DRV_LOG(INFO, "Update virtq %d status %sable -> %sable.", index,
|
||||
virtq->enable ? "en" : "dis", enable ? "en" : "dis");
|
||||
if (virtq->enable == !!enable)
|
||||
return 0;
|
||||
if (!priv->configured) {
|
||||
virtq->enable = !!enable;
|
||||
return 0;
|
||||
}
|
||||
if (enable) {
|
||||
/* Configuration might have been updated - reconfigure virtq. */
|
||||
if (virtq->virtq) {
|
||||
ret = mlx5_vdpa_virtq_stop(priv, index);
|
||||
if (ret)
|
||||
DRV_LOG(WARNING, "Failed to stop virtq %d.",
|
||||
index);
|
||||
mlx5_vdpa_virtq_unset(virtq);
|
||||
if (virtq->enable == !!enable) {
|
||||
if (!enable)
|
||||
return 0;
|
||||
ret = mlx5_vdpa_virtq_is_modified(priv, virtq);
|
||||
if (ret < 0) {
|
||||
DRV_LOG(ERR, "Virtq %d modify check failed.", index);
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
DRV_LOG(INFO, "Virtq %d was modified, recreate it.", index);
|
||||
}
|
||||
if (virtq->virtq) {
|
||||
ret = mlx5_vdpa_virtq_stop(priv, index);
|
||||
if (ret)
|
||||
DRV_LOG(WARNING, "Failed to stop virtq %d.", index);
|
||||
mlx5_vdpa_virtq_unset(virtq);
|
||||
}
|
||||
if (enable) {
|
||||
ret = mlx5_vdpa_virtq_setup(priv, index);
|
||||
if (ret) {
|
||||
DRV_LOG(ERR, "Failed to setup virtq %d.", index);
|
||||
return ret;
|
||||
/* The only case virtq can stay invalid. */
|
||||
}
|
||||
}
|
||||
virtq->enable = !!enable;
|
||||
|
Loading…
x
Reference in New Issue
Block a user