New upstream version 16.11.9
[deb_dpdk.git] / drivers / net / virtio / virtio_ethdev.c
index 452ad2a..6f950f0 100644 (file)
@@ -288,17 +288,6 @@ virtio_dev_queue_release(void *queue __rte_unused)
        /* do nothing */
 }
 
-static int
-virtio_get_queue_type(struct virtio_hw *hw, uint16_t vtpci_queue_idx)
-{
-       if (vtpci_queue_idx == hw->max_queue_pairs * 2)
-               return VTNET_CQ;
-       else if (vtpci_queue_idx % 2 == 0)
-               return VTNET_RQ;
-       else
-               return VTNET_TQ;
-}
-
 static uint16_t
 virtio_get_nr_vq(struct virtio_hw *hw)
 {
@@ -423,7 +412,7 @@ virtio_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx)
                }
        }
 
-       memset(mz->addr, 0, sizeof(mz->len));
+       memset(mz->addr, 0, mz->len);
 
        vq->vq_ring_mem = mz->phys_addr;
        vq->vq_ring_virt_mem = mz->addr;
@@ -847,7 +836,7 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
                /* Note: limit checked in rte_eth_xstats_names() */
 
                for (i = 0; i < dev->data->nb_rx_queues; i++) {
-                       struct virtqueue *rxvq = dev->data->rx_queues[i];
+                       struct virtnet_rx *rxvq = dev->data->rx_queues[i];
                        if (rxvq == NULL)
                                continue;
                        for (t = 0; t < VIRTIO_NB_RXQ_XSTATS; t++) {
@@ -860,7 +849,7 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
                }
 
                for (i = 0; i < dev->data->nb_tx_queues; i++) {
-                       struct virtqueue *txvq = dev->data->tx_queues[i];
+                       struct virtnet_tx *txvq = dev->data->tx_queues[i];
                        if (txvq == NULL)
                                continue;
                        for (t = 0; t < VIRTIO_NB_TXQ_XSTATS; t++) {
@@ -1205,6 +1194,11 @@ virtio_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features)
        /* Reset the device although not necessary at startup */
        vtpci_reset(hw);
 
+       if (hw->vqs) {
+               virtio_dev_free_mbufs(eth_dev);
+               virtio_free_queues(hw);
+       }
+
        /* Tell the host we've noticed this device. */
        vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_ACK);
 
@@ -1400,11 +1394,6 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev)
        if (ret < 0)
                return ret;
 
-       /* Setup interrupt callback  */
-       if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
-               rte_intr_callback_register(&pci_dev->intr_handle,
-                       virtio_interrupt_handler, eth_dev);
-
        return 0;
 }
 
@@ -1429,11 +1418,6 @@ eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev)
        rte_free(eth_dev->data->mac_addrs);
        eth_dev->data->mac_addrs = NULL;
 
-       /* reset interrupt callback  */
-       if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
-               rte_intr_callback_unregister(&pci_dev->intr_handle,
-                                               virtio_interrupt_handler,
-                                               eth_dev);
        rte_eal_pci_unmap_device(pci_dev);
 
        PMD_INIT_LOG(DEBUG, "dev_uninit completed");
