fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / pci / hotplug / pciehp_hpc.c
index 9e70c46..25d3aad 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com>
  *
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
+#include <linux/signal.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
 #include <linux/pci.h>
-#include <asm/system.h>
+#include <linux/interrupt.h>
+
 #include "../pci.h"
 #include "pciehp.h"
-
 #ifdef DEBUG
 #define DBG_K_TRACE_ENTRY      ((unsigned int)0x00000001)      /* On function entry */
 #define DBG_K_TRACE_EXIT       ((unsigned int)0x00000002)      /* On function exit */
@@ -109,20 +107,20 @@ enum ctrl_offsets {
 };
 static int pcie_cap_base = 0;          /* Base of the PCI Express capability item structure */ 
 
-#define PCIE_CAP_ID    ( pcie_cap_base + PCIECAPID )
-#define NXT_CAP_PTR    ( pcie_cap_base + NXTCAPPTR )
-#define CAP_REG                ( pcie_cap_base + CAPREG )
-#define DEV_CAP                ( pcie_cap_base + DEVCAP )
-#define DEV_CTRL       ( pcie_cap_base + DEVCTRL )
-#define DEV_STATUS     ( pcie_cap_base + DEVSTATUS )
-#define LNK_CAP                ( pcie_cap_base + LNKCAP )
-#define LNK_CTRL       ( pcie_cap_base + LNKCTRL )
-#define LNK_STATUS     ( pcie_cap_base + LNKSTATUS )
-#define SLOT_CAP       ( pcie_cap_base + SLOTCAP )
-#define SLOT_CTRL      ( pcie_cap_base + SLOTCTRL )
-#define SLOT_STATUS    ( pcie_cap_base + SLOTSTATUS )
-#define ROOT_CTRL      ( pcie_cap_base + ROOTCTRL )
-#define ROOT_STATUS    ( pcie_cap_base + ROOTSTATUS )
+#define PCIE_CAP_ID(cb)        ( cb + PCIECAPID )
+#define NXT_CAP_PTR(cb)        ( cb + NXTCAPPTR )
+#define CAP_REG(cb)    ( cb + CAPREG )
+#define DEV_CAP(cb)    ( cb + DEVCAP )
+#define DEV_CTRL(cb)   ( cb + DEVCTRL )
+#define DEV_STATUS(cb) ( cb + DEVSTATUS )
+#define LNK_CAP(cb)    ( cb + LNKCAP )
+#define LNK_CTRL(cb)   ( cb + LNKCTRL )
+#define LNK_STATUS(cb) ( cb + LNKSTATUS )
+#define SLOT_CAP(cb)   ( cb + SLOTCAP )
+#define SLOT_CTRL(cb)  ( cb + SLOTCTRL )
+#define SLOT_STATUS(cb)        ( cb + SLOTSTATUS )
+#define ROOT_CTRL(cb)  ( cb + ROOTCTRL )
+#define ROOT_STATUS(cb)        ( cb + ROOTSTATUS )
 
 #define hp_register_read_word(pdev, reg , value)               \
        pci_read_config_word(pdev, reg, &value)
@@ -217,23 +215,6 @@ static int pcie_cap_base = 0;              /* Base of the PCI Express capability item struct
 #define MRL_STATE              0x0020
 #define PRSN_STATE             0x0040
 
-struct php_ctlr_state_s {
-       struct php_ctlr_state_s *pnext;
-       struct pci_dev *pci_dev;
-       unsigned int irq;
-       unsigned long flags;                            /* spinlock's */
-       u32 slot_device_offset;
-       u32 num_slots;
-       struct timer_list       int_poll_timer;         /* Added for poll event */
-       php_intr_callback_t     attention_button_callback;
-       php_intr_callback_t     switch_change_callback;
-       php_intr_callback_t     presence_change_callback;
-       php_intr_callback_t     power_fault_callback;
-       void                    *callback_instance_id;
-       struct ctrl_reg         *creg;                          /* Ptr to controller register space */
-};
-
-
 static spinlock_t hpc_event_lock;
 
 DEFINE_DBG_BUFFER              /* Debug string buffer for entire HPC defined here */
@@ -241,7 +222,7 @@ static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */
 static int ctlr_seq_num = 0;   /* Controller sequence # */
 static spinlock_t list_lock;
 
