aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2014-06-14 11:55:49 -0400
committerBjorn Helgaas <bhelgaas@google.com>2014-06-17 17:26:11 -0400
commit40b960831cfa8ee34d4b1035ddd7074bc5b01ecf (patch)
treef6949cff0740b6f9bae22e8bab44aa805124f1f5
parent3461a068661cd8b833ede63c5a5f089839ae98f8 (diff)
PCI: pciehp: Compute timeout from hotplug command start time
If we issue a hotplug command, go do something else, then come back and wait for the command to complete, we don't have to wait the whole timeout period, because some of it elapsed while we were doing something else. Keep track of the time we issued the command, and wait only until the timeout period from that point has elapsed. For controllers with errata like Intel CF118, we previously timed out before issuing the second hotplug command: At time T1 (during boot): - Write DLLSCE, ABPE, PDCE, etc. to Slot Control At time T2 (hotplug event): - Wait for command completion (CC) in Slot Status - Timeout at T2 + 1 second because CC is never set in Slot Status - Write PCC, PIC, etc. to Slot Control With this change, we wait until T1 + 1 second instead of T2 + 1 second. If the hotplug event is more than 1 second after the boot-time initialization, we won't wait for the timeout at all. We still emit a "Timeout on hotplug command" message if it timed out; we should see this on the first hotplug event on every controller with this erratum, as well as on real errors on controllers without the erratum. 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.h1
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c33
2 files changed, 29 insertions, 5 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index f7bc886c20be..c496258cd9a7 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -94,6 +94,7 @@ struct controller {
94 u32 slot_cap; 94 u32 slot_cap;
95 u32 slot_ctrl; 95 u32 slot_ctrl;
96 struct timer_list poll_timer; 96 struct timer_list poll_timer;
97 unsigned long cmd_started; /* jiffies */
97 unsigned int cmd_busy:1; 98 unsigned int cmd_busy:1;
98 unsigned int no_cmd_complete:1; 99 unsigned int no_cmd_complete:1;
99 unsigned int link_active_reporting:1; 100 unsigned int link_active_reporting:1;
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index b3e700d2a7f7..720dfe5fc48a 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -104,11 +104,10 @@ static inline void pciehp_free_irq(struct controller *ctrl)
104 free_irq(ctrl->pcie->irq, ctrl); 104 free_irq(ctrl->pcie->irq, ctrl);
105} 105}
106 106
107static int pcie_poll_cmd(struct controller *ctrl) 107static int pcie_poll_cmd(struct controller *ctrl, int timeout)
108{ 108{
109 struct pci_dev *pdev = ctrl_dev(ctrl); 109 struct pci_dev *pdev = ctrl_dev(ctrl);
110 u16 slot_status; 110 u16 slot_status;
111 int timeout = 1000;
112 111
113 pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); 112 pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
114 if (slot_status & PCI_EXP_SLTSTA_CC) { 113 if (slot_status & PCI_EXP_SLTSTA_CC) {
@@ -132,7 +131,9 @@ static int pcie_poll_cmd(struct controller *ctrl)
132static void pcie_wait_cmd(struct controller *ctrl) 131static void pcie_wait_cmd(struct controller *ctrl)
133{ 132{
134 unsigned int msecs = pciehp_poll_mode ? 2500 : 1000; 133 unsigned int msecs = pciehp_poll_mode ? 2500 : 1000;
135 unsigned long timeout = msecs_to_jiffies(msecs); 134 unsigned long duration = msecs_to_jiffies(msecs);
135 unsigned long cmd_timeout = ctrl->cmd_started + duration;
136 unsigned long now, timeout;
136 int rc; 137 int rc;
137 138
138 /* 139 /*
@@ -145,13 +146,34 @@ static void pcie_wait_cmd(struct controller *ctrl)
145 if (!ctrl->cmd_busy) 146 if (!ctrl->cmd_busy)
146 return; 147 return;
147 148
149 /*
150 * Even if the command has already timed out, we want to call
151 * pcie_poll_cmd() so it can clear PCI_EXP_SLTSTA_CC.
152 */
153 now = jiffies;
154 if (time_before_eq(cmd_timeout, now))
155 timeout = 1;
156 else
157 timeout = cmd_timeout - now;
158
148 if (ctrl->slot_ctrl & PCI_EXP_SLTCTL_HPIE && 159 if (ctrl->slot_ctrl & PCI_EXP_SLTCTL_HPIE &&
149 ctrl->slot_ctrl & PCI_EXP_SLTCTL_CCIE) 160 ctrl->slot_ctrl & PCI_EXP_SLTCTL_CCIE)
150 rc = wait_event_timeout(ctrl->queue, !ctrl->cmd_busy, timeout); 161 rc = wait_event_timeout(ctrl->queue, !ctrl->cmd_busy, timeout);
151 else 162 else
152 rc = pcie_poll_cmd(ctrl); 163 rc = pcie_poll_cmd(ctrl, timeout);
164
165 /*
166 * Controllers with errata like Intel CF118 don't generate
167 * completion notifications unless the power/indicator/interlock
168 * control bits are changed. On such controllers, we'll emit this
169 * timeout message when we wait for completion of commands that
170 * don't change those bits, e.g., commands that merely enable
171 * interrupts.
172 */
153 if (!rc) 173 if (!rc)
154 ctrl_dbg(ctrl, "Command not completed in 1000 msec\n"); 174 ctrl_info(ctrl, "Timeout on hotplug command %#010x (issued %u msec ago)\n",
175 ctrl->slot_ctrl,
176 jiffies_to_msecs(now - ctrl->cmd_started));
155} 177}
156 178
157/** 179/**
@@ -201,6 +223,7 @@ static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
201 ctrl->cmd_busy = 1; 223 ctrl->cmd_busy = 1;
202 smp_mb(); 224 smp_mb();
203 pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl); 225 pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl);
226 ctrl->cmd_started = jiffies;
204 ctrl->slot_ctrl = slot_ctrl; 227 ctrl->slot_ctrl = slot_ctrl;
205 228
206 mutex_unlock(&ctrl->ctrl_lock); 229 mutex_unlock(&ctrl->ctrl_lock);