Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
new file mode 100644
index 0000000..1012db8
--- /dev/null
+++ b/drivers/pci/pcie/Kconfig
@@ -0,0 +1,36 @@
+#
+# PCI Express Port Bus Configuration
+#
+config PCIEPORTBUS
+	bool "PCI Express support"
+	depends on PCI
+	help
+	  This automatically enables PCI Express Port Bus support. Users can
+	  choose Native Hot-Plug support, Advanced Error Reporting support,
+	  Power Management Event support and Virtual Channel support to run
+	  on PCI Express Ports (Root or Switch).
+
+#
+# Include service Kconfig here
+#
+config HOTPLUG_PCI_PCIE
+	tristate "PCI Express Hotplug driver"
+	depends on HOTPLUG_PCI && PCIEPORTBUS
+	help
+	  Say Y here if you have a motherboard that supports PCI Express Native
+	  Hotplug
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pciehp.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_PCIE_POLL_EVENT_MODE
+	bool "Use polling mechanism for hot-plug events (for testing purpose)"
+	depends on HOTPLUG_PCI_PCIE
+	help
+	  Say Y here if you want to use the polling mechanism for hot-plug 
+	  events for early platform testing.
+	   
+	  When in doubt, say N.
+
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
new file mode 100644
index 0000000..984fa87
--- /dev/null
+++ b/drivers/pci/pcie/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for PCI-Express PORT Driver
+#
+
+pcieportdrv-y			:= portdrv_core.o portdrv_pci.o portdrv_bus.o
+
+obj-$(CONFIG_PCIEPORTBUS)	+= pcieportdrv.o
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
new file mode 100644
index 0000000..6c3ad89
--- /dev/null
+++ b/drivers/pci/pcie/portdrv.h
@@ -0,0 +1,41 @@
+/*
+ * File:	portdrv.h
+ * Purpose:	PCI Express Port Bus Driver's Internal Data Structures
+ *
+ * Copyright (C) 2004 Intel
+ * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
+ */
+
+#ifndef _PORTDRV_H_
+#define _PORTDRV_H_
+
+#if !defined(PCI_CAP_ID_PME)
+#define PCI_CAP_ID_PME			1
+#endif
+
+#if !defined(PCI_CAP_ID_EXP)
+#define PCI_CAP_ID_EXP			0x10
+#endif
+
+#define PORT_TYPE_MASK			0xf
+#define PORT_TO_SLOT_MASK		0x100
+#define SLOT_HP_CAPABLE_MASK		0x40
+#define PCIE_CAPABILITIES_REG		0x2
+#define PCIE_SLOT_CAPABILITIES_REG	0x14
+#define PCIE_PORT_DEVICE_MAXSERVICES	4
+#define PCI_CFG_SPACE_SIZE		256
+
+#define get_descriptor_id(type, service) (((type - 4) << 4) | service)
+
+extern struct bus_type pcie_port_bus_type;
+extern int pcie_port_device_probe(struct pci_dev *dev);
+extern int pcie_port_device_register(struct pci_dev *dev);
+#ifdef CONFIG_PM
+extern int pcie_port_device_suspend(struct pci_dev *dev, u32 state);
+extern int pcie_port_device_resume(struct pci_dev *dev);
+#endif
+extern void pcie_port_device_remove(struct pci_dev *dev);
+extern void pcie_port_bus_register(void);
+extern void pcie_port_bus_unregister(void);
+
+#endif /* _PORTDRV_H_ */
diff --git a/drivers/pci/pcie/portdrv_bus.c b/drivers/pci/pcie/portdrv_bus.c
new file mode 100644
index 0000000..9a02f28
--- /dev/null
+++ b/drivers/pci/pcie/portdrv_bus.c
@@ -0,0 +1,77 @@
+/*
+ * File:	portdrv_bus.c
+ * Purpose:	PCI Express Port Bus Driver's Bus Overloading Functions
+ *
+ * Copyright (C) 2004 Intel
+ * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+
+#include <linux/pcieport_if.h>
+
+static int pcie_port_bus_match(struct device *dev, struct device_driver *drv);
+static int pcie_port_bus_suspend(struct device *dev, u32 state);
+static int pcie_port_bus_resume(struct device *dev);
+
+struct bus_type pcie_port_bus_type = {
+	.name 		= "pci_express",
+	.match 		= pcie_port_bus_match,
+	.suspend	= pcie_port_bus_suspend,
+	.resume		= pcie_port_bus_resume, 
+};
+
+static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct pcie_device *pciedev;
+	struct pcie_port_service_driver *driver;
+
+	if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type)
+		return 0;
+	
+	pciedev = to_pcie_device(dev);
+	driver = to_service_driver(drv);
+	if (   (driver->id_table->vendor != PCI_ANY_ID && 
+		driver->id_table->vendor != pciedev->id.vendor) ||
+	       (driver->id_table->device != PCI_ANY_ID &&
+		driver->id_table->device != pciedev->id.device) ||	
+		driver->id_table->port_type != pciedev->id.port_type ||
+		driver->id_table->service_type != pciedev->id.service_type )
+		return 0;
+
+	return 1;
+}
+
+static int pcie_port_bus_suspend(struct device *dev, u32 state)
+{
+	struct pcie_device *pciedev;
+	struct pcie_port_service_driver *driver;
+
+	if (!dev || !dev->driver)
+		return 0;
+
+	pciedev = to_pcie_device(dev);
+ 	driver = to_service_driver(dev->driver);
+	if (driver && driver->suspend)
+		driver->suspend(pciedev, state);
+	return 0;
+}
+
+static int pcie_port_bus_resume(struct device *dev)
+{
+	struct pcie_device *pciedev;
+	struct pcie_port_service_driver *driver;
+
+	if (!dev || !dev->driver)
+		return 0;
+
+	pciedev = to_pcie_device(dev);
+ 	driver = to_service_driver(dev->driver);
+	if (driver && driver->resume)
+		driver->resume(pciedev);
+	return 0;
+}
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
new file mode 100644
index 0000000..127f64f
--- /dev/null
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -0,0 +1,434 @@
+/*
+ * File:	portdrv_core.c
+ * Purpose:	PCI Express Port Bus Driver's Core Functions
+ *
+ * Copyright (C) 2004 Intel
+ * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/pcieport_if.h>
+
+#include "portdrv.h"
+
+extern int pcie_mch_quirk;	/* MSI-quirk Indicator */
+
+static int pcie_port_probe_service(struct device *dev)
+{
+	struct pcie_device *pciedev;
+	struct pcie_port_service_driver *driver;
+	int status = -ENODEV;
+
+	if (!dev || !dev->driver)
+		return status;
+
+ 	driver = to_service_driver(dev->driver);
+	if (!driver || !driver->probe)
+		return status;
+
+	pciedev = to_pcie_device(dev);
+	status = driver->probe(pciedev, driver->id_table);
+	if (!status) {
+		printk(KERN_DEBUG "Load service driver %s on pcie device %s\n",
+			driver->name, dev->bus_id);
+		get_device(dev);
+	}
+	return status;
+}
+
+static int pcie_port_remove_service(struct device *dev)
+{
+	struct pcie_device *pciedev;
+	struct pcie_port_service_driver *driver;
+
+	if (!dev || !dev->driver)
+		return 0;
+
+	pciedev = to_pcie_device(dev);
+ 	driver = to_service_driver(dev->driver);
+	if (driver && driver->remove) { 
+		printk(KERN_DEBUG "Unload service driver %s on pcie device %s\n",
+			driver->name, dev->bus_id);
+		driver->remove(pciedev);
+		put_device(dev);
+	}
+	return 0;
+}
+
+static void pcie_port_shutdown_service(struct device *dev) {}
+
+static int pcie_port_suspend_service(struct device *dev, u32 state, u32 level)
+{
+	struct pcie_device *pciedev;
+	struct pcie_port_service_driver *driver;
+
+	if (!dev || !dev->driver)
+		return 0;
+
+	pciedev = to_pcie_device(dev);
+ 	driver = to_service_driver(dev->driver);
+	if (driver && driver->suspend)
+		driver->suspend(pciedev, state);
+	return 0;
+}
+
+static int pcie_port_resume_service(struct device *dev, u32 state)
+{
+	struct pcie_device *pciedev;
+	struct pcie_port_service_driver *driver;
+
+	if (!dev || !dev->driver)
+		return 0;
+
+	pciedev = to_pcie_device(dev);
+ 	driver = to_service_driver(dev->driver);
+
+	if (driver && driver->resume)
+		driver->resume(pciedev);
+	return 0;
+}
+
+/*
+ * release_pcie_device
+ *	
+ *	Being invoked automatically when device is being removed 
+ *	in response to device_unregister(dev) call.
+ *	Release all resources being claimed.
+ */
+static void release_pcie_device(struct device *dev)
+{
+	printk(KERN_DEBUG "Free Port Service[%s]\n", dev->bus_id);
+	kfree(to_pcie_device(dev));			
+}
+
+static int is_msi_quirked(struct pci_dev *dev)
+{
+	int port_type, quirk = 0;
+	u16 reg16;
+
+	pci_read_config_word(dev, 
+		pci_find_capability(dev, PCI_CAP_ID_EXP) + 
+		PCIE_CAPABILITIES_REG, &reg16);
+	port_type = (reg16 >> 4) & PORT_TYPE_MASK;
+	switch(port_type) {
+	case PCIE_RC_PORT:
+		if (pcie_mch_quirk == 1)
+			quirk = 1;
+		break;
+	case PCIE_SW_UPSTREAM_PORT:
+	case PCIE_SW_DOWNSTREAM_PORT:
+	default:
+		break;	
+	}
+	return quirk;
+}
+	
+static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
+{
+	int i, pos, nvec, status = -EINVAL;
+	int interrupt_mode = PCIE_PORT_INTx_MODE;
+
+	/* Set INTx as default */
+	for (i = 0, nvec = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
+		if (mask & (1 << i)) 
+			nvec++;
+		vectors[i] = dev->irq;
+	}
+	
+	/* Check MSI quirk */
+	if (is_msi_quirked(dev))
+		return interrupt_mode;
+
+	/* Select MSI-X over MSI if supported */		
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+	if (pos) {
+		struct msix_entry msix_entries[PCIE_PORT_DEVICE_MAXSERVICES] = 
+			{{0, 0}, {0, 1}, {0, 2}, {0, 3}};
+		printk("%s Found MSIX capability\n", __FUNCTION__);
+		status = pci_enable_msix(dev, msix_entries, nvec);
+		if (!status) {
+			int j = 0;
+
+			interrupt_mode = PCIE_PORT_MSIX_MODE;
+			for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
+				if (mask & (1 << i)) 
+					vectors[i] = msix_entries[j++].vector;
+			}
+		}
+	} 
+	if (status) {
+		pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+		if (pos) {
+			printk("%s Found MSI capability\n", __FUNCTION__);
+			status = pci_enable_msi(dev);
+			if (!status) {
+				interrupt_mode = PCIE_PORT_MSI_MODE;
+				for (i = 0;i < PCIE_PORT_DEVICE_MAXSERVICES;i++)
+					vectors[i] = dev->irq;
+			}
+		}
+	} 
+	return interrupt_mode;
+}
+
+static int get_port_device_capability(struct pci_dev *dev)
+{
+	int services = 0, pos;
+	u16 reg16;
+	u32 reg32;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+	pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg16);
+	/* Hot-Plug Capable */
+	if (reg16 & PORT_TO_SLOT_MASK) {
+		pci_read_config_dword(dev, 
+			pos + PCIE_SLOT_CAPABILITIES_REG, &reg32);
+		if (reg32 & SLOT_HP_CAPABLE_MASK)
+			services |= PCIE_PORT_SERVICE_HP;
+	} 
+	/* PME Capable */
+	pos = pci_find_capability(dev, PCI_CAP_ID_PME);
+	if (pos) 
+		services |= PCIE_PORT_SERVICE_PME;
+	
+	pos = PCI_CFG_SPACE_SIZE;
+	while (pos) {
+		pci_read_config_dword(dev, pos, &reg32);
+		switch (reg32 & 0xffff) {
+		case PCI_EXT_CAP_ID_ERR:
+			services |= PCIE_PORT_SERVICE_AER;
+			pos = reg32 >> 20;
+			break;
+		case PCI_EXT_CAP_ID_VC:
+			services |= PCIE_PORT_SERVICE_VC;
+			pos = reg32 >> 20;
+			break;
+		default:
+			pos = 0;
+			break;
+		}
+	}
+
+	return services;
+}
+
+static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, 
+	int port_type, int service_type, int irq, int irq_mode)
+{
+	struct device *device;
+
+	dev->port = parent;
+	dev->interrupt_mode = irq_mode;
+	dev->irq = irq;
+	dev->id.vendor = parent->vendor;
+	dev->id.device = parent->device;
+	dev->id.port_type = port_type;
+	dev->id.service_type = (1 << service_type);
+
+	/* Initialize generic device interface */
+	device = &dev->device;
+	memset(device, 0, sizeof(struct device));
+	INIT_LIST_HEAD(&device->node);
+	INIT_LIST_HEAD(&device->children);
+	INIT_LIST_HEAD(&device->bus_list);
+	device->bus = &pcie_port_bus_type;
+	device->driver = NULL;
+	device->driver_data = NULL; 
+	device->release = release_pcie_device;	/* callback to free pcie dev */
+	sprintf(&device->bus_id[0], "pcie%02x", 
+		get_descriptor_id(port_type, service_type));
+	device->parent = &parent->dev;
+}
+
+static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, 
+	int port_type, int service_type, int irq, int irq_mode)
+{
+	struct pcie_device *device;
+
+	device = kmalloc(sizeof(struct pcie_device), GFP_KERNEL);
+	if (!device)
+		return NULL;
+
+	memset(device, 0, sizeof(struct pcie_device));
+	pcie_device_init(parent, device, port_type, service_type, irq,irq_mode);
+	printk(KERN_DEBUG "Allocate Port Service[%s]\n", device->device.bus_id);
+	return device;
+}
+
+int pcie_port_device_probe(struct pci_dev *dev)
+{
+	int pos, type;
+	u16 reg;
+
+	if (!(pos = pci_find_capability(dev, PCI_CAP_ID_EXP)))
+		return -ENODEV;
+
+	pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg);
+	type = (reg >> 4) & PORT_TYPE_MASK;
+	if (	type == PCIE_RC_PORT || type == PCIE_SW_UPSTREAM_PORT ||
+		type == PCIE_SW_DOWNSTREAM_PORT )  
+		return 0;
+ 
+	return -ENODEV;
+}
+
+int pcie_port_device_register(struct pci_dev *dev)
+{
+	int status, type, capabilities, irq_mode, i;
+	int vectors[PCIE_PORT_DEVICE_MAXSERVICES];
+	u16 reg16;
+
+	/* Get port type */
+	pci_read_config_word(dev, 
+		pci_find_capability(dev, PCI_CAP_ID_EXP) + 
+		PCIE_CAPABILITIES_REG, &reg16);
+	type = (reg16 >> 4) & PORT_TYPE_MASK;
+
+	/* Now get port services */
+	capabilities = get_port_device_capability(dev);
+	irq_mode = assign_interrupt_mode(dev, vectors, capabilities);
+
+	/* Allocate child services if any */
+	for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
+		struct pcie_device *child;
+
+		if (capabilities & (1 << i)) {
+			child = alloc_pcie_device(
+				dev, 		/* parent */
+				type,		/* port type */ 
+				i,		/* service type */
+				vectors[i],	/* irq */
+				irq_mode	/* interrupt mode */);
+			if (child) { 
+				status = device_register(&child->device);
+				if (status) {
+					kfree(child);
+					continue;
+				}
+				get_device(&child->device);
+			}
+		}
+	}
+	return 0;
+}
+
+#ifdef CONFIG_PM
+int pcie_port_device_suspend(struct pci_dev *dev, u32 state)
+{
+	struct list_head 		*head, *tmp;
+	struct device 			*parent, *child;
+	struct device_driver 		*driver;
+	struct pcie_port_service_driver *service_driver;
+
+	parent = &dev->dev;
+	head = &parent->children;
+	tmp = head->next;
+	while (head != tmp) {
+		child = container_of(tmp, struct device, node);
+		tmp = tmp->next;
+		if (child->bus != &pcie_port_bus_type)
+			continue;
+		driver = child->driver;
+		if (!driver)
+			continue;
+		service_driver = to_service_driver(driver);
+		if (service_driver->suspend)  
+			service_driver->suspend(to_pcie_device(child), state);
+	}
+	return 0; 
+}
+
+int pcie_port_device_resume(struct pci_dev *dev) 
+{ 
+	struct list_head 		*head, *tmp;
+	struct device 			*parent, *child;
+	struct device_driver 		*driver;
+	struct pcie_port_service_driver *service_driver;
+
+	parent = &dev->dev;
+	head = &parent->children;
+	tmp = head->next;
+	while (head != tmp) {
+		child = container_of(tmp, struct device, node);
+		tmp = tmp->next;
+		if (child->bus != &pcie_port_bus_type)
+			continue;
+		driver = child->driver;
+		if (!driver)
+			continue;
+		service_driver = to_service_driver(driver);
+		if (service_driver->resume)  
+			service_driver->resume(to_pcie_device(child));
+	}
+	return 0; 
+
+}
+#endif
+
+void pcie_port_device_remove(struct pci_dev *dev)
+{
+	struct list_head 		*head, *tmp;
+	struct device 			*parent, *child;
+	struct device_driver 		*driver;
+	struct pcie_port_service_driver *service_driver;
+	int interrupt_mode = PCIE_PORT_INTx_MODE;
+
+	parent = &dev->dev;
+	head = &parent->children;
+	tmp = head->next;
+	while (head != tmp) {
+		child = container_of(tmp, struct device, node);
+		tmp = tmp->next;
+		if (child->bus != &pcie_port_bus_type)
+			continue;
+		driver = child->driver;
+		if (driver) { 
+			service_driver = to_service_driver(driver);
+			if (service_driver->remove)  
+				service_driver->remove(to_pcie_device(child));
+		}
+		interrupt_mode = (to_pcie_device(child))->interrupt_mode;
+		put_device(child);
+		device_unregister(child);
+	}
+	/* Switch to INTx by default if MSI enabled */
+	if (interrupt_mode == PCIE_PORT_MSIX_MODE)
+		pci_disable_msix(dev);
+	else if (interrupt_mode == PCIE_PORT_MSI_MODE)
+		pci_disable_msi(dev);
+}
+
+void pcie_port_bus_register(void)
+{
+	bus_register(&pcie_port_bus_type);
+}
+
+void pcie_port_bus_unregister(void)
+{
+	bus_unregister(&pcie_port_bus_type);
+}
+
+int pcie_port_service_register(struct pcie_port_service_driver *new)
+{
+	new->driver.name = (char *)new->name;
+	new->driver.bus = &pcie_port_bus_type;
+	new->driver.probe = pcie_port_probe_service;
+	new->driver.remove = pcie_port_remove_service;
+	new->driver.shutdown = pcie_port_shutdown_service;
+	new->driver.suspend = pcie_port_suspend_service;
+	new->driver.resume = pcie_port_resume_service;
+
+	return driver_register(&new->driver);
+} 
+
+void pcie_port_service_unregister(struct pcie_port_service_driver *new)
+{
+	driver_unregister(&new->driver);
+}
+
+EXPORT_SYMBOL(pcie_port_service_register);
+EXPORT_SYMBOL(pcie_port_service_unregister);
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
new file mode 100644
index 0000000..3184843
--- /dev/null
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -0,0 +1,122 @@
+/*
+ * File:	portdrv_pci.c
+ * Purpose:	PCI Express Port Bus Driver
+ *
+ * Copyright (C) 2004 Intel
+ * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/pcieport_if.h>
+
+#include "portdrv.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0"
+#define DRIVER_AUTHOR "tom.l.nguyen@intel.com"
+#define DRIVER_DESC "PCIE Port Bus Driver"
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/* global data */
+static const char device_name[] = "pcieport-driver";
+
+/*
+ * pcie_portdrv_probe - Probe PCI-Express port devices
+ * @dev: PCI-Express port device being probed
+ *
+ * If detected invokes the pcie_port_device_register() method for 
+ * this port device.
+ *
+ */
+static int __devinit pcie_portdrv_probe (struct pci_dev *dev, 
+				const struct pci_device_id *id )
+{
+	int			status;
+
+	status = pcie_port_device_probe(dev);
+	if (status)
+		return status;
+
+	if (pci_enable_device(dev) < 0) 
+		return -ENODEV;
+	
+	pci_set_master(dev);
+        if (!dev->irq) {
+		printk(KERN_WARNING 
+		"%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n", 
+		__FUNCTION__, dev->device, dev->vendor);
+	}
+	if (pcie_port_device_register(dev)) 
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void pcie_portdrv_remove (struct pci_dev *dev)
+{
+	pcie_port_device_remove(dev);
+}
+
+#ifdef CONFIG_PM
+static int pcie_portdrv_suspend (struct pci_dev *dev, u32 state)
+{
+	return pcie_port_device_suspend(dev, state);
+}
+
+static int pcie_portdrv_resume (struct pci_dev *dev)
+{
+	return pcie_port_device_resume(dev);
+}
+#endif
+
+/*
+ * LINUX Device Driver Model
+ */
+static const struct pci_device_id port_pci_ids[] = { {
+	/* handle any PCI-Express port */
+	PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0),
+	}, { /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE(pci, port_pci_ids);
+
+static struct pci_driver pcie_portdrv = {
+	.name		= (char *)device_name,
+	.id_table	= &port_pci_ids[0],
+
+	.probe		= pcie_portdrv_probe,
+	.remove		= pcie_portdrv_remove,
+
+#ifdef	CONFIG_PM
+	.suspend	= pcie_portdrv_suspend,
+	.resume		= pcie_portdrv_resume,
+#endif	/* PM */
+};
+
+static int __init pcie_portdrv_init(void)
+{
+	int retval = 0;
+
+	pcie_port_bus_register();
+	retval = pci_register_driver(&pcie_portdrv);
+	if (retval)
+		pcie_port_bus_unregister();
+	return retval;
+}
+
+static void __exit pcie_portdrv_exit(void) 
+{
+	pci_unregister_driver(&pcie_portdrv);
+	pcie_port_bus_unregister();
+}
+
+module_init(pcie_portdrv_init);
+module_exit(pcie_portdrv_exit);