X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_vhost%2Fvhost_user.c;h=c3c924faecf49c4cee294694b6e32c695096ef39;hb=b53a4972946d4fb82ae323ca036e8d6e61db44d6;hp=a96bc5c16b104134aac2a96d8b2d590d161cb4ae;hpb=a15f9dbba057caf9dfd84ad4528ce2ce722aa24d;p=dpdk.git diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c index a96bc5c16b..c3c924faec 100644 --- a/lib/librte_vhost/vhost_user.c +++ b/lib/librte_vhost/vhost_user.c @@ -87,6 +87,8 @@ static const char *vhost_message_str[VHOST_USER_MAX] = { [VHOST_USER_POSTCOPY_END] = "VHOST_USER_POSTCOPY_END", [VHOST_USER_GET_INFLIGHT_FD] = "VHOST_USER_GET_INFLIGHT_FD", [VHOST_USER_SET_INFLIGHT_FD] = "VHOST_USER_SET_INFLIGHT_FD", + [VHOST_USER_SET_STATUS] = "VHOST_USER_SET_STATUS", + [VHOST_USER_GET_STATUS] = "VHOST_USER_GET_STATUS", }; static int send_vhost_reply(int sockfd, struct VhostUserMsg *msg); @@ -233,6 +235,11 @@ vhost_user_notify_queue_state(struct virtio_net *dev, uint16_t index, int enable) { struct rte_vdpa_device *vdpa_dev = dev->vdpa_dev; + struct vhost_virtqueue *vq = dev->virtqueue[index]; + + /* Configure guest notifications on enable */ + if (enable && vq->notif_enable != VIRTIO_UNINITIALIZED_NOTIF) + vhost_enable_guest_notification(dev, vq, vq->notif_enable); if (vdpa_dev && vdpa_dev->ops->set_vring_state) vdpa_dev->ops->set_vring_state(dev->vid, index, enable); @@ -338,6 +345,9 @@ vhost_user_set_features(struct virtio_net **pdev, struct VhostUserMsg *msg, VHOST_LOG_CONFIG(ERR, "(%d) received invalid negotiated features.\n", dev->vid); + dev->flags |= VIRTIO_DEV_FEATURES_FAILED; + dev->status &= ~VIRTIO_DEVICE_STATUS_FEATURES_OK; + return RTE_VHOST_MSG_RESULT_ERR; } @@ -401,6 +411,7 @@ vhost_user_set_features(struct virtio_net **pdev, struct VhostUserMsg *msg, if (vdpa_dev) vdpa_dev->ops->set_features(dev->vid); + dev->flags &= ~VIRTIO_DEV_FEATURES_FAILED; return RTE_VHOST_MSG_RESULT_OK; } @@ -1353,6 +1364,11 @@ virtio_is_ready(struct virtio_net *dev) return 0; } + /* If supported, ensure the frontend is really done with config */ + if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_STATUS)) + if (!(dev->status & VIRTIO_DEVICE_STATUS_DRIVER_OK)) + return 0; + dev->flags |= VIRTIO_DEV_READY; if (!(dev->flags & VIRTIO_DEV_RUNNING)) @@ -1629,8 +1645,8 @@ vhost_user_set_vring_call(struct virtio_net **pdev, struct VhostUserMsg *msg, vq = dev->virtqueue[file.index]; if (vq->ready) { - vhost_user_notify_queue_state(dev, file.index, 0); vq->ready = 0; + vhost_user_notify_queue_state(dev, file.index, 0); } if (vq->callfd >= 0) @@ -1892,8 +1908,8 @@ vhost_user_set_vring_kick(struct virtio_net **pdev, struct VhostUserMsg *msg, } if (vq->ready) { - vhost_user_notify_queue_state(dev, file.index, 0); vq->ready = 0; + vhost_user_notify_queue_state(dev, file.index, 0); } if (vq->kickfd >= 0) @@ -1923,6 +1939,7 @@ free_zmbufs(struct vhost_virtqueue *vq) drain_zmbuf_list(vq); rte_free(vq->zmbufs); + vq->zmbufs = NULL; } /* @@ -2469,6 +2486,68 @@ vhost_user_postcopy_end(struct virtio_net **pdev, struct VhostUserMsg *msg, return RTE_VHOST_MSG_RESULT_REPLY; } +static int +vhost_user_get_status(struct virtio_net **pdev, struct VhostUserMsg *msg, + int main_fd __rte_unused) +{ + struct virtio_net *dev = *pdev; + + if (validate_msg_fds(msg, 0) != 0) + return RTE_VHOST_MSG_RESULT_ERR; + + msg->payload.u64 = dev->status; + msg->size = sizeof(msg->payload.u64); + msg->fd_num = 0; + + return RTE_VHOST_MSG_RESULT_REPLY; +} + +static int +vhost_user_set_status(struct virtio_net **pdev, struct VhostUserMsg *msg, + int main_fd __rte_unused) +{ + struct virtio_net *dev = *pdev; + + if (validate_msg_fds(msg, 0) != 0) + return RTE_VHOST_MSG_RESULT_ERR; + + /* As per Virtio specification, the device status is 8bits long */ + if (msg->payload.u64 > UINT8_MAX) { + VHOST_LOG_CONFIG(ERR, "Invalid VHOST_USER_SET_STATUS payload 0x%" PRIx64 "\n", + msg->payload.u64); + return RTE_VHOST_MSG_RESULT_ERR; + } + + dev->status = msg->payload.u64; + + if ((dev->status & VIRTIO_DEVICE_STATUS_FEATURES_OK) && + (dev->flags & VIRTIO_DEV_FEATURES_FAILED)) { + VHOST_LOG_CONFIG(ERR, "FEATURES_OK bit is set but feature negotiation failed\n"); + /* + * Clear the bit to let the driver know about the feature + * negotiation failure + */ + dev->status &= ~VIRTIO_DEVICE_STATUS_FEATURES_OK; + } + + VHOST_LOG_CONFIG(INFO, "New device status(0x%08x):\n" + "\t-ACKNOWLEDGE: %u\n" + "\t-DRIVER: %u\n" + "\t-FEATURES_OK: %u\n" + "\t-DRIVER_OK: %u\n" + "\t-DEVICE_NEED_RESET: %u\n" + "\t-FAILED: %u\n", + dev->status, + !!(dev->status & VIRTIO_DEVICE_STATUS_ACK), + !!(dev->status & VIRTIO_DEVICE_STATUS_DRIVER), + !!(dev->status & VIRTIO_DEVICE_STATUS_FEATURES_OK), + !!(dev->status & VIRTIO_DEVICE_STATUS_DRIVER_OK), + !!(dev->status & VIRTIO_DEVICE_STATUS_DEV_NEED_RESET), + !!(dev->status & VIRTIO_DEVICE_STATUS_FAILED)); + + return RTE_VHOST_MSG_RESULT_OK; +} + typedef int (*vhost_message_handler_t)(struct virtio_net **pdev, struct VhostUserMsg *msg, int main_fd); @@ -2501,6 +2580,8 @@ static vhost_message_handler_t vhost_message_handlers[VHOST_USER_MAX] = { [VHOST_USER_POSTCOPY_END] = vhost_user_postcopy_end, [VHOST_USER_GET_INFLIGHT_FD] = vhost_user_get_inflight_fd, [VHOST_USER_SET_INFLIGHT_FD] = vhost_user_set_inflight_fd, + [VHOST_USER_SET_STATUS] = vhost_user_set_status, + [VHOST_USER_GET_STATUS] = vhost_user_get_status, }; /* return bytes# of read on success or negative val on failure. */ @@ -2841,8 +2922,8 @@ skip_to_post_handle: bool cur_ready = vq_is_ready(dev, vq); if (cur_ready != (vq && vq->ready)) { - vhost_user_notify_queue_state(dev, i, cur_ready); vq->ready = cur_ready; + vhost_user_notify_queue_state(dev, i, cur_ready); } }