aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pciehp_hpc.c
diff options
context:
space:
mode:
authorLukas Wunner <lukas@wunner.de>2018-07-19 17:27:41 -0500
committerBjorn Helgaas <helgaas@kernel.org>2018-07-23 17:04:12 -0500
commit0e94916e6091f48391b65110e71c87c583021640 (patch)
treed729a71585394de0ebe2d952ad8f72e8b01adcda /drivers/pci/hotplug/pciehp_hpc.c
parentPCI: pciehp: Stop blinking on slot enable failure (diff)
downloadlinux-dev-0e94916e6091f48391b65110e71c87c583021640.tar.xz
linux-dev-0e94916e6091f48391b65110e71c87c583021640.zip
PCI: pciehp: Handle events synchronously
Up until now, pciehp's IRQ handler schedules a work item for each event, which in turn schedules a work item to enable or disable the slot. This double indirection was necessary because sleeping wasn't allowed in the IRQ handler. However it is now that pciehp has been converted to threaded IRQ handling and polling, so handle events synchronously in pciehp_ist() and remove the work item infrastructure (with the exception of work items to handle a button press after the 5 second delay). For link or presence change events, move the register read to determine the current link or presence state behind acquisition of the slot lock to prevent it from becoming stale while the lock is contended. Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/hotplug/pciehp_hpc.c')
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c27
1 files changed, 8 insertions, 19 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index d36650f2d2bb..31544998e1bd 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -581,8 +581,6 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id)
struct controller *ctrl = (struct controller *)dev_id;
struct slot *slot = ctrl->slot;
u32 events;
- u8 present;
- bool link;
synchronize_hardirq(irq);
events = atomic_xchg(&ctrl->pending_events, 0);
@@ -593,34 +591,25 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id)
if (events & PCI_EXP_SLTSTA_ABP) {
ctrl_info(ctrl, "Slot(%s): Attention button pressed\n",
slot_name(slot));
- pciehp_queue_interrupt_event(slot, INT_BUTTON_PRESS);
+ pciehp_handle_button_press(slot);
}
/*
* Check Link Status Changed at higher precedence than Presence
* Detect Changed. The PDS value may be set to "card present" from
- * out-of-band detection, which may be in conflict with a Link Down
- * and cause the wrong event to queue.
+ * out-of-band detection, which may be in conflict with a Link Down.
*/
- if (events & PCI_EXP_SLTSTA_DLLSC) {
- link = pciehp_check_link_active(ctrl);
- ctrl_info(ctrl, "Slot(%s): Link %s\n", slot_name(slot),
- link ? "Up" : "Down");
- pciehp_queue_interrupt_event(slot, link ? INT_LINK_UP :
- INT_LINK_DOWN);
- } else if (events & PCI_EXP_SLTSTA_PDC) {
- pciehp_get_adapter_status(slot, &present);
- ctrl_info(ctrl, "Slot(%s): Card %spresent\n", slot_name(slot),
- present ? "" : "not ");
- pciehp_queue_interrupt_event(slot, present ? INT_PRESENCE_ON :
- INT_PRESENCE_OFF);
- }
+ if (events & PCI_EXP_SLTSTA_DLLSC)
+ pciehp_handle_link_change(slot);
+ else if (events & PCI_EXP_SLTSTA_PDC)
+ pciehp_handle_presence_change(slot);
/* Check Power Fault Detected */
if ((events & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) {
ctrl->power_fault_detected = 1;
ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(slot));
- pciehp_queue_interrupt_event(slot, INT_POWER_FAULT);
+ pciehp_set_attention_status(slot, 1);
+ pciehp_green_led_off(slot);
}
return IRQ_HANDLED;