-static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs);
+static irqreturn_t pcie_isr(int IRQ, void *dev_id);
 
 static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds);
 
@@ -258,7 +239,7 @@ static void int_poll_timeout(unsigned long lphp_ctlr)
        }
 
        /* Poll for interrupt events.  regs == NULL => polling */
-       pcie_isr( 0, (void *)php_ctlr, NULL );
+       pcie_isr( 0, (void *)php_ctlr );
 
        init_timer(&php_ctlr->int_poll_timer);
 
@@ -297,18 +278,16 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
 
        DBG_ENTER_ROUTINE 
        
-       dbg("%s : Enter\n", __FUNCTION__);
        if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
        if (retval) {
                        err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
                        return retval;
                }
-       dbg("%s : hp_register_read_word SLOT_STATUS %x\n", __FUNCTION__, slot_status);
        
        if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { 
                /* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue 
@@ -316,14 +295,11 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
                dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__);
        }
 
-       dbg("%s: Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd);
-       retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, cmd | CMD_CMPL_INTR_ENABLE);
+       retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE);
        if (retval) {
                err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
                return retval;
        }
-       dbg("%s : hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd | CMD_CMPL_INTR_ENABLE);
-       dbg("%s : Exit\n", __FUNCTION__);
 
        DBG_LEAVE_ROUTINE 
        return retval;
@@ -342,7 +318,7 @@ static int hpc_check_lnk_status(struct controller *ctrl)
                return -1;
        }
        
-       retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(ctrl->cap_base), lnk_status);
 
        if (retval) {
                err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
@@ -376,14 +352,14 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (retval) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
                return retval;
        }
 
-       dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL, slot_ctrl);
+       dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6;
 
@@ -423,13 +399,13 @@ static int hpc_get_power_status(struct slot * slot, u8 *status)
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (retval) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
                return retval;
        }
-       dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl);
+       dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        pwr_state = (slot_ctrl & PWR_CTRL) >> 10;
 
@@ -463,7 +439,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
 
        if (retval) {
                err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
@@ -490,7 +466,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
 
        if (retval) {
                err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
@@ -509,7 +485,6 @@ static int hpc_query_power_fault(struct slot * slot)
        u16 slot_status;
        u8 pwr_fault;
        int retval = 0;
-       u8 status;
 
        DBG_ENTER_ROUTINE 
 
@@ -518,18 +493,16 @@ static int hpc_query_power_fault(struct slot * slot)
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
 
        if (retval) {
-               err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+               err("%s : Cannot check for power fault\n", __FUNCTION__);
                return retval;
        }
        pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
-       status = (pwr_fault != 1) ? 1 : 0;
        
        DBG_LEAVE_ROUTINE
-       /* Note: Logic 0 => fault */
-       return status;
+       return pwr_fault;
 }
 
 static int hpc_set_attention_status(struct slot *slot, u8 value)
@@ -539,7 +512,8 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
        u16 slot_ctrl;
        int rc = 0;
 
-       dbg("%s: \n", __FUNCTION__);
+       DBG_ENTER_ROUTINE
+
        if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
@@ -549,13 +523,12 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
                err("%s: Invalid HPC slot number!\n", __FUNCTION__);
                return -1;
        }
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (rc) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
                return rc;
        }
-       dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
 
        switch (value) {
                case 0 :        /* turn off */
@@ -574,8 +547,9 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
                slot_cmd = slot_cmd | HP_INTR_ENABLE; 
 
        pcie_write_cmd(slot, slot_cmd);
-       dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, slot_cmd);
+       dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
        
+       DBG_LEAVE_ROUTINE
        return rc;
 }
 
@@ -587,7 +561,8 @@ static void hpc_set_green_led_on(struct slot *slot)
        u16 slot_ctrl;
        int rc = 0;
                
-       dbg("%s: \n", __FUNCTION__);    
+       DBG_ENTER_ROUTINE
+
        if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return ;
@@ -598,20 +573,20 @@ static void hpc_set_green_led_on(struct slot *slot)
                return ;
        }
 
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (rc) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
                return;
        }
-       dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
        slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100;
        if (!pciehp_poll_mode)
                slot_cmd = slot_cmd | HP_INTR_ENABLE; 
 
        pcie_write_cmd(slot, slot_cmd);
 
