aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/pciehp.h8
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c22
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c42
3 files changed, 37 insertions, 35 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 8264a7680435..920091c4b18d 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -146,10 +146,10 @@ struct controller {
146 146
147extern int pciehp_sysfs_enable_slot(struct slot *slot); 147extern int pciehp_sysfs_enable_slot(struct slot *slot);
148extern int pciehp_sysfs_disable_slot(struct slot *slot); 148extern int pciehp_sysfs_disable_slot(struct slot *slot);
149extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl); 149extern u8 pciehp_handle_attention_button(struct slot *p_slot);
150extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl); 150 extern u8 pciehp_handle_switch_change(struct slot *p_slot);
151extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl); 151extern u8 pciehp_handle_presence_change(struct slot *p_slot);
152extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl); 152extern u8 pciehp_handle_power_fault(struct slot *p_slot);
153extern int pciehp_configure_device(struct slot *p_slot); 153extern int pciehp_configure_device(struct slot *p_slot);
154extern int pciehp_unconfigure_device(struct slot *p_slot); 154extern int pciehp_unconfigure_device(struct slot *p_slot);
155extern void pciehp_queue_pushbutton_work(struct work_struct *work); 155extern 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 0a7aa628e955..7ad8a7dbc1a4 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
58u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl) 58u8 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
79u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) 76u8 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
110u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) 104u8 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
144u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) 135u8 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 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)
1028static int pcie_init_hardware_part1(struct controller *ctrl, 1046static 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;