diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 0000000..3de1ac7
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,188 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <rte_dev.h>
+#include <rte_devargs.h>
+#include <rte_debug.h>
+#include <rte_devargs.h>
+#include <rte_log.h>
+
+#include "eal_private.h"
+
+/** @internal
+ * Add a device to a bus.
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
+{
+	/* XXX all the additions can be address ordered ?
+	 * for example, calling rte_eal_compare_pci_addr and getting <=
+	 * and performing insert a specific location
+	 */
+	RTE_VERIFY(bus);
+	RTE_VERIFY(dev);
+
+	TAILQ_INSERT_TAIL(&bus->device_list, dev, next);
+}
+
+/** @internal
+ * Remove a device from its bus.
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev)
+{
+	struct rte_bus *bus;
+	RTE_VERIFY(bus);
+	RTE_VERIFY(dev);
+
+	bus = dev->bus;
+	TAILQ_REMOVE(&bus->device_list, dev, next);
+}
+
+/** @internal
+ * Associate a driver with a bus.
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(drv);
+
+	TAILQ_INSERT_TAIL(&bus->driver_list, drv, next);
+}
+
+/** @internal
+ * Disassociate a driver from bus.
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv)
+{
+	struct rte_bus *bus;
+	RTE_VERIFY(bus);
+	RTE_VERIFY(drv);
+
+	bus = drv->bus;
+	TAILQ_REMOVE(&bus->driver_list, dev, next);
+}
+
+/**
+ * Scan all the associated buses
+ */
+int
+rte_eal_bus_scan(void)
+{
+	int ret = 0;
+	struct rte_bus *bus;
+
+	if (TAILQ_EMPTY(&rte_bus_list)) {
+		return 0;
+	}
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for [%s] bus failed.\n",
+				bus->name);
+			continue; /* not a reason to break other bus scan */
+		}
+	}
+
+	/* This function essentially never returns an error - in case of error
+	 * no devices (or limited devices) are available to the application
+	 * which then can fail/report error.
+	 */
+	return 0;
+}
+
+/**
+ * Get the bus handle using its name
+ */
+struct rte_bus *
+rte_eal_get_bus(const char *bus_name)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(bus_name);
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		RTE_VERIFY(bus->name);
+
+		if (!strncmp(bus_name, bus->name)) {
+			RTE_LOG(DEBUG, EAL, "Returning Bus object %p\n", bus);
+			return bus;
+		}
+	}
+
+	/* Unable to find bus requested */
+	return NULL;
+}
+
+/* register a bus */
+void
+rte_eal_bus_register(struct rte_bus *bus)
+{
+	/* 3 conditions must meet:
+	 * 1. scan hook should be defined.
+	 * 2. match hook should be defined.
+	 * 3. Name should be a valid string. (valid?)
+	 */
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->probe);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	/* Initialize the driver and device list associated with the bus */
+	TAILQ_HEAD_INITIALIZER(&(bus->driver_list));
+	TAILQ_HEAD_INITIALIZER(&(bus->device_list));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+/* unregister a bus */
+void
+rte_eal_bus_unregister(struct rte_bus *bus)
+{
+	/* All devices and drivers associated with the bus should have been
+	 * 'device->uninit' and 'driver->remove()' already.
+	 */
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->driver_list)));
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->device_list)));
+
+	TAILQ_REMOVE(&rte_bus_list, bus, next);
+}
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..bb8d266 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -45,35 +45,44 @@
 
 #include "eal_private.h"
 
