diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index 39af9c325f3532e37013d53a6fbf0412bc482d63..51cb9f817c22a6f8ec6c25db2b8f9a57c97b1d65 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -25,6 +25,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -33,10 +34,184 @@
 #include <acpi/actypes.h>
 #include "pci_hotplug.h"
 
+#define MY_NAME	"acpi_pcihp"
+
+#define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
+
 #define	METHOD_NAME__SUN	"_SUN"
 #define	METHOD_NAME__HPP	"_HPP"
 #define	METHOD_NAME_OSHP	"OSHP"
 
+static int debug_acpi;
+
+static acpi_status
+decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
+{
+	int i;
+	union acpi_object *fields = record->package.elements;
+	u32 revision = fields[1].integer.value;
+
+	switch (revision) {
+	case 1:
+		if (record->package.count != 6)
+			return AE_ERROR;
+		for (i = 2; i < 6; i++)
+			if (fields[i].type != ACPI_TYPE_INTEGER)
+				return AE_ERROR;
+		hpx->t0 = &hpx->type0_data;
+		hpx->t0->revision        = revision;
+		hpx->t0->cache_line_size = fields[2].integer.value;
+		hpx->t0->latency_timer   = fields[3].integer.value;
+		hpx->t0->enable_serr     = fields[4].integer.value;
+		hpx->t0->enable_perr     = fields[5].integer.value;
+		break;
+	default:
+		printk(KERN_WARNING
+		       "%s: Type 0 Revision %d record not supported\n",
+		       __FUNCTION__, revision);
+		return AE_ERROR;
+	}
+	return AE_OK;
+}
+
+static acpi_status
+decode_type1_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
+{
+	int i;
+	union acpi_object *fields = record->package.elements;
+	u32 revision = fields[1].integer.value;
+
+	switch (revision) {
+	case 1:
+		if (record->package.count != 5)
+			return AE_ERROR;
+		for (i = 2; i < 5; i++)
+			if (fields[i].type != ACPI_TYPE_INTEGER)
+				return AE_ERROR;
+		hpx->t1 = &hpx->type1_data;
+		hpx->t1->revision      = revision;
+		hpx->t1->max_mem_read  = fields[2].integer.value;
+		hpx->t1->avg_max_split = fields[3].integer.value;
+		hpx->t1->tot_max_split = fields[4].integer.value;
+		break;
+	default:
+		printk(KERN_WARNING
+		       "%s: Type 1 Revision %d record not supported\n",
+		       __FUNCTION__, revision);
+		return AE_ERROR;
+	}
+	return AE_OK;
+}
+
+static acpi_status
+decode_type2_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
+{
+	int i;
+	union acpi_object *fields = record->package.elements;
+	u32 revision = fields[1].integer.value;
+
+	switch (revision) {
+	case 1:
+		if (record->package.count != 18)
+			return AE_ERROR;
+		for (i = 2; i < 18; i++)
+			if (fields[i].type != ACPI_TYPE_INTEGER)
+				return AE_ERROR;
+		hpx->t2 = &hpx->type2_data;
+		hpx->t2->revision      = revision;
+		hpx->t2->unc_err_mask_and      = fields[2].integer.value;
+		hpx->t2->unc_err_mask_or       = fields[3].integer.value;
+		hpx->t2->unc_err_sever_and     = fields[4].integer.value;
+		hpx->t2->unc_err_sever_or      = fields[5].integer.value;
+		hpx->t2->cor_err_mask_and      = fields[6].integer.value;
+		hpx->t2->cor_err_mask_or       = fields[7].integer.value;
+		hpx->t2->adv_err_cap_and       = fields[8].integer.value;
+		hpx->t2->adv_err_cap_or        = fields[9].integer.value;
+		hpx->t2->pci_exp_devctl_and    = fields[10].integer.value;
+		hpx->t2->pci_exp_devctl_or     = fields[11].integer.value;
+		hpx->t2->pci_exp_lnkctl_and    = fields[12].integer.value;
+		hpx->t2->pci_exp_lnkctl_or     = fields[13].integer.value;
+		hpx->t2->sec_unc_err_sever_and = fields[14].integer.value;
+		hpx->t2->sec_unc_err_sever_or  = fields[15].integer.value;
+		hpx->t2->sec_unc_err_mask_and  = fields[16].integer.value;
+		hpx->t2->sec_unc_err_mask_or   = fields[17].integer.value;
+		break;
+	default:
+		printk(KERN_WARNING
+		       "%s: Type 2 Revision %d record not supported\n",
+		       __FUNCTION__, revision);
+		return AE_ERROR;
+	}
+	return AE_OK;
+}
+
+static acpi_status
+acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx)
+{
+	acpi_status status;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *package, *record, *fields;
+	u32 type;
+	int i;
+
+	/* Clear the return buffer with zeros */
+	memset(hpx, 0, sizeof(struct hotplug_params));
+
+	status = acpi_evaluate_object(handle, "_HPX", NULL, &buffer);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	package = (union acpi_object *)buffer.pointer;
+	if (package->type != ACPI_TYPE_PACKAGE) {
+		status = AE_ERROR;
+		goto exit;
+	}
+
+	for (i = 0; i < package->package.count; i++) {
+		record = &package->package.elements[i];
+		if (record->type != ACPI_TYPE_PACKAGE) {
+			status = AE_ERROR;
+			goto exit;
+		}
+
+		fields = record->package.elements;
+		if (fields[0].type != ACPI_TYPE_INTEGER ||
+		    fields[1].type != ACPI_TYPE_INTEGER) {
+			status = AE_ERROR;
+			goto exit;
+		}
+
+		type = fields[0].integer.value;
+		switch (type) {
+		case 0:
+			status = decode_type0_hpx_record(record, hpx);
+			if (ACPI_FAILURE(status))
+				goto exit;
+			break;
+		case 1:
+			status = decode_type1_hpx_record(record, hpx);
+			if (ACPI_FAILURE(status))
+				goto exit;
+			break;
+		case 2:
+			status = decode_type2_hpx_record(record, hpx);
+			if (ACPI_FAILURE(status))
+				goto exit;
+			break;
+		default:
+			printk(KERN_ERR "%s: Type %d record not supported\n",
+			       __FUNCTION__, type);
+			status = AE_ERROR;
+			goto exit;
+		}
+	}
+ exit:
+	kfree(buffer.pointer);
+	return status;
+}
 
 static acpi_status
 acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
@@ -50,6 +225,9 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
 
 	acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
 
+	/* Clear the return buffer with zeros */
+	memset(hpp, 0, sizeof(struct hotplug_params));
+
 	/* get _hpp */
 	status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
 	switch (status) {
@@ -58,7 +236,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
 		if (!ret_buf.pointer) {
 			printk(KERN_ERR "%s:%s alloc for _HPP fail\n",
 				__FUNCTION__, (char *)string.pointer);
-			acpi_os_free(string.pointer);
+			kfree(string.pointer);
 			return AE_NO_MEMORY;
 		}
 		status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
@@ -69,7 +247,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
 		if (ACPI_FAILURE(status)) {
 			pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
 				(char *)string.pointer, status);
-			acpi_os_free(string.pointer);
+			kfree(string.pointer);
 			return status;
 		}
 	}
@@ -98,19 +276,20 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
 		}
 	}
 
-	hpp->cache_line_size = nui[0];
-	hpp->latency_timer = nui[1];
-	hpp->enable_serr = nui[2];
-	hpp->enable_perr = nui[3];
+	hpp->t0 = &hpp->type0_data;
+	hpp->t0->cache_line_size = nui[0];
+	hpp->t0->latency_timer = nui[1];
+	hpp->t0->enable_serr = nui[2];
+	hpp->t0->enable_perr = nui[3];
 
-	pr_debug("  _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
-	pr_debug("  _HPP: latency timer  =0x%x\n", hpp->latency_timer);
-	pr_debug("  _HPP: enable SERR    =0x%x\n", hpp->enable_serr);
-	pr_debug("  _HPP: enable PERR    =0x%x\n", hpp->enable_perr);
+	pr_debug("  _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size);
+	pr_debug("  _HPP: latency timer  =0x%x\n", hpp->t0->latency_timer);
+	pr_debug("  _HPP: enable SERR    =0x%x\n", hpp->t0->enable_serr);
+	pr_debug("  _HPP: enable PERR    =0x%x\n", hpp->t0->enable_perr);
 
 free_and_return:
-	acpi_os_free(string.pointer);
-	acpi_os_free(ret_buf.pointer);
+	kfree(string.pointer);
+	kfree(ret_buf.pointer);
 	return status;
 }
 
@@ -130,13 +309,17 @@ acpi_status acpi_run_oshp(acpi_handle handle)
 	/* run OSHP */
 	status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
 	if (ACPI_FAILURE(status))
-		printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__,
-			(char *)string.pointer, status);
+		if (status != AE_NOT_FOUND)
+			printk(KERN_ERR "%s:%s OSHP fails=0x%x\n",
+			       __FUNCTION__, (char *)string.pointer, status);
+		else
+			dbg("%s:%s OSHP not found\n",
+			    __FUNCTION__, (char *)string.pointer);
 	else
 		pr_debug("%s:%s OSHP passes\n", __FUNCTION__,
 			(char *)string.pointer);
 
-	acpi_os_free(string.pointer);
+	kfree(string.pointer);
 	return status;
 }
 EXPORT_SYMBOL_GPL(acpi_run_oshp);
@@ -145,14 +328,27 @@ EXPORT_SYMBOL_GPL(acpi_run_oshp);
 
 /* acpi_get_hp_params_from_firmware
  *
- * @dev - the pci_dev of the newly added device
+ * @bus - the pci_bus of the bus on which the device is newly added
  * @hpp - allocated by the caller
  */
-acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
+acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
 		struct hotplug_params *hpp)
 {
 	acpi_status status = AE_NOT_FOUND;
-	struct pci_dev *pdev = dev;
+	acpi_handle handle, phandle;
+	struct pci_bus *pbus = bus;
+	struct pci_dev *pdev;
+
+	do {
+		pdev = pbus->self;
+		if (!pdev) {
+			handle = acpi_get_pci_rootbridge_handle(
+				pci_domain_nr(pbus), pbus->number);
+			break;
+		}
+		handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
+		pbus = pbus->parent;
+	} while (!handle);
 
 	/*
 	 * _HPP settings apply to all child buses, until another _HPP is
@@ -160,15 +356,19 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
 	 * look for it in the parent device scope since that would apply to
 	 * this pci dev. If we don't find any _HPP, use hardcoded defaults
 	 */
-	while (pdev && (ACPI_FAILURE(status))) {
-		acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
-		if (!handle)
+	while (handle) {
+		status = acpi_run_hpx(handle, hpp);
+		if (ACPI_SUCCESS(status))
 			break;
 		status = acpi_run_hpp(handle, hpp);
-		if (!(pdev->bus->parent))
+		if (ACPI_SUCCESS(status))
 			break;
-		/* Check if a parent object supports _HPP */
-		pdev = pdev->bus->parent->self;
+		if (acpi_root_bridge(handle))
+			break;
+		status = acpi_get_parent(handle, &phandle);
+		if (ACPI_FAILURE(status))
+			break;
+		handle = phandle;
 	}
 	return status;
 }
@@ -192,20 +392,23 @@ int acpi_root_bridge(acpi_handle handle)
 		if ((info->valid & ACPI_VALID_HID) &&
 			!strcmp(PCI_ROOT_HID_STRING,
 					info->hardware_id.value)) {
-			acpi_os_free(buffer.pointer);
+			kfree(buffer.pointer);
 			return 1;
 		}
 		if (info->valid & ACPI_VALID_CID) {
 			for (i=0; i < info->compatibility_id.count; i++) {
 				if (!strcmp(PCI_ROOT_HID_STRING,
 					info->compatibility_id.id[i].value)) {
-					acpi_os_free(buffer.pointer);
+					kfree(buffer.pointer);
 					return 1;
 				}
 			}
 		}
-		acpi_os_free(buffer.pointer);
+		kfree(buffer.pointer);
 	}
 	return 0;
 }
 EXPORT_SYMBOL_GPL(acpi_root_bridge);
