The hyper-v device driver forces the base EAL code to change
to support multiple bus types. This is done changing the pci_device
in ether driver to a generic union.

As much as possible this is done in a backwards source compatiable
way. It will break ABI for device drivers.

Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
---
 lib/librte_eal/common/Makefile             |   2 +-
 lib/librte_eal/common/eal_common_options.c |   5 ++
 lib/librte_eal/common/eal_internal_cfg.h   |   1 +
 lib/librte_eal/common/eal_options.h        |   2 +
 lib/librte_eal/common/eal_private.h        |  10 +++
 lib/librte_eal/linuxapp/eal/Makefile       |   3 +
 lib/librte_eal/linuxapp/eal/eal.c          |  11 +++
 lib/librte_ether/rte_ethdev.c              | 128 +++++++++++++++++++++++++++--
 lib/librte_ether/rte_ethdev.h              |  15 +++-
 9 files changed, 168 insertions(+), 9 deletions(-)

diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index 3ea3bbf..202485e 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -33,7 +33,7 @@ include $(RTE_SDK)/mk/rte.vars.mk

 INC := rte_branch_prediction.h rte_common.h
 INC += rte_debug.h rte_eal.h rte_errno.h rte_launch.h rte_lcore.h
-INC += rte_log.h rte_memory.h rte_memzone.h rte_pci.h
+INC += rte_log.h rte_memory.h rte_memzone.h rte_pci.h rte_vmbus.h
 INC += rte_pci_dev_ids.h rte_per_lcore.h rte_random.h
 INC += rte_rwlock.h rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