-/** Global list of device drivers. */
-static struct rte_driver_list dev_driver_list =
-	TAILQ_HEAD_INITIALIZER(dev_driver_list);
-/** Global list of device drivers. */
-static struct rte_device_list dev_device_list =
-	TAILQ_HEAD_INITIALIZER(dev_device_list);
-
 /* register a driver */
 void
 rte_eal_driver_register(struct rte_driver *driver)
 {
-	TAILQ_INSERT_TAIL(&dev_driver_list, driver, next);
+	struct rte_bus *bus;
+
+	RTE_VERIFY(driver && driver->bus);
+	bus = driver->bus;
+	TAILQ_INSERT_TAIL(&(bus->driver_list), driver, next);
 }
 
 /* unregister a driver */
 void
 rte_eal_driver_unregister(struct rte_driver *driver)
 {
-	TAILQ_REMOVE(&dev_driver_list, driver, next);
+	struct rte_bus;
+
+	RTE_VERIFY(driver && driver->bus);
+	bus = driver->bus;
+	TAILQ_REMOVE(&(bus->driver_list), driver, next);
 }
 
 void rte_eal_device_insert(struct rte_device *dev)
 {
-	TAILQ_INSERT_TAIL(&dev_device_list, dev, next);
+	struct rte_bus *bus;
+
+	RTE_VERIFY(dev && dev->bus);
+	bus = dev->bus;
+	TAILQ_INSERT_TAIL(&(bus->device_list), dev, next);
 }
 
 void rte_eal_device_remove(struct rte_device *dev)
 {
-	TAILQ_REMOVE(&dev_device_list, dev, next);
+	struct rte_bus *bus;
+
+	RTE_VERIFY(dev && dev->bus);
+	bus = dev->bus;
+	TAILQ_REMOVE(&(bus->device_list), dev, next);
 }
 
 int
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 971ad20..7a6d258 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -82,12 +82,13 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-	TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
+#define PCI_BUS_NAME "pci_bus"
+
+static struct rte_bus_list pci_bus_list =
+	TAILQ_HEAD_INITIALIZER(pci_bus_list);
+
+struct rte_bus pci_bus;
 
 const char *pci_get_sysfs_path(void)
 {
@@ -160,64 +161,40 @@ static int
 rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
 {
 	int ret;
-	const struct rte_pci_id *id_table;
-
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
-
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-				id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-				id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->class_id != dev->id.class_id &&
-				id_table->class_id != RTE_CLASS_ANY_ID)
-			continue;
-
-		struct rte_pci_addr *loc = &dev->addr;
-
-		RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid, loc->function,
-				dev->device.numa_node);
-
-		/* no initialization when blacklisted, return without error */
-		if (dev->device.devargs != NULL &&
-			dev->device.devargs->type ==
-				RTE_DEVTYPE_BLACKLISTED_PCI) {
-			RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
-			return 1;
-		}
-
-		RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	struct rte_pci_addr *loc = &dev->addr;
+
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			dev->device.numa_node);
+
+	/* no initialization when blacklisted, return without error */
+	if (dev->device.devargs != NULL &&
+		dev->device.devargs->type ==
+			RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
+		return 1;
+	}
 
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-			/* map resources for devices that use igb_uio */
-			ret = rte_eal_pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
-				rte_eal_process_type() == RTE_PROC_PRIMARY) {
-			/* unbind current driver */
-			if (pci_unbind_kernel_driver(dev) < 0)
-				return -1;
-		}
+	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+			dev->id.device_id, dr->driver.name);
+
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+		/* map resources for devices that use igb_uio */
+		ret = rte_eal_pci_map_device(dev);
+		if (ret != 0)
+			return ret;
+	} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
+			rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		/* unbind current driver */
+		if (pci_unbind_kernel_driver(dev) < 0)
+			return -1;
+	}
 
-		/* reference driver structure */
-		dev->driver = dr;
+	/* reference driver structure */
+	dev->driver = dr;
 
