diff options
| -rw-r--r-- | drivers/pci/hotplug/pciehp.h | 8 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 22 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 42 |
3 files changed, 37 insertions, 35 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 8264a768043..920091c4b18 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
| @@ -146,10 +146,10 @@ struct controller { | |||
| 146 | 146 | ||
| 147 | extern int pciehp_sysfs_enable_slot(struct slot *slot); | 147 | extern int pciehp_sysfs_enable_slot(struct slot *slot); |
| 148 | extern int pciehp_sysfs_disable_slot(struct slot *slot); | 148 | extern int pciehp_sysfs_disable_slot(struct slot *slot); |
| 149 | extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl); | 149 | extern u8 pciehp_handle_attention_button(struct slot *p_slot); |
| 150 | extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl); | 150 | extern u8 pciehp_handle_switch_change(struct slot *p_slot); |
| 151 | extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl); | 151 | extern u8 pciehp_handle_presence_change(struct slot *p_slot); |
| 152 | extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl); | 152 | extern u8 pciehp_handle_power_fault(struct slot *p_slot); |
| 153 | extern int pciehp_configure_device(struct slot *p_slot); | 153 | extern int pciehp_configure_device(struct slot *p_slot); |
| 154 | extern int pciehp_unconfigure_device(struct slot *p_slot); | 154 | extern int pciehp_unconfigure_device(struct slot *p_slot); |
| 155 | extern void pciehp_queue_pushbutton_work(struct work_struct *work); | 155 | extern void pciehp_queue_pushbutton_work(struct work_struct *work); |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 0a7aa628e95..7ad8a7dbc1a 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
| @@ -55,16 +55,13 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) | |||
| 55 | return 0; | 55 | return 0; |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl) | 58 | u8 pciehp_handle_attention_button(struct slot *p_slot) |
| 59 | { | 59 | { |
| 60 | struct slot *p_slot; | ||
| 61 | u32 event_type; | 60 | u32 event_type; |
| 62 | 61 | ||
| 63 | /* Attention Button Change */ | 62 | /* Attention Button Change */ |
| 64 | dbg("pciehp: Attention button interrupt received.\n"); | 63 | dbg("pciehp: Attention button interrupt received.\n"); |
| 65 | 64 | ||
| 66 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | ||
| 67 | |||
| 68 | /* | 65 | /* |
| 69 | * Button pressed - See if need to TAKE ACTION!!! | 66 | * Button pressed - See if need to TAKE ACTION!!! |
| 70 | */ | 67 | */ |
| @@ -76,18 +73,15 @@ u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl) | |||
| 76 | return 0; | 73 | return 0; |
| 77 | } | 74 | } |
| 78 | 75 | ||
| 79 | u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) | 76 | u8 pciehp_handle_switch_change(struct slot *p_slot) |
| 80 | { | 77 | { |
| 81 | struct slot *p_slot; | ||
| 82 | u8 getstatus; | 78 | u8 getstatus; |
| 83 | u32 event_type; | 79 | u32 event_type; |
| 84 | 80 | ||
| 85 | /* Switch Change */ | 81 | /* Switch Change */ |
| 86 | dbg("pciehp: Switch interrupt received.\n"); | 82 | dbg("pciehp: Switch interrupt received.\n"); |
| 87 | 83 | ||
| 88 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | ||
| 89 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 84 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 90 | |||
| 91 | if (getstatus) { | 85 | if (getstatus) { |
| 92 | /* | 86 | /* |
| 93 | * Switch opened | 87 | * Switch opened |
| @@ -107,17 +101,14 @@ u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) | |||
| 107 | return 1; | 101 | return 1; |
| 108 | } | 102 | } |
| 109 | 103 | ||
| 110 | u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) | 104 | u8 pciehp_handle_presence_change(struct slot *p_slot) |
| 111 | { | 105 | { |
| 112 | struct slot *p_slot; | ||
| 113 | u32 event_type; | 106 | u32 event_type; |
| 114 | u8 presence_save; | 107 | u8 presence_save; |
| 115 | 108 | ||
| 116 | /* Presence Change */ | 109 | /* Presence Change */ |
| 117 | dbg("pciehp: Presence/Notify input change.\n"); | 110 | dbg("pciehp: Presence/Notify input change.\n"); |
| 118 | 111 | ||
| 119 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | ||
| 120 | |||
| 121 | /* Switch is open, assume a presence change | 112 | /* Switch is open, assume a presence change |
| 122 | * Save the presence state | 113 | * Save the presence state |
| 123 | */ | 114 | */ |
| @@ -141,16 +132,13 @@ u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) | |||
| 141 | return 1; | 132 | return 1; |
| 142 | } | 133 | } |
| 143 | 134 | ||
| 144 | u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) | 135 | u8 pciehp_handle_power_fault(struct slot *p_slot) |
| 145 | { | 136 | { |
| 146 | struct slot *p_slot; | ||
| 147 | u32 event_type; | 137 | u32 event_type; |
| 148 | 138 | ||
| 149 | /* power fault */ | 139 | /* power fault */ |
| 150 | dbg("pciehp: Power fault interrupt received.\n"); | 140 | dbg("pciehp: Power fault interrupt received.\n"); |
| 151 | 141 | ||
| 152 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | ||
| 153 | |||
| 154 | if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { | 142 | if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { |
| 155 | /* | 143 | /* |
| 156 | * power fault Cleared | 144 | * power fault Cleared |
| @@ -163,7 +151,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) | |||
| 163 | */ | 151 | */ |
| 164 | info("Power fault on Slot(%s)\n", p_slot->name); | 152 | info("Power fault on Slot(%s)\n", p_slot->name); |
| 165 | event_type = INT_POWER_FAULT; | 153 | event_type = INT_POWER_FAULT; |
| 166 | info("power fault bit %x set\n", hp_slot); | 154 | info("power fault bit %x set\n", 0); |
| 167 | } | 155 | } |
| 168 | 156 | ||
| 169 | queue_interrupt_event(p_slot, event_type); | 157 | queue_interrupt_event(p_slot, event_type); |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 891f81a0400..425a0f60997 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; |
