|
@@ -619,33 +619,37 @@ static void pcie_disable_notification(struct controller *ctrl)
|
|
|
|
|
|
/*
|
|
|
* pciehp has a 1:1 bus:slot relationship so we ultimately want a secondary
|
|
|
- * bus reset of the bridge, but if the slot supports surprise removal we need
|
|
|
- * to disable presence detection around the bus reset and clear any spurious
|
|
|
+ * bus reset of the bridge, but if the slot supports surprise removal (or
|
|
|
+ * link state change based hotplug), we need to disable presence detection
|
|
|
+ * (or link state notifications) around the bus reset and clear any spurious
|
|
|
* events after.
|
|
|
*/
|
|
|
int pciehp_reset_slot(struct slot *slot, int probe)
|
|
|
{
|
|
|
struct controller *ctrl = slot->ctrl;
|
|
|
struct pci_dev *pdev = ctrl_dev(ctrl);
|
|
|
+ u16 stat_mask = 0, ctrl_mask = 0;
|
|
|
|
|
|
if (probe)
|
|
|
return 0;
|
|
|
|
|
|
- if (HP_SUPR_RM(ctrl)) {
|
|
|
- pcie_write_cmd(ctrl, 0, PCI_EXP_SLTCTL_PDCE);
|
|
|
- if (pciehp_poll_mode)
|
|
|
- del_timer_sync(&ctrl->poll_timer);
|
|
|
+ if (HP_SUPR_RM(ctrl) && !ATTN_BUTTN(ctrl)) {
|
|
|
+ ctrl_mask |= PCI_EXP_SLTCTL_PDCE;
|
|
|
+ stat_mask |= PCI_EXP_SLTSTA_PDC;
|
|
|
}
|
|
|
+ ctrl_mask |= PCI_EXP_SLTCTL_DLLSCE;
|
|
|
+ stat_mask |= PCI_EXP_SLTSTA_DLLSC;
|
|
|
+
|
|
|
+ pcie_write_cmd(ctrl, 0, ctrl_mask);
|
|
|
+ if (pciehp_poll_mode)
|
|
|
+ del_timer_sync(&ctrl->poll_timer);
|
|
|
|
|
|
pci_reset_bridge_secondary_bus(ctrl->pcie->port);
|
|
|
|
|
|
- if (HP_SUPR_RM(ctrl)) {
|
|
|
- pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
|
|
|
- PCI_EXP_SLTSTA_PDC);
|
|
|
- pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PDCE, PCI_EXP_SLTCTL_PDCE);
|
|
|
- if (pciehp_poll_mode)
|
|
|
- int_poll_timeout(ctrl->poll_timer.data);
|
|
|
- }
|
|
|
+ pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, stat_mask);
|
|
|
+ pcie_write_cmd(ctrl, ctrl_mask, ctrl_mask);
|
|
|
+ if (pciehp_poll_mode)
|
|
|
+ int_poll_timeout(ctrl->poll_timer.data);
|
|
|
|
|
|
return 0;
|
|
|
}
|