aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pciehp_hpc.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2012-01-27 13:55:11 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2012-02-14 11:45:00 -0500
commit2f5d8e4ff947ad6673397083b48719cd6c59cd61 (patch)
tree46e1c6901937b7f983b511d6e14498000e2989bb /drivers/pci/hotplug/pciehp_hpc.c
parentefdc87dab1cdf25ba631181ac0ead3fb2023dd10 (diff)
PCI: pciehp: replace unconditional sleep with config space access check
During reviewing | PCI: pciehp: wait 1000 ms before Link Training check Linus said: >... > That's a *long* time, and it's irritating to the user. It makes the > user think "the machine is slow". >... > And quite frankly, an unconditional one-second delay here seems bad. >Two seconds was unacceptable, one second is just bad. Try to access the pci conf of a pci device that is supposed to show up in 1s. If we can read back a valid vendor/device id, we can return early. Related discussion could be found: https://lkml.org/lkml/2011/12/6/339 -v2: seperate code to pci_bus_read_dev_vendor_id() from pci_scan_device() and reuse it from pciehp code. Suggested by Matthew Wilcox. -v3: According to Kenj, don't use array in stack, and don't wait too long for crs, also return fail status if not found. Also separate pci_bus_dev_read_vendor_id() change to another patch. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/hotplug/pciehp_hpc.c')
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c49
1 files changed, 34 insertions, 15 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index bcdbb1643621..7dc9e33746a6 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -265,10 +265,37 @@ static void pcie_wait_link_active(struct controller *ctrl)
265 ctrl_dbg(ctrl, "Data Link Layer Link Active not set in 1000 msec\n"); 265 ctrl_dbg(ctrl, "Data Link Layer Link Active not set in 1000 msec\n");
266} 266}
267 267
268static bool pci_bus_check_dev(struct pci_bus *bus, int devfn)
269{
270 u32 l;
271 int count = 0;
272 int delay = 1000, step = 20;
273 bool found = false;
274
275 do {
276 found = pci_bus_read_dev_vendor_id(bus, devfn, &l, 0);
277 count++;
278
279 if (found)
280 break;
281
282 msleep(step);
283 delay -= step;
284 } while (delay > 0);
285
286 if (count > 1 && pciehp_debug)
287 printk(KERN_DEBUG "pci %04x:%02x:%02x.%d id reading try %d times with interval %d ms to get %08x\n",
288 pci_domain_nr(bus), bus->number, PCI_SLOT(devfn),
289 PCI_FUNC(devfn), count, step, l);
290
291 return found;
292}
293
268int pciehp_check_link_status(struct controller *ctrl) 294int pciehp_check_link_status(struct controller *ctrl)
269{ 295{
270 u16 lnk_status; 296 u16 lnk_status;
271 int retval = 0; 297 int retval = 0;
298 bool found = false;
272 299
273 /* 300 /*
274 * Data Link Layer Link Active Reporting must be capable for 301 * Data Link Layer Link Active Reporting must be capable for
@@ -280,13 +307,10 @@ int pciehp_check_link_status(struct controller *ctrl)
280 else 307 else
281 msleep(1000); 308 msleep(1000);
282 309
283 /* 310 /* wait 100ms before read pci conf, and try in 1s */
284 * Need to wait for 1000 ms after Data Link Layer Link Active 311 msleep(100);
285 * (DLLLA) bit reads 1b before sending configuration request. 312 found = pci_bus_check_dev(ctrl->pcie->port->subordinate,
286 * We need it before checking Link Training (LT) bit becuase 313 PCI_DEVFN(0, 0));
287 * LT is still set even after DLLLA bit is set on some platform.
288 */
289 msleep(1000);
290 314
291 retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); 315 retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
292 if (retval) { 316 if (retval) {
@@ -302,16 +326,11 @@ int pciehp_check_link_status(struct controller *ctrl)
302 return retval; 326 return retval;
303 } 327 }
304 328
305 /*
306 * If the port supports Link speeds greater than 5.0 GT/s, we
307 * must wait for 100 ms after Link training completes before
308 * sending configuration request.
309 */
310 if (ctrl->pcie->port->subordinate->max_bus_speed > PCIE_SPEED_5_0GT)
311 msleep(100);
312
313 pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status); 329 pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
314 330
331 if (!found && !retval)
332 retval = -1;
333
315 return retval; 334 return retval;
316} 335}
317 336