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;
}
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;
}
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);
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;
}
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;
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;
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;
}
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);
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);
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;
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;
}
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)
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)
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)
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;
retval = pciehp_writew(ctrl, SLOTSTATUS, slot_status);
if (retval) {
err("%s: Cannot write to SLOTSTATUS register\n",
- __FUNCTION__);
+ __func__);
return retval;
}
}
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, ®);
+ 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, ®);
+ 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", __FUNCTION__, slot->hp_slot);
+ dbg("%s: slot->hp_slot %x\n", __func__, 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;
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;
}
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;
}
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;
}
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;
}
}
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 */
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;
}
rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (rc) {
err("%s: Cannot read SLOT_STATUS register\n",
- __FUNCTION__);
+ __func__);
return IRQ_NONE;
}
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;
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;
}
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;
}
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;
}
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;
}
}
#endif
-int pcie_init_hardware(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;
- u16 intr_enable = 0;
u32 slot_cap;
u16 slot_status;
- struct pci_dev *pdev;
-
- pdev = dev->port;
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__);
+ return -1;
}
/* 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;
+ err("%s: Cannot read SLOTCTRL register\n", __func__);
+ return -1;
}
dbg("%s: SLOTCTRL %x value read %x\n",
- __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
+ __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", __FUNCTION__);
- goto abort_free_ctlr;
+ 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", __FUNCTION__);
- goto abort_free_ctlr;
+ 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", __FUNCTION__);
- goto abort_free_ctlr;
- }
-
- 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",
- __FUNCTION__, 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;
- }
+ err("%s: Cannot write to SLOTSTATUS register\n", __func__);
+ return -1;
}
- 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);
+ return 0;
+}
- /*
- * If this is the first controller to be initialized,
- * initialize the pciehp work queue
- */
- if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
- pciehp_wq = create_singlethread_workqueue("pciehpd");
- if (!pciehp_wq) {
- rc = -ENOMEM;
- goto abort_free_irq;
- }
- }
+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", __FUNCTION__);
- goto abort_free_irq;
+ 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;
*/
rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
if (rc) {
- err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
- goto abort_free_irq;
+ 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", __FUNCTION__);
+ 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", __FUNCTION__);
+ err("%s: Cannot write to SLOTSTATUS register\n", __func__);
goto abort_disable_intr;
}
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:
+ err("%s : disabling interrupts failed\n", __func__);
+abort:
return -1;
}
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);
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", __FUNCTION__);
+ 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__);
+ 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__);
+ "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__);
+ 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__);
+ 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__);
+ 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__);
+ 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)
ctrl->first_slot = slot_cap >> 19;
ctrl->ctrlcap = slot_cap & 0x0000007f;
- rc = pcie_init_hardware(ctrl, dev);
+ rc = pcie_init_hardware_part1(ctrl, dev);
+ if (rc)
+ 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 this is the first controller to be initialized,
+ * initialize the pciehp work queue
+ */
+ 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;
}
+abort_free_irq:
+ if (pciehp_poll_mode)
+ del_timer_sync(&ctrl->poll_timer);
+ else
+ free_irq(ctrl->pci_dev->irq, ctrl);
abort:
return -1;
}