@@ -1477,37 +1461,19 @@ virtio_dev_configure(struct rte_eth_dev *dev)
 {
        const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
        struct virtio_hw *hw = dev->data->dev_private;
-       uint64_t req_features;
-       int ret;
 
        PMD_INIT_LOG(DEBUG, "configure");
-       req_features = VIRTIO_PMD_DEFAULT_GUEST_FEATURES;
-       if (rxmode->hw_ip_checksum)
-               req_features |= (1ULL << VIRTIO_NET_F_GUEST_CSUM);
-       if (rxmode->enable_lro)
-               req_features |=
-                       (1ULL << VIRTIO_NET_F_GUEST_TSO4) |
-                       (1ULL << VIRTIO_NET_F_GUEST_TSO6);
-
-       /* if request features changed, reinit the device */
-       if (req_features != hw->req_guest_features) {
-               ret = virtio_init_device(dev, req_features);
-               if (ret < 0)
-                       return ret;
-       }
 
-       if (rxmode->hw_ip_checksum &&
-               !vtpci_with_feature(hw, VIRTIO_NET_F_GUEST_CSUM)) {
+       /* Virtio does L4 checksum but not L3! */
+       if (rxmode->hw_ip_checksum) {
                PMD_DRV_LOG(NOTICE,
-                       "rx ip checksum not available on this host");
+                           "virtio does not support IP checksum");
                return -ENOTSUP;
        }
 
-       if (rxmode->enable_lro &&
-               (!vtpci_with_feature(hw, VIRTIO_NET_F_GUEST_TSO4) ||
-                       !vtpci_with_feature(hw, VIRTIO_NET_F_GUEST_TSO4))) {
+       if (rxmode->enable_lro) {
                PMD_DRV_LOG(NOTICE,
-                       "lro not available on this host");
+                           "virtio does not support Large Receive Offload");
                return -ENOTSUP;
        }
 
@@ -1541,6 +1507,19 @@ virtio_dev_start(struct rte_eth_dev *dev)
        struct virtnet_rx *rxvq;
        struct virtnet_tx *txvq __rte_unused;
        struct virtio_hw *hw = dev->data->dev_private;
+       int ret;
+
+       /* Finish the initialization of the queues */
+       for (i = 0; i < dev->data->nb_rx_queues; i++) {
+               ret = virtio_dev_rx_queue_setup_finish(dev, i);
+               if (ret < 0)
+                       return ret;
+       }
+       for (i = 0; i < dev->data->nb_tx_queues; i++) {
+               ret = virtio_dev_tx_queue_setup_finish(dev, i);
+               if (ret < 0)
+                       return ret;
+       }
 
        /* check if lsc interrupt feature is enabled */
        if (dev->data->dev_conf.intr_conf.lsc) {
@@ -1549,6 +1528,12 @@ virtio_dev_start(struct rte_eth_dev *dev)
                        return -ENOTSUP;
                }
 
+               /* Setup interrupt callback  */
+               if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
+                       rte_intr_callback_register(&dev->pci_dev->intr_handle,
+                                                  virtio_interrupt_handler,
+                                                  dev);
+
                if (rte_intr_enable(&dev->pci_dev->intr_handle) < 0) {
                        PMD_DRV_LOG(ERR, "interrupt enable failed");
                        return -EIO;
@@ -1569,6 +1554,8 @@ virtio_dev_start(struct rte_eth_dev *dev)
 
        for (i = 0; i < dev->data->nb_rx_queues; i++) {
                rxvq = dev->data->rx_queues[i];
+               /* Flush the old packets */
+               virtqueue_rxvq_flush(rxvq->vq);
                virtqueue_notify(rxvq->vq);
        }
 
@@ -1600,12 +1587,15 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev)
        for (i = 0; i < dev->data->nb_rx_queues; i++) {
                struct virtnet_rx *rxvq = dev->data->rx_queues[i];
 
+               if (rxvq == NULL || rxvq->vq == NULL)
+                       continue;
+
                PMD_INIT_LOG(DEBUG,
                             "Before freeing rxq[%d] used and unused buf", i);
                VIRTQUEUE_DUMP(rxvq->vq);
 
                PMD_INIT_LOG(DEBUG, "rx_queues[%d]=%p", i, rxvq);
-               while ((buf = virtqueue_detatch_unused(rxvq->vq)) != NULL) {
+               while ((buf = virtqueue_detach_unused(rxvq->vq)) != NULL) {
                        rte_pktmbuf_free(buf);
                        mbuf_num++;
                }
@@ -1619,13 +1609,16 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev)
        for (i = 0; i < dev->data->nb_tx_queues; i++) {
                struct virtnet_tx *txvq = dev->data->tx_queues[i];
 
+               if (txvq == NULL || txvq->vq == NULL)
+                       continue;
+
                PMD_INIT_LOG(DEBUG,
                             "Before freeing txq[%d] used and unused bufs",
                             i);
                VIRTQUEUE_DUMP(txvq->vq);
 
                mbuf_num = 0;
-               while ((buf = virtqueue_detatch_unused(txvq->vq)) != NULL) {
+               while ((buf = virtqueue_detach_unused(txvq->vq)) != NULL) {
                        rte_pktmbuf_free(buf);
                        mbuf_num++;
                }
@@ -1648,9 +1641,17 @@ virtio_dev_stop(struct rte_eth_dev *dev)
 
        PMD_INIT_LOG(DEBUG, "stop");
 
-       if (dev->data->dev_conf.intr_conf.lsc)
+       if (dev->data->dev_conf.intr_conf.lsc) {
                rte_intr_disable(&dev->pci_dev->intr_handle);
 
+               /* Reset interrupt callback  */
+               if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) {
+                       rte_intr_callback_unregister(&dev->pci_dev->intr_handle,
+                                                    virtio_interrupt_handler,
+                                                    dev);
+               }
+       }
+
        hw->started = 0;
        memset(&link, 0, sizeof(link));
        virtio_dev_atomic_write_link_status(dev, &link);
@@ -1714,8 +1715,8 @@ virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
        };
        dev_info->rx_offload_capa =
                DEV_RX_OFFLOAD_TCP_CKSUM |
-               DEV_RX_OFFLOAD_UDP_CKSUM |
-               DEV_RX_OFFLOAD_TCP_LRO;
+               DEV_RX_OFFLOAD_UDP_CKSUM;
+
        dev_info->tx_offload_capa = 0;
 
        if (hw->guest_features & (1ULL << VIRTIO_NET_F_CSUM)) {