net/virtio: fix link status always being up
[dpdk.git] / drivers / net / virtio / virtio_ethdev.c
index d9986ab..e6c57b3 100644 (file)
@@ -38,6 +38,7 @@
 #include <unistd.h>
 
 #include <rte_ethdev.h>
+#include <rte_ethdev_pci.h>
 #include <rte_memcpy.h>
 #include <rte_string_fns.h>
 #include <rte_memzone.h>
@@ -1205,9 +1206,8 @@ virtio_negotiate_features(struct virtio_hw *hw, uint64_t req_features)
  * Process Virtio Config changed interrupt and call the callback
  * if link state changed.
  */
-static void
-virtio_interrupt_handler(struct rte_intr_handle *handle,
-                        void *param)
+void
+virtio_interrupt_handler(void *param)
 {
        struct rte_eth_dev *dev = param;
        struct virtio_hw *hw = dev->data->dev_private;
@@ -1217,7 +1217,7 @@ virtio_interrupt_handler(struct rte_intr_handle *handle,
        isr = vtpci_isr(hw);
        PMD_DRV_LOG(INFO, "interrupt status = %#x", isr);
 
-       if (rte_intr_enable(handle) < 0)
+       if (rte_intr_enable(dev->intr_handle) < 0)
                PMD_DRV_LOG(ERR, "interrupt enable failed");
 
        if (isr & VIRTIO_PCI_ISR_CONFIG) {
@@ -1613,19 +1613,26 @@ eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev)
        return 0;
 }
 
-static struct eth_driver rte_virtio_pmd = {
-       .pci_drv = {
-               .driver = {
-                       .name = "net_virtio",
-               },
-               .id_table = pci_id_virtio_map,
-               .drv_flags = 0,
-               .probe = rte_eth_dev_pci_probe,
-               .remove = rte_eth_dev_pci_remove,
+static int eth_virtio_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+       struct rte_pci_device *pci_dev)
+{
+       return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct virtio_hw),
+               eth_virtio_dev_init);
+}
+
+static int eth_virtio_pci_remove(struct rte_pci_device *pci_dev)
+{
+       return rte_eth_dev_pci_generic_remove(pci_dev, eth_virtio_dev_uninit);
+}
+
+static struct rte_pci_driver rte_virtio_pmd = {
+       .driver = {
+               .name = "net_virtio",
        },
-       .eth_dev_init = eth_virtio_dev_init,
-       .eth_dev_uninit = eth_virtio_dev_uninit,
-       .dev_private_size = sizeof(struct virtio_hw),
+       .id_table = pci_id_virtio_map,
+       .drv_flags = 0,
+       .probe = eth_virtio_pci_probe,
+       .remove = eth_virtio_pci_remove,
 };
 
 RTE_INIT(rte_virtio_pmd_init);
@@ -1637,7 +1644,7 @@ rte_virtio_pmd_init(void)
                return;
        }
 
-       rte_eal_pci_register(&rte_virtio_pmd.pci_drv);
+       rte_eal_pci_register(&rte_virtio_pmd);
 }
 
 /*
@@ -1769,6 +1776,7 @@ virtio_dev_start(struct rte_eth_dev *dev)
                txvq = dev->data->tx_queues[i];
                VIRTQUEUE_DUMP(txvq->vq);
        }
+       hw->started = 1;
 
        return 0;
 }
@@ -1824,6 +1832,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;
        struct rte_intr_conf *intr_conf = &dev->data->dev_conf.intr_conf;
 
@@ -1832,6 +1841,7 @@ virtio_dev_stop(struct rte_eth_dev *dev)
        if (intr_conf->lsc || intr_conf->rxq)
                rte_intr_disable(dev->intr_handle);
 
+       hw->started = 0;
        memset(&link, 0, sizeof(link));
        virtio_dev_atomic_write_link_status(dev, &link);
 }
@@ -1848,7 +1858,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),