]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/pci/hotplug/pciehp_hpc.c
Merge branch 'for-2.6.26' of git://git.kernel.dk/linux-2.6-block
[karo-tx-linux.git] / drivers / pci / hotplug / pciehp_hpc.c
index 06d025b8b13f6a8f276e396bfc36a742c5a676a4..b4bbd07d1e3902ff756a2280c01480c2ffb73320 100644 (file)
@@ -258,7 +258,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
 
        retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
        if (retval) {
-               err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+               err("%s: Cannot read SLOTSTATUS register\n", __func__);
                goto out;
        }
 
@@ -267,13 +267,13 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
                   proceed forward to issue the next command according
                   to spec.  Just print out the error message */
                dbg("%s: CMD_COMPLETED not clear after 1 sec.\n",
-                   __FUNCTION__);
+                   __func__);
        }
 
        spin_lock_irqsave(&ctrl->lock, flags);
        retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
        if (retval) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+               err("%s: Cannot read SLOTCTRL register\n", __func__);
                goto out_spin_unlock;
        }
 
@@ -283,7 +283,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
        ctrl->cmd_busy = 1;
        retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
        if (retval)
-               err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+               err("%s: Cannot write to SLOTCTRL register\n", __func__);
 
  out_spin_unlock:
        spin_unlock_irqrestore(&ctrl->lock, flags);
@@ -305,14 +305,14 @@ static int hpc_check_lnk_status(struct controller *ctrl)
 
        retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
        if (retval) {
-               err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);
+               err("%s: Cannot read LNKSTATUS register\n", __func__);
                return retval;
        }
 
-       dbg("%s: lnk_status = %x\n", __FUNCTION__, lnk_status);
+       dbg("%s: lnk_status = %x\n", __func__, lnk_status);
        if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) ||
                !(lnk_status & NEG_LINK_WD)) {
-               err("%s : Link Training Error occurs \n", __FUNCTION__);
+               err("%s : Link Training Error occurs \n", __func__);
                retval = -1;
                return retval;
        }