+
+module_param(debug_acpi, bool, 0644);
+MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not");
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 467ac70a46ff5aa888fcc0a9eee8d5bded62dfed..17a93f890dba9d2626e621b7f9dda91a1b5dc90e 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -75,6 +75,10 @@ struct acpiphp_bridge {
 	struct list_head list;
 	acpi_handle handle;
 	struct acpiphp_slot *slots;
+
+	/* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */
+	struct acpiphp_func *func;
+
 	int type;
 	int nr_slots;
 
@@ -122,6 +126,7 @@ struct acpiphp_slot {
  */
 struct acpiphp_func {
 	struct acpiphp_slot *slot;	/* parent */
+	struct acpiphp_bridge *bridge;	/* Ejectable PCI-to-PCI bridge */
 
 	struct list_head sibling;
 	struct pci_dev *pci_dev;
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 053ee843863c1891bc1398b968456cffd6fc31c0..d370f999782e9575793299203154d5970e695eb9 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -286,13 +286,19 @@ static void decode_hpp(struct acpiphp_bridge *bridge)
 {
 	acpi_status status;
 
-	status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp);
-	if (ACPI_FAILURE(status)) {
+	status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp);
+	if (ACPI_FAILURE(status) ||
+	    !bridge->hpp.t0 || (bridge->hpp.t0->revision > 1)) {
 		/* use default numbers */
-		bridge->hpp.cache_line_size = 0x10;
-		bridge->hpp.latency_timer = 0x40;
-		bridge->hpp.enable_serr = 0;
-		bridge->hpp.enable_perr = 0;
+		printk(KERN_WARNING
+		       "%s: Could not get hotplug parameters. Use defaults\n",
+		       __FUNCTION__);
+		bridge->hpp.t0 = &bridge->hpp.type0_data;
+		bridge->hpp.t0->revision = 0;
+		bridge->hpp.t0->cache_line_size = 0x10;
+		bridge->hpp.t0->latency_timer = 0x40;
+		bridge->hpp.t0->enable_serr = 0;
+		bridge->hpp.t0->enable_perr = 0;
 	}
 }
 
@@ -319,6 +325,13 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
 
 	/* install notify handler */
 	if (bridge->type != BRIDGE_TYPE_HOST) {
+		if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
+			status = acpi_remove_notify_handler(bridge->func->handle,
+						ACPI_SYSTEM_NOTIFY,
+						handle_hotplug_event_func);
+			if (ACPI_FAILURE(status))
+				err("failed to remove notify handler\n");
+		}
 		status = acpi_install_notify_handler(bridge->handle,
 					     ACPI_SYSTEM_NOTIFY,
 					     handle_hotplug_event_bridge,
@@ -331,6 +344,66 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
 }
 
 
+/* find acpiphp_func from acpiphp_bridge */
+static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle)
+{
+	struct list_head *node, *l;
+	struct acpiphp_bridge *bridge;
+	struct acpiphp_slot *slot;
+	struct acpiphp_func *func;
+
+	list_for_each(node, &bridge_list) {
+		bridge = list_entry(node, struct acpiphp_bridge, list);
+		for (slot = bridge->slots; slot; slot = slot->next) {
+			list_for_each(l, &slot->funcs) {
+				func = list_entry(l, struct acpiphp_func,
+							sibling);
+				if (func->handle == handle)
+					return func;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+
+static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge)
+{
+	acpi_handle dummy_handle;
+
+	if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
+					"_STA", &dummy_handle)))
+		bridge->flags |= BRIDGE_HAS_STA;
+
+	if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
+					"_EJ0", &dummy_handle)))
+		bridge->flags |= BRIDGE_HAS_EJ0;
+
+	if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
+					"_PS0", &dummy_handle)))
+		bridge->flags |= BRIDGE_HAS_PS0;
+
+	if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
+					"_PS3", &dummy_handle)))
+		bridge->flags |= BRIDGE_HAS_PS3;
+
+	/* is this ejectable p2p bridge? */
+	if (bridge->flags & BRIDGE_HAS_EJ0) {
+		struct acpiphp_func *func;
+
+		dbg("found ejectable p2p bridge\n");
+
+		/* make link between PCI bridge and PCI function */
+		func = acpiphp_bridge_handle_to_function(bridge->handle);
+		if (!func)
+			return;
+		bridge->func = func;
+		func->bridge = bridge;
+	}
+}
+
+
 /* allocate and initialize host bridge data structure */
 static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus)
 {
@@ -364,6 +437,7 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
 
 	bridge->type = BRIDGE_TYPE_P2P;
 	bridge->handle = handle;
+	config_p2p_bridge_flags(bridge);
 
 	bridge->pci_dev = pci_dev_get(pci_dev);
 	bridge->pci_bus = pci_dev->subordinate;
@@ -423,7 +497,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
 	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
 				     find_p2p_bridge, dev->subordinate, NULL);
 	if (ACPI_FAILURE(status))
-		warn("find_p2p_bridge faied (error code = 0x%x)\n", status);
+		warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
 
  out:
 	pci_dev_put(dev);
@@ -478,7 +552,6 @@ static int add_bridge(acpi_handle handle)
 	if (detect_ejectable_slots(handle) > 0) {
 		dbg("found PCI host-bus bridge with hot-pluggable slots\n");
 		add_host_bridge(handle, pci_bus);
-		return 0;
 	}
 
 	/* search P2P bridges under this host bridge */
@@ -486,7 +559,7 @@ static int add_bridge(acpi_handle handle)
 				     find_p2p_bridge, pci_bus, NULL);
 
 	if (ACPI_FAILURE(status))
-		warn("find_p2p_bridge faied (error code = 0x%x)\n",status);
+		warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
 
 	return 0;
 }
@@ -516,6 +589,16 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
 	if (ACPI_FAILURE(status))
 		err("failed to remove notify handler\n");
 
+	if ((bridge->type != BRIDGE_TYPE_HOST) &&
+	    ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) {
+		status = acpi_install_notify_handler(bridge->func->handle,
+						ACPI_SYSTEM_NOTIFY,
+						handle_hotplug_event_func,
+						bridge->func);
+		if (ACPI_FAILURE(status))
+			err("failed to install interrupt notify handler\n");
+	}
+
 	slot = bridge->slots;
 	while (slot) {
 		struct acpiphp_slot *next = slot->next;
@@ -549,6 +632,11 @@ cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
 	struct acpiphp_bridge *bridge;
 
+	/* cleanup p2p bridges under this P2P bridge
+	   in a depth-first manner */
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
+				cleanup_p2p_bridge, NULL, NULL);
+
 	if (!(bridge = acpiphp_handle_to_bridge(handle)))
 		return AE_OK;
 	cleanup_bridge(bridge);
@@ -559,15 +647,14 @@ static void remove_bridge(acpi_handle handle)
 {
 	struct acpiphp_bridge *bridge;
 
+	/* cleanup p2p bridges under this host bridge
+	   in a depth-first manner */
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+				(u32)1, cleanup_p2p_bridge, NULL, NULL);
+
 	bridge = acpiphp_handle_to_bridge(handle);
-	if (bridge) {
+	if (bridge)
 		cleanup_bridge(bridge);
-	} else {
-		/* clean-up p2p bridges under this host bridge */
-		acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-				    ACPI_UINT32_MAX, cleanup_p2p_bridge,
-				    NULL, NULL);
-	}
 }
 
 static struct pci_dev * get_apic_pci_info(acpi_handle handle)
@@ -634,7 +721,7 @@ static int get_gsi_base(acpi_handle handle, u32 *gsi_base)
 		break;
 	}
  out:
-	acpi_os_free(buffer.pointer);
+	kfree(buffer.pointer);
 	return result;
 }
 
@@ -797,36 +884,6 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
 }
 
 
-
-/**
- *  get_func - get a pointer to acpiphp_func given a slot, device
- *  @slot: slot to search
- *  @dev:  pci_dev struct to match.
- *
- *  This function will increase the reference count of pci_dev,
- *  so callers should call pci_dev_put when complete.
- *
- */
-static struct acpiphp_func *
-get_func(struct acpiphp_slot *slot, struct pci_dev *dev)
-{
-	struct acpiphp_func *func = NULL;
-	struct pci_bus *bus = slot->bridge->pci_bus;
-	struct pci_dev *pdev;
-
-	list_for_each_entry(func, &slot->funcs, sibling) {
-		pdev = pci_get_slot(bus, PCI_DEVFN(slot->device,
-					func->function));
-		if (pdev) {
-			if (pdev == dev)
-				break;
-			pci_dev_put(pdev);
-		}
-	}
-	return func;
-}
-
-
 /**
  * acpiphp_bus_add - add a new bus to acpi subsystem
  * @func: acpiphp_func of the bridge
@@ -872,6 +929,28 @@ static int acpiphp_bus_add(struct acpiphp_func *func)
 }
 
 
+/**
+ * acpiphp_bus_trim - trim a bus from acpi subsystem
+ * @handle: handle to acpi namespace
+ *
+ */
+int acpiphp_bus_trim(acpi_handle handle)
+{
+	struct acpi_device *device;
+	int retval;
+
+	retval = acpi_bus_get_device(handle, &device);
+	if (retval) {
+		dbg("acpi_device not found\n");
+		return retval;
+	}
+
+	retval = acpi_bus_trim(device, 1);
+	if (retval)
+		err("cannot remove from acpi list\n");
+
+	return retval;
+}
 
 /**
  * enable_device - enable, configure a slot
@@ -889,6 +968,7 @@ static int enable_device(struct acpiphp_slot *slot)
 	struct acpiphp_func *func;
 	int retval = 0;
 	int num, max, pass;
+	acpi_status status;
 
 	if (slot->flags & SLOT_ENABLED)
 		goto err_exit;
@@ -918,19 +998,17 @@ static int enable_device(struct acpiphp_slot *slot)
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
 				max = pci_scan_bridge(bus, dev, max, pass);
-				if (pass && dev->subordinate) {
+				if (pass && dev->subordinate)
 					pci_bus_size_bridges(dev->subordinate);
-					func = get_func(slot, dev);
-					if (func) {
-						acpiphp_bus_add(func);
-						/* side effect of get_func */
-						pci_dev_put(dev);
-					}
-				}
 			}
 		}
 	}
 
+	list_for_each (l, &slot->funcs) {
+		func = list_entry(l, struct acpiphp_func, sibling);
+		acpiphp_bus_add(func);
+	}
+
 	pci_bus_assign_resources(bus);
 	acpiphp_sanitize_bus(bus);
 	pci_enable_bridges(bus);
@@ -943,6 +1021,17 @@ static int enable_device(struct acpiphp_slot *slot)
 		func = list_entry(l, struct acpiphp_func, sibling);
 		func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device,
 							func->function));
+		if (!func->pci_dev)
+			continue;
+
+		if (func->pci_dev->hdr_type != PCI_HEADER_TYPE_BRIDGE &&
+		    func->pci_dev->hdr_type != PCI_HEADER_TYPE_CARDBUS)
+			continue;
+
+		status = find_p2p_bridge(func->handle, (u32)1, bus, NULL);
+		if (ACPI_FAILURE(status))
+			warn("find_p2p_bridge failed (error code = 0x%x)\n",
+				status);
 	}
 
 	slot->flags |= SLOT_ENABLED;
