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: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
Родитель
81b840cd27
Коммит
99f0169c17
|
@ -112,6 +112,7 @@ struct controller {
|
|||
unsigned int no_cmd_complete:1;
|
||||
unsigned int link_active_reporting:1;
|
||||
unsigned int notification_enabled:1;
|
||||
unsigned int power_fault_detected;
|
||||
};
|
||||
|
||||
#define INT_BUTTON_IGNORE 0
|
||||
|
|
|
@ -548,23 +548,21 @@ static int hpc_power_on_slot(struct slot * slot)
|
|||
|
||||
slot_cmd = POWER_ON;
|
||||
cmd_mask = PCI_EXP_SLTCTL_PCC;
|
||||
/* Enable detection that we turned off at slot power-off time */
|
||||
if (!pciehp_poll_mode) {
|
||||
slot_cmd |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE |
|
||||
PCI_EXP_SLTCTL_PDCE);
|
||||
cmd_mask |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE |
|
||||
PCI_EXP_SLTCTL_PDCE);
|
||||
/* 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);
|
||||
return -1;
|
||||
return retval;
|
||||
}
|
||||
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
|
||||
__func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
|
||||
|
||||
ctrl->power_fault_detected = 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -621,18 +619,10 @@ static int hpc_power_off_slot(struct slot * slot)
|
|||
|
||||
slot_cmd = POWER_OFF;
|
||||
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) {
|
||||
slot_cmd &= ~(PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE |
|
||||
PCI_EXP_SLTCTL_PDCE);
|
||||
cmd_mask |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE |
|
||||
PCI_EXP_SLTCTL_PDCE);
|
||||
/* 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);
|
||||
|
@ -710,9 +700,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
|
|||
pciehp_handle_presence_change(p_slot);
|
||||
|
||||
/* 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);
|
||||
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче