Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (21 commits)
  pciehp: fix error message about getting hotplug control
  pci/irq: let pci_device_shutdown to call pci_msi_shutdown v2
  pci/irq: restore mask_bits in msi shutdown -v3
  doc: replace yet another dev with pdev for consistency in DMA-mapping.txt
  PCI: don't expose struct pci_vpd to userspace
  doc: fix an incorrect suggestion to pass NULL for PCI like buses
  Consistently use pdev as the variable of type struct pci_dev *.
  pciehp: Fix command write
  shpchp: fix slot name
  make pciehp_acpi_get_hp_hw_control_from_firmware()
  pciehp: Clean up pcie_init()
  pciehp: Mask hotplug interrupt at controller release
  pciehp: Remove useless hotplug interrupt enabling
  pciehp: Fix wrong slot capability check
  pciehp: Fix wrong slot control register access
  pciehp: Add missing memory barrier
  pciehp: Fix interrupt event handlig
  pciehp: fix slot name
  Update MAINTAINERS with location of PCI tree
  PCI: Add Intel SCH PCI IDs
  ...
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
index d84f89d..b463ecd 100644
--- a/Documentation/DMA-mapping.txt
+++ b/Documentation/DMA-mapping.txt
@@ -315,11 +315,11 @@
 
 	dma_addr_t dma_handle;
 
-	cpu_addr = pci_alloc_consistent(dev, size, &dma_handle);
+	cpu_addr = pci_alloc_consistent(pdev, size, &dma_handle);
 
-where dev is a struct pci_dev *. You should pass NULL for PCI like buses
-where devices don't have struct pci_dev (like ISA, EISA).  This may be
-called in interrupt context. 
+where pdev is a struct pci_dev *. This may be called in interrupt context.
+You should use dma_alloc_coherent (see DMA-API.txt) for buses
+where devices don't have struct pci_dev (like ISA, EISA).
 
 This argument is needed because the DMA translations may be bus
 specific (and often is private to the bus which the device is attached
@@ -332,7 +332,7 @@
 driver needs regions sized smaller than a page, you may prefer using
 the pci_pool interface, described below.
 
-The consistent DMA mapping interfaces, for non-NULL dev, will by
+The consistent DMA mapping interfaces, for non-NULL pdev, will by
 default return a DMA address which is SAC (Single Address Cycle)
 addressable.  Even if the device indicates (via PCI dma mask) that it
 may address the upper 32-bits and thus perform DAC cycles, consistent
@@ -354,9 +354,9 @@
 
 To unmap and free such a DMA region, you call:
 
-	pci_free_consistent(dev, size, cpu_addr, dma_handle);
+	pci_free_consistent(pdev, size, cpu_addr, dma_handle);
 
-where dev, size are the same as in the above call and cpu_addr and
+where pdev, size are the same as in the above call and cpu_addr and
 dma_handle are the values pci_alloc_consistent returned to you.
 This function may not be called in interrupt context.
 
@@ -371,9 +371,9 @@
 
 	struct pci_pool *pool;
 
-	pool = pci_pool_create(name, dev, size, align, alloc);
+	pool = pci_pool_create(name, pdev, size, align, alloc);
 
-The "name" is for diagnostics (like a kmem_cache name); dev and size
+The "name" is for diagnostics (like a kmem_cache name); pdev and size
 are as above.  The device's hardware alignment requirement for this
 type of data is "align" (which is expressed in bytes, and must be a
 power of two).  If your device has no boundary crossing restrictions,
@@ -472,11 +472,11 @@
 	void *addr = buffer->ptr;
 	size_t size = buffer->len;
 
-	dma_handle = pci_map_single(dev, addr, size, direction);
+	dma_handle = pci_map_single(pdev, addr, size, direction);
 
 and to unmap it:
 
-	pci_unmap_single(dev, dma_handle, size, direction);
+	pci_unmap_single(pdev, dma_handle, size, direction);
 
 You should call pci_unmap_single when the DMA activity is finished, e.g.
 from the interrupt which told you that the DMA transfer is done.
@@ -493,17 +493,17 @@
 	unsigned long offset = buffer->offset;
 	size_t size = buffer->len;
 
-	dma_handle = pci_map_page(dev, page, offset, size, direction);
+	dma_handle = pci_map_page(pdev, page, offset, size, direction);
 
 	...
 
-	pci_unmap_page(dev, dma_handle, size, direction);
+	pci_unmap_page(pdev, dma_handle, size, direction);
 
 Here, "offset" means byte offset within the given page.
 
 With scatterlists, you map a region gathered from several regions by:
 
-	int i, count = pci_map_sg(dev, sglist, nents, direction);
+	int i, count = pci_map_sg(pdev, sglist, nents, direction);
 	struct scatterlist *sg;
 
 	for_each_sg(sglist, sg, count, i) {
@@ -527,7 +527,7 @@
 
 To unmap a scatterlist, just call:
 
-	pci_unmap_sg(dev, sglist, nents, direction);
+	pci_unmap_sg(pdev, sglist, nents, direction);
 
 Again, make sure DMA activity has already finished.
 
@@ -550,11 +550,11 @@
 So, firstly, just map it with pci_map_{single,sg}, and after each DMA
 transfer call either:
 
-	pci_dma_sync_single_for_cpu(dev, dma_handle, size, direction);
+	pci_dma_sync_single_for_cpu(pdev, dma_handle, size, direction);
 
 or:
 
-	pci_dma_sync_sg_for_cpu(dev, sglist, nents, direction);
+	pci_dma_sync_sg_for_cpu(pdev, sglist, nents, direction);
 
 as appropriate.
 
@@ -562,7 +562,7 @@
 finish accessing the data with the cpu, and then before actually
 giving the buffer to the hardware call either:
 
-	pci_dma_sync_single_for_device(dev, dma_handle, size, direction);
+	pci_dma_sync_single_for_device(pdev, dma_handle, size, direction);
 
 or:
 
@@ -739,7 +739,7 @@
 
 	dma_addr_t dma_handle;
 
-	dma_handle = pci_map_single(dev, addr, size, direction);
+	dma_handle = pci_map_single(pdev, addr, size, direction);
 	if (pci_dma_mapping_error(dma_handle)) {
 		/*
 		 * reduce current DMA mapping usage,
diff --git a/MAINTAINERS b/MAINTAINERS
index d103766..c4e5b5d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3114,6 +3114,7 @@
 M:	jbarnes@virtuousgeek.org
 L:	linux-kernel@vger.kernel.org
 L:	linux-pci@atrey.karlin.mff.cuni.cz
+T:	git kernel.org:/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git
 S:	Supported
 
 PCI HOTPLUG CORE
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index f14267e1..8264a76 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -93,11 +93,10 @@
 	u8 slot_device_offset;
 	u32 first_slot;		/* First physical slot number */  /* PCIE only has 1 slot */
 	u8 slot_bus;		/* Bus where the slots handled by this controller sit */
-	u8 ctrlcap;
+	u32 slot_cap;
 	u8 cap_base;
 	struct timer_list poll_timer;
 	volatile int cmd_busy;
-	spinlock_t lock;
 };
 
 #define INT_BUTTON_IGNORE		0
@@ -137,13 +136,13 @@
 #define HP_SUPR_RM_SUP	0x00000020
 #define EMI_PRSN	0x00020000
 
-#define ATTN_BUTTN(cap)		(cap & ATTN_BUTTN_PRSN)
-#define POWER_CTRL(cap)		(cap & PWR_CTRL_PRSN)
-#define MRL_SENS(cap)		(cap & MRL_SENS_PRSN)
-#define ATTN_LED(cap)		(cap & ATTN_LED_PRSN)
-#define PWR_LED(cap)		(cap & PWR_LED_PRSN) 
-#define HP_SUPR_RM(cap)		(cap & HP_SUPR_RM_SUP)
-#define EMI(cap)		(cap & EMI_PRSN)
+#define ATTN_BUTTN(ctrl)	((ctrl)->slot_cap & ATTN_BUTTN_PRSN)
+#define POWER_CTRL(ctrl)	((ctrl)->slot_cap & PWR_CTRL_PRSN)
+#define MRL_SENS(ctrl)		((ctrl)->slot_cap & MRL_SENS_PRSN)
+#define ATTN_LED(ctrl)		((ctrl)->slot_cap & ATTN_LED_PRSN)
+#define PWR_LED(ctrl)		((ctrl)->slot_cap & PWR_LED_PRSN)
+#define HP_SUPR_RM(ctrl)	((ctrl)->slot_cap & HP_SUPR_RM_SUP)
+#define EMI(ctrl)		((ctrl)->slot_cap & EMI_PRSN)
 
 extern int pciehp_sysfs_enable_slot(struct slot *slot);
 extern int pciehp_sysfs_disable_slot(struct slot *slot);
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index aee19f0..43d8ddb 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -41,6 +41,7 @@
 int pciehp_poll_mode;
 int pciehp_poll_time;
 int pciehp_force;
+int pciehp_slot_with_bus;
 struct workqueue_struct *pciehp_wq;
 
 #define DRIVER_VERSION	"0.4"
@@ -55,10 +56,12 @@
 module_param(pciehp_poll_mode, bool, 0644);
 module_param(pciehp_poll_time, int, 0644);
 module_param(pciehp_force, bool, 0644);
+module_param(pciehp_slot_with_bus, bool, 0644);
 MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
 MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
 MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
 MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing");
+MODULE_PARM_DESC(pciehp_slot_with_bus, "Use bus number in the slot name");
 
 #define PCIE_MODULE_NAME "pciehp"
 
@@ -193,8 +196,12 @@
 
 static void make_slot_name(struct slot *slot)
 {
-	snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
-		 slot->bus, slot->number);
+	if (pciehp_slot_with_bus)
+		snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
+			 slot->bus, slot->number);
+	else
+		snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
+			 slot->number);
 }
 
 static int init_slots(struct controller *ctrl)
