X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fvirtio%2Fvirtio_user_ethdev.c;h=f3b35d1bdd6f4b90dfedf7a29601aeef72f7cb11;hb=6ebbf4109f3529a1af880ce195869cee84647178;hp=2df6eb695760c7883ac011cd7026a2d5545582bc;hpb=9070f88b81dab42739fb169265e3ea727e47dfa2;p=dpdk.git diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c index 2df6eb6957..f3b35d1bdd 100644 --- a/drivers/net/virtio/virtio_user_ethdev.c +++ b/drivers/net/virtio/virtio_user_ethdev.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "virtio_ethdev.h" #include "virtio_logs.h" @@ -20,16 +21,53 @@ #include "virtqueue.h" #include "virtio_rxtx.h" #include "virtio_user/virtio_user_dev.h" +#include "virtio_user/vhost.h" #define virtio_user_get_dev(hw) \ ((struct virtio_user_dev *)(hw)->virtio_user_dev) +static void +virtio_user_reset_queues_packed(struct rte_eth_dev *dev) +{ + struct virtio_hw *hw = dev->data->dev_private; + 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 < dev->data->nb_rx_queues; i++) { + rxvq = dev->data->rx_queues[i]; + virtqueue_rxvq_reset_packed(rxvq->vq); + virtio_dev_rx_queue_setup_finish(dev, i); + } + + for (i = 0; i < dev->data->nb_tx_queues; i++) { + txvq = 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; int connectfd; struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->port_id]; + struct virtio_hw *hw = eth_dev->data->dev_private; connectfd = accept(dev->listenfd, NULL, NULL); if (connectfd < 0) @@ -50,6 +88,12 @@ virtio_user_server_reconnect(struct virtio_user_dev *dev) dev->features &= dev->device_features; + /* For packed ring, resetting queues is required in reconnection. */ + if (vtpci_packed_queue(hw)) + PMD_INIT_LOG(NOTICE, "Packets on the fly will be dropped" + " when packed ring reconnecting."); + virtio_user_reset_queues_packed(eth_dev); + ret = virtio_user_start_device(dev); if (ret < 0) return -1; @@ -118,8 +162,8 @@ virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset, struct virtio_user_dev *dev = virtio_user_get_dev(hw); if (offset == offsetof(struct virtio_net_config, mac) && - length == ETHER_ADDR_LEN) { - for (i = 0; i < ETHER_ADDR_LEN; ++i) + length == RTE_ETHER_ADDR_LEN) { + for (i = 0; i < RTE_ETHER_ADDR_LEN; ++i) ((uint8_t *)dst)[i] = dev->mac_addr[i]; return; } @@ -179,8 +223,8 @@ virtio_user_write_dev_config(struct virtio_hw *hw, size_t offset, struct virtio_user_dev *dev = virtio_user_get_dev(hw); if ((offset == offsetof(struct virtio_net_config, mac)) && - (length == ETHER_ADDR_LEN)) - for (i = 0; i < ETHER_ADDR_LEN; ++i) + (length == RTE_ETHER_ADDR_LEN)) + for (i = 0; i < RTE_ETHER_ADDR_LEN; ++i) dev->mac_addr[i] = ((const uint8_t *)src)[i]; else PMD_DRV_LOG(ERR, "not supported offset=%zu, len=%d", @@ -271,10 +315,38 @@ virtio_user_get_queue_num(struct virtio_hw *hw, uint16_t queue_id __rte_unused) return dev->queue_size; } -static int -virtio_user_setup_queue(struct virtio_hw *hw, struct virtqueue *vq) +static void +virtio_user_setup_queue_packed(struct virtqueue *vq, + struct virtio_user_dev *dev) +{ + uint16_t queue_idx = vq->vq_queue_index; + struct vring_packed *vring; + uint64_t desc_addr; + uint64_t avail_addr; + uint64_t used_addr; + uint16_t i; + + vring = &dev->packed_vrings[queue_idx]; + desc_addr = (uintptr_t)vq->vq_ring_virt_mem; + avail_addr = desc_addr + vq->vq_nentries * + sizeof(struct vring_packed_desc); + used_addr = RTE_ALIGN_CEIL(avail_addr + + sizeof(struct vring_packed_desc_event), + VIRTIO_PCI_VRING_ALIGN); + vring->num = vq->vq_nentries; + vring->desc = (void *)(uintptr_t)desc_addr; + vring->driver = (void *)(uintptr_t)avail_addr; + vring->device = (void *)(uintptr_t)used_addr; + dev->packed_queues[queue_idx].avail_wrap_counter = true; + dev->packed_queues[queue_idx].used_wrap_counter = true; + + for (i = 0; i < vring->num; i++) + vring->desc[i].flags = 0; +} + +static void +virtio_user_setup_queue_split(struct virtqueue *vq, struct virtio_user_dev *dev) { - struct virtio_user_dev *dev = virtio_user_get_dev(hw); uint16_t queue_idx = vq->vq_queue_index; uint64_t desc_addr, avail_addr, used_addr; @@ -288,6 +360,17 @@ virtio_user_setup_queue(struct virtio_hw *hw, struct virtqueue *vq) dev->vrings[queue_idx].desc = (void *)(uintptr_t)desc_addr; dev->vrings[queue_idx].avail = (void *)(uintptr_t)avail_addr; dev->vrings[queue_idx].used = (void *)(uintptr_t)used_addr; +} + +static int +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)) + virtio_user_setup_queue_packed(vq, dev); + else + virtio_user_setup_queue_split(vq, dev); return 0; } @@ -317,7 +400,10 @@ 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)) { - virtio_user_handle_cq(dev, vq->vq_queue_index); + if (vtpci_packed_queue(vq->hw)) + virtio_user_handle_cq_packed(dev, vq->vq_queue_index); + else + virtio_user_handle_cq(dev, vq->vq_queue_index); return; } @@ -398,8 +484,6 @@ get_integer_arg(const char *key __rte_unused, return 0; } -static struct rte_vdev_driver virtio_user_driver; - static struct rte_eth_dev * virtio_user_eth_dev_alloc(struct rte_vdev_device *vdev) { @@ -472,6 +556,26 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev) char *mac_addr = NULL; int ret = -1; + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { + const char *name = rte_vdev_device_name(dev); + eth_dev = rte_eth_dev_attach_secondary(name); + if (!eth_dev) { + RTE_LOG(ERR, PMD, "Failed to probe %s\n", name); + return -1; + } + + if (eth_virtio_dev_init(eth_dev) < 0) { + PMD_INIT_LOG(ERR, "eth_virtio_dev_init fails"); + rte_eth_dev_release_port(eth_dev); + return -1; + } + + eth_dev->dev_ops = &virtio_user_secondary_eth_dev_ops; + eth_dev->device = &dev->device; + rte_eth_dev_probing_finish(eth_dev); + return 0; + } + kvlist = rte_kvargs_parse(rte_vdev_device_args(dev), valid_args); if (!kvlist) { PMD_INIT_LOG(ERR, "error when parsing param"); @@ -593,33 +697,19 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev) } } - if (rte_eal_process_type() == RTE_PROC_PRIMARY) { - struct virtio_user_dev *vu_dev; - - eth_dev = virtio_user_eth_dev_alloc(dev); - if (!eth_dev) { - PMD_INIT_LOG(ERR, "virtio_user fails to alloc device"); - goto end; - } - - hw = eth_dev->data->dev_private; - vu_dev = virtio_user_get_dev(hw); - if (server_mode == 1) - vu_dev->is_server = true; - else - vu_dev->is_server = false; - if (virtio_user_dev_init(hw->virtio_user_dev, path, queues, cq, - queue_size, mac_addr, &ifname, mrg_rxbuf, - in_order, packed_vq) < 0) { - PMD_INIT_LOG(ERR, "virtio_user_dev_init fails"); - virtio_user_eth_dev_free(eth_dev); - goto end; - } + eth_dev = virtio_user_eth_dev_alloc(dev); + if (!eth_dev) { + PMD_INIT_LOG(ERR, "virtio_user fails to alloc device"); + goto end; + } - } else { - eth_dev = rte_eth_dev_attach_secondary(rte_vdev_device_name(dev)); - if (!eth_dev) - goto end; + hw = eth_dev->data->dev_private; + if (virtio_user_dev_init(hw->virtio_user_dev, path, queues, cq, + queue_size, mac_addr, &ifname, server_mode, + mrg_rxbuf, in_order, packed_vq) < 0) { + PMD_INIT_LOG(ERR, "virtio_user_dev_init fails"); + virtio_user_eth_dev_free(eth_dev); + goto end; } /* previously called by rte_pci_probe() for physical dev */ @@ -649,8 +739,6 @@ virtio_user_pmd_remove(struct rte_vdev_device *vdev) { const char *name; struct rte_eth_dev *eth_dev; - struct virtio_hw *hw; - struct virtio_user_dev *dev; if (!vdev) return -EINVAL; @@ -658,18 +746,16 @@ virtio_user_pmd_remove(struct rte_vdev_device *vdev) name = rte_vdev_device_name(vdev); PMD_DRV_LOG(INFO, "Un-Initializing %s", name); eth_dev = rte_eth_dev_allocated(name); + /* Port has already been released by close. */ if (!eth_dev) - return -ENODEV; + return 0; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return rte_eth_dev_release_port(eth_dev); /* make sure the device is stopped, queues freed */ rte_eth_dev_close(eth_dev->data->port_id); - hw = eth_dev->data->dev_private; - dev = hw->virtio_user_dev; - virtio_user_dev_uninit(dev); - - rte_eth_dev_release_port(eth_dev); - return 0; }