-       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
+       DBG_LEAVE_ROUTINE
        return;
 }
 
@@ -622,7 +597,8 @@ static void hpc_set_green_led_off(struct slot *slot)
        u16 slot_ctrl;
        int rc = 0;
 
-       dbg("%s: \n", __FUNCTION__);    
+       DBG_ENTER_ROUTINE
+
        if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return ;
@@ -633,21 +609,21 @@ static void hpc_set_green_led_off(struct slot *slot)
                return ;
        }
 
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (rc) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
                return;
        }
-       dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
 
        slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300;
 
        if (!pciehp_poll_mode)
                slot_cmd = slot_cmd | HP_INTR_ENABLE; 
        pcie_write_cmd(slot, slot_cmd);
-       dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, slot_cmd);
+       dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
 
+       DBG_LEAVE_ROUTINE
        return;
 }
 
@@ -658,7 +634,8 @@ static void hpc_set_green_led_blink(struct slot *slot)
        u16 slot_ctrl;
        int rc = 0; 
        
-       dbg("%s: \n", __FUNCTION__);    
+       DBG_ENTER_ROUTINE
+
        if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return ;
@@ -669,13 +646,12 @@ static void hpc_set_green_led_blink(struct slot *slot)
                return ;
        }
 
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (rc) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
                return;
        }
-       dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
 
        slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200;
 
@@ -683,7 +659,8 @@ static void hpc_set_green_led_blink(struct slot *slot)
                slot_cmd = slot_cmd | HP_INTR_ENABLE; 
        pcie_write_cmd(slot, slot_cmd);
 
-       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
+       DBG_LEAVE_ROUTINE
        return;
 }
 
@@ -707,7 +684,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl,
        *first_device_num = 0;
        *num_ctlr_slots = 1; 
 
-       rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap);
+       rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap);
 
        if (rc) {
                err("%s : hp_register_read_dword SLOT_CAP failed\n", __FUNCTION__);
@@ -741,8 +718,6 @@ static void hpc_release_ctlr(struct controller *ctrl)
                if (php_ctlr->irq) {
                        free_irq(php_ctlr->irq, ctrl);
                        php_ctlr->irq = 0;
-                       if (!pcie_mch_quirk) 
-                               pci_disable_msi(php_ctlr->pci_dev);
                }
        }
        if (php_ctlr->pci_dev) 
@@ -775,12 +750,11 @@ static int hpc_power_on_slot(struct slot * slot)
 {
        struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 slot_cmd;
-       u16 slot_ctrl;
+       u16 slot_ctrl, slot_status;
 
        int retval = 0;
 
        DBG_ENTER_ROUTINE 
-       dbg("%s: \n", __FUNCTION__);    
 
        if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
@@ -793,19 +767,30 @@ static int hpc_power_on_slot(struct slot * slot)
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       /* Clear sticky power-fault bit from previous power failures */
+       hp_register_read_word(php_ctlr->pci_dev,
+                       SLOT_STATUS(slot->ctrl->cap_base), slot_status);
+       slot_status &= PWR_FAULT_DETECTED;
+       if (slot_status)
+               hp_register_write_word(php_ctlr->pci_dev,
+                       SLOT_STATUS(slot->ctrl->cap_base), slot_status);
+
+       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (retval) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
                return retval;
        }
-       dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL, 
-               slot_ctrl);
 
        slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
 
+       /* Enable detection that we turned off at slot power-off time */
        if (!pciehp_poll_mode)
-               slot_cmd = slot_cmd | HP_INTR_ENABLE; 
+               slot_cmd = slot_cmd |
+                          PWR_FAULT_DETECT_ENABLE |
+                          MRL_DETECT_ENABLE |
+                          PRSN_DETECT_ENABLE |
+                          HP_INTR_ENABLE;
 
        retval = pcie_write_cmd(slot, slot_cmd);
 
@@ -813,7 +798,7 @@ static int hpc_power_on_slot(struct slot * slot)
                err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
                return -1;
        }
-       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
 
        DBG_LEAVE_ROUTINE
 
@@ -829,7 +814,6 @@ static int hpc_power_off_slot(struct slot * slot)
        int retval = 0;
 
        DBG_ENTER_ROUTINE 
