X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fvirtio%2Fvirtio_user_ethdev.c;h=1810a546942db7fa3fbcab763ce56db3a1a4f01f;hb=387e72ed7f7f5d5336c3aafe50bb2b81f2c73080;hp=b4a433123cce246782da1a946f002b71a2e2e8bd;hpb=f12908c81a2b462452f8574c4d880269ee9183dd;p=dpdk.git diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c index b4a433123c..1810a54694 100644 --- a/drivers/net/virtio/virtio_user_ethdev.c +++ b/drivers/net/virtio/virtio_user_ethdev.c @@ -20,7 +20,7 @@ #include "virtio_ethdev.h" #include "virtio_logs.h" -#include "virtio_pci.h" +#include "virtio.h" #include "virtqueue.h" #include "virtio_rxtx.h" #include "virtio_user/virtio_user_dev.h" @@ -28,175 +28,6 @@ #define virtio_user_get_dev(hwp) container_of(hwp, struct virtio_user_dev, hw) -static void -virtio_user_reset_queues_packed(struct rte_eth_dev *eth_dev) -{ - struct virtio_user_dev *dev = eth_dev->data->dev_private; - struct virtio_hw *hw = &dev->hw; - struct virtnet_rx *rxvq; - struct virtnet_tx *txvq; - uint16_t i; - - /* Add lock to avoid queue contention. */ - rte_spinlock_lock(&hw->state_lock); - hw->started = 0; - - /* - * Waitting for datapath to complete before resetting queues. - * 1 ms should be enough for the ongoing Tx/Rx function to finish. - */ - rte_delay_ms(1); - - /* Vring reset for each Tx queue and Rx queue. */ - for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { - rxvq = eth_dev->data->rx_queues[i]; - virtqueue_rxvq_reset_packed(rxvq->vq); - virtio_dev_rx_queue_setup_finish(eth_dev, i); - } - - for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { - txvq = eth_dev->data->tx_queues[i]; - virtqueue_txvq_reset_packed(txvq->vq); - } - - hw->started = 1; - rte_spinlock_unlock(&hw->state_lock); -} - - -static int -virtio_user_server_reconnect(struct virtio_user_dev *dev) -{ - int ret, connectfd, old_status; - struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->port_id]; - struct virtio_hw *hw = &dev->hw; - uint64_t protocol_features; - - connectfd = accept(dev->listenfd, NULL, NULL); - if (connectfd < 0) - return -1; - - dev->vhostfd = connectfd; - old_status = dev->status; - - vtpci_reset(hw); - - vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_ACK); - - vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER); - - if (dev->ops->send_request(dev, VHOST_USER_GET_FEATURES, - &dev->device_features) < 0) { - PMD_INIT_LOG(ERR, "get_features failed: %s", - strerror(errno)); - return -1; - } - - if (dev->device_features & - (1ULL << VHOST_USER_F_PROTOCOL_FEATURES)) { - if (dev->ops->send_request(dev, - VHOST_USER_GET_PROTOCOL_FEATURES, - &protocol_features)) - return -1; - - /* Offer VHOST_USER_PROTOCOL_F_STATUS */ - dev->protocol_features |= - (1ULL << VHOST_USER_PROTOCOL_F_STATUS); - dev->protocol_features &= protocol_features; - - if (dev->ops->send_request(dev, - VHOST_USER_SET_PROTOCOL_FEATURES, - &dev->protocol_features)) - return -1; - - if (!(dev->protocol_features & - (1ULL << VHOST_USER_PROTOCOL_F_MQ))) - dev->unsupported_features |= (1ull << VIRTIO_NET_F_MQ); - } - - dev->device_features |= dev->frontend_features; - - /* umask vhost-user unsupported features */ - dev->device_features &= ~(dev->unsupported_features); - - dev->features &= dev->device_features; - - /* For packed ring, resetting queues is required in reconnection. */ - if (vtpci_packed_queue(hw) && - (old_status & VIRTIO_CONFIG_STATUS_DRIVER_OK)) { - PMD_INIT_LOG(NOTICE, "Packets on the fly will be dropped" - " when packed ring reconnecting."); - virtio_user_reset_queues_packed(eth_dev); - } - - vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_FEATURES_OK); - - /* Start the device */ - vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK); - if (!dev->started) - return -1; - - if (dev->queue_pairs > 1) { - ret = virtio_user_handle_mq(dev, dev->queue_pairs); - if (ret != 0) { - PMD_INIT_LOG(ERR, "Fails to enable multi-queue pairs!"); - return -1; - } - } - if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) { - if (rte_intr_disable(eth_dev->intr_handle) < 0) { - PMD_DRV_LOG(ERR, "interrupt disable failed"); - return -1; - } - rte_intr_callback_unregister(eth_dev->intr_handle, - virtio_interrupt_handler, - eth_dev); - eth_dev->intr_handle->fd = connectfd; - rte_intr_callback_register(eth_dev->intr_handle, - virtio_interrupt_handler, eth_dev); - - if (rte_intr_enable(eth_dev->intr_handle) < 0) { - PMD_DRV_LOG(ERR, "interrupt enable failed"); - return -1; - } - } - PMD_INIT_LOG(NOTICE, "server mode virtio-user reconnection succeeds!"); - return 0; -} - -static void -virtio_user_delayed_handler(void *param) -{ - struct virtio_hw *hw = (struct virtio_hw *)param; - struct rte_eth_dev *eth_dev = &rte_eth_devices[hw->port_id]; - struct virtio_user_dev *dev = virtio_user_get_dev(hw); - - if (rte_intr_disable(eth_dev->intr_handle) < 0) { - PMD_DRV_LOG(ERR, "interrupt disable failed"); - return; - } - rte_intr_callback_unregister(eth_dev->intr_handle, - virtio_interrupt_handler, eth_dev); - if (dev->is_server) { - if (dev->vhostfd >= 0) { - close(dev->vhostfd); - dev->vhostfd = -1; - /* Until the featuers are negotiated again, don't assume - * the backend supports VHOST_USER_PROTOCOL_F_STATUS - */ - dev->protocol_features &= - ~(1ULL << VHOST_USER_PROTOCOL_F_STATUS); - } - eth_dev->intr_handle->fd = dev->listenfd; - rte_intr_callback_register(eth_dev->intr_handle, - virtio_interrupt_handler, eth_dev); - if (rte_intr_enable(eth_dev->intr_handle) < 0) { - PMD_DRV_LOG(ERR, "interrupt enable failed"); - return; - } - } -} - static void virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset, void *dst, int length) @@ -212,44 +43,7 @@ virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset, } if (offset == offsetof(struct virtio_net_config, status)) { - char buf[128]; - - if (dev->vhostfd >= 0) { - int r; - int flags; - - flags = fcntl(dev->vhostfd, F_GETFL); - if (fcntl(dev->vhostfd, F_SETFL, - flags | O_NONBLOCK) == -1) { - PMD_DRV_LOG(ERR, "error setting O_NONBLOCK flag"); - return; - } - r = recv(dev->vhostfd, buf, 128, MSG_PEEK); - if (r == 0 || (r < 0 && errno != EAGAIN)) { - dev->net_status &= (~VIRTIO_NET_S_LINK_UP); - PMD_DRV_LOG(ERR, "virtio-user port %u is down", - hw->port_id); - - /* This function could be called in the process - * of interrupt handling, callback cannot be - * unregistered here, set an alarm to do it. - */ - rte_eal_alarm_set(1, - virtio_user_delayed_handler, - (void *)hw); - } else { - dev->net_status |= VIRTIO_NET_S_LINK_UP; - } - if (fcntl(dev->vhostfd, F_SETFL, - flags & ~O_NONBLOCK) == -1) { - PMD_DRV_LOG(ERR, "error clearing O_NONBLOCK flag"); - return; - } - } else if (dev->is_server) { - dev->net_status &= (~VIRTIO_NET_S_LINK_UP); - if (virtio_user_server_reconnect(dev) >= 0) - dev->net_status |= VIRTIO_NET_S_LINK_UP; - } + virtio_user_dev_update_link_state(dev); *(uint16_t *)dst = dev->net_status; } @@ -327,13 +121,19 @@ virtio_user_set_features(struct virtio_hw *hw, uint64_t features) dev->features = features & dev->device_features; } +static int +virtio_user_features_ok(struct virtio_hw *hw __rte_unused) +{ + return 0; +} + static uint8_t virtio_user_get_isr(struct virtio_hw *hw __rte_unused) { /* rxq interrupts and config interrupt are separated in virtio-user, * here we only report config change. */ - return VIRTIO_PCI_ISR_CONFIG; + return VIRTIO_ISR_CONFIG; } static uint16_t @@ -382,7 +182,7 @@ virtio_user_setup_queue_packed(struct virtqueue *vq, sizeof(struct vring_packed_desc); used_addr = RTE_ALIGN_CEIL(avail_addr + sizeof(struct vring_packed_desc_event), - VIRTIO_PCI_VRING_ALIGN); + VIRTIO_VRING_ALIGN); vring->num = vq->vq_nentries; vring->desc = (void *)(uintptr_t)desc_addr; vring->driver = (void *)(uintptr_t)avail_addr; @@ -404,7 +204,7 @@ virtio_user_setup_queue_split(struct virtqueue *vq, struct virtio_user_dev *dev) avail_addr = desc_addr + vq->vq_nentries * sizeof(struct vring_desc); used_addr = RTE_ALIGN_CEIL(avail_addr + offsetof(struct vring_avail, ring[vq->vq_nentries]), - VIRTIO_PCI_VRING_ALIGN); + VIRTIO_VRING_ALIGN); dev->vrings[queue_idx].num = vq->vq_nentries; dev->vrings[queue_idx].desc = (void *)(uintptr_t)desc_addr; @@ -417,7 +217,7 @@ virtio_user_setup_queue(struct virtio_hw *hw, struct virtqueue *vq) { struct virtio_user_dev *dev = virtio_user_get_dev(hw); - if (vtpci_packed_queue(hw)) + if (virtio_with_packed_queue(hw)) virtio_user_setup_queue_packed(vq, dev); else virtio_user_setup_queue_split(vq, dev); @@ -450,7 +250,7 @@ virtio_user_notify_queue(struct virtio_hw *hw, struct virtqueue *vq) struct virtio_user_dev *dev = virtio_user_get_dev(hw); if (hw->cvq && (hw->cvq->vq == vq)) { - if (vtpci_packed_queue(vq->hw)) + if (virtio_with_packed_queue(vq->hw)) virtio_user_handle_cq_packed(dev, vq->vq_queue_index); else virtio_user_handle_cq(dev, vq->vq_queue_index); @@ -472,13 +272,14 @@ virtio_user_dev_close(struct virtio_hw *hw) return 0; } -const struct virtio_pci_ops virtio_user_ops = { +const struct virtio_ops virtio_user_ops = { .read_dev_cfg = virtio_user_read_dev_config, .write_dev_cfg = virtio_user_write_dev_config, .get_status = virtio_user_get_status, .set_status = virtio_user_set_status, .get_features = virtio_user_get_features, .set_features = virtio_user_set_features, + .features_ok = virtio_user_features_ok, .get_isr = virtio_user_get_isr, .set_config_irq = virtio_user_set_config_irq, .set_queue_irq = virtio_user_set_queue_irq, @@ -628,13 +429,9 @@ virtio_user_eth_dev_alloc(struct rte_vdev_device *vdev) hw->port_id = data->port_id; dev->port_id = data->port_id; - virtio_hw_internal[hw->port_id].vtpci_ops = &virtio_user_ops; - /* - * MSIX is required to enable LSC (see virtio_init_device). - * Here just pretend that we support msix. - */ - hw->use_msix = 1; - hw->bus_type = VIRTIO_BUS_USER; + VIRTIO_OPS(hw) = &virtio_user_ops; + + hw->intr_lsc = 1; hw->use_vec_rx = 0; hw->use_vec_tx = 0; hw->use_inorder_rx = 0; @@ -684,6 +481,10 @@ virtio_user_pmd_probe(struct rte_vdev_device *vdev) return -1; } + dev = eth_dev->data->dev_private; + hw = &dev->hw; + VIRTIO_OPS(hw) = &virtio_user_ops; + if (eth_virtio_dev_init(eth_dev) < 0) { PMD_INIT_LOG(ERR, "eth_virtio_dev_init fails"); rte_eth_dev_release_port(eth_dev);