@@ -967,6 +1056,18 @@ static int disable_device(struct acpiphp_slot *slot)
 
 	list_for_each (l, &slot->funcs) {
 		func = list_entry(l, struct acpiphp_func, sibling);
+
+		if (func->bridge) {
+			/* cleanup p2p bridges under this P2P bridge */
+			cleanup_p2p_bridge(func->bridge->handle,
+						(u32)1, NULL, NULL);
+			func->bridge = NULL;
+		}
+
+		acpiphp_bus_trim(func->handle);
+		/* try to remove anyway.
+		 * acpiphp_bus_add might have been failed */
+
 		if (!func->pci_dev)
 			continue;
 
@@ -1111,16 +1212,17 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
 			(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
 			(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
 		return;
+
 	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
-			bridge->hpp.cache_line_size);
+			bridge->hpp.t0->cache_line_size);
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER,
-			bridge->hpp.latency_timer);
+			bridge->hpp.t0->latency_timer);
 	pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
-	if (bridge->hpp.enable_serr)
+	if (bridge->hpp.t0->enable_serr)
 		pci_cmd |= PCI_COMMAND_SERR;
 	else
 		pci_cmd &= ~PCI_COMMAND_SERR;
-	if (bridge->hpp.enable_perr)
+	if (bridge->hpp.t0->enable_perr)
 		pci_cmd |= PCI_COMMAND_PARITY;
 	else
 		pci_cmd &= ~PCI_COMMAND_PARITY;
@@ -1129,13 +1231,13 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
 	/* Program bridge control value and child devices */
 	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
 		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
-				bridge->hpp.latency_timer);
+				bridge->hpp.t0->latency_timer);
 		pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
-		if (bridge->hpp.enable_serr)
+		if (bridge->hpp.t0->enable_serr)
 			pci_bctl |= PCI_BRIDGE_CTL_SERR;
 		else
 			pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
-		if (bridge->hpp.enable_perr)
+		if (bridge->hpp.t0->enable_perr)
 			pci_bctl |= PCI_BRIDGE_CTL_PARITY;
 		else
 			pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
@@ -1155,6 +1257,7 @@ static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus)
 
 	memset(&bridge, 0, sizeof(bridge));
 	bridge.handle = handle;
+	bridge.pci_bus = bus;
 	bridge.pci_dev = bus->self;
 	decode_hpp(&bridge);
 	list_for_each_entry(dev, &bus->devices, bus_list)
@@ -1297,6 +1400,13 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		/* request device eject */
 		dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
+		if ((bridge->type != BRIDGE_TYPE_HOST) &&
+		    (bridge->flags & BRIDGE_HAS_EJ0)) {
+			struct acpiphp_slot *slot;
+			slot = bridge->func->slot;
+			if (!acpiphp_disable_slot(slot))
+				acpiphp_eject_slot(slot);
+		}
 		break;
 
 	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
@@ -1490,9 +1600,15 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
 	if (retval)
 		goto err_exit;
 
-	if (get_slot_status(slot) == ACPI_STA_ALL)
+	if (get_slot_status(slot) == ACPI_STA_ALL) {
 		/* configure all functions */
 		retval = enable_device(slot);
+		if (retval)
+			power_off_slot(slot);
+	} else {
+		dbg("%s: Slot status is not ACPI_STA_ALL\n", __FUNCTION__);
+		power_off_slot(slot);
+	}
 
  err_exit:
 	mutex_unlock(&slot->crit_sect);
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index e13d5b87241a870c3eba6c150fb6f4b291d0753a..59392946c2bd350b0605877eaf4ae42af0ea81b3 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -285,7 +285,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)
 					(ulong) hotplug_slot, (ulong) value);
         
 	ibmphp_lock_operations();
-	if (hotplug_slot && value) {
+	if (hotplug_slot) {
 		pslot = hotplug_slot->private;
 		if (pslot) {
 			memcpy(&myslot, pslot, sizeof(struct slot));
@@ -315,7 +315,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value)
 	debug("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",
 					(ulong) hotplug_slot, (ulong) value);
 	ibmphp_lock_operations();
-	if (hotplug_slot && value) {
+	if (hotplug_slot) {
 		pslot = hotplug_slot->private;
 		if (pslot) {
 			memcpy(&myslot, pslot, sizeof(struct slot));
@@ -342,7 +342,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)
 	debug("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",
 					(ulong) hotplug_slot, (ulong) value);
 	ibmphp_lock_operations();
-	if (hotplug_slot && value) {
+	if (hotplug_slot) {
 		pslot = hotplug_slot->private;
 		if (pslot) {
 			memcpy(&myslot, pslot, sizeof(struct slot));
@@ -369,7 +369,7 @@ static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value)
 	debug("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",
 					(ulong) hotplug_slot, (ulong) value);
 	ibmphp_lock_operations();
-	if (hotplug_slot && value) {
+	if (hotplug_slot) {
 		pslot = hotplug_slot->private;
 		if (pslot) {
 			memcpy(&myslot, pslot, sizeof(struct slot));
@@ -401,7 +401,7 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
 
 	ibmphp_lock_operations();
 
-	if (hotplug_slot && value) {
+	if (hotplug_slot) {
 		pslot = hotplug_slot->private;
 		if (pslot) {
 			rc = 0;
@@ -441,7 +441,7 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
 
 	ibmphp_lock_operations();
 
-	if (hotplug_slot && value) {
+	if (hotplug_slot) {
 		pslot = hotplug_slot->private;
 		if (pslot) {
 			rc = get_cur_bus_info(&pslot);
diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h
index eb0d01d47236700ef4b3fb8dc60fcfdf6422f8e2..e929b7c114296c6a348af75fe921731a0f2e8220 100644
--- a/drivers/pci/hotplug/pci_hotplug.h
+++ b/drivers/pci/hotplug/pci_hotplug.h
@@ -176,11 +176,51 @@ extern int pci_hp_change_slot_info	(struct hotplug_slot *slot,
 					 struct hotplug_slot_info *info);
 extern struct subsystem pci_hotplug_slots_subsys;
 
+/* PCI Setting Record (Type 0) */
+struct hpp_type0 {
+	u32 revision;
+	u8  cache_line_size;
+	u8  latency_timer;
+	u8  enable_serr;
+	u8  enable_perr;
+};
+
+/* PCI-X Setting Record (Type 1) */
+struct hpp_type1 {
+	u32 revision;
+	u8  max_mem_read;
+	u8  avg_max_split;
+	u16 tot_max_split;
+};
+
+/* PCI Express Setting Record (Type 2) */
+struct hpp_type2 {
+	u32 revision;
+	u32 unc_err_mask_and;
+	u32 unc_err_mask_or;
+	u32 unc_err_sever_and;
+	u32 unc_err_sever_or;
+	u32 cor_err_mask_and;
+	u32 cor_err_mask_or;
+	u32 adv_err_cap_and;
+	u32 adv_err_cap_or;
+	u16 pci_exp_devctl_and;
+	u16 pci_exp_devctl_or;
+	u16 pci_exp_lnkctl_and;
+	u16 pci_exp_lnkctl_or;
+	u32 sec_unc_err_sever_and;
+	u32 sec_unc_err_sever_or;
+	u32 sec_unc_err_mask_and;
+	u32 sec_unc_err_mask_or;
+};
+
 struct hotplug_params {
-	u8 cache_line_size;
-	u8 latency_timer;
-	u8 enable_serr;
-	u8 enable_perr;
+	struct hpp_type0 *t0;		/* Type0: NULL if not available */
+	struct hpp_type1 *t1;		/* Type1: NULL if not available */
+	struct hpp_type2 *t2;		/* Type2: NULL if not available */
+	struct hpp_type0 type0_data;
+	struct hpp_type1 type1_data;
+	struct hpp_type2 type2_data;
 };
 
 #ifdef CONFIG_ACPI
@@ -188,7 +228,7 @@ struct hotplug_params {
 #include <acpi/acpi_bus.h>
 #include <acpi/actypes.h>
 extern acpi_status acpi_run_oshp(acpi_handle handle);
-extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
+extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
 				struct hotplug_params *hpp);
 int acpi_root_bridge(acpi_handle handle);
 #endif
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 92c1f0f1e1ad606ca671e0246c149235acd9f0c8..ce89f5815861ed4a9a4c8a9f0502f8514ff7194d 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -284,7 +284,7 @@ struct hpc_ops {
 static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
 			struct hotplug_params *hpp)
 {
-	if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp)))
+	if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp)))
 		return -ENODEV;
 	return 0;
 }
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 601cf9045b200e73ab348dcc7e3523c62987e6a3..c67b7c3f1ddf3e485df6b5c820c6338214b5c670 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -69,6 +69,7 @@ static int get_power_status	(struct hotplug_slot *slot, u8 *value);
 static int get_attention_status	(struct hotplug_slot *slot, u8 *value);
 static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
 static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
+static int get_address		(struct hotplug_slot *slot, u32 *value);
 static int get_max_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 static int get_cur_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 
@@ -81,6 +82,7 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
 	.get_attention_status =	get_attention_status,
 	.get_latch_status =	get_latch_status,
 	.get_adapter_status =	get_adapter_status,
+	.get_address =		get_address,
   	.get_max_bus_speed =	get_max_bus_speed,
   	.get_cur_bus_speed =	get_cur_bus_speed,
 };
@@ -331,6 +333,18 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
 	return 0;
 }
 
+static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
+{
+	struct slot *slot = hotplug_slot->private;
+	struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	*value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
+
+	return 0;
+}
+
 static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 {
 	struct slot *slot = hotplug_slot->private;
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 6c14d9e46b2e1f1a911191e3e7e40df61aa9d841..d77138ecb0981ec827a6d482d96f31eb6c5acc43 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -1288,7 +1288,7 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
 		if (ACPI_SUCCESS(status)) {
 			dbg("Gained control for hotplug HW for pci %s (%s)\n",
 				pci_name(dev), (char *)string.pointer);
-			acpi_os_free(string.pointer);
+			kfree(string.pointer);
 			return 0;
 		}
 		if (acpi_root_bridge(handle))
@@ -1302,7 +1302,7 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
 	err("Cannot get control of hotplug hardware for pci %s\n",
 			pci_name(dev));
 
-	acpi_os_free(string.pointer);
+	kfree(string.pointer);
 	return -1;
 }
 #endif
@@ -1404,9 +1404,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 	info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, 
 		pdev->subsystem_vendor, pdev->subsystem_device);
 
-	if (pci_enable_device(pdev))
-		goto abort_free_ctlr;
-	
 	mutex_init(&ctrl->crit_sect);
 	/* setup wait queue */
 	init_waitqueue_head(&ctrl->queue);
@@ -1474,7 +1471,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 	rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
 	if (rc) {
 		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort_free_irq;
 	}
 
 	intr_enable = intr_enable | PRSN_DETECT_ENABLE;
@@ -1500,19 +1497,19 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 	rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
 	if (rc) {
 		err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort_free_irq;
 	}
 	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
 	if (rc) {
 		err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort_disable_intr;
 	}
 	
 	temp_word =  0x1F; /* Clear all events */
 	rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
 	if (rc) {
 		err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort_disable_intr;
 	}
 	
 	if (pciehp_force) {
@@ -1521,7 +1518,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 	} else {
 		rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
 		if (rc)
-			goto abort_free_ctlr;
+			goto abort_disable_intr;
 	}
 
 	/*  Add this HPC instance into the HPC list */
@@ -1548,6 +1545,21 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 	return 0;
 
 	/* We end up here for the many possible ways to fail this API.  */
+abort_disable_intr:
+	rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
+	if (!rc) {
+		temp_word &= ~(intr_enable | HP_INTR_ENABLE);
+		rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
+	}
+	if (rc)
+		err("%s : disabling interrupts failed\n", __FUNCTION__);
+
+abort_free_irq:
+	if (pciehp_poll_mode)
+		del_timer_sync(&php_ctlr->int_poll_timer);
+	else
+		free_irq(php_ctlr->irq, ctrl);
+
 abort_free_ctlr:
 	pcie_cap_base = saved_cap_base;
 	kfree(php_ctlr);
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 4017fb03a0b81dacee1169f92b1d6d2795c77d7e..854aaea09e4db788bc048739ffbe9b20bc8e0140 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -34,6 +34,144 @@
 #include "../pci.h"
 #include "pciehp.h"
 
+static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp)
+{
+	u16 pci_cmd, pci_bctl;
+
+	if (hpp->revision > 1) {
+		printk(KERN_WARNING "%s: Rev.%d type0 record not supported\n",
+		       __FUNCTION__, hpp->revision);
+		return;
+	}
+
+	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer);
+	pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+	if (hpp->enable_serr)
+		pci_cmd |= PCI_COMMAND_SERR;
+	else
+		pci_cmd &= ~PCI_COMMAND_SERR;
+	if (hpp->enable_perr)
+		pci_cmd |= PCI_COMMAND_PARITY;
+	else
+		pci_cmd &= ~PCI_COMMAND_PARITY;
+	pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+
+	/* Program bridge control value */
+	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
+				      hpp->latency_timer);
+		pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
+		if (hpp->enable_serr)
+			pci_bctl |= PCI_BRIDGE_CTL_SERR;
+		else
+			pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
+		if (hpp->enable_perr)
+			pci_bctl |= PCI_BRIDGE_CTL_PARITY;
+		else
+			pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
+		pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
+	}
+}
+
+static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
+{
+	int pos;
+	u16 reg16;
+	u32 reg32;
+
+	if (hpp->revision > 1) {
+		printk(KERN_WARNING "%s: Rev.%d type2 record not supported\n",
+		       __FUNCTION__, hpp->revision);
+		return;
+	}
+
+	/* Find PCI Express capability */
+	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+	if (!pos)
+		return;
+
+	/* Initialize Device Control Register */
+	pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &reg16);
+	reg16 = (reg16 & hpp->pci_exp_devctl_and) | hpp->pci_exp_devctl_or;
+	pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16);
+
+	/* Initialize Link Control Register */
+	if (dev->subordinate) {
+		pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &reg16);
+		reg16 = (reg16 & hpp->pci_exp_lnkctl_and)
+			| hpp->pci_exp_lnkctl_or;
+		pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16);
+	}
+
+	/* Find Advanced Error Reporting Enhanced Capability */
+	pos = 256;
+	do {
+		pci_read_config_dword(dev, pos, &reg32);
+		if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
+			break;
+	} while ((pos = PCI_EXT_CAP_NEXT(reg32)));
+	if (!pos)
+		return;
+
+	/* Initialize Uncorrectable Error Mask Register */
+	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &reg32);
+	reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or;
+	pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32);
+
+	/* Initialize Uncorrectable Error Severity Register */
+	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &reg32);
+	reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or;
+	pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32);
+
+	/* Initialize Correctable Error Mask Register */
+	pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg32);
+	reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or;
+	pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32);
+
+	/* Initialize Advanced Error Capabilities and Control Register */
+	pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
+	reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or;
+	pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
+
+	/*
+	 * FIXME: The following two registers are not supported yet.
+	 *
+	 *   o Secondary Uncorrectable Error Severity Register
+	 *   o Secondary Uncorrectable Error Mask Register
+	 */
+}
+
+static void program_fw_provided_values(struct pci_dev *dev)
+{
+	struct pci_dev *cdev;
+	struct hotplug_params hpp;
+
+	/* Program hpp values for this device */
+	if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
+			(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
+			(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
+		return;
+
+	if (pciehp_get_hp_params_from_firmware(dev, &hpp)) {
+		printk(KERN_WARNING "%s: Could not get hotplug parameters\n",
+		       __FUNCTION__);
+		return;
+	}
+
+	if (hpp.t2)
+		program_hpp_type2(dev, hpp.t2);
+	if (hpp.t0)
+		program_hpp_type0(dev, hpp.t0);
+
+	/* Program child devices */
+	if (dev->subordinate) {
+		list_for_each_entry(cdev, &dev->subordinate->devices,
+				    bus_list)
+			program_fw_provided_values(cdev);
+	}
+}
+
 static int pciehp_add_bridge(struct pci_dev *dev)
 {
 	struct pci_bus *parent = dev->bus;
@@ -66,10 +204,11 @@ int pciehp_configure_device(struct slot *p_slot)
 	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
 	int num, fn;
 
-	dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0));
+	dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
 	if (dev) {
 		err("Device %s already exists at %x:%x, cannot hot-add\n",
 				pci_name(dev), p_slot->bus, p_slot->device);
+		pci_dev_put(dev);
 		return -EINVAL;
 	}
 
@@ -86,14 +225,15 @@ int pciehp_configure_device(struct slot *p_slot)
 		if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
 			err("Cannot hot-add display device %s\n",
 					pci_name(dev));
+			pci_dev_put(dev);
 			continue;
 		}
 		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
 				(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
 			pciehp_add_bridge(dev);
 		}