diff --git a/lib/librte_eal/common/eal_common_options.c 
b/lib/librte_eal/common/eal_common_options.c
index 8fcb1ab..76a3394 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -80,6 +80,7 @@ eal_long_options[] = {
        {OPT_NO_HPET,           0, NULL, OPT_NO_HPET_NUM          },
        {OPT_NO_HUGE,           0, NULL, OPT_NO_HUGE_NUM          },
        {OPT_NO_PCI,            0, NULL, OPT_NO_PCI_NUM           },
+       {OPT_NO_VMBUS,          0, NULL, OPT_NO_VMBUS_NUM         },
        {OPT_NO_SHCONF,         0, NULL, OPT_NO_SHCONF_NUM        },
        {OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
        {OPT_PCI_WHITELIST,     1, NULL, OPT_PCI_WHITELIST_NUM    },
@@ -726,6 +727,10 @@ eal_parse_common_option(int opt, const char *optarg,
                conf->no_pci = 1;
                break;

+       case OPT_NO_VMBUS_NUM:
+               conf->no_vmbus = 1;
+               break;
+
        case OPT_NO_HPET_NUM:
                conf->no_hpet = 1;
                break;
diff --git a/lib/librte_eal/common/eal_internal_cfg.h 
b/lib/librte_eal/common/eal_internal_cfg.h
index e2ecb0d..0e7de34 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -66,6 +66,7 @@ struct internal_config {
        volatile unsigned no_hugetlbfs;   /**< true to disable hugetlbfs */
        volatile unsigned xen_dom0_support; /**< support app running on Xen 
Dom0*/
        volatile unsigned no_pci;         /**< true to disable PCI */
+       volatile unsigned no_vmbus;       /**< true to disable VMBUS */
        volatile unsigned no_hpet;        /**< true to disable HPET */
        volatile unsigned vmware_tsc_map; /**< true to use VMware TSC mapping
                                                                                
* instead of native TSC */
diff --git a/lib/librte_eal/common/eal_options.h 
b/lib/librte_eal/common/eal_options.h
index f6714d9..54f03dc 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -67,6 +67,8 @@ enum {
        OPT_NO_HUGE_NUM,
 #define OPT_NO_PCI            "no-pci"
        OPT_NO_PCI_NUM,
+#define OPT_NO_VMBUS          "no-vmbus"
+       OPT_NO_VMBUS_NUM,
 #define OPT_NO_SHCONF         "no-shconf"
        OPT_NO_SHCONF_NUM,
 #define OPT_SOCKET_MEM        "socket-mem"
diff --git a/lib/librte_eal/common/eal_private.h 
b/lib/librte_eal/common/eal_private.h
index 4acf5a0..039e9f3 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -180,6 +180,16 @@ int rte_eal_pci_close_one_driver(struct rte_pci_driver *dr,
                struct rte_pci_device *dev);

 /**
+ * VMBUS related functions and structures
+ */
+int rte_eal_vmbus_init(void);
+
+struct rte_vmbus_driver;
+struct rte_vmbus_device;
+
+int rte_eal_vmbus_probe_one_driver(struct rte_vmbus_driver *dr,
+               struct rte_vmbus_device *dev);
+/**
  * Init tail queues for non-EAL library structures. This is to allow
  * the rings, mempools, etc. lists to be shared among multiple processes
  *
diff --git a/lib/librte_eal/linuxapp/eal/Makefile 
b/lib/librte_eal/linuxapp/eal/Makefile
index 01f7b70..acd5127 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -74,6 +74,9 @@ SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_alarm.c
 ifeq ($(CONFIG_RTE_LIBRTE_IVSHMEM),y)
 SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_ivshmem.c
 endif
+ifeq ($(CONFIG_RTE_LIBRTE_HV_PMD),y)
+SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_vmbus.c
+endif

 # from common dir
 SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_memzone.c
diff --git a/lib/librte_eal/linuxapp/eal/eal.c 
b/lib/librte_eal/linuxapp/eal/eal.c
index bd770cf..86d0e31 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -70,6 +70,7 @@
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
 #include <rte_pci.h>
+#include <rte_vmbus.h>
 #include <rte_devargs.h>
 #include <rte_common.h>
 #include <rte_version.h>
@@ -796,6 +797,11 @@ rte_eal_init(int argc, char **argv)

        rte_eal_mcfg_complete();

+#ifdef RTE_LIBRTE_HV_PMD
+       if (rte_eal_vmbus_init() < 0)
+               RTE_LOG(ERR, EAL, "Cannot init VMBUS\n");
+#endif
+
        TAILQ_FOREACH(solib, &solib_list, next) {
                RTE_LOG(INFO, EAL, "open shared lib %s\n", solib->name);
                solib->lib_handle = dlopen(solib->name, RTLD_NOW);
@@ -845,6 +851,11 @@ rte_eal_init(int argc, char **argv)
        if (rte_eal_pci_probe())
                rte_panic("Cannot probe PCI\n");

+#ifdef RTE_LIBRTE_HV_PMD
+       if (rte_eal_vmbus_probe() < 0)
+               rte_panic("Cannot probe VMBUS\n");
+#endif
+
        return fctret;
 }

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 9577d17..9093966 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -379,6 +379,98 @@ rte_eth_dev_uninit(struct rte_pci_device *pci_dev)
        return 0;
 }

+#ifdef RTE_LIBRTE_HV_PMD
+static int
+rte_vmbus_dev_init(struct rte_vmbus_driver *vmbus_drv,
+                  struct rte_vmbus_device *vmbus_dev)
+{
+       struct eth_driver  *eth_drv = (struct eth_driver *)vmbus_drv;
+       struct rte_eth_dev *eth_dev;
+       char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+       int diag;
+
+       snprintf(ethdev_name, RTE_ETH_NAME_MAX_LEN, "%u_%u",
+                vmbus_dev->id.device_id, vmbus_dev->id.sysfs_num);
+
+       eth_dev = rte_eth_dev_allocate(ethdev_name, RTE_ETH_DEV_PCI);
+       if (eth_dev == NULL)
+               return -ENOMEM;
+
+       if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+               eth_dev->data->dev_private = rte_zmalloc("ethdev private 
structure",
+                                 eth_drv->dev_private_size,
+                                 RTE_CACHE_LINE_SIZE);
+               if (eth_dev->data->dev_private == NULL)
+                       rte_panic("Cannot allocate memzone for private port 
data\n");
+       }
+       eth_dev->vmbus_dev = vmbus_dev;
+       eth_dev->driver = eth_drv;
+       eth_dev->data->rx_mbuf_alloc_failed = 0;
+
+       /* init user callbacks */
+       TAILQ_INIT(&(eth_dev->link_intr_cbs));
+
+       /*
+        * Set the default maximum frame size.
+        */
+       eth_dev->data->mtu = ETHER_MTU;
+
+       /* Invoke PMD device initialization function */
+       diag = (*eth_drv->eth_dev_init)(eth_dev);
+       if (diag == 0)
+               return 0;
+
+       PMD_DEBUG_TRACE("driver %s: eth_dev_init(device_id=0x%x)"
+                       " failed\n", vmbus_drv->name,
+                       (unsigned) vmbus_dev->id.device_id);
+       if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+               rte_free(eth_dev->data->dev_private);
+       nb_ports--;
+       return diag;
+}
+
+
+static int
+rte_vmbus_dev_uninit(struct rte_vmbus_device *vmbus_dev)
+{
+       const struct eth_driver *eth_drv;
+       struct rte_eth_dev *eth_dev;
+       char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+       int ret;
+
+       if (vmbus_dev == NULL)
+               return -EINVAL;
+
+       snprintf(ethdev_name, RTE_ETH_NAME_MAX_LEN, "%u_%u",
+                vmbus_dev->id.device_id, vmbus_dev->id.sysfs_num);
+
+       eth_dev = rte_eth_dev_allocated(ethdev_name);
+       if (eth_dev == NULL)
+               return -ENODEV;
+
+       eth_drv = (const struct eth_driver *)vmbus_dev->driver;
+
+       /* Invoke PMD device uninit function */
+       if (*eth_drv->eth_dev_uninit) {
+               ret = (*eth_drv->eth_dev_uninit)(eth_dev);
+               if (ret)
+                       return ret;
+       }
+
+       /* free ether device */
+       rte_eth_dev_release_port(eth_dev);
+
+       if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+               rte_free(eth_dev->data->dev_private);
+
+       eth_dev->pci_dev = NULL;
+       eth_dev->driver = NULL;
+       eth_dev->data = NULL;
+
+       return 0;
+}
+#endif
+
 /**
  * Register an Ethernet [Poll Mode] driver.
  *
@@ -396,9 +488,22 @@ rte_eth_dev_uninit(struct rte_pci_device *pci_dev)
 void
 rte_eth_driver_register(struct eth_driver *eth_drv)
 {
-       eth_drv->pci_drv.devinit = rte_eth_dev_init;
-       eth_drv->pci_drv.devuninit = rte_eth_dev_uninit;
-       rte_eal_pci_register(&eth_drv->pci_drv);
+       switch (eth_drv->bus_type) {
+       case RTE_BUS_PCI:
+               eth_drv->pci_drv.devinit = rte_eth_dev_init;
+               eth_drv->pci_drv.devuninit = rte_eth_dev_uninit;
+               rte_eal_pci_register(&eth_drv->pci_drv);
+               break;
+#ifdef RTE_LIBRTE_HV_PMD
+       case RTE_BUS_VMBUS:
+               eth_drv->vmbus_drv.devinit = rte_vmbus_dev_init;
+               eth_drv->vmbus_drv.devuninit = rte_vmbus_dev_uninit;
+               rte_eal_vmbus_register(&eth_drv->vmbus_drv);
+               break;
+#endif
+       default:
+               rte_panic("unknown bus type %u\n", eth_drv->bus_type);
+       }
 }

 static int
@@ -1351,6 +1456,9 @@ rte_eth_has_link_state(uint8_t port_id)
        }
        dev = &rte_eth_devices[port_id];

+       if (dev->driver->bus_type != RTE_BUS_PCI)
+               return 0;
+
        return (dev->pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) != 0;
 }

@@ -1901,9 +2009,17 @@ rte_eth_dev_info_get(uint8_t port_id, struct 
rte_eth_dev_info *dev_info)

        FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
        (*dev->dev_ops->dev_infos_get)(dev, dev_info);
-       dev_info->pci_dev = dev->pci_dev;
-       if (dev->driver)
-               dev_info->driver_name = dev->driver->pci_drv.name;
+
+       if (dev->driver) {
+               switch (dev->driver->bus_type) {
+               case RTE_BUS_PCI:
+                       dev_info->driver_name = dev->driver->pci_drv.name;
+                       dev_info->pci_dev = dev->pci_dev;
+                       break;
+               case RTE_BUS_VMBUS:
+                       dev_info->driver_name = dev->driver->vmbus_drv.name;
+               }
+       }
 }

 void
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 991023b..9e08f3e 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -178,6 +178,7 @@ extern "C" {
 #include <rte_log.h>
 #include <rte_interrupts.h>
 #include <rte_pci.h>
+#include <rte_vmbus.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
 #include <rte_mbuf.h>
@@ -1477,7 +1478,10 @@ struct rte_eth_dev {
        struct rte_eth_dev_data *data;  /**< Pointer to device data */
        const struct eth_driver *driver;/**< Driver for this device */
        const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */
-       struct rte_pci_device *pci_dev; /**< PCI info. supplied by probing */
+       union {
+               struct rte_pci_device *pci_dev; /**< PCI info. supplied by 
probig */
+               struct rte_vmbus_device *vmbus_dev; /**< VMBUS info. supplied 
by probing */
+       };
        /** User application callbacks for NIC interrupts */
        struct rte_eth_dev_cb_list link_intr_cbs;
        /**
@@ -1696,7 +1700,14 @@ typedef int (*eth_dev_uninit_t)(struct rte_eth_dev 
*eth_dev);
  * - The size of the private data to allocate for each matching device.
  */
 struct eth_driver {
-       struct rte_pci_driver pci_drv;    /**< The PMD is also a PCI driver. */
+       union {
+               struct rte_pci_driver pci_drv;    /**< The PMD is also a PCI 
driver. */
+               struct rte_vmbus_driver vmbus_drv;/**< The PMD is also a VMBUS 
drv. */
+       };
+       enum {
+               RTE_BUS_PCI=0,
+               RTE_BUS_VMBUS
+       } bus_type;                       /**< Device bus type. */
        eth_dev_init_t eth_dev_init;      /**< Device init function. */
        eth_dev_uninit_t eth_dev_uninit;  /**< Device uninit function. */
        unsigned int dev_private_size;    /**< Size of device private data. */
-- 
2.1.4

Reply via email to