-		/* call the driver probe() function */
-		return dr->probe(dr, dev);
-	}
-	/* return positive value if driver doesn't support this device */
-	return 1;
+	/* call the driver probe() function */
+	return dr->probe(dr, dev);
 }
 
 /*
@@ -284,6 +261,7 @@ static int
 pci_probe_all_drivers(struct rte_pci_device *dev)
 {
 	struct rte_pci_driver *dr = NULL;
+	struct rte_bus *pci_bus;
 	int rc = 0;
 
 	if (dev == NULL)
@@ -293,15 +271,21 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
-		rc = rte_eal_pci_probe_one_driver(dr, dev);
-		if (rc < 0)
-			/* negative value is an error */
-			return -1;
-		if (rc > 0)
-			/* positive value means driver doesn't support it */
-			continue;
-		return 0;
+	TAILQ_FOREACH(dr, &(pci_bus->driver_list), next) {
+		rc = pci_bus->match(dr, dev);
+		if (!rc) {
+			rc = rte_eal_pci_probe_one_driver(dr, dev);
+			if (rc < 0)
+				/* negative value is an error */
+				return -1;
+			if (rc > 0)
+				/* positive value means driver doesn't support
+				 * it
+				 */
+				continue;
+			return 0;
+		}
+		/* Else, continue to next driver */
 	}
 	return 1;
 }