-		/* TBD: program firmware provided _HPP values */
-		/* program_fw_provided_values(dev); */
+		program_fw_provided_values(dev);
+		pci_dev_put(dev);
 	}
 
 	pci_bus_assign_resources(parent);
@@ -106,18 +246,20 @@ int pciehp_unconfigure_device(struct slot *p_slot)
 	int rc = 0;
 	int j;
 	u8 bctl = 0;
+	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
 
 	dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
 				p_slot->device);
 
 	for (j=0; j<8 ; j++) {
-		struct pci_dev* temp = pci_find_slot(p_slot->bus,
+		struct pci_dev* temp = pci_get_slot(parent,
 				(p_slot->device << 3) | j);
 		if (!temp)
 			continue;
 		if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
 			err("Cannot remove display device %s\n",
 					pci_name(temp));
+			pci_dev_put(temp);
 			continue;
 		}
 		if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
@@ -125,10 +267,12 @@ int pciehp_unconfigure_device(struct slot *p_slot)
 			if (bctl & PCI_BRIDGE_CTL_VGA) {
 				err("Cannot remove display device %s\n",
 						pci_name(temp));
+				pci_dev_put(temp);
 				continue;
 			}
 		}
 		pci_remove_bus_device(temp);
+		pci_dev_put(temp);
 	}
 	/* 
 	 * Some PCI Express root ports require fixup after hot-plug operation.
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index 8cb9abde736b43e40e6a72d6008838e60697c02d..f31d83c2c633c678d040190ff57b2f7246cce626 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -18,11 +18,13 @@
 #include <linux/mutex.h>
 
 #include <asm/sn/addrs.h>
+#include <asm/sn/geo.h>
 #include <asm/sn/l1.h>
 #include <asm/sn/module.h>
 #include <asm/sn/pcibr_provider.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
+#include <asm/sn/sn_feature_sets.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/types.h>
 
@@ -102,8 +104,7 @@ static struct hotplug_slot_attribute sn_slot_path_attr = __ATTR_RO(path);
 static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
 {
 	struct pcibus_info *pcibus_info;
-	int bricktype;
-	int bus_num;
+	u16 busnum, segment, ioboard_type;
 
 	pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
 
@@ -111,12 +112,14 @@ static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
 	if (!(pcibus_info->pbi_valid_devices & (1 << device)))
 		return -EPERM;
 
-	bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
-	bus_num = pcibus_info->pbi_buscommon.bs_persist_busnum & 0xf;
+	ioboard_type = sn_ioboard_to_pci_bus(pci_bus);
+	busnum = pcibus_info->pbi_buscommon.bs_persist_busnum;
+	segment = pci_domain_nr(pci_bus) & 0xf;
 
 	/* Do not allow hotplug operations on base I/O cards */
-	if ((bricktype == L1_BRICKTYPE_IX ||  bricktype == L1_BRICKTYPE_IA) &&
-	    (bus_num == 1 && device != 1))
+	if ((ioboard_type == L1_BRICKTYPE_IX ||
+	     ioboard_type == L1_BRICKTYPE_IA) &&
+	    (segment == 1 && busnum == 0 && device != 1))
 		return -EPERM;
 
 	return 1;
@@ -125,23 +128,23 @@ static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
 static int sn_pci_bus_valid(struct pci_bus *pci_bus)
 {
 	struct pcibus_info *pcibus_info;
-	int asic_type;
-	int bricktype;
-
-	pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
+	u32 asic_type;
+	u16 ioboard_type;
 
 	/* Don't register slots hanging off the TIOCA bus */
+	pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
 	asic_type = pcibus_info->pbi_buscommon.bs_asic_type;
 	if (asic_type == PCIIO_ASIC_TYPE_TIOCA)
 		return -EPERM;
 
 	/* Only register slots in I/O Bricks that support hotplug */
-	bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
-	switch (bricktype) {
+	ioboard_type = sn_ioboard_to_pci_bus(pci_bus);
+	switch (ioboard_type) {
 		case L1_BRICKTYPE_IX:
 		case L1_BRICKTYPE_PX:
 		case L1_BRICKTYPE_IA:
 		case L1_BRICKTYPE_PA:
+		case L1_BOARDTYPE_PCIX3SLOT:
 			return 1;
 			break;
 		default:
@@ -175,14 +178,11 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
 	slot->pci_bus = pci_bus;
 	sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x",
 		pci_domain_nr(pci_bus),
-		((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf,
+		((u16)pcibus_info->pbi_buscommon.bs_persist_busnum),
 		device + 1);
-	sprintf(slot->physical_path, "module_%c%c%c%c%.2d",
-		'0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
-		'0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
-		'0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
-		MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid),
-		MODULE_GET_BPOS(pcibus_info->pbi_moduleid));
+
+	sn_generate_path(pci_bus, slot->physical_path);
+
 	slot->hotplug_slot = bss_hotplug_slot;
 	list_add(&slot->hp_list, &sn_hp_list);
 
@@ -461,10 +461,12 @@ static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot,
 {
 	struct slot *slot = bss_hotplug_slot->private;
 	struct pcibus_info *pcibus_info;
+	u32 power;
 
 	pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
 	mutex_lock(&sn_hotplug_mutex);
-	*value = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
+	power = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
+	*value = power ? 1 : 0;
 	mutex_unlock(&sn_hotplug_mutex);
 	return 0;
 }
@@ -553,8 +555,8 @@ static int sn_pci_hotplug_init(void)
 	int rc;
 	int registered = 0;
 
-	if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) {
-		printk(KERN_ERR "%s: PROM version must be greater than 4.30\n",
+	if (!sn_prom_feature_available(PRF_HOTPLUG_SUPPORT)) {
+		printk(KERN_ERR "%s: PROM version does not support hotplug.\n",
 		       __FUNCTION__);
 		return -EPERM;
 	}
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index 5c70f43908c4288408e8e209f8783a4741a1d819..7208b95c6ee779585ff056bcdaeb091140f44961 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -168,9 +168,9 @@ struct controller {
  * error Messages
  */
 #define msg_initialization_err	"Initialization failure, error=%d\n"
-#define msg_button_on		"PCI slot #%d - powering on due to button press.\n"
-#define msg_button_off		"PCI slot #%d - powering off due to button press.\n"
-#define msg_button_cancel	"PCI slot #%d - action canceled due to button press.\n"
+#define msg_button_on		"PCI slot #%s - powering on due to button press.\n"
+#define msg_button_off		"PCI slot #%s - powering off due to button press.\n"
+#define msg_button_cancel	"PCI slot #%s - action canceled due to button press.\n"
 
 /* sysfs functions for the hotplug controller info */
 extern void shpchp_create_ctrl_files	(struct controller *ctrl);
@@ -196,7 +196,7 @@ extern void	queue_pushbutton_work(void *data);
 static inline int get_hp_params_from_firmware(struct pci_dev *dev,
 			struct hotplug_params *hpp)
 {
-	if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp)))
+	if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp)))
 			return -ENODEV;
 	return 0;
 }
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 3be4d492ccc2cf0143125fb154b94a7d4d2e05d0..a14e7de1984621cd9281751df06cc0624fee5d87 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -491,16 +491,9 @@ static int __init shpcd_init(void)
 	shpchp_poll_mode = 1;
 #endif
 