@@ -329,12 +329,12 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
 
        retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
        if (retval) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+               err("%s: Cannot read SLOTCTRL register\n", __func__);
                return retval;
        }
 
        dbg("%s: SLOTCTRL %x, value read %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+           __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
 
        atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6;
 
@@ -368,11 +368,11 @@ static int hpc_get_power_status(struct slot *slot, u8 *status)
 
        retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
        if (retval) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+               err("%s: Cannot read SLOTCTRL register\n", __func__);
                return retval;
        }
        dbg("%s: SLOTCTRL %x value read %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+           __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
 
        pwr_state = (slot_ctrl & PWR_CTRL) >> 10;
 
@@ -399,7 +399,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
 
        retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
        if (retval) {
-               err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+               err("%s: Cannot read SLOTSTATUS register\n", __func__);
                return retval;
        }
 
@@ -417,7 +417,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
 
        retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
        if (retval) {
-               err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+               err("%s: Cannot read SLOTSTATUS register\n", __func__);
                return retval;
        }
        card_state = (u8)((slot_status & PRSN_STATE) >> 6);
@@ -435,7 +435,7 @@ static int hpc_query_power_fault(struct slot *slot)
 
        retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
        if (retval) {
-               err("%s: Cannot check for power fault\n", __FUNCTION__);
+               err("%s: Cannot check for power fault\n", __func__);
                return retval;
        }
        pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
@@ -451,7 +451,7 @@ static int hpc_get_emi_status(struct slot *slot, u8 *status)
 
        retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
        if (retval) {
-               err("%s : Cannot check EMI status\n", __FUNCTION__);
+               err("%s : Cannot check EMI status\n", __func__);
                return retval;
        }
        *status = (slot_status & EMI_STATE) >> EMI_STATUS_BIT;
@@ -506,7 +506,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
 
        rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
        dbg("%s: SLOTCTRL %x write cmd %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+           __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 
        return rc;
 }
@@ -527,7 +527,7 @@ static void hpc_set_green_led_on(struct slot *slot)
        pcie_write_cmd(slot, slot_cmd, cmd_mask);
 
        dbg("%s: SLOTCTRL %x write cmd %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+           __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 }
 
 static void hpc_set_green_led_off(struct slot *slot)
@@ -545,7 +545,7 @@ static void hpc_set_green_led_off(struct slot *slot)
 
        pcie_write_cmd(slot, slot_cmd, cmd_mask);
        dbg("%s: SLOTCTRL %x write cmd %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+           __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 }
 
 static void hpc_set_green_led_blink(struct slot *slot)
@@ -564,7 +564,7 @@ static void hpc_set_green_led_blink(struct slot *slot)
        pcie_write_cmd(slot, slot_cmd, cmd_mask);
 
        dbg("%s: SLOTCTRL %x write cmd %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+           __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 }
 
 static void hpc_release_ctlr(struct controller *ctrl)
@@ -590,12 +590,12 @@ static int hpc_power_on_slot(struct slot * slot)
        u16 slot_status;
        int retval = 0;
 
-       dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
+       dbg("%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
 
        /* Clear sticky power-fault bit from previous power failures */
        retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
        if (retval) {
-               err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+               err("%s: Cannot read SLOTSTATUS register\n", __func__);
                return retval;
        }
        slot_status &= PWR_FAULT_DETECTED;
@@ -603,7 +603,7 @@ static int hpc_power_on_slot(struct slot * slot)
                retval = pciehp_writew(ctrl, SLOTSTATUS, slot_status);
                if (retval) {
                        err("%s: Cannot write to SLOTSTATUS register\n",
-                           __FUNCTION__);
+                           __func__);
                        return retval;
                }
        }
@@ -627,23 +627,65 @@ static int hpc_power_on_slot(struct slot * slot)
        retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
 
        if (retval) {
-               err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
+               err("%s: Write %x command failed!\n", __func__, slot_cmd);
                return -1;
        }
        dbg("%s: SLOTCTRL %x write cmd %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+           __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 
        return retval;
 }
 
+static inline int pcie_mask_bad_dllp(struct controller *ctrl)
+{
+       struct pci_dev *dev = ctrl->pci_dev;
+       int pos;
+       u32 reg;
+
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+       if (!pos)
+               return 0;
+       pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+       if (reg & PCI_ERR_COR_BAD_DLLP)
+               return 0;
+       reg |= PCI_ERR_COR_BAD_DLLP;
+       pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+       return 1;
+}
+
+static inline void pcie_unmask_bad_dllp(struct controller *ctrl)
+{
+       struct pci_dev *dev = ctrl->pci_dev;
+       u32 reg;
+       int pos;
+
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+       if (!pos)
+               return;
+       pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+       if (!(reg & PCI_ERR_COR_BAD_DLLP))
+               return;
+       reg &= ~PCI_ERR_COR_BAD_DLLP;
+       pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+}
+
 static int hpc_power_off_slot(struct slot * slot)
 {
        struct controller *ctrl = slot->ctrl;
        u16 slot_cmd;
        u16 cmd_mask;
        int retval = 0;
+       int changed;
+
+       dbg("%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
 
-       dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
+       /*
+        * Set Bad DLLP Mask bit in Correctable Error Mask
+        * Register. This is the workaround against Bad DLLP error
+        * that sometimes happens during turning power off the slot
+        * which conforms to PCI Express 1.0a spec.
+        */
+       changed = pcie_mask_bad_dllp(ctrl);
 
        slot_cmd = POWER_OFF;
        cmd_mask = PWR_CTRL;
@@ -668,11 +710,22 @@ static int hpc_power_off_slot(struct slot * slot)
 
        retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
        if (retval) {
-               err("%s: Write command failed!\n", __FUNCTION__);
-               return -1;
+               err("%s: Write command failed!\n", __func__);
+               retval = -1;
+               goto out;
        }
        dbg("%s: SLOTCTRL %x write cmd %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+           __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+
+       /*
+        * After turning power off, we must wait for at least 1 second
+        * before taking any action that relies on power having been
+        * removed from the slot/adapter.
+        */
+       msleep(1000);
+ out:
+       if (changed)
+               pcie_unmask_bad_dllp(ctrl);
 
        return retval;
 }
@@ -688,7 +741,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
 
        rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
        if (rc) {
-               err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+               err("%s: Cannot read SLOTSTATUS register\n", __func__);
                return IRQ_NONE;
        }
 
@@ -701,26 +754,26 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
        if ( !intr_loc )
                return IRQ_NONE;
 
-       dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
+       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",
-                           __FUNCTION__);
+                           __func__);
                        spin_unlock_irqrestore(&ctrl->lock, flags);
                        return IRQ_NONE;
                }
 
                dbg("%s: pciehp_readw(SLOTCTRL) with value %x\n",
-                   __FUNCTION__, temp_word);
+                   __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",
-                           __FUNCTION__);
+                           __func__);
                        spin_unlock_irqrestore(&ctrl->lock, flags);
                        return IRQ_NONE;
                }
