diff options
Diffstat (limited to 'kernel/drivers/pci/hotplug/pciehp_hpc.c')
-rw-r--r-- | kernel/drivers/pci/hotplug/pciehp_hpc.c | 125 |
1 files changed, 57 insertions, 68 deletions
diff --git a/kernel/drivers/pci/hotplug/pciehp_hpc.c b/kernel/drivers/pci/hotplug/pciehp_hpc.c index 6d6868811..5c24e9380 100644 --- a/kernel/drivers/pci/hotplug/pciehp_hpc.c +++ b/kernel/drivers/pci/hotplug/pciehp_hpc.c @@ -109,21 +109,23 @@ static int pcie_poll_cmd(struct controller *ctrl, int timeout) struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_status; - pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); - if (slot_status & PCI_EXP_SLTSTA_CC) { - pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, - PCI_EXP_SLTSTA_CC); - return 1; - } - while (timeout > 0) { - msleep(10); - timeout -= 10; + while (true) { pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); + if (slot_status == (u16) ~0) { + ctrl_info(ctrl, "%s: no response from device\n", + __func__); + return 0; + } + if (slot_status & PCI_EXP_SLTSTA_CC) { pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC); return 1; } + if (timeout < 0) + break; + msleep(10); + timeout -= 10; } return 0; /* timeout */ } @@ -190,6 +192,11 @@ static void pcie_do_write_cmd(struct controller *ctrl, u16 cmd, pcie_wait_cmd(ctrl); pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); + if (slot_ctrl == (u16) ~0) { + ctrl_info(ctrl, "%s: no response from device\n", __func__); + goto out; + } + slot_ctrl &= ~mask; slot_ctrl |= (cmd & mask); ctrl->cmd_busy = 1; @@ -205,6 +212,7 @@ static void pcie_do_write_cmd(struct controller *ctrl, u16 cmd, if (wait) pcie_wait_cmd(ctrl); +out: mutex_unlock(&ctrl->ctrl_lock); } @@ -312,7 +320,8 @@ int pciehp_check_link_status(struct controller *ctrl) ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status); if ((lnk_status & PCI_EXP_LNKSTA_LT) || !(lnk_status & PCI_EXP_LNKSTA_NLW)) { - ctrl_err(ctrl, "Link Training Error occurs\n"); + ctrl_err(ctrl, "link training error: status %#06x\n", + lnk_status); return -1; } @@ -534,6 +543,8 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) struct pci_dev *dev; struct slot *slot = ctrl->slot; u16 detected, intr_loc; + u8 present; + bool link; /* * In order to guarantee that all interrupt events are @@ -543,9 +554,14 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) intr_loc = 0; do { pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &detected); + if (detected == (u16) ~0) { + ctrl_info(ctrl, "%s: no response from device\n", + __func__); + return IRQ_HANDLED; + } detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | - PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | + PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC); detected &= ~intr_loc; intr_loc |= detected; @@ -556,7 +572,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) intr_loc); } while (detected); - ctrl_dbg(ctrl, "%s: intr_loc %x\n", __func__, intr_loc); + ctrl_dbg(ctrl, "pending interrupts %#06x from Slot Status\n", intr_loc); /* Check Command Complete Interrupt Pending */ if (intr_loc & PCI_EXP_SLTSTA_CC) { @@ -578,26 +594,36 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) if (!(intr_loc & ~PCI_EXP_SLTSTA_CC)) return IRQ_HANDLED; - /* Check MRL Sensor Changed */ - if (intr_loc & PCI_EXP_SLTSTA_MRLSC) - pciehp_handle_switch_change(slot); - /* Check Attention Button Pressed */ - if (intr_loc & PCI_EXP_SLTSTA_ABP) - pciehp_handle_attention_button(slot); + if (intr_loc & PCI_EXP_SLTSTA_ABP) { + ctrl_info(ctrl, "Button pressed on Slot(%s)\n", + slot_name(slot)); + pciehp_queue_interrupt_event(slot, INT_BUTTON_PRESS); + } /* Check Presence Detect Changed */ - if (intr_loc & PCI_EXP_SLTSTA_PDC) - pciehp_handle_presence_change(slot); + if (intr_loc & PCI_EXP_SLTSTA_PDC) { + pciehp_get_adapter_status(slot, &present); + ctrl_info(ctrl, "Card %spresent on Slot(%s)\n", + present ? "" : "not ", slot_name(slot)); + pciehp_queue_interrupt_event(slot, present ? INT_PRESENCE_ON : + INT_PRESENCE_OFF); + } /* Check Power Fault Detected */ if ((intr_loc & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) { ctrl->power_fault_detected = 1; - pciehp_handle_power_fault(slot); + ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(slot)); + pciehp_queue_interrupt_event(slot, INT_POWER_FAULT); } - if (intr_loc & PCI_EXP_SLTSTA_DLLSC) - pciehp_handle_linkstate_change(slot); + if (intr_loc & PCI_EXP_SLTSTA_DLLSC) { + link = pciehp_check_link_active(ctrl); + ctrl_info(ctrl, "slot(%s): Link %s event\n", + slot_name(slot), link ? "Up" : "Down"); + pciehp_queue_interrupt_event(slot, link ? INT_LINK_UP : + INT_LINK_DOWN); + } return IRQ_HANDLED; } @@ -627,13 +653,11 @@ void pcie_enable_notification(struct controller *ctrl) cmd |= PCI_EXP_SLTCTL_ABPE; else cmd |= PCI_EXP_SLTCTL_PDCE; - if (MRL_SENS(ctrl)) - cmd |= PCI_EXP_SLTCTL_MRLSCE; if (!pciehp_poll_mode) cmd |= PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE; mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | - PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | + PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_DLLSCE); @@ -748,48 +772,13 @@ static void pcie_cleanup_slot(struct controller *ctrl) static inline void dbg_ctrl(struct controller *ctrl) { - int i; - u16 reg16; struct pci_dev *pdev = ctrl->pcie->port; + u16 reg16; if (!pciehp_debug) return; - ctrl_info(ctrl, "Hotplug Controller:\n"); - ctrl_info(ctrl, " Seg/Bus/Dev/Func/IRQ : %s IRQ %d\n", - pci_name(pdev), pdev->irq); - ctrl_info(ctrl, " Vendor ID : 0x%04x\n", pdev->vendor); - ctrl_info(ctrl, " Device ID : 0x%04x\n", pdev->device); - ctrl_info(ctrl, " Subsystem ID : 0x%04x\n", - pdev->subsystem_device); - ctrl_info(ctrl, " Subsystem Vendor ID : 0x%04x\n", - pdev->subsystem_vendor); - ctrl_info(ctrl, " PCIe Cap offset : 0x%02x\n", - pci_pcie_cap(pdev)); - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - if (!pci_resource_len(pdev, i)) - continue; - ctrl_info(ctrl, " PCI resource [%d] : %pR\n", - i, &pdev->resource[i]); - } ctrl_info(ctrl, "Slot Capabilities : 0x%08x\n", ctrl->slot_cap); - ctrl_info(ctrl, " Physical Slot Number : %d\n", PSN(ctrl)); - ctrl_info(ctrl, " Attention Button : %3s\n", - ATTN_BUTTN(ctrl) ? "yes" : "no"); - ctrl_info(ctrl, " Power Controller : %3s\n", - POWER_CTRL(ctrl) ? "yes" : "no"); - ctrl_info(ctrl, " MRL Sensor : %3s\n", - MRL_SENS(ctrl) ? "yes" : "no"); - ctrl_info(ctrl, " Attention Indicator : %3s\n", - ATTN_LED(ctrl) ? "yes" : "no"); - ctrl_info(ctrl, " Power Indicator : %3s\n", - PWR_LED(ctrl) ? "yes" : "no"); - ctrl_info(ctrl, " Hot-Plug Surprise : %3s\n", - HP_SUPR_RM(ctrl) ? "yes" : "no"); - ctrl_info(ctrl, " EMI Present : %3s\n", - EMI(ctrl) ? "yes" : "no"); - ctrl_info(ctrl, " Command Completed : %3s\n", - NO_CMD_CMPL(ctrl) ? "no" : "yes"); pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, ®16); ctrl_info(ctrl, "Slot Status : 0x%04x\n", reg16); pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, ®16); @@ -818,10 +807,8 @@ struct controller *pcie_init(struct pcie_device *dev) /* Check if Data Link Layer Link Active Reporting is implemented */ pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap); - if (link_cap & PCI_EXP_LNKCAP_DLLLARC) { - ctrl_dbg(ctrl, "Link Active Reporting supported\n"); + if (link_cap & PCI_EXP_LNKCAP_DLLLARC) ctrl->link_active_reporting = 1; - } /* Clear all remaining event bits in Slot Status register */ pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, @@ -829,13 +816,15 @@ struct controller *pcie_init(struct pcie_device *dev) PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC); - ctrl_info(ctrl, "Slot #%d AttnBtn%c AttnInd%c PwrInd%c PwrCtrl%c MRL%c Interlock%c NoCompl%c LLActRep%c\n", + ctrl_info(ctrl, "Slot #%d AttnBtn%c PwrCtrl%c MRL%c AttnInd%c PwrInd%c HotPlug%c Surprise%c Interlock%c NoCompl%c LLActRep%c\n", (slot_cap & PCI_EXP_SLTCAP_PSN) >> 19, FLAG(slot_cap, PCI_EXP_SLTCAP_ABP), - FLAG(slot_cap, PCI_EXP_SLTCAP_AIP), - FLAG(slot_cap, PCI_EXP_SLTCAP_PIP), FLAG(slot_cap, PCI_EXP_SLTCAP_PCP), FLAG(slot_cap, PCI_EXP_SLTCAP_MRLSP), + FLAG(slot_cap, PCI_EXP_SLTCAP_AIP), + FLAG(slot_cap, PCI_EXP_SLTCAP_PIP), + FLAG(slot_cap, PCI_EXP_SLTCAP_HPC), + FLAG(slot_cap, PCI_EXP_SLTCAP_HPS), FLAG(slot_cap, PCI_EXP_SLTCAP_EIP), FLAG(slot_cap, PCI_EXP_SLTCAP_NCCS), FLAG(link_cap, PCI_EXP_LNKCAP_DLLLARC)); |