-	shpchp_wq = create_singlethread_workqueue("shpchpd");
-	if (!shpchp_wq)
-		return -ENOMEM;
-
 	retval = pci_register_driver(&shpc_driver);
 	dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-	if (retval) {
-		destroy_workqueue(shpchp_wq);
-	}
 	return retval;
 }
 
@@ -508,7 +501,6 @@ static void __exit shpcd_cleanup(void)
 {
 	dbg("unload_shpchpd()\n");
 	pci_unregister_driver(&shpc_driver);
-	destroy_workqueue(shpchp_wq);
 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 4e6381481c5501a30d84ece1e4e3b98917496ea2..c39901dbff202ee46cb04096e639060088e017f9 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -72,7 +72,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
 	/*
 	 *  Button pressed - See if need to TAKE ACTION!!!
 	 */
-	info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot);
+	info("Button pressed on Slot(%s)\n", p_slot->name);
 	event_type = INT_BUTTON_PRESS;
 
 	queue_interrupt_event(p_slot, event_type);
@@ -101,7 +101,7 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
 		/*
 		 * Switch opened
 		 */
-		info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Latch open on Slot(%s)\n", p_slot->name);
 		event_type = INT_SWITCH_OPEN;
 		if (p_slot->pwr_save && p_slot->presence_save) {
 			event_type = INT_POWER_FAULT;
@@ -111,7 +111,7 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
 		/*
 		 *  Switch closed
 		 */
-		info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Latch close on Slot(%s)\n", p_slot->name);
 		event_type = INT_SWITCH_CLOSE;
 	}
 
@@ -139,13 +139,13 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
 		/*
 		 * Card Present
 		 */
-		info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Card present on Slot(%s)\n", p_slot->name);
 		event_type = INT_PRESENCE_ON;
 	} else {
 		/*
 		 * Not Present
 		 */
-		info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Card not present on Slot(%s)\n", p_slot->name);
 		event_type = INT_PRESENCE_OFF;
 	}
 
@@ -169,14 +169,14 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
 		/*
 		 * Power fault Cleared
 		 */
-		info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Power fault cleared on Slot(%s)\n", p_slot->name);
 		p_slot->status = 0x00;
 		event_type = INT_POWER_FAULT_CLEAR;
 	} else {
 		/*
 		 *   Power fault
 		 */
-		info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Power fault on Slot(%s)\n", p_slot->name);
 		event_type = INT_POWER_FAULT;
 		/* set power fault status for this board */
 		p_slot->status = 0xFF;
@@ -496,10 +496,10 @@ static void handle_button_press_event(struct slot *p_slot)
 		p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 		if (getstatus) {
 			p_slot->state = BLINKINGOFF_STATE;
-			info(msg_button_off, p_slot->number);
+			info(msg_button_off, p_slot->name);
 		} else {
 			p_slot->state = BLINKINGON_STATE;
-			info(msg_button_on, p_slot->number);
+			info(msg_button_on, p_slot->name);
 		}
 		/* blink green LED and turn off amber */
 		p_slot->hpc_ops->green_led_blink(p_slot);
@@ -522,7 +522,7 @@ static void handle_button_press_event(struct slot *p_slot)
 		else
 			p_slot->hpc_ops->green_led_off(p_slot);
 		p_slot->hpc_ops->set_attention_status(p_slot, 0);
-		info(msg_button_cancel, p_slot->number);
+		info(msg_button_cancel, p_slot->name);
 		p_slot->state = STATIC_STATE;
 		break;
 	case POWEROFF_STATE:
@@ -575,17 +575,17 @@ static int shpchp_enable_slot (struct slot *p_slot)
 	mutex_lock(&p_slot->ctrl->crit_sect);
 	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 	if (rc || !getstatus) {
-		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
+		info("No adapter on slot(%s)\n", p_slot->name);
 		goto out;
 	}
 	rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	if (rc || getstatus) {
-		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+		info("Latch open on slot(%s)\n", p_slot->name);
 		goto out;
 	}
 	rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 	if (rc || getstatus) {
-		info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
+		info("Already enabled on slot(%s)\n", p_slot->name);
 		goto out;
 	}
 
@@ -634,17 +634,17 @@ static int shpchp_disable_slot (struct slot *p_slot)
 
 	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 	if (rc || !getstatus) {
-		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
+		info("No adapter on slot(%s)\n", p_slot->name);
 		goto out;
 	}
 	rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	if (rc || getstatus) {
-		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+		info("Latch open on slot(%s)\n", p_slot->name);
 		goto out;
 	}
 	rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 	if (rc || !getstatus) {
-		info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
+		info("Already disabled slot(%s)\n", p_slot->name);
 		goto out;
 	}
 
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 66123cf4deaa8bdcf17eee3391b9cac0edea8645..45facaad39bddc4ecec7135c0651408a31d0ac73 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -90,77 +90,94 @@
 #define	MRLSENSOR		0x40000000
 #define ATTN_BUTTON		0x80000000
 
-/* Slot Status Field Definitions */
-/* Slot State */
-#define PWR_ONLY		0x0001
-#define ENABLED			0x0002
-#define DISABLED		0x0003
-
-/* Power Indicator State */
-#define PWR_LED_ON		0x0004
-#define PWR_LED_BLINK		0x0008
-#define PWR_LED_OFF		0x000c
-
-/* Attention Indicator State */
-#define ATTEN_LED_ON		0x0010
-#define	ATTEN_LED_BLINK		0x0020
-#define ATTEN_LED_OFF		0x0030
-
-/* Power Fault */
-#define pwr_fault		0x0040
-
-/* Attention Button */
-#define ATTEN_BUTTON		0x0080
-
-/* MRL Sensor */
-#define MRL_SENSOR		0x0100
-
-/* 66 MHz Capable */
-#define IS_66MHZ_CAP		0x0200
-
-/* PRSNT1#/PRSNT2# */
-#define SLOT_EMP		0x0c00
-
-/* PCI-X Capability */
-#define NON_PCIX		0x0000
-#define PCIX_66			0x1000
-#define PCIX_133		0x3000
-#define PCIX_266		0x4000  /* For PI = 2 only */
-#define PCIX_533		0x5000	/* For PI = 2 only */
-
-/* SHPC 'write' operations/commands */
-
-/* Slot operation - 0x00h to 0x3Fh */
-
-#define NO_CHANGE		0x00
-
-/* Slot state - Bits 0 & 1 of controller command register */
-#define SET_SLOT_PWR		0x01	
-#define SET_SLOT_ENABLE		0x02	
-#define SET_SLOT_DISABLE	0x03	
+/*
+ * Interrupt Locator Register definitions
+ */
+#define CMD_INTR_PENDING	(1 << 0)
+#define SLOT_INTR_PENDING(i)	(1 << (i + 1))
 
-/* Power indicator state - Bits 2 & 3 of controller command register*/
-#define SET_PWR_ON		0x04	
-#define SET_PWR_BLINK		0x08	
-#define SET_PWR_OFF		0x0C	
+/*
+ * Controller SERR-INT Register
+ */
+#define GLOBAL_INTR_MASK	(1 << 0)
+#define GLOBAL_SERR_MASK	(1 << 1)
+#define COMMAND_INTR_MASK	(1 << 2)
+#define ARBITER_SERR_MASK	(1 << 3)
+#define COMMAND_DETECTED	(1 << 16)
+#define ARBITER_DETECTED	(1 << 17)
+#define SERR_INTR_RSVDZ_MASK	0xfffc0000
 
-/* Attention indicator state - Bits 4 & 5 of controller command register*/
-#define SET_ATTN_ON		0x010	
-#define SET_ATTN_BLINK		0x020
-#define SET_ATTN_OFF		0x030	
+/*
+ * Logical Slot Register definitions
+ */
+#define SLOT_REG(i)		(SLOT1 + (4 * i))
+
+#define SLOT_STATE_SHIFT	(0)
+#define SLOT_STATE_MASK		(3 << 0)
+#define SLOT_STATE_PWRONLY	(1)
+#define SLOT_STATE_ENABLED	(2)
+#define SLOT_STATE_DISABLED	(3)
+#define PWR_LED_STATE_SHIFT	(2)
+#define PWR_LED_STATE_MASK	(3 << 2)
+#define ATN_LED_STATE_SHIFT	(4)
+#define ATN_LED_STATE_MASK	(3 << 4)
+#define ATN_LED_STATE_ON	(1)
+#define ATN_LED_STATE_BLINK	(2)
+#define ATN_LED_STATE_OFF	(3)
+#define POWER_FAULT		(1 << 6)
+#define ATN_BUTTON		(1 << 7)
+#define MRL_SENSOR		(1 << 8)
+#define MHZ66_CAP		(1 << 9)
+#define PRSNT_SHIFT		(10)
+#define PRSNT_MASK		(3 << 10)
+#define PCIX_CAP_SHIFT		(12)
+#define PCIX_CAP_MASK_PI1	(3 << 12)
+#define PCIX_CAP_MASK_PI2	(7 << 12)
+#define PRSNT_CHANGE_DETECTED	(1 << 16)
+#define ISO_PFAULT_DETECTED	(1 << 17)
+#define BUTTON_PRESS_DETECTED	(1 << 18)
+#define MRL_CHANGE_DETECTED	(1 << 19)
+#define CON_PFAULT_DETECTED	(1 << 20)
+#define PRSNT_CHANGE_INTR_MASK	(1 << 24)
+#define ISO_PFAULT_INTR_MASK	(1 << 25)
+#define BUTTON_PRESS_INTR_MASK	(1 << 26)
+#define MRL_CHANGE_INTR_MASK	(1 << 27)
+#define CON_PFAULT_INTR_MASK	(1 << 28)
+#define MRL_CHANGE_SERR_MASK	(1 << 29)
+#define CON_PFAULT_SERR_MASK	(1 << 30)
+#define SLOT_REG_RSVDZ_MASK	(1 << 15) | (7 << 21)
 
-/* Set bus speed/mode A - 0x40h to 0x47h */
-#define SETA_PCI_33MHZ		0x40
+/*
+ * SHPC Command Code definitnions
+ *
+ *     Slot Operation				00h - 3Fh
+ *     Set Bus Segment Speed/Mode A		40h - 47h
+ *     Power-Only All Slots			48h
+ *     Enable All Slots				49h
+ *     Set Bus Segment Speed/Mode B (PI=2)	50h - 5Fh
+ *     Reserved Command Codes			60h - BFh
+ *     Vendor Specific Commands			C0h - FFh
+ */
+#define SET_SLOT_PWR		0x01	/* Slot Operation */
+#define SET_SLOT_ENABLE		0x02
+#define SET_SLOT_DISABLE	0x03
+#define SET_PWR_ON		0x04
+#define SET_PWR_BLINK		0x08
+#define SET_PWR_OFF		0x0c
+#define SET_ATTN_ON		0x10
+#define SET_ATTN_BLINK		0x20
+#define SET_ATTN_OFF		0x30
+#define SETA_PCI_33MHZ		0x40	/* Set Bus Segment Speed/Mode A */
 #define SETA_PCI_66MHZ		0x41
 #define SETA_PCIX_66MHZ		0x42
 #define SETA_PCIX_100MHZ	0x43
 #define SETA_PCIX_133MHZ	0x44
-#define RESERV_1		0x45
-#define RESERV_2		0x46
-#define RESERV_3		0x47
-
-/* Set bus speed/mode B - 0x50h to 0x5fh */
-#define	SETB_PCI_33MHZ		0x50
+#define SETA_RESERVED1		0x45
+#define SETA_RESERVED2		0x46
+#define SETA_RESERVED3		0x47
+#define SET_PWR_ONLY_ALL	0x48	/* Power-Only All Slots */
+#define SET_ENABLE_ALL		0x49	/* Enable All Slots */
+#define	SETB_PCI_33MHZ		0x50	/* Set Bus Segment Speed/Mode B */
 #define SETB_PCI_66MHZ		0x51
 #define SETB_PCIX_66MHZ_PM	0x52
 #define SETB_PCIX_100MHZ_PM	0x53
@@ -174,81 +191,115 @@
 #define SETB_PCIX_66MHZ_533	0x5b
 #define SETB_PCIX_100MHZ_533	0x5c
 #define SETB_PCIX_133MHZ_533	0x5d
+#define SETB_RESERVED1		0x5e
+#define SETB_RESERVED2		0x5f
 
-
-/* Power-on all slots - 0x48h */
-#define SET_PWR_ON_ALL		0x48
-
-/* Enable all slots	- 0x49h */
-#define SET_ENABLE_ALL		0x49
-
-/*  SHPC controller command error code */
+/*
+ * SHPC controller command error code
+ */
 #define SWITCH_OPEN		0x1
 #define INVALID_CMD		0x2
 #define INVALID_SPEED_MODE	0x4
 
-/* For accessing SHPC Working Register Set */
+/*
+ * For accessing SHPC Working Register Set via PCI Configuration Space
+ */
 #define DWORD_SELECT		0x2
 #define DWORD_DATA		0x4
-#define BASE_OFFSET		0x0
 
 /* Field Offset in Logical Slot Register - byte boundary */
 #define SLOT_EVENT_LATCH	0x2
 #define SLOT_SERR_INT_MASK	0x3
 
-static spinlock_t hpc_event_lock;
-
 DEFINE_DBG_BUFFER		/* Debug string buffer for entire HPC defined here */
 static struct php_ctlr_state_s *php_ctlr_list_head;	/* HPC state linked list */
 static int ctlr_seq_num = 0;	/* Controller sequenc # */
 static spinlock_t list_lock;
 
-static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs);
+static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
 
