Skip to content

Commit

Permalink
PCI pciehp: fix power fault interrupt storm problem
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Kenji Kaneshige authored and Jesse Barnes committed Nov 24, 2009
1 parent 1359837 commit 5651c48
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 36 deletions.
27 changes: 6 additions & 21 deletions drivers/pci/hotplug/pciehp_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,23 +142,9 @@ u8 pciehp_handle_power_fault(struct slot *p_slot)

/* power fault */
ctrl_dbg(ctrl, "Power fault interrupt received\n");

if (!pciehp_query_power_fault(p_slot)) {
/*
* power fault Cleared
*/
ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n",
slot_name(p_slot));
event_type = INT_POWER_FAULT_CLEAR;
} else {
/*
* power fault
*/
ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot));
event_type = INT_POWER_FAULT;
ctrl_info(ctrl, "Power fault bit %x set\n", 0);
}

ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
event_type = INT_POWER_FAULT;
ctrl_info(ctrl, "Power fault bit %x set\n", 0);
queue_interrupt_event(p_slot, event_type);

return 1;
Expand Down Expand Up @@ -224,13 +210,12 @@ static int board_added(struct slot *p_slot)
retval = pciehp_check_link_status(ctrl);
if (retval) {
ctrl_err(ctrl, "Failed to check link status\n");
set_slot_off(ctrl, p_slot);
return retval;
goto err_exit;
}

/* Check for a power fault */
if (pciehp_query_power_fault(p_slot)) {
ctrl_dbg(ctrl, "Power fault detected\n");
if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
retval = -EIO;
goto err_exit;
}
Expand Down
26 changes: 11 additions & 15 deletions drivers/pci/hotplug/pciehp_hpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -511,15 +511,10 @@ int pciehp_power_on_slot(struct slot * slot)
return retval;
}
}
ctrl->power_fault_detected = 0;

slot_cmd = POWER_ON;
cmd_mask = PCI_EXP_SLTCTL_PCC;
if (!pciehp_poll_mode) {
/* Enable power fault detection turned off at power off time */
slot_cmd |= PCI_EXP_SLTCTL_PFDE;
cmd_mask |= PCI_EXP_SLTCTL_PFDE;
}

retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
if (retval) {
ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd);
Expand All @@ -528,7 +523,6 @@ int pciehp_power_on_slot(struct slot * slot)
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);

ctrl->power_fault_detected = 0;
return retval;
}

Expand All @@ -541,12 +535,6 @@ int pciehp_power_off_slot(struct slot * slot)

slot_cmd = POWER_OFF;
cmd_mask = PCI_EXP_SLTCTL_PCC;
if (!pciehp_poll_mode) {
/* Disable power fault detection */
slot_cmd &= ~PCI_EXP_SLTCTL_PFDE;
cmd_mask |= PCI_EXP_SLTCTL_PFDE;
}

retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
if (retval) {
ctrl_err(ctrl, "Write command failed!\n");
Expand Down Expand Up @@ -790,11 +778,19 @@ int pcie_enable_notification(struct controller *ctrl)
{
u16 cmd, mask;

/*
* TBD: Power fault detected software notification support.
*
* Power fault detected software notification is not enabled
* now, because it caused power fault detected interrupt storm
* on some 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.
*/
cmd = PCI_EXP_SLTCTL_PDCE;
if (ATTN_BUTTN(ctrl))
cmd |= PCI_EXP_SLTCTL_ABPE;
if (POWER_CTRL(ctrl))
cmd |= PCI_EXP_SLTCTL_PFDE;
if (MRL_SENS(ctrl))
cmd |= PCI_EXP_SLTCTL_MRLSCE;
if (!pciehp_poll_mode)
Expand Down

0 comments on commit 5651c48

Please sign in to comment.