@@ -251,7 +258,7 @@
 			goto error_info;
 		}
 		/* create additional sysfs entries */
-		if (EMI(ctrl->ctrlcap)) {
+		if (EMI(ctrl)) {
 			retval = sysfs_create_file(&hotplug_slot->kobj,
 				&hotplug_slot_attr_lock.attr);
 			if (retval) {
@@ -284,7 +291,7 @@
 	list_for_each_safe(tmp, next, &ctrl->slot_list) {
 		slot = list_entry(tmp, struct slot, slot_list);
 		list_del(&slot->slot_list);
-		if (EMI(ctrl->ctrlcap))
+		if (EMI(ctrl))
 			sysfs_remove_file(&slot->hotplug_slot->kobj,
 				&hotplug_slot_attr_lock.attr);
 		cancel_delayed_work(&slot->work);
@@ -305,7 +312,7 @@
 
 	hotplug_slot->info->attention_status = status;
 
-	if (ATTN_LED(slot->ctrl->ctrlcap))
+	if (ATTN_LED(slot->ctrl))
 		slot->hpc_ops->set_attention_status(slot, status);
 
 	return 0;
@@ -472,7 +479,7 @@
 		if (rc)	/* -ENODEV: shouldn't happen, but deal with it */
 			value = 0;
 	}
-	if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
+	if ((POWER_CTRL(ctrl)) && !value) {
 		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
 		if (rc)
 			goto err_out_free_ctrl_slot;
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 0c481f7..0a7aa62 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -178,7 +178,7 @@
 static void set_slot_off(struct controller *ctrl, struct slot * pslot)
 {
 	/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
-	if (POWER_CTRL(ctrl->ctrlcap)) {
+	if (POWER_CTRL(ctrl)) {
 		if (pslot->hpc_ops->power_off_slot(pslot)) {
 			err("%s: Issue of Slot Power Off command failed\n",
 			    __func__);
@@ -186,10 +186,10 @@
 		}
 	}
 
-	if (PWR_LED(ctrl->ctrlcap))
+	if (PWR_LED(ctrl))
 		pslot->hpc_ops->green_led_off(pslot);
 
-	if (ATTN_LED(ctrl->ctrlcap)) {
+	if (ATTN_LED(ctrl)) {
 		if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
 			err("%s: Issue of Set Attention Led command failed\n",
 			    __func__);
@@ -214,14 +214,14 @@
 			__func__, p_slot->device,
 			ctrl->slot_device_offset, p_slot->hp_slot);
 
-	if (POWER_CTRL(ctrl->ctrlcap)) {
+	if (POWER_CTRL(ctrl)) {
 		/* Power on slot */
 		retval = p_slot->hpc_ops->power_on_slot(p_slot);
 		if (retval)
 			return retval;
 	}
 
-	if (PWR_LED(ctrl->ctrlcap))
+	if (PWR_LED(ctrl))
 		p_slot->hpc_ops->green_led_blink(p_slot);
 
 	/* Wait for ~1 second */
@@ -254,7 +254,7 @@
 	 */
 	if (pcie_mch_quirk)
 		pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
-	if (PWR_LED(ctrl->ctrlcap))
+	if (PWR_LED(ctrl))
   		p_slot->hpc_ops->green_led_on(p_slot);
 
 	return 0;
@@ -279,7 +279,7 @@
 
 	dbg("In %s, hp_slot = %d\n", __func__, p_slot->hp_slot);
 
-	if (POWER_CTRL(ctrl->ctrlcap)) {
+	if (POWER_CTRL(ctrl)) {
 		/* power off slot */
 		retval = p_slot->hpc_ops->power_off_slot(p_slot);
 		if (retval) {
@@ -289,7 +289,7 @@
 		}
 	}
 
-	if (PWR_LED(ctrl->ctrlcap))
+	if (PWR_LED(ctrl))
 		/* turn off Green LED */
 		p_slot->hpc_ops->green_led_off(p_slot);
 
@@ -327,7 +327,7 @@
 	case POWERON_STATE:
 		mutex_unlock(&p_slot->lock);
 		if (pciehp_enable_slot(p_slot) &&
-		    PWR_LED(p_slot->ctrl->ctrlcap))
+		    PWR_LED(p_slot->ctrl))
 			p_slot->hpc_ops->green_led_off(p_slot);
 		mutex_lock(&p_slot->lock);
 		p_slot->state = STATIC_STATE;
@@ -409,9 +409,9 @@
 			     "press.\n", p_slot->name);
 		}
 		/* blink green LED and turn off amber */
-		if (PWR_LED(ctrl->ctrlcap))
+		if (PWR_LED(ctrl))
 			p_slot->hpc_ops->green_led_blink(p_slot);
-		if (ATTN_LED(ctrl->ctrlcap))
+		if (ATTN_LED(ctrl))
 			p_slot->hpc_ops->set_attention_status(p_slot, 0);
 
 		schedule_delayed_work(&p_slot->work, 5*HZ);
@@ -427,13 +427,13 @@
 		dbg("%s: button cancel\n", __func__);
 		cancel_delayed_work(&p_slot->work);
 		if (p_slot->state == BLINKINGOFF_STATE) {
-			if (PWR_LED(ctrl->ctrlcap))
+			if (PWR_LED(ctrl))
 				p_slot->hpc_ops->green_led_on(p_slot);
 		} else {
-			if (PWR_LED(ctrl->ctrlcap))
+			if (PWR_LED(ctrl))
 				p_slot->hpc_ops->green_led_off(p_slot);
 		}
-		if (ATTN_LED(ctrl->ctrlcap))
+		if (ATTN_LED(ctrl))
 			p_slot->hpc_ops->set_attention_status(p_slot, 0);
 		info("PCI slot #%s - action canceled due to button press\n",
 		     p_slot->name);
@@ -492,16 +492,16 @@
 		handle_button_press_event(p_slot);
 		break;
 	case INT_POWER_FAULT:
-		if (!POWER_CTRL(ctrl->ctrlcap))
+		if (!POWER_CTRL(ctrl))
 			break;
-		if (ATTN_LED(ctrl->ctrlcap))
+		if (ATTN_LED(ctrl))
 			p_slot->hpc_ops->set_attention_status(p_slot, 1);
-		if (PWR_LED(ctrl->ctrlcap))
+		if (PWR_LED(ctrl))
 			p_slot->hpc_ops->green_led_off(p_slot);
 		break;
 	case INT_PRESENCE_ON:
 	case INT_PRESENCE_OFF:
-		if (!HP_SUPR_RM(ctrl->ctrlcap))
+		if (!HP_SUPR_RM(ctrl))
 			break;
 		dbg("Surprise Removal\n");
 		update_slot_info(p_slot);
@@ -531,7 +531,7 @@
 		mutex_unlock(&p_slot->ctrl->crit_sect);
 		return -ENODEV;
 	}
-	if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
+	if (MRL_SENS(p_slot->ctrl)) {
 		rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 		if (rc || getstatus) {
 			info("%s: latch open on slot(%s)\n", __func__,
@@ -541,7 +541,7 @@
 		}
 	}
 
-	if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
+	if (POWER_CTRL(p_slot->ctrl)) {
 		rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 		if (rc || getstatus) {
 			info("%s: already enabled on slot(%s)\n", __func__,
@@ -576,7 +576,7 @@
 	/* Check to see if (latch closed, card present, power on) */
 	mutex_lock(&p_slot->ctrl->crit_sect);
 
-	if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {
+	if (!HP_SUPR_RM(p_slot->ctrl)) {
 		ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 		if (ret || !getstatus) {
 			info("%s: no adapter on slot(%s)\n", __func__,
@@ -586,7 +586,7 @@
 		}
 	}
 
-	if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
+	if (MRL_SENS(p_slot->ctrl)) {
 		ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 		if (ret || getstatus) {
 			info("%s: latch open on slot(%s)\n", __func__,
@@ -596,7 +596,7 @@
 		}
 	}
 
-	if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
+	if (POWER_CTRL(p_slot->ctrl)) {
 		ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 		if (ret || !getstatus) {
 			info("%s: already disabled slot(%s)\n", __func__,
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index b4bbd07..891f81a 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -221,6 +221,32 @@
 	add_timer(&ctrl->poll_timer);
 }
 
+static inline int pciehp_request_irq(struct controller *ctrl)
+{
+	int retval, irq = ctrl->pci_dev->irq;
+
+	/* Install interrupt polling timer. Start with 10 sec delay */
+	if (pciehp_poll_mode) {
+		init_timer(&ctrl->poll_timer);
+		start_int_poll_timer(ctrl, 10);
+		return 0;
+	}
+
+	/* Installs the interrupt handler */
+	retval = request_irq(irq, pcie_isr, IRQF_SHARED, MY_NAME, ctrl);
+	if (retval)
+		err("Cannot get irq %d for the hotplug controller\n", irq);
+	return retval;
+}
+
+static inline void pciehp_free_irq(struct controller *ctrl)
+{
+	if (pciehp_poll_mode)
+		del_timer_sync(&ctrl->poll_timer);
+	else
+		free_irq(ctrl->pci_dev->irq, ctrl);
+}
+
 static inline int pcie_wait_cmd(struct controller *ctrl)
 {
 	int retval = 0;
@@ -242,17 +268,15 @@
 
 /**
  * pcie_write_cmd - Issue controller command
- * @slot: slot to which the command is issued
+ * @ctrl: controller to which the command is issued
  * @cmd:  command value written to slot control register
  * @mask: bitmask of slot control register to be modified
  */
-static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
+static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
 {
-	struct controller *ctrl = slot->ctrl;
 	int retval = 0;
 	u16 slot_status;
 	u16 slot_ctrl;
-	unsigned long flags;
 
 	mutex_lock(&ctrl->ctrl_lock);
 
@@ -270,24 +294,24 @@
 		    __func__);
 	}
 
-	spin_lock_irqsave(&ctrl->lock, flags);
 	retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
 	if (retval) {
 		err("%s: Cannot read SLOTCTRL register\n", __func__);
-		goto out_spin_unlock;
+		goto out;
 	}
 
 	slot_ctrl &= ~mask;
-	slot_ctrl |= ((cmd & mask) | CMD_CMPL_INTR_ENABLE);
+	slot_ctrl |= (cmd & mask);
+	/* Don't enable command completed if caller is changing it. */
+	if (!(mask & CMD_CMPL_INTR_ENABLE))
+		slot_ctrl |= CMD_CMPL_INTR_ENABLE;
 
 	ctrl->cmd_busy = 1;
+	smp_mb();
 	retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
 	if (retval)
 		err("%s: Cannot write to SLOTCTRL register\n", __func__);
 
- out_spin_unlock:
-	spin_unlock_irqrestore(&ctrl->lock, flags);
-
 	/*
 	 * Wait for command completion.
 	 */
@@ -467,12 +491,7 @@
 
 	slot_cmd = EMI_CTRL;
 	cmd_mask = EMI_CTRL;
-	if (!pciehp_poll_mode) {
-		slot_cmd = slot_cmd | HP_INTR_ENABLE;
-		cmd_mask = cmd_mask | HP_INTR_ENABLE;
-	}
-
-	rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+	rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask);
 	slot->last_emi_toggle = get_seconds();
 
 	return rc;
@@ -499,12 +518,7 @@
 		default:
 			return -1;
 	}
-	if (!pciehp_poll_mode) {
-		slot_cmd = slot_cmd | HP_INTR_ENABLE;
-		cmd_mask = cmd_mask | HP_INTR_ENABLE;
-	}
-
-	rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+	rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
 	dbg("%s: SLOTCTRL %x write cmd %x\n",
 	    __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 
@@ -519,13 +533,7 @@
 
 	slot_cmd = 0x0100;
 	cmd_mask = PWR_LED_CTRL;
-	if (!pciehp_poll_mode) {
-		slot_cmd = slot_cmd | HP_INTR_ENABLE;
-		cmd_mask = cmd_mask | HP_INTR_ENABLE;
-	}
-
-	pcie_write_cmd(slot, slot_cmd, cmd_mask);
-
+	pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
 	dbg("%s: SLOTCTRL %x write cmd %x\n",
 	    __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 }
@@ -538,12 +546,7 @@
 
 	slot_cmd = 0x0300;
 	cmd_mask = PWR_LED_CTRL;
-	if (!pciehp_poll_mode) {
-		slot_cmd = slot_cmd | HP_INTR_ENABLE;
-		cmd_mask = cmd_mask | HP_INTR_ENABLE;
-	}
-
-	pcie_write_cmd(slot, slot_cmd, cmd_mask);
+	pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
 	dbg("%s: SLOTCTRL %x write cmd %x\n",
 	    __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 }
@@ -556,23 +559,19 @@
 
 	slot_cmd = 0x0200;
 	cmd_mask = PWR_LED_CTRL;
-	if (!pciehp_poll_mode) {
-		slot_cmd = slot_cmd | HP_INTR_ENABLE;
-		cmd_mask = cmd_mask | HP_INTR_ENABLE;
-	}
-
-	pcie_write_cmd(slot, slot_cmd, cmd_mask);
-
+	pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
 	dbg("%s: SLOTCTRL %x write cmd %x\n",
 	    __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 }
 
 static void hpc_release_ctlr(struct controller *ctrl)
 {
-	if (pciehp_poll_mode)
-		del_timer(&ctrl->poll_timer);
-	else
-		free_irq(ctrl->pci_dev->irq, ctrl);
+	/* Mask Hot-plug Interrupt Enable */
+	if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE))
+		err("%s: Cannot mask hotplut interrupt enable\n", __func__);
+
+	/* Free interrupt handler or interrupt polling timer */
+	pciehp_free_irq(ctrl);
 
 	/*
 	 * If this is the last controller to be released, destroy the
@@ -612,19 +611,13 @@
 	cmd_mask = PWR_CTRL;
 	/* Enable detection that we turned off at slot power-off time */
 	if (!pciehp_poll_mode) {
-		slot_cmd = slot_cmd |
-		           PWR_FAULT_DETECT_ENABLE |
-		           MRL_DETECT_ENABLE |
-		           PRSN_DETECT_ENABLE |
-		           HP_INTR_ENABLE;
-		cmd_mask = cmd_mask |
-		           PWR_FAULT_DETECT_ENABLE |
-		           MRL_DETECT_ENABLE |
-		           PRSN_DETECT_ENABLE |
-		           HP_INTR_ENABLE;
+		slot_cmd |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
+			     PRSN_DETECT_ENABLE);
+		cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
+			     PRSN_DETECT_ENABLE);
 	}
 
-	retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+	retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
 
 	if (retval) {
 		err("%s: Write %x command failed!\n", __func__, slot_cmd);
@@ -697,18 +690,13 @@
 	 * till the slot is powered on again.
 	 */
 	if (!pciehp_poll_mode) {
-		slot_cmd = (slot_cmd &
-		            ~PWR_FAULT_DETECT_ENABLE &
-		            ~MRL_DETECT_ENABLE &
-		            ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE;
-		cmd_mask = cmd_mask |
-			   PWR_FAULT_DETECT_ENABLE |
-			   MRL_DETECT_ENABLE |
-			   PRSN_DETECT_ENABLE |
-			   HP_INTR_ENABLE;
+		slot_cmd &= ~(PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
+			      PRSN_DETECT_ENABLE);
+		cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
+			     PRSN_DETECT_ENABLE);
 	}
 
-	retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+	retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
 	if (retval) {
 		err("%s: Write command failed!\n", __func__);
 		retval = -1;
@@ -733,139 +721,56 @@
 static irqreturn_t pcie_isr(int irq, void *dev_id)
 {
 	struct controller *ctrl = (struct controller *)dev_id;
-	u16 slot_status, intr_detect, intr_loc;
-	u16 temp_word;
-	int hp_slot = 0;	/* only 1 slot per PCI Express port */
-	int rc = 0;
-	unsigned long flags;
+	u16 detected, intr_loc;
 
-	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-	if (rc) {
-		err("%s: Cannot read SLOTSTATUS register\n", __func__);
-		return IRQ_NONE;
-	}
-
-	intr_detect = (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED |
-		       MRL_SENS_CHANGED | PRSN_DETECT_CHANGED | CMD_COMPLETED);
-
-	intr_loc = slot_status & intr_detect;
-
-	/* Check to see if it was our interrupt */
-	if ( !intr_loc )
-		return IRQ_NONE;
-
-	dbg("%s: intr_loc %x\n", __func__, intr_loc);
-	/* Mask Hot-plug Interrupt Enable */
-	if (!pciehp_poll_mode) {
-		spin_lock_irqsave(&ctrl->lock, flags);
-		rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-		if (rc) {
-			err("%s: Cannot read SLOT_CTRL register\n",
-			    __func__);
-			spin_unlock_irqrestore(&ctrl->lock, flags);
+	/*
+	 * In order to guarantee that all interrupt events are
+	 * serviced, we need to re-inspect Slot Status register after
+	 * clearing what is presumed to be the last pending interrupt.
+	 */
+	intr_loc = 0;
+	do {
+		if (pciehp_readw(ctrl, SLOTSTATUS, &detected)) {
+			err("%s: Cannot read SLOTSTATUS\n", __func__);
 			return IRQ_NONE;
 		}
 
-		dbg("%s: pciehp_readw(SLOTCTRL) with value %x\n",
-		    __func__, temp_word);
-		temp_word = (temp_word & ~HP_INTR_ENABLE &
-			     ~CMD_CMPL_INTR_ENABLE) | 0x00;
-		rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-		if (rc) {
-			err("%s: Cannot write to SLOTCTRL register\n",
-			    __func__);
-			spin_unlock_irqrestore(&ctrl->lock, flags);
+		detected &= (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED |
+			     MRL_SENS_CHANGED | PRSN_DETECT_CHANGED |
+			     CMD_COMPLETED);
+		intr_loc |= detected;
+		if (!intr_loc)
+			return IRQ_NONE;
+		if (pciehp_writew(ctrl, SLOTSTATUS, detected)) {
+			err("%s: Cannot write to SLOTSTATUS\n", __func__);
 			return IRQ_NONE;
 		}
-		spin_unlock_irqrestore(&ctrl->lock, flags);
+	} while (detected);
 
-		rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-		if (rc) {
-			err("%s: Cannot read SLOT_STATUS register\n",
-			    __func__);
-			return IRQ_NONE;
-		}
-		dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n",
-		    __func__, slot_status);
+	dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
 
-		/* Clear command complete interrupt caused by this write */
-		temp_word = 0x1f;
-		rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-		if (rc) {
-			err("%s: Cannot write to SLOTSTATUS register\n",
-			    __func__);
-			return IRQ_NONE;
-		}
-	}
-
+	/* Check Command Complete Interrupt Pending */
 	if (intr_loc & CMD_COMPLETED) {
-		/*
-		 * Command Complete Interrupt Pending
-		 */
 		ctrl->cmd_busy = 0;
+		smp_mb();
 		wake_up_interruptible(&ctrl->queue);
 	}
 
+	/* Check MRL Sensor Changed */
 	if (intr_loc & MRL_SENS_CHANGED)
-		pciehp_handle_switch_change(hp_slot, ctrl);
+		pciehp_handle_switch_change(0, ctrl);
 
+	/* Check Attention Button Pressed */
 	if (intr_loc & ATTN_BUTTN_PRESSED)
-		pciehp_handle_attention_button(hp_slot, ctrl);
+		pciehp_handle_attention_button(0, ctrl);
 
+	/* Check Presence Detect Changed */
 	if (intr_loc & PRSN_DETECT_CHANGED)
-		pciehp_handle_presence_change(hp_slot, ctrl);
+		pciehp_handle_presence_change(0, ctrl);
 
+	/* Check Power Fault Detected */
 	if (intr_loc & PWR_FAULT_DETECTED)
-		pciehp_handle_power_fault(hp_slot, ctrl);
-
-	/* Clear all events after serving them */
-	temp_word = 0x1F;
-	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-	if (rc) {
-		err("%s: Cannot write to SLOTSTATUS register\n", __func__);
-		return IRQ_NONE;
-	}
-	/* Unmask Hot-plug Interrupt Enable */
-	if (!pciehp_poll_mode) {
-		spin_lock_irqsave(&ctrl->lock, flags);
-		rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-		if (rc) {
-			err("%s: Cannot read SLOTCTRL register\n",
-			    __func__);
-			spin_unlock_irqrestore(&ctrl->lock, flags);
-			return IRQ_NONE;
-		}
-
-		dbg("%s: Unmask Hot-plug Interrupt Enable\n", __func__);
-		temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
-
-		rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-		if (rc) {
-			err("%s: Cannot write to SLOTCTRL register\n",
-			    __func__);
-			spin_unlock_irqrestore(&ctrl->lock, flags);
-			return IRQ_NONE;
-		}
-		spin_unlock_irqrestore(&ctrl->lock, flags);
-
-		rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-		if (rc) {
-			err("%s: Cannot read SLOT_STATUS register\n",
-			    __func__);
-			return IRQ_NONE;
-		}
-
-		/* Clear command complete interrupt caused by this write */
-		temp_word = 0x1F;
-		rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-		if (rc) {
-			err("%s: Cannot write to SLOTSTATUS failed\n",
-			    __func__);
-			return IRQ_NONE;
-		}
-		dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n",
-		    __func__, temp_word);
-	}
+		pciehp_handle_power_fault(0, ctrl);
 
 	return IRQ_HANDLED;
 }
@@ -1052,7 +957,7 @@
 };
 
 #ifdef CONFIG_ACPI
-int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
+static int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
 {
 	acpi_status status;
 	acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
@@ -1112,7 +1017,7 @@
 			break;
 	}
 
-	err("Cannot get control of hotplug hardware for pci %s\n",
+	dbg("Cannot get control of hotplug hardware for pci %s\n",
 			pci_name(dev));
 
 	kfree(string.pointer);
@@ -1123,45 +1028,9 @@
 static int pcie_init_hardware_part1(struct controller *ctrl,
 				    struct pcie_device *dev)
 {
-	int rc;
-	u16 temp_word;
-	u32 slot_cap;
-	u16 slot_status;
-
-	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
-	if (rc) {
-		err("%s: Cannot read SLOTCAP register\n", __func__);
-		return -1;
-	}
-
 	/* Mask Hot-plug Interrupt Enable */
-	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-	if (rc) {
-		err("%s: Cannot read SLOTCTRL register\n", __func__);
-		return -1;
-	}
-
-	dbg("%s: SLOTCTRL %x value read %x\n",
-	    __func__, ctrl->cap_base + SLOTCTRL, temp_word);
-	temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
-		0x00;
-
-	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-	if (rc) {
-		err("%s: Cannot write to SLOTCTRL register\n", __func__);
-		return -1;
-	}
-
-	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-	if (rc) {
-		err("%s: Cannot read SLOTSTATUS register\n", __func__);
-		return -1;
-	}
-
-	temp_word = 0x1F; /* Clear all events */
-	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-	if (rc) {
-		err("%s: Cannot write to SLOTSTATUS register\n", __func__);
+	if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) {
+		err("%s: Cannot mask hotplug interrupt enable\n", __func__);
 		return -1;
 	}
 	return 0;
@@ -1169,205 +1038,125 @@
 
 int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
 {
-	int rc;
-	u16 temp_word;
-	u16 intr_enable = 0;
-	u32 slot_cap;
-	u16 slot_status;
-
-	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-	if (rc) {
-		err("%s: Cannot read SLOTCTRL register\n", __func__);
-		goto abort;
-	}
-
-	intr_enable = intr_enable | PRSN_DETECT_ENABLE;
-
-	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
-	if (rc) {
-		err("%s: Cannot read SLOTCAP register\n", __func__);
-		goto abort;
-	}
-
-	if (ATTN_BUTTN(slot_cap))
-		intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
-
-	if (POWER_CTRL(slot_cap))
-		intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
-
-	if (MRL_SENS(slot_cap))
-		intr_enable = intr_enable | MRL_DETECT_ENABLE;
-
-	temp_word = (temp_word & ~intr_enable) | intr_enable;
-
-	if (pciehp_poll_mode) {
-		temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
-	} else {
-		temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
-	}
+	u16 cmd, mask;
 
 	/*
-	 * Unmask Hot-plug Interrupt Enable for the interrupt
-	 * notification mechanism case.
+	 * We need to clear all events before enabling hotplug interrupt
+	 * notification mechanism in order for hotplug controler to
+	 * generate interrupts.
 	 */
-	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-	if (rc) {
-		err("%s: Cannot write to SLOTCTRL register\n", __func__);
+	if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) {
+		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
+		return -1;
+	}
+
+	cmd = PRSN_DETECT_ENABLE;
+	if (ATTN_BUTTN(ctrl))
+		cmd |= ATTN_BUTTN_ENABLE;
+	if (POWER_CTRL(ctrl))
+		cmd |= PWR_FAULT_DETECT_ENABLE;
+	if (MRL_SENS(ctrl))
+		cmd |= MRL_DETECT_ENABLE;
+	if (!pciehp_poll_mode)
+		cmd |= HP_INTR_ENABLE;
+
+	mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE |
+		PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | HP_INTR_ENABLE;
+
+	if (pcie_write_cmd(ctrl, cmd, mask)) {
+		err("%s: Cannot enable software notification\n", __func__);
 		goto abort;
 	}
-	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-	if (rc) {
-		err("%s: Cannot read SLOTSTATUS register\n", __func__);
-		goto abort_disable_intr;
-	}
 
-	temp_word =  0x1F; /* Clear all events */
-	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-	if (rc) {
-		err("%s: Cannot write to SLOTSTATUS register\n", __func__);
-		goto abort_disable_intr;
-	}
-
-	if (pciehp_force) {
+	if (pciehp_force)
 		dbg("Bypassing BIOS check for pciehp use on %s\n",
 				pci_name(ctrl->pci_dev));
-	} else {
-		rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
-		if (rc)
-			goto abort_disable_intr;
-	}
+	else if (pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev))
+		goto abort_disable_intr;
 
 	return 0;
 
 	/* We end up here for the many possible ways to fail this API. */
 abort_disable_intr:
-	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-	if (!rc) {
-		temp_word &= ~(intr_enable | HP_INTR_ENABLE);
-		rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-	}
-	if (rc)
+	if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE))
 		err("%s : disabling interrupts failed\n", __func__);
 abort:
 	return -1;
 }
 
+static inline void dbg_ctrl(struct controller *ctrl)
+{
+	int i;
+	u16 reg16;
+	struct pci_dev *pdev = ctrl->pci_dev;
+
+	if (!pciehp_debug)
+		return;
+
+	dbg("Hotplug Controller:\n");
+	dbg("  Seg/Bus/Dev/Func/IRQ : %s IRQ %d\n", pci_name(pdev), pdev->irq);
+	dbg("  Vendor ID            : 0x%04x\n", pdev->vendor);
+	dbg("  Device ID            : 0x%04x\n", pdev->device);
+	dbg("  Subsystem ID         : 0x%04x\n", pdev->subsystem_device);
+	dbg("  Subsystem Vendor ID  : 0x%04x\n", pdev->subsystem_vendor);
+	dbg("  PCIe Cap offset      : 0x%02x\n", ctrl->cap_base);
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		if (!pci_resource_len(pdev, i))
+			continue;
+		dbg("  PCI resource [%d]     : 0x%llx@0x%llx\n", i,
+		    (unsigned long long)pci_resource_len(pdev, i),
+		    (unsigned long long)pci_resource_start(pdev, i));
+	}
+	dbg("Slot Capabilities      : 0x%08x\n", ctrl->slot_cap);
+	dbg("  Physical Slot Number : %d\n", ctrl->first_slot);
+	dbg("  Attention Button     : %3s\n", ATTN_BUTTN(ctrl) ? "yes" : "no");
+	dbg("  Power Controller     : %3s\n", POWER_CTRL(ctrl) ? "yes" : "no");
+	dbg("  MRL Sensor           : %3s\n", MRL_SENS(ctrl)   ? "yes" : "no");
+	dbg("  Attention Indicator  : %3s\n", ATTN_LED(ctrl)   ? "yes" : "no");
+	dbg("  Power Indicator      : %3s\n", PWR_LED(ctrl)    ? "yes" : "no");
+	dbg("  Hot-Plug Surprise    : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no");
+	dbg("  EMI Present          : %3s\n", EMI(ctrl)        ? "yes" : "no");
+	pciehp_readw(ctrl, SLOTSTATUS, &reg16);
+	dbg("Slot Status            : 0x%04x\n", reg16);
+	pciehp_readw(ctrl, SLOTSTATUS, &reg16);
+	dbg("Slot Control           : 0x%04x\n", reg16);
+}
+
 int pcie_init(struct controller *ctrl, struct pcie_device *dev)
 {
-	int rc;
-	u16 cap_reg;
 	u32 slot_cap;
-	int cap_base;
-	u16 slot_status, slot_ctrl;
-	struct pci_dev *pdev;
+	struct pci_dev *pdev = dev->port;
 
-	pdev = dev->port;
-	ctrl->pci_dev = pdev;	/* save pci_dev in context */
-
-	dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
-			__func__, pdev->vendor, pdev->device);
-
-	cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-	if (cap_base == 0) {
-		dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __func__);
+	ctrl->pci_dev = pdev;
+	ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	if (!ctrl->cap_base) {
+		err("%s: Cannot find PCI Express capability\n", __func__);
 		goto abort;
 	}
-
-	ctrl->cap_base = cap_base;
-
-	dbg("%s: pcie_cap_base %x\n", __func__, cap_base);
-
-	rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
-	if (rc) {
-		err("%s: Cannot read CAPREG register\n", __func__);
-		goto abort;
-	}
-	dbg("%s: CAPREG offset %x cap_reg %x\n",
-	    __func__, ctrl->cap_base + CAPREG, cap_reg);
-
-	if (((cap_reg & SLOT_IMPL) == 0) ||
-	    (((cap_reg & DEV_PORT_TYPE) != 0x0040)
-		&& ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
-		dbg("%s : This is not a root port or the port is not "
-		    "connected to a slot\n", __func__);
-		goto abort;
-	}
-
-	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
-	if (rc) {
+	if (pciehp_readl(ctrl, SLOTCAP, &slot_cap)) {
 		err("%s: Cannot read SLOTCAP register\n", __func__);
 		goto abort;
 	}
-	dbg("%s: SLOTCAP offset %x slot_cap %x\n",
-	    __func__, ctrl->cap_base + SLOTCAP, slot_cap);
 
-	if (!(slot_cap & HP_CAP)) {
-		dbg("%s : This slot is not hot-plug capable\n", __func__);
-		goto abort;
-	}
-	/* For debugging purpose */
-	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-	if (rc) {
-		err("%s: Cannot read SLOTSTATUS register\n", __func__);
-		goto abort;
-	}
-	dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
-	    __func__, ctrl->cap_base + SLOTSTATUS, slot_status);
-
-	rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-	if (rc) {
-		err("%s: Cannot read SLOTCTRL register\n", __func__);
-		goto abort;
-	}
-	dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
-	    __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
-
-	for (rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
-		if (pci_resource_len(pdev, rc) > 0)
-			dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc,
-			    (unsigned long long)pci_resource_start(pdev, rc),
-			    (unsigned long long)pci_resource_len(pdev, rc));
+	ctrl->slot_cap = slot_cap;
+	ctrl->first_slot = slot_cap >> 19;
+	ctrl->slot_device_offset = 0;
+	ctrl->num_slots = 1;
+	ctrl->hpc_ops = &pciehp_hpc_ops;
+	mutex_init(&ctrl->crit_sect);
+	mutex_init(&ctrl->ctrl_lock);
+	init_waitqueue_head(&ctrl->queue);
+	dbg_ctrl(ctrl);
 
 	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);
 
-	mutex_init(&ctrl->crit_sect);
-	mutex_init(&ctrl->ctrl_lock);
-	spin_lock_init(&ctrl->lock);
-
-	/* setup wait queue */
-	init_waitqueue_head(&ctrl->queue);
-
-	/* return PCI Controller Info */
-	ctrl->slot_device_offset = 0;
-	ctrl->num_slots = 1;
-	ctrl->first_slot = slot_cap >> 19;
-	ctrl->ctrlcap = slot_cap & 0x0000007f;
-
-	rc = pcie_init_hardware_part1(ctrl, dev);
-	if (rc)
+	if (pcie_init_hardware_part1(ctrl, dev))
 		goto abort;
 
-	if (pciehp_poll_mode) {
-		/* Install interrupt polling timer. Start with 10 sec delay */
-		init_timer(&ctrl->poll_timer);
-		start_int_poll_timer(ctrl, 10);
-	} else {
-		/* Installs the interrupt handler */
-		rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED,
-				 MY_NAME, (void *)ctrl);
-		dbg("%s: request_irq %d for hpc%d (returns %d)\n",
-		    __func__, ctrl->pci_dev->irq,
-		    atomic_read(&pciehp_num_controllers), rc);
-		if (rc) {
-			err("Can't get irq %d for the hotplug controller\n",
-			    ctrl->pci_dev->irq);
-			goto abort;
-		}
-	}
-	dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
-		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
+	if (pciehp_request_irq(ctrl))
+		goto abort;
 
 	/*
 	 * If this is the first controller to be initialized,
@@ -1376,21 +1165,17 @@
 	if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
 		pciehp_wq = create_singlethread_workqueue("pciehpd");
 		if (!pciehp_wq) {
-			rc = -ENOMEM;
 			goto abort_free_irq;
 		}
 	}
 
-	rc = pcie_init_hardware_part2(ctrl, dev);
-	if (rc == 0) {
-		ctrl->hpc_ops = &pciehp_hpc_ops;
-		return 0;
-	}
+	if (pcie_init_hardware_part2(ctrl, dev))
+		goto abort_free_irq;
+
+	return 0;
+
 abort_free_irq:
-	if (pciehp_poll_mode)
-		del_timer_sync(&ctrl->poll_timer);
-	else
-		free_irq(ctrl->pci_dev->irq, ctrl);
+	pciehp_free_irq(ctrl);
 abort:
 	return -1;
 }
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 43816d4..1648076 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -39,6 +39,7 @@
 int shpchp_debug;
 int shpchp_poll_mode;
 int shpchp_poll_time;
+int shpchp_slot_with_bus;
 struct workqueue_struct *shpchp_wq;
 
 #define DRIVER_VERSION	"0.4"
@@ -52,9 +53,11 @@
 module_param(shpchp_debug, bool, 0644);
 module_param(shpchp_poll_mode, bool, 0644);
 module_param(shpchp_poll_time, int, 0644);
+module_param(shpchp_slot_with_bus, bool, 0644);
 MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not");
 MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not");
 MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");
+MODULE_PARM_DESC(shpchp_slot_with_bus, "Use bus number in the slot name");
 
 #define SHPC_MODULE_NAME "shpchp"
 
@@ -100,8 +103,12 @@
 
 static void make_slot_name(struct slot *slot)
 {
-	snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
-		 slot->bus, slot->number);
+	if (shpchp_slot_with_bus)
+		snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
+			 slot->bus, slot->number);
+	else
+		snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
+			 slot->number);
 }
 
 static int init_slots(struct controller *ctrl)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 26938da..8c61304 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -123,7 +123,7 @@
 	}
 }
 
-static void msi_set_mask_bit(unsigned int irq, int flag)
+static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
 {
 	struct msi_desc *entry;
 
@@ -137,8 +137,8 @@
 
 			pos = (long)entry->mask_base;
 			pci_read_config_dword(entry->dev, pos, &mask_bits);
-			mask_bits &= ~(1);
-			mask_bits |= flag;
+			mask_bits &= ~(mask);
+			mask_bits |= flag & mask;
 			pci_write_config_dword(entry->dev, pos, mask_bits);
 		} else {
 			msi_set_enable(entry->dev, !flag);
@@ -241,13 +241,13 @@
 
 void mask_msi_irq(unsigned int irq)
 {
-	msi_set_mask_bit(irq, 1);
+	msi_set_mask_bits(irq, 1, 1);
 	msix_flush_writes(irq);
 }
 
 void unmask_msi_irq(unsigned int irq)
 {
-	msi_set_mask_bit(irq, 0);
+	msi_set_mask_bits(irq, 1, 0);
 	msix_flush_writes(irq);
 }
 
@@ -291,7 +291,8 @@
 	msi_set_enable(dev, 0);
 	write_msi_msg(dev->irq, &entry->msg);
 	if (entry->msi_attrib.maskbit)
-		msi_set_mask_bit(dev->irq, entry->msi_attrib.masked);
+		msi_set_mask_bits(dev->irq, entry->msi_attrib.maskbits_mask,
+				  entry->msi_attrib.masked);
 
 	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
 	control &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
@@ -315,7 +316,7 @@
 
 	list_for_each_entry(entry, &dev->msi_list, list) {
 		write_msi_msg(entry->irq, &entry->msg);
-		msi_set_mask_bit(entry->irq, entry->msi_attrib.masked);
+		msi_set_mask_bits(entry->irq, 1, entry->msi_attrib.masked);
 	}
 
 	BUG_ON(list_empty(&dev->msi_list));
@@ -382,6 +383,7 @@
 		pci_write_config_dword(dev,
 			msi_mask_bits_reg(pos, is_64bit_address(control)),
 			maskbits);
+		entry->msi_attrib.maskbits_mask = temp;
 	}
 	list_add_tail(&entry->list, &dev->msi_list);
 
@@ -569,10 +571,9 @@
 }
 EXPORT_SYMBOL(pci_enable_msi);
 
-void pci_disable_msi(struct pci_dev* dev)
+void pci_msi_shutdown(struct pci_dev* dev)
 {
 	struct msi_desc *entry;
-	int default_irq;
 
 	if (!pci_msi_enable || !dev || !dev->msi_enabled)
 		return;
@@ -583,15 +584,31 @@
 
 	BUG_ON(list_empty(&dev->msi_list));
 	entry = list_entry(dev->msi_list.next, struct msi_desc, list);
-	if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
-		return;
+	/* Return the the pci reset with msi irqs unmasked */
+	if (entry->msi_attrib.maskbit) {
+		u32 mask = entry->msi_attrib.maskbits_mask;
+		msi_set_mask_bits(dev->irq, mask, ~mask);
 	}
-
-	default_irq = entry->msi_attrib.default_irq;
-	msi_free_irqs(dev);
+	if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI)
+		return;
 
 	/* Restore dev->irq to its default pin-assertion irq */
-	dev->irq = default_irq;
+	dev->irq = entry->msi_attrib.default_irq;
+}
+void pci_disable_msi(struct pci_dev* dev)
+{
+	struct msi_desc *entry;
+
+	if (!pci_msi_enable || !dev || !dev->msi_enabled)
+		return;
+
+	pci_msi_shutdown(dev);
+
+	entry = list_entry(dev->msi_list.next, struct msi_desc, list);
+	if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI)
+		return;
+
+	msi_free_irqs(dev);
 }
 EXPORT_SYMBOL(pci_disable_msi);
 
@@ -684,7 +701,7 @@
 	msi_free_irqs(dev);
 }
 
-void pci_disable_msix(struct pci_dev* dev)
+void pci_msix_shutdown(struct pci_dev* dev)
 {
 	if (!pci_msi_enable || !dev || !dev->msix_enabled)
 		return;
@@ -692,6 +709,13 @@
 	msix_set_enable(dev, 0);
 	pci_intx_for_msi(dev, 1);
 	dev->msix_enabled = 0;
+}
+void pci_disable_msix(struct pci_dev* dev)
+{
+	if (!pci_msi_enable || !dev || !dev->msix_enabled)
+		return;
+
+	pci_msix_shutdown(dev);
 
 	msix_free_all_irqs(dev);
 }
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index e8d94fa..72cf61e 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -360,6 +360,8 @@
 
 	if (drv && drv->shutdown)
 		drv->shutdown(pci_dev);
+	pci_msi_shutdown(pci_dev);
+	pci_msix_shutdown(pci_dev);
 }
 
 /**
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index 25b04fb..5a0c6ad 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -33,7 +33,7 @@
 config PCIEASPM
 	bool "PCI Express ASPM support(Experimental)"
 	depends on PCI && EXPERIMENTAL && PCIEPORTBUS
-	default y
+	default n
 	help
 	  This enables PCI Express ASPM (Active State Power Management) and
 	  Clock Power Management. ASPM supports state L0/L0s/L1.
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 94bb46d..8f29392 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -22,6 +22,7 @@
 		__u8	masked	: 1;
 		__u8	is_64	: 1;	/* Address size: 0=32bit 1=64bit  */
 		__u8	pos;	 	/* Location of the msi capability */
+		__u32	maskbits_mask;  /* mask bits mask */
 		__u16	entry_nr;    	/* specific enabled entry 	  */
 		unsigned default_irq;	/* default pre-assigned irq	  */
 	}msi_attrib;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index abc998f..96acd0d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -20,8 +20,6 @@
 /* Include the pci register defines */
 #include <linux/pci_regs.h>
 
-struct pci_vpd;
-
 /*
  * The PCI interface treats multi-function devices as independent
  * devices.  The slot/function address of each device is encoded
@@ -131,6 +129,8 @@
 };
 
 struct pcie_link_state;
+struct pci_vpd;
+
 /*
  * The pci_dev structure is used to describe PCI devices.
  */
@@ -702,6 +702,8 @@
 	return -1;
 }
 
+static inline void pci_msi_shutdown(struct pci_dev *dev)
+{ }
 static inline void pci_disable_msi(struct pci_dev *dev)
 { }
 
@@ -711,6 +713,8 @@
 	return -1;
 }
 