-static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds);
+static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs);
+static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec);
 static int hpc_check_cmd_status(struct controller *ctrl);
 
-/* This is the interrupt polling timeout function. */
-static void int_poll_timeout(unsigned long lphp_ctlr)
+static inline u8 shpc_readb(struct controller *ctrl, int reg)
 {
-    struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *)lphp_ctlr;
+	return readb(ctrl->hpc_ctlr_handle->creg + reg);
+}
 
-    DBG_ENTER_ROUTINE
+static inline void shpc_writeb(struct controller *ctrl, int reg, u8 val)
+{
+	writeb(val, ctrl->hpc_ctlr_handle->creg + reg);
+}
 
-    if ( !php_ctlr ) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return;
-    }
+static inline u16 shpc_readw(struct controller *ctrl, int reg)
+{
+	return readw(ctrl->hpc_ctlr_handle->creg + reg);
+}
 
-    /* Poll for interrupt events.  regs == NULL => polling */
-    shpc_isr( 0, (void *)php_ctlr, NULL );
+static inline void shpc_writew(struct controller *ctrl, int reg, u16 val)
+{
+	writew(val, ctrl->hpc_ctlr_handle->creg + reg);
+}
 
-    init_timer(&php_ctlr->int_poll_timer);
-	if (!shpchp_poll_time)
-		shpchp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/
+static inline u32 shpc_readl(struct controller *ctrl, int reg)
+{
+	return readl(ctrl->hpc_ctlr_handle->creg + reg);
+}
 
-    start_int_poll_timer(php_ctlr, shpchp_poll_time);  
-	
-	return;
+static inline void shpc_writel(struct controller *ctrl, int reg, u32 val)
+{
+	writel(val, ctrl->hpc_ctlr_handle->creg + reg);
 }
 
-/* This function starts the interrupt polling timer. */
-static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds)
+static inline int shpc_indirect_read(struct controller *ctrl, int index,
+				     u32 *value)
 {
-    if (!php_ctlr) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return;
-	}
+	int rc;
+	u32 cap_offset = ctrl->cap_offset;
+	struct pci_dev *pdev = ctrl->pci_dev;
+
+	rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index);
+	if (rc)
+		return rc;
+	return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value);
+}
+
+/*
+ * This is the interrupt polling timeout function.
+ */
+static void int_poll_timeout(unsigned long lphp_ctlr)
+{
+	struct php_ctlr_state_s *php_ctlr =
+		(struct php_ctlr_state_s *)lphp_ctlr;
+
+	DBG_ENTER_ROUTINE
+
+	/* Poll for interrupt events.  regs == NULL => polling */
+	shpc_isr(0, php_ctlr->callback_instance_id, NULL);
+
+	init_timer(&php_ctlr->int_poll_timer);
+	if (!shpchp_poll_time)
+		shpchp_poll_time = 2; /* default polling interval is 2 sec */
 
-    if ( ( seconds <= 0 ) || ( seconds > 60 ) )
-        seconds = 2;            /* Clamp to sane value */
+	start_int_poll_timer(php_ctlr, shpchp_poll_time);
 
-    php_ctlr->int_poll_timer.function = &int_poll_timeout;
-    php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr;    /* Instance data */
-    php_ctlr->int_poll_timer.expires = jiffies + seconds * HZ;
-    add_timer(&php_ctlr->int_poll_timer);
+	DBG_LEAVE_ROUTINE
+}
 
-	return;
+/*
+ * This function starts the interrupt polling timer.
+ */
+static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec)
+{
+	/* Clamp to sane value */
+	if ((sec <= 0) || (sec > 60))
+		sec = 2;
+
+	php_ctlr->int_poll_timer.function = &int_poll_timeout;
+	php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr;
+	php_ctlr->int_poll_timer.expires = jiffies + sec * HZ;
+	add_timer(&php_ctlr->int_poll_timer);
 }
 
 static inline int shpc_wait_cmd(struct controller *ctrl)
@@ -272,7 +323,7 @@ static inline int shpc_wait_cmd(struct controller *ctrl)
 
 static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u16 cmd_status;
 	int retval = 0;
 	u16 temp_word;
@@ -282,14 +333,8 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
 
 	mutex_lock(&slot->ctrl->cmd_lock);
 
-	if (!php_ctlr) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		retval = -EINVAL;
-		goto out;
-	}
-
 	for (i = 0; i < 10; i++) {
-		cmd_status = readw(php_ctlr->creg + CMD_STATUS);
+		cmd_status = shpc_readw(ctrl, CMD_STATUS);
 		
 		if (!(cmd_status & 0x1))
 			break;
@@ -297,7 +342,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
 		msleep(100);
 	}
 
-	cmd_status = readw(php_ctlr->creg + CMD_STATUS);
+	cmd_status = shpc_readw(ctrl, CMD_STATUS);
 	
 	if (cmd_status & 0x1) { 
 		/* After 1 sec and and the controller is still busy */
@@ -314,7 +359,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
 	 * command. 
 	 */
 	slot->ctrl->cmd_busy = 1;
-	writew(temp_word, php_ctlr->creg + CMD);
+	shpc_writew(ctrl, CMD, temp_word);
 
 	/*
 	 * Wait for command completion.
@@ -338,18 +383,12 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
 
 static int hpc_check_cmd_status(struct controller *ctrl)
 {
-	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
 	u16 cmd_status;
 	int retval = 0;
 
 	DBG_ENTER_ROUTINE 
-	
-	if (!ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
 
-	cmd_status = readw(php_ctlr->creg + CMD_STATUS) & 0x000F;
+	cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F;
 	
 	switch (cmd_status >> 1) {
 	case 0:
@@ -378,37 +417,27 @@ static int hpc_check_cmd_status(struct controller *ctrl)
 
 static int hpc_get_attention_status(struct slot *slot, u8 *status)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u32 slot_reg;
-	u16 slot_status;
-	u8 atten_led_state;
+	u8 state;
 	
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
-	slot_status = (u16) slot_reg;
-	atten_led_state = (slot_status & 0x0030) >> 4;
+	slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
+	state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT;
 
-	switch (atten_led_state) {
-	case 0:
-		*status = 0xFF;	/* Reserved */
-		break;
-	case 1:
+	switch (state) {
+	case ATN_LED_STATE_ON:
 		*status = 1;	/* On */
 		break;
-	case 2:
+	case ATN_LED_STATE_BLINK:
 		*status = 2;	/* Blink */
 		break;
-	case 3:
+	case ATN_LED_STATE_OFF:
 		*status = 0;	/* Off */
 		break;
 	default:
-		*status = 0xFF;
+		*status = 0xFF;	/* Reserved */
 		break;
 	}
 
@@ -418,64 +447,44 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
 
 static int hpc_get_power_status(struct slot * slot, u8 *status)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u32 slot_reg;
-	u16 slot_status;
-	u8 slot_state;
-	int	retval = 0;
+	u8 state;
 	
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
-	slot_status = (u16) slot_reg;
-	slot_state = (slot_status & 0x0003);
+	slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
+	state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT;
 
-	switch (slot_state) {
-	case 0:
-		*status = 0xFF;
-		break;
-	case 1:
+	switch (state) {
+	case SLOT_STATE_PWRONLY:
 		*status = 2;	/* Powered only */
 		break;
-	case 2:
+	case SLOT_STATE_ENABLED:
 		*status = 1;	/* Enabled */
 		break;
-	case 3:
+	case SLOT_STATE_DISABLED:
 		*status = 0;	/* Disabled */
 		break;
 	default:
-		*status = 0xFF;
+		*status = 0xFF;	/* Reserved */
 		break;
 	}
 
 	DBG_LEAVE_ROUTINE 
-	return retval;
+	return 0;
 }
 
 
 static int hpc_get_latch_status(struct slot *slot, u8 *status)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u32 slot_reg;
-	u16 slot_status;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
-	slot_status = (u16)slot_reg;
-
-	*status = ((slot_status & 0x0100) == 0) ? 0 : 1;   /* 0 -> close; 1 -> open */
-
+	slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
+	*status = !!(slot_reg & MRL_SENSOR);	/* 0 -> close; 1 -> open */
 
 	DBG_LEAVE_ROUTINE 
 	return 0;
@@ -483,22 +492,15 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
 
 static int hpc_get_adapter_status(struct slot *slot, u8 *status)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u32 slot_reg;
-	u16 slot_status;
-	u8 card_state;
+	u8 state;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
-	slot_status = (u16)slot_reg;
-	card_state = (u8)((slot_status & 0x0C00) >> 10);
-	*status = (card_state != 0x3) ? 1 : 0;
+	slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
+	state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT;
+	*status = (state != 0x3) ? 1 : 0;
 
 	DBG_LEAVE_ROUTINE 
 	return 0;
@@ -506,16 +508,11 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
 
 static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 
 	DBG_ENTER_ROUTINE 
-	
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
 
-	*prog_int = readb(php_ctlr->creg + PROG_INTERFACE);
+	*prog_int = shpc_readb(ctrl, PROG_INTERFACE);
 
 	DBG_LEAVE_ROUTINE 
 	return 0;
@@ -524,13 +521,27 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
 static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
 {
 	int retval = 0;
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u32 slot_reg = readl(php_ctlr->creg + SLOT1 + 4 * slot->hp_slot);
-	u8 pcix_cap = (slot_reg >> 12) & 7;
-	u8 m66_cap  = (slot_reg >> 9) & 1;
+	struct controller *ctrl = slot->ctrl;
+	u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
+	u8 m66_cap  = !!(slot_reg & MHZ66_CAP);
+	u8 pi, pcix_cap;
 
 	DBG_ENTER_ROUTINE 
 
+	if ((retval = hpc_get_prog_int(slot, &pi)))
+		return retval;
+
+	switch (pi) {
+	case 1:
+		pcix_cap = (slot_reg & PCIX_CAP_MASK_PI1) >> PCIX_CAP_SHIFT;
+		break;
+	case 2:
+		pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT;
+		break;
+	default:
+		return -ENODEV;
+	}
+
 	dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n",
 	    __FUNCTION__, slot_reg, pcix_cap, m66_cap);
 
@@ -564,20 +575,15 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
 
 static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u16 sec_bus_status;
 	u8 pi;
 	int retval = 0;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	pi = readb(php_ctlr->creg + PROG_INTERFACE);
-	sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG);
+	pi = shpc_readb(ctrl, PROG_INTERFACE);
+	sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG);
 
 	if (pi == 2) {
 		*mode = (sec_bus_status & 0x0100) >> 8;
@@ -593,128 +599,53 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
 
 static int hpc_query_power_fault(struct slot * slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u32 slot_reg;
-	u16 slot_status;
-	u8 pwr_fault_state, status;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
-	slot_status = (u16) slot_reg;
-	pwr_fault_state = (slot_status & 0x0040) >> 7;
-	status = (pwr_fault_state == 1) ? 0 : 1;
+	slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
 
 	DBG_LEAVE_ROUTINE
 	/* Note: Logic 0 => fault */
-	return status;
+	return !(slot_reg & POWER_FAULT);
 }
 
 static int hpc_set_attention_status(struct slot *slot, u8 value)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u8 slot_cmd = 0;
-	int rc = 0;
-
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return -1;
-	}
 
 	switch (value) {
 		case 0 :	
-			slot_cmd = 0x30;	/* OFF */
+			slot_cmd = SET_ATTN_OFF;	/* OFF */
 			break;
 		case 1:
-			slot_cmd = 0x10;	/* ON */
+			slot_cmd = SET_ATTN_ON;		/* ON */
 			break;
 		case 2:
-			slot_cmd = 0x20;	/* BLINK */
+			slot_cmd = SET_ATTN_BLINK;	/* BLINK */
 			break;
 		default:
 			return -1;
 	}
 
