summaryrefslogtreecommitdiff
path: root/drivers/pci/hotplug/pciehp_hpc.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2014-06-13 15:06:40 -0600
committerBjorn Helgaas <bhelgaas@google.com>2014-06-17 15:26:02 -0600
commit3461a068661cd8b833ede63c5a5f089839ae98f8 (patch)
tree227621f9802769da14584ff3809684141343295a /drivers/pci/hotplug/pciehp_hpc.c
parent4283c70e91dcabe36f3545afabc5ee2b7d4da34a (diff)
PCI: pciehp: Wait for hotplug command completion lazily
Previously we issued a hotplug command and waited for it to complete. But there's no need to wait until we're ready to issue the *next* command. The next command will probably be much later, so the first one may have already completed and we may not have to actually wait at all. Because of hardware errata, some controllers generate command completion events for some commands but not others. In the case of Intel CF118 (see spec update reference), the controller indicates command completion only for Slot Control writes that change the value of the following bits: Power Controller Control Power Indicator Control Attention Indicator Control Electromechanical Interlock Control Changes to other bits, e.g., the interrupt enable bits, do not cause the Command Completed bit to be set. Controllers from AMD and Nvidia are reported to have similar errata. These errata cause timeouts when pcie_enable_notification() enables interrupts. Previously that timeout occurred at boot-time. With this change, the timeout occurs later, when we change the state of the slot power, indicators, or interlock. This speeds up boot but causes a timeout at the first hotplug event on the slot. Subsequent events don't timeout because only the first (boot-time) hotplug command updates Slot Control without touching the power/indicator/interlock controls. Link: http://www.intel.com/content/www/us/en/processors/xeon/xeon-e7-v2-spec-update.html Tested-by: Rajat Jain <rajatxjain@gmail.com> (IDT 807a controller) Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Yinghai Lu <yinghai@kernel.org>
Diffstat (limited to 'drivers/pci/hotplug/pciehp_hpc.c')
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c7
1 files changed, 3 insertions, 4 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 7c2a9dd6f6a4..b3e700d2a7f7 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -168,6 +168,9 @@ static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
mutex_lock(&ctrl->ctrl_lock);
+ /* Wait for any previous command that might still be in progress */
+ pcie_wait_cmd(ctrl);
+
pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
if (slot_status & PCI_EXP_SLTSTA_CC) {
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
@@ -200,10 +203,6 @@ static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl);
ctrl->slot_ctrl = slot_ctrl;
- /*
- * Wait for command completion.
- */
- pcie_wait_cmd(ctrl);
mutex_unlock(&ctrl->ctrl_lock);
}