New upstream version 16.11.3
[deb_dpdk.git] / drivers / net / virtio / virtio_ethdev.c
index f5961ab..67ebb1e 100644 (file)
@@ -423,7 +423,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;
@@ -545,6 +545,9 @@ virtio_free_queues(struct virtio_hw *hw)
        int queue_type;
        uint16_t i;
 
+       if (hw->vqs == NULL)
+               return;
+
        for (i = 0; i < nr_vq; i++) {
                vq = hw->vqs[i];
                if (!vq)
@@ -563,9 +566,11 @@ virtio_free_queues(struct virtio_hw *hw)
                }
 
                rte_free(vq);
+               hw->vqs[i] = NULL;
        }
 
        rte_free(hw->vqs);
+       hw->vqs = NULL;
 }
 
 static int
@@ -1210,11 +1215,11 @@ virtio_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features)
 
        rte_eth_copy_pci_info(eth_dev, pci_dev);
 
-       /* If host does not support status then disable LSC */
-       if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS))
-               eth_dev->data->dev_flags &= ~RTE_ETH_DEV_INTR_LSC;
-       else
+       /* If host does not support both status and MSI-X then disable LSC */
+       if (vtpci_with_feature(hw, VIRTIO_NET_F_STATUS) && hw->use_msix)
                eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
+       else
+               eth_dev->data->dev_flags &= ~RTE_ETH_DEV_INTR_LSC;
 
        rx_func_get(eth_dev);
 
@@ -1472,37 +1477,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;
        }
 
@@ -1550,9 +1537,6 @@ virtio_dev_start(struct rte_eth_dev *dev)
                }
        }
 
-       /* Initialize Link state */
-       virtio_dev_link_update(dev, 0);
-
        /*Notify the backend
         *Otherwise the tap backend might already stop its queue due to fullness.
         *vhost backend will have no chance to be waked up
@@ -1582,6 +1566,11 @@ virtio_dev_start(struct rte_eth_dev *dev)
                VIRTQUEUE_DUMP(txvq->vq);
        }
 
+       hw->started = 1;
+
+       /* Initialize Link state */
+       virtio_dev_link_update(dev, 0);
+
        return 0;
 }
 
@@ -1636,6 +1625,7 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev)
 static void
 virtio_dev_stop(struct rte_eth_dev *dev)
 {
+       struct virtio_hw *hw = dev->data->dev_private;
        struct rte_eth_link link;
 
        PMD_INIT_LOG(DEBUG, "stop");
@@ -1643,6 +1633,7 @@ virtio_dev_stop(struct rte_eth_dev *dev)
        if (dev->data->dev_conf.intr_conf.lsc)
                rte_intr_disable(&dev->pci_dev->intr_handle);
 
+       hw->started = 0;
        memset(&link, 0, sizeof(link));
        virtio_dev_atomic_write_link_status(dev, &link);
 }
@@ -1659,7 +1650,9 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet
        link.link_duplex = ETH_LINK_FULL_DUPLEX;
        link.link_speed  = SPEED_10G;
 
-       if (vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) {
+       if (hw->started == 0) {
+               link.link_status = ETH_LINK_DOWN;
+       } else if (vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) {
                PMD_INIT_LOG(DEBUG, "Get link status from hw");
                vtpci_read_dev_config(hw,
                                offsetof(struct virtio_net_config, status),
@@ -1703,8 +1696,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)) {