-	shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-	
-	return rc;
+	return shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
 }
 
 
 static void hpc_set_green_led_on(struct slot *slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u8 slot_cmd;
-
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return ;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return ;
-	}
-
-	slot_cmd = 0x04;
-
-	shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-
-	return;
+	shpc_write_cmd(slot, slot->hp_slot, SET_PWR_ON);
 }
 
 static void hpc_set_green_led_off(struct slot *slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u8 slot_cmd;
-
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return ;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return ;
-	}
-
-	slot_cmd = 0x0C;
-
-	shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-
-	return;
+	shpc_write_cmd(slot, slot->hp_slot, SET_PWR_OFF);
 }
 
 static void hpc_set_green_led_blink(struct slot *slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u8 slot_cmd;
-
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return ;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return ;
-	}
-
-	slot_cmd = 0x08;
-
-	shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-
-	return;
+	shpc_write_cmd(slot, slot->hp_slot, SET_PWR_BLINK);
 }
 
 int shpc_get_ctlr_slot_config(struct controller *ctrl,
@@ -724,21 +655,17 @@ int shpc_get_ctlr_slot_config(struct controller *ctrl,
 	int *updown,		/* physical_slot_num increament: 1 or -1	*/
 	int *flags)
 {
-	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
+	u32 slot_config;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	*first_device_num = php_ctlr->slot_device_offset;	/* Obtained in shpc_init() */
-	*num_ctlr_slots = php_ctlr->num_slots;			/* Obtained in shpc_init() */
+	slot_config = shpc_readl(ctrl, SLOT_CONFIG);
+	*first_device_num = (slot_config & FIRST_DEV_NUM) >> 8;
+	*num_ctlr_slots = slot_config & SLOT_NUM;
+	*physical_slot_num = (slot_config & PSN) >> 16;
+	*updown = ((slot_config & UPDOWN) >> 29) ? 1 : -1;
 
-	*physical_slot_num = (readl(php_ctlr->creg + SLOT_CONFIG) & PSN) >> 16;
 	dbg("%s: physical_slot_num = %x\n", __FUNCTION__, *physical_slot_num);
-	*updown = ((readl(php_ctlr->creg + SLOT_CONFIG) & UPDOWN ) >> 29) ? 1 : -1;	
 
 	DBG_LEAVE_ROUTINE 
 	return 0;
@@ -749,22 +676,34 @@ static void hpc_release_ctlr(struct controller *ctrl)
 	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
 	struct php_ctlr_state_s *p, *p_prev;
 	int i;
+	u32 slot_reg, serr_int;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return ;
-	}
-
 	/*
-	 * Mask all slot event interrupts
+	 * Mask event interrupts and SERRs of all slots
 	 */
-	for (i = 0; i < ctrl->num_slots; i++)
-		writel(0xffff3fff, php_ctlr->creg + SLOT1 + (4 * i));
+	for (i = 0; i < ctrl->num_slots; i++) {
+		slot_reg = shpc_readl(ctrl, SLOT_REG(i));
+		slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
+			     BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
+			     CON_PFAULT_INTR_MASK   | MRL_CHANGE_SERR_MASK |
+			     CON_PFAULT_SERR_MASK);
+		slot_reg &= ~SLOT_REG_RSVDZ_MASK;
+		shpc_writel(ctrl, SLOT_REG(i), slot_reg);
+	}
 
 	cleanup_slots(ctrl);
 
+	/*
+	 * Mask SERR and System Interrut generation
+	 */
+	serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
+	serr_int |= (GLOBAL_INTR_MASK  | GLOBAL_SERR_MASK |
+		     COMMAND_INTR_MASK | ARBITER_SERR_MASK);
+	serr_int &= ~SERR_INTR_RSVDZ_MASK;
+	shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
+
 	if (shpchp_poll_mode) {
 	    del_timer(&php_ctlr->int_poll_timer);
 	} else {	
@@ -800,113 +739,79 @@ static void hpc_release_ctlr(struct controller *ctrl)
 
 	kfree(php_ctlr);
 
+	/*
+	 * If this is the last controller to be released, destroy the
+	 * shpchpd work queue
+	 */
+	if (atomic_dec_and_test(&shpchp_num_controllers))
+		destroy_workqueue(shpchp_wq);
+
 DBG_LEAVE_ROUTINE
 			  
 }
 
 static int hpc_power_on_slot(struct slot * slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u8 slot_cmd;
-	int retval = 0;
+	int retval;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return -1;
-	}
-	slot_cmd = 0x01;
-
-	retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-
+	retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR);
 	if (retval) {
 		err("%s: Write command failed!\n", __FUNCTION__);
-		return -1;
+		return retval;
 	}
 
 	DBG_LEAVE_ROUTINE
 
-	return retval;
+	return 0;
 }
 
 static int hpc_slot_enable(struct slot * slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u8 slot_cmd;
-	int retval = 0;
+	int retval;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return -1;
-	}
-	/* 3A => Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */
-	slot_cmd = 0x3A;  
-
-	retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-
+	/* Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */
+	retval = shpc_write_cmd(slot, slot->hp_slot,
+			SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF);
 	if (retval) {
 		err("%s: Write command failed!\n", __FUNCTION__);
-		return -1;
+		return retval;
 	}
 
 	DBG_LEAVE_ROUTINE
-	return retval;
+	return 0;
 }
 
 static int hpc_slot_disable(struct slot * slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u8 slot_cmd;
-	int retval = 0;
+	int retval;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return -1;
-	}
-
-	/* 1F => Slot - Disable, Power Indicator - Off, Attention Indicator - On */
-	slot_cmd = 0x1F;
-
-	retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-
+	/* Slot - Disable, Power Indicator - Off, Attention Indicator - On */
+	retval = shpc_write_cmd(slot, slot->hp_slot,
+			SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON);
 	if (retval) {
 		err("%s: Write command failed!\n", __FUNCTION__);
-		return -1;
+		return retval;
 	}
 
 	DBG_LEAVE_ROUTINE
-	return retval;
+	return 0;
 }
 
 static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
 {
 	int retval;
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u8 pi, cmd;
 
 	DBG_ENTER_ROUTINE 
 
-	pi = readb(php_ctlr->creg + PROG_INTERFACE);
+	pi = shpc_readb(ctrl, PROG_INTERFACE);
 	if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX))
 		return -EINVAL;
 
@@ -965,100 +870,86 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
 	return retval;
 }
 
-static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
+static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct controller *ctrl = NULL;
-	struct php_ctlr_state_s *php_ctlr;
-	u8 schedule_flag = 0;
-	u8 temp_byte;
-	u32 temp_dword, intr_loc, intr_loc2;
+	struct controller *ctrl = (struct controller *)dev_id;
+	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
+	u32 serr_int, slot_reg, intr_loc, intr_loc2;
 	int hp_slot;
 
-	if (!dev_id)
-		return IRQ_NONE;
-
-	if (!shpchp_poll_mode) { 
-		ctrl = (struct controller *)dev_id;
-		php_ctlr = ctrl->hpc_ctlr_handle;
-	} else { 
-		php_ctlr = (struct php_ctlr_state_s *) dev_id;
-		ctrl = (struct controller *)php_ctlr->callback_instance_id;
-	}
-
-	if (!ctrl)
-		return IRQ_NONE;
-	
-	if (!php_ctlr || !php_ctlr->creg)
-		return IRQ_NONE;
-
 	/* Check to see if it was our interrupt */
-	intr_loc = readl(php_ctlr->creg + INTR_LOC);  
-
+	intr_loc = shpc_readl(ctrl, INTR_LOC);
 	if (!intr_loc)
 		return IRQ_NONE;
+
 	dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); 
 
 	if(!shpchp_poll_mode) {
-		/* Mask Global Interrupt Mask - see implementation note on p. 139 */
-		/* of SHPC spec rev 1.0*/
-		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-		temp_dword |= 0x00000001;
-		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+		/*
+		 * Mask Global Interrupt Mask - see implementation
+		 * note on p. 139 of SHPC spec rev 1.0
+		 */
+		serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
+		serr_int |= GLOBAL_INTR_MASK;
+		serr_int &= ~SERR_INTR_RSVDZ_MASK;
+		shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
 
-		intr_loc2 = readl(php_ctlr->creg + INTR_LOC);  
+		intr_loc2 = shpc_readl(ctrl, INTR_LOC);
 		dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); 
 	}
 
