aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2014-06-13 17:06:40 -0400
committerBjorn Helgaas <bhelgaas@google.com>2014-06-17 17:26:02 -0400
commit3461a068661cd8b833ede63c5a5f089839ae98f8 (patch)
tree227621f9802769da14584ff3809684141343295a
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>
-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)
168 168
169 mutex_lock(&ctrl->ctrl_lock); 169 mutex_lock(&ctrl->ctrl_lock);
170 170
171 /* Wait for any previous command that might still be in progress */
172 pcie_wait_cmd(ctrl);
173
171 pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); 174 pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
172 if (slot_status & PCI_EXP_SLTSTA_CC) { 175 if (slot_status & PCI_EXP_SLTSTA_CC) {
173 pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, 176 pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
@@ -200,10 +203,6 @@ static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
200 pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl); 203 pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl);
201 ctrl->slot_ctrl = slot_ctrl; 204 ctrl->slot_ctrl = slot_ctrl;
202 205
203 /*
204 * Wait for command completion.
205 */
206 pcie_wait_cmd(ctrl);
207 mutex_unlock(&ctrl->ctrl_lock); 206 mutex_unlock(&ctrl->ctrl_lock);
208} 207}
209 208