+static inline void pci_msix_shutdown(struct pci_dev *dev)
+{ }
 static inline void pci_disable_msix(struct pci_dev *dev)
 { }
 
@@ -721,9 +725,11 @@
 { }
 #else
 extern int pci_enable_msi(struct pci_dev *dev);
+extern void pci_msi_shutdown(struct pci_dev *dev);
 extern void pci_disable_msi(struct pci_dev *dev);
 extern int pci_enable_msix(struct pci_dev *dev,
 	struct msix_entry *entries, int nvec);
+extern void pci_msix_shutdown(struct pci_dev *dev);
 extern void pci_disable_msix(struct pci_dev *dev);
 extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
 extern void pci_restore_msi_state(struct pci_dev *dev);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 70eb3c8..e5a53da 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2413,6 +2413,8 @@
 #define PCI_DEVICE_ID_INTEL_82443GX_0	0x71a0
 #define PCI_DEVICE_ID_INTEL_82443GX_2	0x71a2
 #define PCI_DEVICE_ID_INTEL_82372FB_1	0x7601
+#define PCI_DEVICE_ID_INTEL_SCH_LPC	0x8119
+#define PCI_DEVICE_ID_INTEL_SCH_IDE	0x811a
 #define PCI_DEVICE_ID_INTEL_82454GX	0x84c4
 #define PCI_DEVICE_ID_INTEL_82450GX	0x84c5
 #define PCI_DEVICE_ID_INTEL_82451NX	0x84ca