-	if (intr_loc & 0x0001) {
+	if (intr_loc & CMD_INTR_PENDING) {
 		/* 
 		 * Command Complete Interrupt Pending 
 		 * RO only - clear by writing 1 to the Command Completion
 		 * Detect bit in Controller SERR-INT register
 		 */
-		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-		temp_dword &= 0xfffdffff;
-		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+		serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
+		serr_int &= ~SERR_INTR_RSVDZ_MASK;
+		shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
+
 		ctrl->cmd_busy = 0;
 		wake_up_interruptible(&ctrl->queue);
 	}
 
-	if ((intr_loc = (intr_loc >> 1)) == 0)
+	if (!(intr_loc & ~CMD_INTR_PENDING))
 		goto out;
 
 	for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { 
-	/* To find out which slot has interrupt pending */
-		if ((intr_loc >> hp_slot) & 0x01) {
-			temp_dword = readl(php_ctlr->creg + SLOT1 + (4*hp_slot));
-			dbg("%s: Slot %x with intr, slot register = %x\n",
-				__FUNCTION__, hp_slot, temp_dword);
-			temp_byte = (temp_dword >> 16) & 0xFF;
-			if ((php_ctlr->switch_change_callback) && (temp_byte & 0x08))
-				schedule_flag += php_ctlr->switch_change_callback(
-					hp_slot, php_ctlr->callback_instance_id);
-			if ((php_ctlr->attention_button_callback) && (temp_byte & 0x04))
-				schedule_flag += php_ctlr->attention_button_callback(
-					hp_slot, php_ctlr->callback_instance_id);
-			if ((php_ctlr->presence_change_callback) && (temp_byte & 0x01))
-				schedule_flag += php_ctlr->presence_change_callback(
-					hp_slot , php_ctlr->callback_instance_id);
-			if ((php_ctlr->power_fault_callback) && (temp_byte & 0x12))
-				schedule_flag += php_ctlr->power_fault_callback(
-					hp_slot, php_ctlr->callback_instance_id);
-			
-			/* Clear all slot events */
-			temp_dword = 0xe01f3fff;
-			writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot));
-
-			intr_loc2 = readl(php_ctlr->creg + INTR_LOC);  
-			dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); 
-		}
+		/* To find out which slot has interrupt pending */
+		if (!(intr_loc & SLOT_INTR_PENDING(hp_slot)))
+			continue;
+
+		slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
+		dbg("%s: Slot %x with intr, slot register = %x\n",
+		    __FUNCTION__, hp_slot, slot_reg);
+
+		if (slot_reg & MRL_CHANGE_DETECTED)
+			php_ctlr->switch_change_callback(
+				hp_slot, php_ctlr->callback_instance_id);
+
+		if (slot_reg & BUTTON_PRESS_DETECTED)
+			php_ctlr->attention_button_callback(
+				hp_slot, php_ctlr->callback_instance_id);
+
+		if (slot_reg & PRSNT_CHANGE_DETECTED)
+			php_ctlr->presence_change_callback(
+				hp_slot , php_ctlr->callback_instance_id);
+
+		if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED))
+			php_ctlr->power_fault_callback(
+				hp_slot, php_ctlr->callback_instance_id);
+
+		/* Clear all slot events */
+		slot_reg &= ~SLOT_REG_RSVDZ_MASK;
+		shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
 	}
  out:
 	if (!shpchp_poll_mode) {
 		/* Unmask Global Interrupt Mask */
-		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-		temp_dword &= 0xfffffffe;
-		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+		serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
+		serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK);
+		shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
 	}
 	
 	return IRQ_HANDLED;
@@ -1067,11 +958,11 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
 static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 {
 	int retval = 0;
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
-	u8 pi = readb(php_ctlr->creg + PROG_INTERFACE);
-	u32 slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1);
-	u32 slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2);
+	u8 pi = shpc_readb(ctrl, PROG_INTERFACE);
+	u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1);
+	u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2);
 
 	DBG_ENTER_ROUTINE 
 
@@ -1114,10 +1005,10 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 {
 	int retval = 0;
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
-	u16 sec_bus_reg = readw(php_ctlr->creg + SEC_BUS_CONFIG);
-	u8 pi = readb(php_ctlr->creg + PROG_INTERFACE);
+	u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG);
+	u8 pi = shpc_readb(ctrl, PROG_INTERFACE);
 	u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7);
 
 	DBG_ENTER_ROUTINE 
@@ -1206,28 +1097,14 @@ static struct hpc_ops shpchp_hpc_ops = {
 	.release_ctlr			= hpc_release_ctlr,
 };
 
-inline static int shpc_indirect_creg_read(struct controller *ctrl, int index,
-					  u32 *value)
-{
-	int rc;
-	u32 cap_offset = ctrl->cap_offset;
-	struct pci_dev *pdev = ctrl->pci_dev;
-
-	rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index);
-	if (rc)
-		return rc;
-	return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value);
-}
-
 int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 {
 	struct php_ctlr_state_s *php_ctlr, *p;
 	void *instance_id = ctrl;
 	int rc, num_slots = 0;
 	u8 hp_slot;
-	static int first = 1;
 	u32 shpc_base_offset;
-	u32 tempdword, slot_reg;
+	u32 tempdword, slot_reg, slot_config;
 	u8 i;
 
 	DBG_ENTER_ROUTINE
@@ -1257,13 +1134,13 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 		}
 		dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset);
 
-		rc = shpc_indirect_creg_read(ctrl, 0, &shpc_base_offset);
+		rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset);
 		if (rc) {
 			err("%s: cannot read base_offset\n", __FUNCTION__);
 			goto abort_free_ctlr;
 		}
 
-		rc = shpc_indirect_creg_read(ctrl, 3, &tempdword);
+		rc = shpc_indirect_read(ctrl, 3, &tempdword);
 		if (rc) {
 			err("%s: cannot read slot config\n", __FUNCTION__);
 			goto abort_free_ctlr;
@@ -1272,7 +1149,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 		dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots);
 
 		for (i = 0; i < 9 + num_slots; i++) {
-			rc = shpc_indirect_creg_read(ctrl, i, &tempdword);
+			rc = shpc_indirect_read(ctrl, i, &tempdword);
 			if (rc) {
 				err("%s: cannot read creg (index = %d)\n",
 				    __FUNCTION__, i);
@@ -1287,11 +1164,6 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 		ctrl->mmio_size = 0x24 + 0x4 * num_slots;
 	}
 
-	if (first) {
-		spin_lock_init(&hpc_event_lock);
-		first = 0;
-	}
-
 	info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, 
 		pdev->subsystem_device);
 	
@@ -1326,29 +1198,39 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 	php_ctlr->power_fault_callback = shpchp_handle_power_fault;
 	php_ctlr->callback_instance_id = instance_id;
 
+	ctrl->hpc_ctlr_handle = php_ctlr;
+	ctrl->hpc_ops = &shpchp_hpc_ops;
+
 	/* Return PCI Controller Info */
-	php_ctlr->slot_device_offset = (readl(php_ctlr->creg + SLOT_CONFIG) & FIRST_DEV_NUM ) >> 8;
-	php_ctlr->num_slots = readl(php_ctlr->creg + SLOT_CONFIG) & SLOT_NUM;
+	slot_config = shpc_readl(ctrl, SLOT_CONFIG);
+	php_ctlr->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8;
+	php_ctlr->num_slots = slot_config & SLOT_NUM;
 	dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset);
 	dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots);
 
 	/* Mask Global Interrupt Mask & Command Complete Interrupt Mask */
-	tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+	tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
 	dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
-	tempdword = 0x0003000f;   
-	writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE);
-	tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+	tempdword |= (GLOBAL_INTR_MASK  | GLOBAL_SERR_MASK |
+		      COMMAND_INTR_MASK | ARBITER_SERR_MASK);
+	tempdword &= ~SERR_INTR_RSVDZ_MASK;
+	shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
+	tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
 	dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
 
 	/* Mask the MRL sensor SERR Mask of individual slot in
 	 * Slot SERR-INT Mask & clear all the existing event if any
 	 */
 	for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) {
-		slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot );
+		slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
 		dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
 			hp_slot, slot_reg);
-		tempdword = 0xffff3fff;  
-		writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot));
+		slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
+			     BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
+			     CON_PFAULT_INTR_MASK   | MRL_CHANGE_SERR_MASK |
+			     CON_PFAULT_SERR_MASK);
+		slot_reg &= ~SLOT_REG_RSVDZ_MASK;
+		shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
 	}
 	
 	if (shpchp_poll_mode)  {/* Install interrupt polling code */
@@ -1392,24 +1274,37 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 	}
 	spin_unlock(&list_lock);
 
-
 	ctlr_seq_num++;
-	ctrl->hpc_ctlr_handle = php_ctlr;
-	ctrl->hpc_ops = &shpchp_hpc_ops;
 
+	/*
+	 * If this is the first controller to be initialized,
+	 * initialize the shpchpd work queue
+	 */
+	if (atomic_add_return(1, &shpchp_num_controllers) == 1) {
+		shpchp_wq = create_singlethread_workqueue("shpchpd");
+		if (!shpchp_wq)
+			return -ENOMEM;
+	}
+
+	/*
+	 * Unmask all event interrupts of all slots
+	 */
 	for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) {
-		slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot );
+		slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
 		dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
 			hp_slot, slot_reg);
-		tempdword = 0xe01f3fff;  
-		writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot));
+		slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
+			      BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
+			      CON_PFAULT_INTR_MASK | SLOT_REG_RSVDZ_MASK);
+		shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
 	}
 	if (!shpchp_poll_mode) {
 		/* Unmask all general input interrupts and SERR */
-		tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-		tempdword = 0x0000000a;
-		writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE);
-		tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+		tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
+		tempdword &= ~(GLOBAL_INTR_MASK | COMMAND_INTR_MASK |
+			       SERR_INTR_RSVDZ_MASK);
+		shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
+		tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
 		dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
 	}
 
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index 257adc2339966ac856ab2056097a528d82a6c7fa..0a6b25ef194c2991e36d3be4e2bb605b61a4bed4 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -47,21 +47,28 @@ static void program_fw_provided_values(struct pci_dev *dev)
 		return;
 
 	/* use default values if we can't get them from firmware */
-	if (get_hp_params_from_firmware(dev, &hpp)) {
-		hpp.cache_line_size = 8;
-		hpp.latency_timer = 0x40;
-		hpp.enable_serr = 0;
-		hpp.enable_perr = 0;
+	if (get_hp_params_from_firmware(dev, &hpp) ||
+	    !hpp.t0 || (hpp.t0->revision > 1)) {
+		printk(KERN_WARNING
+		       "%s: Could not get hotplug parameters. Use defaults\n",
+		       __FUNCTION__);
+		hpp.t0 = &hpp.type0_data;
+		hpp.t0->revision = 0;
+		hpp.t0->cache_line_size = 8;
+		hpp.t0->latency_timer = 0x40;
+		hpp.t0->enable_serr = 0;
+		hpp.t0->enable_perr = 0;
 	}
 
-	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size);
-	pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer);
+	pci_write_config_byte(dev,
+			      PCI_CACHE_LINE_SIZE, hpp.t0->cache_line_size);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.t0->latency_timer);
 	pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
-	if (hpp.enable_serr)
+	if (hpp.t0->enable_serr)
 		pci_cmd |= PCI_COMMAND_SERR;
 	else
 		pci_cmd &= ~PCI_COMMAND_SERR;
-	if (hpp.enable_perr)
+	if (hpp.t0->enable_perr)
 		pci_cmd |= PCI_COMMAND_PARITY;
 	else
 		pci_cmd &= ~PCI_COMMAND_PARITY;
@@ -70,13 +77,13 @@ static void program_fw_provided_values(struct pci_dev *dev)
 	/* Program bridge control value and child devices */
 	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
 		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
-				hpp.latency_timer);
+				hpp.t0->latency_timer);
 		pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
-		if (hpp.enable_serr)
+		if (hpp.t0->enable_serr)
 			pci_bctl |= PCI_BRIDGE_CTL_SERR;
 		else
 			pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
-		if (hpp.enable_perr)
+		if (hpp.t0->enable_perr)
 			pci_bctl |= PCI_BRIDGE_CTL_PARITY;
 		else
 			pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;