aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2009-11-13 01:14:10 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-11-24 18:25:19 -0500
commit5651c48cfafef1b9a7ebdc00ebeb32f2af887a89 (patch)
tree98fa6b66b5a88d1a53d041fd0473d9711b8dd88a
parent13598378f29c125d78047b23330eb2294b03d414 (diff)
PCI pciehp: fix power fault interrupt storm problem
Enabling power fault detected event notification in current pciehp might cause power fault interrupt storm on some machines. On those machines. On those machines, power fault detected bit in the slot status register was set again immediately when it is cleared in the interrupt service routine, and next power fault detected interrupt was notified again. Therefore, disable power fault detected event notification for now. This patch also removes unnecessary handling for power fault cleared event because this event is not supported by PCIe spec. Tested-by: Jens Axboe <jens.axboe@oracle.com> Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c27
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c26
2 files changed, 17 insertions, 36 deletions
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 15ce2a3cc0f1..d6ac1b261dd9 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -142,23 +142,9 @@ u8 pciehp_handle_power_fault(struct slot *p_slot)
142 142
143 /* power fault */ 143 /* power fault */
144 ctrl_dbg(ctrl, "Power fault interrupt received\n"); 144 ctrl_dbg(ctrl, "Power fault interrupt received\n");
145 145 ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
146 if (!pciehp_query_power_fault(p_slot)) { 146 event_type = INT_POWER_FAULT;
147 /* 147 ctrl_info(ctrl, "Power fault bit %x set\n", 0);
148 * power fault Cleared
149 */
150 ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n",
151 slot_name(p_slot));
152 event_type = INT_POWER_FAULT_CLEAR;
153 } else {
154 /*
155 * power fault
156 */
157 ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot));
158 event_type = INT_POWER_FAULT;
159 ctrl_info(ctrl, "Power fault bit %x set\n", 0);
160 }
161
162 queue_interrupt_event(p_slot, event_type); 148 queue_interrupt_event(p_slot, event_type);
163 149
164 return 1; 150 return 1;
@@ -224,13 +210,12 @@ static int board_added(struct slot *p_slot)
224 retval = pciehp_check_link_status(ctrl); 210 retval = pciehp_check_link_status(ctrl);
225 if (retval) { 211 if (retval) {
226 ctrl_err(ctrl, "Failed to check link status\n"); 212 ctrl_err(ctrl, "Failed to check link status\n");
227 set_slot_off(ctrl, p_slot); 213 goto err_exit;
228 return retval;
229 } 214 }
230 215
231 /* Check for a power fault */ 216 /* Check for a power fault */
232 if (pciehp_query_power_fault(p_slot)) { 217 if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
233 ctrl_dbg(ctrl, "Power fault detected\n"); 218 ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
234 retval = -EIO; 219 retval = -EIO;
235 goto err_exit; 220 goto err_exit;
236 } 221 }
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 90dac515b60f..10040d58c8ef 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -511,15 +511,10 @@ int pciehp_power_on_slot(struct slot * slot)
511 return retval; 511 return retval;
512 } 512 }
513 } 513 }
514 ctrl->power_fault_detected = 0;
514 515
515 slot_cmd = POWER_ON; 516 slot_cmd = POWER_ON;
516 cmd_mask = PCI_EXP_SLTCTL_PCC; 517 cmd_mask = PCI_EXP_SLTCTL_PCC;
517 if (!pciehp_poll_mode) {
518 /* Enable power fault detection turned off at power off time */
519 slot_cmd |= PCI_EXP_SLTCTL_PFDE;
520 cmd_mask |= PCI_EXP_SLTCTL_PFDE;
521 }
522
523 retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); 518 retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
524 if (retval) { 519 if (retval) {
525 ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); 520 ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd);
@@ -528,7 +523,6 @@ int pciehp_power_on_slot(struct slot * slot)
528 ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, 523 ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
529 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); 524 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
530 525
531 ctrl->power_fault_detected = 0;
532 return retval; 526 return retval;
533} 527}
534 528
@@ -541,12 +535,6 @@ int pciehp_power_off_slot(struct slot * slot)
541 535
542 slot_cmd = POWER_OFF; 536 slot_cmd = POWER_OFF;
543 cmd_mask = PCI_EXP_SLTCTL_PCC; 537 cmd_mask = PCI_EXP_SLTCTL_PCC;
544 if (!pciehp_poll_mode) {
545 /* Disable power fault detection */
546 slot_cmd &= ~PCI_EXP_SLTCTL_PFDE;
547 cmd_mask |= PCI_EXP_SLTCTL_PFDE;
548 }
549
550 retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); 538 retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
551 if (retval) { 539 if (retval) {
552 ctrl_err(ctrl, "Write command failed!\n"); 540 ctrl_err(ctrl, "Write command failed!\n");
@@ -790,11 +778,19 @@ int pcie_enable_notification(struct controller *ctrl)
790{ 778{
791 u16 cmd, mask; 779 u16 cmd, mask;
792 780
781 /*
782 * TBD: Power fault detected software notification support.
783 *
784 * Power fault detected software notification is not enabled
785 * now, because it caused power fault detected interrupt storm
786 * on some machines. On those machines, power fault detected
787 * bit in the slot status register was set again immediately
788 * when it is cleared in the interrupt service routine, and
789 * next power fault detected interrupt was notified again.
790 */
793 cmd = PCI_EXP_SLTCTL_PDCE; 791 cmd = PCI_EXP_SLTCTL_PDCE;
794 if (ATTN_BUTTN(ctrl)) 792 if (ATTN_BUTTN(ctrl))
795 cmd |= PCI_EXP_SLTCTL_ABPE; 793 cmd |= PCI_EXP_SLTCTL_ABPE;
796 if (POWER_CTRL(ctrl))
797 cmd |= PCI_EXP_SLTCTL_PFDE;
798 if (MRL_SENS(ctrl)) 794 if (MRL_SENS(ctrl))
799 cmd |= PCI_EXP_SLTCTL_MRLSCE; 795 cmd |= PCI_EXP_SLTCTL_MRLSCE;
800 if (!pciehp_poll_mode) 796 if (!pciehp_poll_mode)