aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorRajat Jain <rajatxjain@gmail.com>2014-02-04 21:30:40 -0500
committerBjorn Helgaas <bhelgaas@google.com>2014-02-11 18:13:01 -0500
commit06a8d89af551b6151fa2289dd8660647ea9d2faa (patch)
tree59c7425efbb769d79fbd2f3fb48dedff2559817d /drivers/pci
parent02e93a8a7c1dcecc1a33ea762a0c041cbb6a0a66 (diff)
PCI: pciehp: Disable link notification across slot reset
Disable the link notification (in addition to presence detect notifications) across the slot reset since the reset could flap the link, and we don't want to treat it as hot unplug followed by a hotplug. Signed-off-by: Rajat Jain <rajatxjain@gmail.com> Signed-off-by: Rajat Jain <rajatjain@juniper.net> Signed-off-by: Guenter Roeck <groeck@juniper.net> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c30
1 files changed, 17 insertions, 13 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 15ca3a1cad8d..6433e73aa2df 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -619,33 +619,37 @@ static void pcie_disable_notification(struct controller *ctrl)
619 619
620/* 620/*
621 * pciehp has a 1:1 bus:slot relationship so we ultimately want a secondary 621 * pciehp has a 1:1 bus:slot relationship so we ultimately want a secondary
622 * bus reset of the bridge, but if the slot supports surprise removal we need 622 * bus reset of the bridge, but if the slot supports surprise removal (or
623 * to disable presence detection around the bus reset and clear any spurious 623 * link state change based hotplug), we need to disable presence detection
624 * (or link state notifications) around the bus reset and clear any spurious
624 * events after. 625 * events after.
625 */ 626 */
626int pciehp_reset_slot(struct slot *slot, int probe) 627int pciehp_reset_slot(struct slot *slot, int probe)
627{ 628{
628 struct controller *ctrl = slot->ctrl; 629 struct controller *ctrl = slot->ctrl;
629 struct pci_dev *pdev = ctrl_dev(ctrl); 630 struct pci_dev *pdev = ctrl_dev(ctrl);
631 u16 stat_mask = 0, ctrl_mask = 0;
630 632
631 if (probe) 633 if (probe)
632 return 0; 634 return 0;
633 635
634 if (HP_SUPR_RM(ctrl)) { 636 if (HP_SUPR_RM(ctrl) && !ATTN_BUTTN(ctrl)) {
635 pcie_write_cmd(ctrl, 0, PCI_EXP_SLTCTL_PDCE); 637 ctrl_mask |= PCI_EXP_SLTCTL_PDCE;
636 if (pciehp_poll_mode) 638 stat_mask |= PCI_EXP_SLTSTA_PDC;
637 del_timer_sync(&ctrl->poll_timer);
638 } 639 }
640 ctrl_mask |= PCI_EXP_SLTCTL_DLLSCE;
641 stat_mask |= PCI_EXP_SLTSTA_DLLSC;
642
643 pcie_write_cmd(ctrl, 0, ctrl_mask);
644 if (pciehp_poll_mode)
645 del_timer_sync(&ctrl->poll_timer);
639 646
640 pci_reset_bridge_secondary_bus(ctrl->pcie->port); 647 pci_reset_bridge_secondary_bus(ctrl->pcie->port);
641 648
642 if (HP_SUPR_RM(ctrl)) { 649 pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, stat_mask);
643 pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, 650 pcie_write_cmd(ctrl, ctrl_mask, ctrl_mask);
644 PCI_EXP_SLTSTA_PDC); 651 if (pciehp_poll_mode)
645 pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PDCE, PCI_EXP_SLTCTL_PDCE); 652 int_poll_timeout(ctrl->poll_timer.data);
646 if (pciehp_poll_mode)
647 int_poll_timeout(ctrl->poll_timer.data);
648 }
649 653
650 return 0; 654 return 0;
651} 655}