@@ -314,13 +298,19 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 static int
 pci_detach_all_drivers(struct rte_pci_device *dev)
 {
-	struct rte_pci_driver *dr = NULL;
+	struct rte_pci_driver *pci_drv= NULL;
+	struct rte_driver *drv = NULL;
+	struct rte_bus *pci_bus;
 	int rc = 0;
 
 	if (dev == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	RTE_VERIFY(dev->device->bus);
+	pci_bus = dev->device->bus;
+
+	TAILQ_FOREACH(drv, &pci_bus->driver_list, next) {
+		pci_drv = container_of(drv, struct rte_pci_driver, driver);
 		rc = rte_eal_pci_detach_dev(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -340,19 +330,28 @@ pci_detach_all_drivers(struct rte_pci_device *dev)
 int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
-	struct rte_pci_device *dev = NULL;
+	struct rte_bus *pci_bus = NULL;
+	struct rte_device *dev = NULL;
+	struct rte_pci_device *pci_dev = NULL;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
+	pci_bus = rte_eal_get_bus(PCI_BUS_NAME);
+	if (!pci_bus) {
+		RTE_LOG(DEBUG, EAL, "Unable to find PCI bus\n");
+		return -1;
+	}
+
 	/* update current pci device in global list, kernel bindings might have
 	 * changed since last time we looked at it.
 	 */
 	if (pci_update_device(addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(dev, &pci_bus->device_list, next) {
+		pci_dev = container_of(dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -376,22 +375,31 @@ err_return:
 int
 rte_eal_pci_detach(const struct rte_pci_addr *addr)
 {
-	struct rte_pci_device *dev = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct rte_bus *pci_bus = NULL;
+	struct rte_device *dev = NULL;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
-		if (rte_eal_compare_pci_addr(&dev->addr, addr))
+	pci_bus = rte_eal_get_bus(PCI_BUS_NAME);
+	if (!pci_bus) {
+		RTE_LOG(DEBUG, EAL, "Unable to find PCI bus\n");
+		return -1;
+	}
+
+	TAILQ_FOREACH(dev, &(bus->device_list), next) {
+		pci_dev = container_of(dev, struct rte_pci_device, device);
+		if (rte_eal_compare_pci_addr(&pci_dev->addr, addr))
 			continue;
 
-		ret = pci_detach_all_drivers(dev);
+		ret = pci_detach_all_drivers(pci_dev);
 		if (ret < 0)
 			goto err_return;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
-		free(dev);
+		TAILQ_REMOVE(&pci_bus->device_list, dev, next);
+		free(pci_dev);
 		return 0;
 	}
 	return -1;
@@ -411,31 +419,42 @@ err_return:
 int
 rte_eal_pci_probe(void)
 {
-	struct rte_pci_device *dev = NULL;
+	struct rte_device *dev = NULL;
+	struct rte_bus *pci_bus;
+	struct rte_pci_device *pci_dev;
 	struct rte_devargs *devargs;
 	int probe_all = 0;
 	int ret = 0;
 
+	pci_bus = rte_eal_get_bus(PCI_BUS_NAME);
+	if (!pci_bus) {
+		RTE_LOG(INFO, EAL, "(%s): No such bus exists\n", PCI_BUS_NAME);
+		/* Cannot continue ahead and this is not an error */
+		return;
+	}
+
 	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
 		probe_all = 1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(dev, &(pci_bus->device_list), next) {
+		pci_dev = container_of(dev, struct rte_pci_device, device);
 
 		/* set devargs in PCI structure */
-		devargs = pci_devargs_lookup(dev);
+		devargs = pci_devargs_lookup(pci_dev);
 		if (devargs != NULL)
-			dev->device.devargs = devargs;
+			pci_dev->device.devargs = devargs;
 
 		/* probe all or only whitelisted devices */
 		if (probe_all)
-			ret = pci_probe_all_drivers(dev);
+			ret = pci_probe_all_drivers(pci_dev);`
 		else if (devargs != NULL &&
 			devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
-			ret = pci_probe_all_drivers(dev);
+			ret = pci_probe_all_drivers(pci_dev);
 		if (ret < 0)
 			rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT
-				 " cannot be used\n", dev->addr.domain, dev->addr.bus,
-				 dev->addr.devid, dev->addr.function);
+				 " cannot be used\n", pci_dev->addr.domain,
+				 pci_dev->addr.bus, pci_dev->addr.devid,
+				 pci_dev->addr.function);
 	}
 
 	return 0;
@@ -465,10 +484,19 @@ pci_dump_one_device(FILE *f, struct rte_pci_device *dev)
 void
 rte_eal_pci_dump(FILE *f)
 {
-	struct rte_pci_device *dev = NULL;
+	struct rte_device *dev = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct rte_bus *bus;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
-		pci_dump_one_device(f, dev);
+	bus = rte_eal_get_bus(PCI_BUS_NAME);
+	if (!bus) {
+		RTE_LOG(INFO, EAL, "(%s): No such bus exists\n", PCI_BUS_NAME);
+		return;
+	}
+
+	TAILQ_FOREACH(dev, &(bus->device_list), next) {
+		pci_dev = container_of(dev, struct rte_pci_device, device);
+		pci_dump_one_device(f, pci_dev);
 	}
 }
 
@@ -476,7 +504,16 @@ rte_eal_pci_dump(FILE *f)
 void
 rte_eal_pci_register(struct rte_pci_driver *driver)
 {
-	TAILQ_INSERT_TAIL(&pci_driver_list, driver, next);
+	struct rte_bus *pci_bus;
+
+	pci_bus = rte_eal_get_bus(PCI_BUS_NAME);
+	if (!pci_bus) {
+		RTE_LOG(INFO, EAL, "(%s) No such bus exists\n", PCI_BUS_NAME);
+		return;
+		/* TODO: How to return error from here? */
+	}
+
+	driver->driver->bus = pci_bus;
 	rte_eal_driver_register(&driver->driver);
 }
 
@@ -484,6 +521,9 @@ rte_eal_pci_register(struct rte_pci_driver *driver)
 void
 rte_eal_pci_unregister(struct rte_pci_driver *driver)
 {
-	rte_eal_driver_unregister(&driver->driver);
-	TAILQ_REMOVE(&pci_driver_list, driver, next);
+	struct rte_bus *pci_bus;
+
+	pci_bus = driver->driver->bus;
+	rte_eal_driver_unregister(&pci_bus, &driver->driver);
+	driver->driver->bus = NULL;
 }
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 9ce8847..cffc449 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -110,7 +110,7 @@ const char *pci_get_sysfs_path(void);
 
 /** Maximum number of PCI resources. */
 #define PCI_MAX_RESOURCE 6
-
+/
 /**
  * A structure describing an ID for a PCI driver. Each driver provides a
  * table of these IDs for each device that it supports.
@@ -360,15 +360,6 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 }
 
 /**
- * Scan the content of the PCI bus, and the devices in the devices
- * list
- *
- * @return
- *  0 on success, negative on error
- */
-int rte_eal_pci_scan(void);
-
-/**
  * Probe the PCI bus for registered drivers.
  *
  * Scan the content of the PCI bus, and call the probe() function for
