aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pciehp_hpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/pciehp_hpc.c')
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index b2255736ac81..51f56ef4ab6f 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -749,6 +749,37 @@ static void pcie_disable_notification(struct controller *ctrl)
749 ctrl_warn(ctrl, "Cannot disable software notification\n"); 749 ctrl_warn(ctrl, "Cannot disable software notification\n");
750} 750}
751 751
752/*
753 * pciehp has a 1:1 bus:slot relationship so we ultimately want a secondary
754 * bus reset of the bridge, but if the slot supports surprise removal we need
755 * to disable presence detection around the bus reset and clear any spurious
756 * events after.
757 */
758int pciehp_reset_slot(struct slot *slot, int probe)
759{
760 struct controller *ctrl = slot->ctrl;
761
762 if (probe)
763 return 0;
764
765 if (HP_SUPR_RM(ctrl)) {
766 pcie_write_cmd(ctrl, 0, PCI_EXP_SLTCTL_PDCE);
767 if (pciehp_poll_mode)
768 del_timer_sync(&ctrl->poll_timer);
769 }
770
771 pci_reset_bridge_secondary_bus(ctrl->pcie->port);
772
773 if (HP_SUPR_RM(ctrl)) {
774 pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDC);
775 pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PDCE, PCI_EXP_SLTCTL_PDCE);
776 if (pciehp_poll_mode)
777 int_poll_timeout(ctrl->poll_timer.data);
778 }
779
780 return 0;
781}
782
752int pcie_init_notification(struct controller *ctrl) 783int pcie_init_notification(struct controller *ctrl)
753{ 784{
754 if (pciehp_request_irq(ctrl)) 785 if (pciehp_request_irq(ctrl))