-       dbg("%s: \n", __FUNCTION__);    
 
        if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
@@ -842,19 +826,27 @@ static int hpc_power_off_slot(struct slot * slot)
                err("%s: Invalid HPC slot number!\n", __FUNCTION__);
                return -1;
        }
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (retval) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
                return retval;
        }
-       dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL, 
-               slot_ctrl);
 
        slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
 
+       /*
+        * If we get MRL or presence detect interrupts now, the isr
+        * will notice the sticky power-fault bit too and issue power
+        * indicator change commands. This will lead to an endless loop
+        * of command completions, since the power-fault bit remains on
+        * till the slot is powered on again.
+        */
        if (!pciehp_poll_mode)
-               slot_cmd = slot_cmd | HP_INTR_ENABLE; 
+               slot_cmd = (slot_cmd &
+                           ~PWR_FAULT_DETECT_ENABLE &
+                           ~MRL_DETECT_ENABLE &
+                           ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE;
 
        retval = pcie_write_cmd(slot, slot_cmd);
 
@@ -862,14 +854,14 @@ static int hpc_power_off_slot(struct slot * slot)
                err("%s: Write command failed!\n", __FUNCTION__);
                return -1;
        }
-       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
 
        DBG_LEAVE_ROUTINE
 
        return retval;
 }
 
-static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pcie_isr(int IRQ, void *dev_id)
 {
        struct controller *ctrl = NULL;
        struct php_ctlr_state_s *php_ctlr;
@@ -900,7 +892,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
                return IRQ_NONE;
        }
 
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+       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__);
                return IRQ_NONE;
@@ -918,24 +910,22 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
        dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
        /* Mask Hot-plug Interrupt Enable */
        if (!pciehp_poll_mode) {
-               rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+               rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
                if (rc) {
                        err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
                        return IRQ_NONE;
                }
 
-               dbg("%s: Set Mask Hot-plug Interrupt Enable\n", __FUNCTION__);
                dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
                temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
 
-               rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+               rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
                if (rc) {
                        err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
                        return IRQ_NONE;
                }
-               dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
                
-               rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+               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__);
                        return IRQ_NONE;
@@ -944,19 +934,17 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
                
                /* Clear command complete interrupt caused by this write */
                temp_word = 0x1f;
-               rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+               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__);
                        return IRQ_NONE;
                }
-               dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word);
        }
        
        if (intr_loc & CMD_COMPLETED) {
                /* 
                 * Command Complete Interrupt Pending 
                 */
-               dbg("%s: In Command Complete Interrupt Pending\n", __FUNCTION__);
                wake_up_interruptible(&ctrl->queue);
        }
 
@@ -975,40 +963,37 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
 
        /* Clear all events after serving them */
        temp_word = 0x1F;
-       rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+       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__);
                return IRQ_NONE;
        }
        /* Unmask Hot-plug Interrupt Enable */
        if (!pciehp_poll_mode) {
-               rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+               rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
                if (rc) {
                        err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
                        return IRQ_NONE;
                }
 
                dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__);
-               dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
                temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
 
-               rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+               rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
                if (rc) {
                        err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
                        return IRQ_NONE;
                }
-               dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);   
        
-               rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+               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__);
                        return IRQ_NONE;
                }
-               dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); 
                
                /* Clear command complete interrupt caused by this write */
                temp_word = 0x1F;
-               rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+               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__);
                        return IRQ_NONE;
@@ -1038,7 +1023,7 @@ static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
                return -1;
        }
 
-       retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap);
+       retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap);
 
        if (retval) {
                err("%s : hp_register_read_dword  LNK_CAP failed\n", __FUNCTION__);
@@ -1079,7 +1064,7 @@ static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value
                return -1;
        }
 
