aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2012-01-27 13:55:15 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2012-02-14 11:45:02 -0500
commit2debd9289997fc5d1c0043b41201a8b40d5e11d0 (patch)
treea05fc1c9a3af920eb3f5844bcca0bfa878396d62 /drivers/pci
parent7f822999e12a144e68c915194267108f8051cf9b (diff)
PCI: pciehp: Disable/enable link during slot power off/on
On a system with a repeater on the system board to support gen2 hotplug, we found that when an ExpressModule is removed from some slots, /var/log/messages will be full of "card present/not present" warnings. It turns out the root complex is continually trying to train the link to the repeater because the repeater has not been reset. This patch will disable the link at removal time to allow the repeater to be reset properly. This also prevents a potential AER message at removal time. Also, when testing hotplug on a system under development, we found if we boot the system without an EM installed, and later hot-add an EM, it does not work with Linux, but another OS is ok. The root cause is that BIOS left link disabled when slot was empty at boot time, and other OS is modifying the link disable bit in link ctrl during power on/off. So we should do the same thing to disable/enable link during power off/on. -v2: check link DLLA bit instead of 100ms waiting. Separate link disable/enable functions to another patch. Signed-off-by: Yinghai Lu <yinghai.lu@oracle.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index db33688af588..a960faec1021 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -606,6 +606,10 @@ int pciehp_power_on_slot(struct slot * slot)
606 ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, 606 ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
607 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); 607 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
608 608
609 retval = pciehp_link_enable(ctrl);
610 if (retval)
611 ctrl_err(ctrl, "%s: Can not enable the link!\n", __func__);
612
609 return retval; 613 return retval;
610} 614}
611 615
@@ -616,6 +620,14 @@ int pciehp_power_off_slot(struct slot * slot)
616 u16 cmd_mask; 620 u16 cmd_mask;
617 int retval; 621 int retval;
618 622
623 /* Disable the link at first */
624 pciehp_link_disable(ctrl);
625 /* wait the link is down */
626 if (ctrl->link_active_reporting)
627 pcie_wait_link_not_active(ctrl);
628 else
629 msleep(1000);
630
619 slot_cmd = POWER_OFF; 631 slot_cmd = POWER_OFF;
620 cmd_mask = PCI_EXP_SLTCTL_PCC; 632 cmd_mask = PCI_EXP_SLTCTL_PCC;
621 retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); 633 retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);