@@ -729,18 +782,18 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
                rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
                if (rc) {
                        err("%s: Cannot read SLOT_STATUS register\n",
-                           __FUNCTION__);
+                           __func__);
                        return IRQ_NONE;
                }
                dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n",
-                   __FUNCTION__, slot_status);
+                   __func__, slot_status);
 
                /* 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",
-                           __FUNCTION__);
+                           __func__);
                        return IRQ_NONE;
                }
        }
@@ -769,7 +822,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
        temp_word = 0x1F;
        rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
        if (rc) {
-               err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
+               err("%s: Cannot write to SLOTSTATUS register\n", __func__);
                return IRQ_NONE;
        }
        /* Unmask Hot-plug Interrupt Enable */
@@ -778,18 +831,18 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
                rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
                if (rc) {
                        err("%s: Cannot read SLOTCTRL register\n",
-                           __FUNCTION__);
+                           __func__);
                        spin_unlock_irqrestore(&ctrl->lock, flags);
                        return IRQ_NONE;
                }
 
-               dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__);
+               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",
-                           __FUNCTION__);
+                           __func__);
                        spin_unlock_irqrestore(&ctrl->lock, flags);
                        return IRQ_NONE;
                }
@@ -798,7 +851,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
                rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
                if (rc) {
                        err("%s: Cannot read SLOT_STATUS register\n",
-                           __FUNCTION__);
+                           __func__);
                        return IRQ_NONE;
                }
 
@@ -807,11 +860,11 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
                rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
                if (rc) {
                        err("%s: Cannot write to SLOTSTATUS failed\n",
-                           __FUNCTION__);
+                           __func__);
                        return IRQ_NONE;
                }
                dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n",
-                   __FUNCTION__, temp_word);
+                   __func__, temp_word);
        }
 
        return IRQ_HANDLED;
@@ -826,7 +879,7 @@ static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
 
        retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
        if (retval) {
-               err("%s: Cannot read LNKCAP register\n", __FUNCTION__);
+               err("%s: Cannot read LNKCAP register\n", __func__);
                return retval;
        }
 
@@ -855,7 +908,7 @@ static int hpc_get_max_lnk_width(struct slot *slot,
 
        retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
        if (retval) {
-               err("%s: Cannot read LNKCAP register\n", __FUNCTION__);
+               err("%s: Cannot read LNKCAP register\n", __func__);
                return retval;
        }
 
@@ -904,7 +957,7 @@ static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
 
        retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
        if (retval) {
-               err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);
+               err("%s: Cannot read LNKSTATUS register\n", __func__);
                return retval;
        }
 
@@ -933,7 +986,7 @@ static int hpc_get_cur_lnk_width(struct slot *slot,
 
        retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
        if (retval) {
-               err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);
+               err("%s: Cannot read LNKSTATUS register\n", __func__);
                return retval;
        }
 
@@ -1067,13 +1120,143 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
 }
 #endif
 
-int pcie_init(struct controller * ctrl, struct pcie_device *dev)
+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__);
+               return -1;
+       }
+       return 0;
+}
+
+int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
 {
        int rc;
        u16 temp_word;
-       u16 cap_reg;
        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;
+       }
+
+       /*
+        * Unmask Hot-plug Interrupt Enable for the interrupt
+        * notification mechanism case.
+        */
+       rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+       if (rc) {
+               err("%s: Cannot write to SLOTCTRL register\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) {
+               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;
+       }
+
+       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)
+               err("%s : disabling interrupts failed\n", __func__);
+abort:
+       return -1;
+}
+
+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;
@@ -1082,61 +1265,62 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
        ctrl->pci_dev = pdev;   /* save pci_dev in context */
 
        dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