-       retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap);
+       retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap);
 
        if (retval) {
                err("%s : hp_register_read_dword  LNK_CAP failed\n", __FUNCTION__);
@@ -1141,7 +1126,7 @@ static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status);
 
        if (retval) {
                err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
@@ -1182,7 +1167,7 @@ static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status);
 
        if (retval) {
                err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
@@ -1248,12 +1233,77 @@ static struct hpc_ops pciehp_hpc_ops = {
        .check_lnk_status               = hpc_check_lnk_status,
 };
 
-int pcie_init(struct controller * ctrl,
-       struct pcie_device *dev,
-       php_intr_callback_t attention_button_callback,
-       php_intr_callback_t switch_change_callback,
-       php_intr_callback_t presence_change_callback,
-       php_intr_callback_t power_fault_callback)
+#ifdef CONFIG_ACPI
+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));
+       struct pci_dev *pdev = dev;
+       struct pci_bus *parent;
+       struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
+
+       /*
+        * Per PCI firmware specification, we should run the ACPI _OSC
+        * method to get control of hotplug hardware before using it.
+        * If an _OSC is missing, we look for an OSHP to do the same thing.
+        * To handle different BIOS behavior, we look for _OSC and OSHP
+        * within the scope of the hotplug controller and its parents, upto
+        * the host bridge under which this controller exists.
+        */
+       while (!handle) {
+               /*
+                * This hotplug controller was not listed in the ACPI name
+                * space at all. Try to get acpi handle of parent pci bus.
+                */
+               if (!pdev || !pdev->bus->parent)
+                       break;
+               parent = pdev->bus->parent;
+               dbg("Could not find %s in acpi namespace, trying parent\n",
+                               pci_name(pdev));
+               if (!parent->self)
+                       /* Parent must be a host bridge */
+                       handle = acpi_get_pci_rootbridge_handle(
+                                       pci_domain_nr(parent),
+                                       parent->number);
+               else
+                       handle = DEVICE_ACPI_HANDLE(
+                                       &(parent->self->dev));
+               pdev = parent->self;
+       }
+
+       while (handle) {
+               acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
+               dbg("Trying to get hotplug control for %s \n",
+                       (char *)string.pointer);
+               status = pci_osc_control_set(handle,
+                               OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
+               if (status == AE_NOT_FOUND)
+                       status = acpi_run_oshp(handle);
+               if (ACPI_SUCCESS(status)) {
+                       dbg("Gained control for hotplug HW for pci %s (%s)\n",
+                               pci_name(dev), (char *)string.pointer);
+                       kfree(string.pointer);
+                       return 0;
+               }
+               if (acpi_root_bridge(handle))
+                       break;
+               chandle = handle;
+               status = acpi_get_parent(chandle, &handle);
+               if (ACPI_FAILURE(status))
+                       break;
+       }
+
+       err("Cannot get control of hotplug hardware for pci %s\n",
+                       pci_name(dev));
+
+       kfree(string.pointer);
+       return -1;
+}
+#endif
+
+
+
+int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 {
        struct php_ctlr_state_s *php_ctlr, *p;
        void *instance_id = ctrl;
@@ -1270,7 +1320,7 @@ int pcie_init(struct controller * ctrl,
        DBG_ENTER_ROUTINE
        
        spin_lock_init(&list_lock);     
-       php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
+       php_ctlr = kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
 
        if (!php_ctlr) {        /* allocate controller state data */
                err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
@@ -1282,8 +1332,8 @@ int pcie_init(struct controller * ctrl,
        pdev = dev->port;
        php_ctlr->pci_dev = pdev;       /* save pci_dev in context */
 
-       dbg("%s: pdev->vendor %x pdev->device %x\n", __FUNCTION__,
-               pdev->vendor, pdev->device);
+       dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
+                       __FUNCTION__, pdev->vendor, pdev->device);
 
        saved_cap_base = pcie_cap_base;
 
@@ -1292,79 +1342,77 @@ int pcie_init(struct controller * ctrl,
                goto abort_free_ctlr;
        }
 
-       pcie_cap_base = cap_base;
+       ctrl->cap_base = cap_base;
 
        dbg("%s: pcie_cap_base %x\n", __FUNCTION__, pcie_cap_base);
 
-       rc = hp_register_read_word(pdev, CAP_REG, cap_reg);
+       rc = hp_register_read_word(pdev, CAP_REG(ctrl->cap_base), cap_reg);
        if (rc) {
                err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__);
                goto abort_free_ctlr;
        }
-       dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG, cap_reg);
+       dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG(ctrl->cap_base), cap_reg);
 
