diff options
Diffstat (limited to 'drivers/pci/hotplug/pciehp_hpc.c')
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 891f81a0400c..425a0f609977 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -722,6 +722,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
722 | { | 722 | { |
723 | struct controller *ctrl = (struct controller *)dev_id; | 723 | struct controller *ctrl = (struct controller *)dev_id; |
724 | u16 detected, intr_loc; | 724 | u16 detected, intr_loc; |
725 | struct slot *p_slot; | ||
725 | 726 | ||
726 | /* | 727 | /* |
727 | * In order to guarantee that all interrupt events are | 728 | * In order to guarantee that all interrupt events are |
@@ -756,21 +757,38 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
756 | wake_up_interruptible(&ctrl->queue); | 757 | wake_up_interruptible(&ctrl->queue); |
757 | } | 758 | } |
758 | 759 | ||
760 | if (!(intr_loc & ~CMD_COMPLETED)) | ||
761 | return IRQ_HANDLED; | ||
762 | |||
763 | /* | ||
764 | * Return without handling events if this handler routine is | ||
765 | * called before controller initialization is done. This may | ||
766 | * happen if hotplug event or another interrupt that shares | ||
767 | * the IRQ with pciehp arrives before slot initialization is | ||
768 | * done after interrupt handler is registered. | ||
769 | * | ||
770 | * FIXME - Need more structural fixes. We need to be ready to | ||
771 | * handle the event before installing interrupt handler. | ||
772 | */ | ||
773 | p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); | ||
774 | if (!p_slot || !p_slot->hpc_ops) | ||
775 | return IRQ_HANDLED; | ||
776 | |||
759 | /* Check MRL Sensor Changed */ | 777 | /* Check MRL Sensor Changed */ |
760 | if (intr_loc & MRL_SENS_CHANGED) | 778 | if (intr_loc & MRL_SENS_CHANGED) |
761 | pciehp_handle_switch_change(0, ctrl); | 779 | pciehp_handle_switch_change(p_slot); |
762 | 780 | ||
763 | /* Check Attention Button Pressed */ | 781 | /* Check Attention Button Pressed */ |
764 | if (intr_loc & ATTN_BUTTN_PRESSED) | 782 | if (intr_loc & ATTN_BUTTN_PRESSED) |
765 | pciehp_handle_attention_button(0, ctrl); | 783 | pciehp_handle_attention_button(p_slot); |
766 | 784 | ||
767 | /* Check Presence Detect Changed */ | 785 | /* Check Presence Detect Changed */ |
768 | if (intr_loc & PRSN_DETECT_CHANGED) | 786 | if (intr_loc & PRSN_DETECT_CHANGED) |
769 | pciehp_handle_presence_change(0, ctrl); | 787 | pciehp_handle_presence_change(p_slot); |
770 | 788 | ||
771 | /* Check Power Fault Detected */ | 789 | /* Check Power Fault Detected */ |
772 | if (intr_loc & PWR_FAULT_DETECTED) | 790 | if (intr_loc & PWR_FAULT_DETECTED) |
773 | pciehp_handle_power_fault(0, ctrl); | 791 | pciehp_handle_power_fault(p_slot); |
774 | 792 | ||
775 | return IRQ_HANDLED; | 793 | return IRQ_HANDLED; |
776 | } | 794 | } |
@@ -1028,6 +1046,12 @@ static int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) | |||
1028 | static int pcie_init_hardware_part1(struct controller *ctrl, | 1046 | static int pcie_init_hardware_part1(struct controller *ctrl, |
1029 | struct pcie_device *dev) | 1047 | struct pcie_device *dev) |
1030 | { | 1048 | { |
1049 | /* Clear all remaining event bits in Slot Status register */ | ||
1050 | if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) { | ||
1051 | err("%s: Cannot write to SLOTSTATUS register\n", __func__); | ||
1052 | return -1; | ||
1053 | } | ||
1054 | |||
1031 | /* Mask Hot-plug Interrupt Enable */ | 1055 | /* Mask Hot-plug Interrupt Enable */ |
1032 | if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) { | 1056 | if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) { |
1033 | err("%s: Cannot mask hotplug interrupt enable\n", __func__); | 1057 | err("%s: Cannot mask hotplug interrupt enable\n", __func__); |
@@ -1040,16 +1064,6 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev) | |||
1040 | { | 1064 | { |
1041 | u16 cmd, mask; | 1065 | u16 cmd, mask; |
1042 | 1066 | ||
1043 | /* | ||
1044 | * We need to clear all events before enabling hotplug interrupt | ||
1045 | * notification mechanism in order for hotplug controler to | ||
1046 | * generate interrupts. | ||
1047 | */ | ||
1048 | if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) { | ||
1049 | err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); | ||
1050 | return -1; | ||
1051 | } | ||
1052 | |||
1053 | cmd = PRSN_DETECT_ENABLE; | 1067 | cmd = PRSN_DETECT_ENABLE; |
1054 | if (ATTN_BUTTN(ctrl)) | 1068 | if (ATTN_BUTTN(ctrl)) |
1055 | cmd |= ATTN_BUTTN_ENABLE; | 1069 | cmd |= ATTN_BUTTN_ENABLE; |