提交 99f0169c 编写于 作者: K Kenji Kaneshige 提交者: Jesse Barnes

PCI: pciehp: enable software notification on empty slots

Current pciehp disables software notification of adapter presence
changed event and MRL changed event when slot is turned off. Because
of this, there is no way to detect those events on empty slots in the
current pciehp implementation.

According to the past discussion(*), this behavior was introduced to
prevent endless loop that could happen if pcie_isr() runs after power
fault is detected on a certain platform whose stickey power-fault bit
remains on till the slot is powered on again.

(*) http://sourceforge.net/mailarchive/message.php?msg_id=20051130135409.A14918%40unix-os.sc.intel.com

I think this endless loop can be avoided using one bit flag that
indicates power fault had been detected, instead of disabling software
notification of adapter present changed event and MRL changed event.

With this patch, we can enable software notification mechanism of
presence changed and MRL changed event on the empty slots again.
Signed-off-by: NKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: NJesse Barnes <jbarnes@virtuousgeek.org>
上级 81b840cd
...@@ -112,6 +112,7 @@ struct controller { ...@@ -112,6 +112,7 @@ struct controller {
unsigned int no_cmd_complete:1; unsigned int no_cmd_complete:1;
unsigned int link_active_reporting:1; unsigned int link_active_reporting:1;
unsigned int notification_enabled:1; unsigned int notification_enabled:1;
unsigned int power_fault_detected;
}; };
#define INT_BUTTON_IGNORE 0 #define INT_BUTTON_IGNORE 0
......
...@@ -548,23 +548,21 @@ static int hpc_power_on_slot(struct slot * slot) ...@@ -548,23 +548,21 @@ static int hpc_power_on_slot(struct slot * slot)
slot_cmd = POWER_ON; slot_cmd = POWER_ON;
cmd_mask = PCI_EXP_SLTCTL_PCC; cmd_mask = PCI_EXP_SLTCTL_PCC;
/* Enable detection that we turned off at slot power-off time */
if (!pciehp_poll_mode) { if (!pciehp_poll_mode) {
slot_cmd |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | /* Enable power fault detection turned off at power off time */
PCI_EXP_SLTCTL_PDCE); slot_cmd |= PCI_EXP_SLTCTL_PFDE;
cmd_mask |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | cmd_mask |= PCI_EXP_SLTCTL_PFDE;
PCI_EXP_SLTCTL_PDCE);
} }
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
if (retval) { if (retval) {
ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd);
return -1; return retval;
} }
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
__func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
ctrl->power_fault_detected = 0;
return retval; return retval;
} }
...@@ -621,18 +619,10 @@ static int hpc_power_off_slot(struct slot * slot) ...@@ -621,18 +619,10 @@ static int hpc_power_off_slot(struct slot * slot)
slot_cmd = POWER_OFF; slot_cmd = POWER_OFF;
cmd_mask = PCI_EXP_SLTCTL_PCC; cmd_mask = PCI_EXP_SLTCTL_PCC;
/*
* If we get MRL or presence detect interrupts now, the isr
* will notice the sticky power-fault bit too and issue power
* indicator change commands. This will lead to an endless loop
* of command completions, since the power-fault bit remains on
* till the slot is powered on again.
*/
if (!pciehp_poll_mode) { if (!pciehp_poll_mode) {
slot_cmd &= ~(PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | /* Disable power fault detection */
PCI_EXP_SLTCTL_PDCE); slot_cmd &= ~PCI_EXP_SLTCTL_PFDE;
cmd_mask |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | cmd_mask |= PCI_EXP_SLTCTL_PFDE;
PCI_EXP_SLTCTL_PDCE);
} }
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
...@@ -710,9 +700,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) ...@@ -710,9 +700,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
pciehp_handle_presence_change(p_slot); pciehp_handle_presence_change(p_slot);
/* Check Power Fault Detected */ /* Check Power Fault Detected */
if (intr_loc & PCI_EXP_SLTSTA_PFD) if ((intr_loc & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) {
ctrl->power_fault_detected = 1;
pciehp_handle_power_fault(p_slot); pciehp_handle_power_fault(p_slot);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册