-                       __FUNCTION__, pdev->vendor, pdev->device);
+                       __func__, pdev->vendor, pdev->device);
 
-       if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) {
-               dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
-               goto abort_free_ctlr;
+       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__);
+               goto abort;
        }
 
        ctrl->cap_base = cap_base;
 
-       dbg("%s: pcie_cap_base %x\n", __FUNCTION__, 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", __FUNCTION__);
-               goto abort_free_ctlr;
+               err("%s: Cannot read CAPREG register\n", __func__);
+               goto abort;
        }
        dbg("%s: CAPREG offset %x cap_reg %x\n",
-           __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);
+           __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", __FUNCTION__);
-               goto abort_free_ctlr;
+                   "connected to a slot\n", __func__);
+               goto abort;
        }
 
        rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
        if (rc) {
-               err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
-               goto abort_free_ctlr;
+               err("%s: Cannot read SLOTCAP register\n", __func__);
+               goto abort;
        }
        dbg("%s: SLOTCAP offset %x slot_cap %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap);
+           __func__, ctrl->cap_base + SLOTCAP, slot_cap);
 
        if (!(slot_cap & HP_CAP)) {
-               dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
-               goto abort_free_ctlr;
+               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", __FUNCTION__);
-               goto abort_free_ctlr;
+               err("%s: Cannot read SLOTSTATUS register\n", __func__);
+               goto abort;
        }
        dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status);
+           __func__, ctrl->cap_base + SLOTSTATUS, slot_status);
 
        rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
        if (rc) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-               goto abort_free_ctlr;
+               err("%s: Cannot read SLOTCTRL register\n", __func__);
+               goto abort;
        }
        dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+           __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
 
        for (rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
                if (pci_resource_len(pdev, rc) > 0)
@@ -1161,36 +1345,9 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
        ctrl->first_slot = slot_cap >> 19;
        ctrl->ctrlcap = slot_cap & 0x0000007f;
 
-       /* Mask Hot-plug Interrupt Enable */
-       rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-       if (rc) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
-
-       dbg("%s: SLOTCTRL %x value read %x\n",
-           __FUNCTION__, 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", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
-
-       rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-       if (rc) {
-               err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
-
-       temp_word = 0x1F; /* Clear all events */
-       rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-       if (rc) {
-               err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
+       rc = pcie_init_hardware_part1(ctrl, dev);
+       if (rc)
+               goto abort;
 
        if (pciehp_poll_mode) {
                /* Install interrupt polling timer. Start with 10 sec delay */
@@ -1201,12 +1358,12 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
                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",
-                   __FUNCTION__, ctrl->pci_dev->irq,
+                   __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_free_ctlr;
+                       goto abort;
                }
        }
        dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
@@ -1224,82 +1381,16 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
                }
        }
 
-       rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-       if (rc) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-               goto abort_free_irq;
+       rc = pcie_init_hardware_part2(ctrl, dev);
+       if (rc == 0) {
+               ctrl->hpc_ops = &pciehp_hpc_ops;
+               return 0;
        }
-
-       intr_enable = intr_enable | PRSN_DETECT_ENABLE;
-
-       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;
-       }
-
-       /*
-        * Unmask Hot-plug Interrupt Enable for the interrupt
-        * notification mechanism case.
-        */
-       rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-       if (rc) {
-               err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
-               goto abort_free_irq;
-       }
-       rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-       if (rc) {
-               err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
-               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", __FUNCTION__);
-               goto abort_disable_intr;
-       }
-
-       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;
-       }
-
-       ctrl->hpc_ops = &pciehp_hpc_ops;
-
-       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)
-               err("%s : disabling interrupts failed\n", __FUNCTION__);
-
 abort_free_irq:
        if (pciehp_poll_mode)
                del_timer_sync(&ctrl->poll_timer);
        else
                free_irq(ctrl->pci_dev->irq, ctrl);
-
-abort_free_ctlr:
+abort:
        return -1;
 }