-       if (((cap_reg & SLOT_IMPL) == 0) || ((cap_reg & DEV_PORT_TYPE) != 0x0040)){
+       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", __FUNCTION__);
                goto abort_free_ctlr;
        }
 
-       rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap);
+       rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap);
        if (rc) {
                err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__);
                goto abort_free_ctlr;
        }
-       dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP, slot_cap);
+       dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP(ctrl->cap_base), slot_cap);
 
        if (!(slot_cap & HP_CAP)) {
                dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
                goto abort_free_ctlr;
        }
        /* For debugging purpose */
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+       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;
        }
-       dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status);
+       dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), slot_status);
 
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), slot_ctrl);
        if (rc) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
                goto abort_free_ctlr;
        }
-       dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl);
+       dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), slot_ctrl);
 
        if (first) {
                spin_lock_init(&hpc_event_lock);
                first = 0;
        }
 
-       dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, 
-               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
        for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
                if (pci_resource_len(pdev, rc) > 0)
-                       dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc,
-                               pci_resource_start(pdev, rc), pci_resource_len(pdev, rc));
+                       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));
 
        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;
-       
-       init_MUTEX(&ctrl->crit_sect);
+       mutex_init(&ctrl->crit_sect);
+       mutex_init(&ctrl->ctrl_lock);
+
        /* setup wait queue */
        init_waitqueue_head(&ctrl->queue);
 
        /* find the IRQ */
        php_ctlr->irq = dev->irq;
-       dbg("HPC interrupt = %d\n", php_ctlr->irq);
 
        /* Save interrupt callback info */
-       php_ctlr->attention_button_callback = attention_button_callback;
-       php_ctlr->switch_change_callback = switch_change_callback;
-       php_ctlr->presence_change_callback = presence_change_callback;
-       php_ctlr->power_fault_callback = power_fault_callback;
+       php_ctlr->attention_button_callback = pciehp_handle_attention_button;
+       php_ctlr->switch_change_callback = pciehp_handle_switch_change;
+       php_ctlr->presence_change_callback = pciehp_handle_presence_change;
+       php_ctlr->power_fault_callback = pciehp_handle_power_fault;
        php_ctlr->callback_instance_id = instance_id;
 
        /* return PCI Controller Info */
@@ -1372,36 +1420,33 @@ int pcie_init(struct controller * ctrl,
        php_ctlr->num_slots = 1;
 
        /* Mask Hot-plug Interrupt Enable */
-       rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word);
+       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;
        }
 
-       dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
+       dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word);
        temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
 
-       rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word);
+       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;
        }
-       dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word);
 
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+       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;
        }
-       dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status);
 
        temp_word = 0x1F; /* Clear all events */
-       rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+       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;
        }
-       dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, temp_word);
 
        if (pciehp_poll_mode)  {/* Install interrupt polling code */
                /* Install and start the interrupt polling timer */
@@ -1409,7 +1454,7 @@ int pcie_init(struct controller * ctrl,
                start_int_poll_timer( php_ctlr, 10 );   /* start with 10 second delay */
        } else {
                /* Installs the interrupt handler */
-               rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);
+               rc = request_irq(php_ctlr->irq, pcie_isr, IRQF_SHARED, MY_NAME, (void *) ctrl);
                dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
                if (rc) {
                        err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);
@@ -1417,13 +1462,14 @@ int pcie_init(struct controller * ctrl,
                }
        }
 
-       rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word);
+       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);
+
+       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;
        }
-       dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
-       dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap);
 
        intr_enable = intr_enable | PRSN_DETECT_ENABLE;
 
@@ -1443,31 +1489,35 @@ int pcie_init(struct controller * ctrl,
        } else {
                temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
        }
-       dbg("%s: temp_word %x\n", __FUNCTION__, temp_word);
 
        /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */
-       rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word);
+       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;
        }
-       dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word);
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+       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;
        }
-       dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, 
-               SLOT_STATUS, slot_status);
        
        temp_word =  0x1F; /* Clear all events */
-       rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+       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;
        }
-       dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, temp_word);
        
+       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;
+       }
+
        /*  Add this HPC instance into the HPC list */
        spin_lock(&list_lock);
        if (php_ctlr_list_head == 0) {
@@ -1492,6 +1542,21 @@ int pcie_init(struct controller * ctrl,
        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);