Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: Use msleep instead of cpu_relax during ASPM link retraining

The cpu_relax() function can be a noop on certain architectures like
IA-64 when CPU threads are disabled, so use msleep instead during link
retraining busy/wait loop.

Introduce define LINK_RETRAIN_TIMEOUT instead of hard-coding timeout in
pcie_aspm_configure_common_clock.

Use time_after() to avoid jiffy wraparound when checking for expired
timeout.

After timeout expires, recheck link status register link training bit
instead of checking for expired timeout to avoid possible false
positive.

Note that Matthew Wilcox came up with the first rough version of this
patch.

Reviewed-by: Matthew Wilcox <willy@linux.intel.com>
Signed-off-by: Andrew Patterson <andrew.patterson@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

authored by

Andrew Patterson and committed by
Jesse Barnes
987a4c78 d9347371

+9 -4
+9 -4
drivers/pci/pcie/aspm.c
··· 17 17 #include <linux/init.h> 18 18 #include <linux/slab.h> 19 19 #include <linux/jiffies.h> 20 + #include <linux/delay.h> 20 21 #include <linux/pci-aspm.h> 21 22 #include "../pci.h" 22 23 ··· 75 74 [POLICY_PERFORMANCE] = "performance", 76 75 [POLICY_POWERSAVE] = "powersave" 77 76 }; 77 + 78 + #define LINK_RETRAIN_TIMEOUT HZ 78 79 79 80 static int policy_to_aspm_state(struct pci_dev *pdev) 80 81 { ··· 241 238 pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); 242 239 243 240 /* Wait for link training end */ 244 - /* break out after waiting for 1 second */ 241 + /* break out after waiting for timeout */ 245 242 start_jiffies = jiffies; 246 - while ((jiffies - start_jiffies) < HZ) { 243 + for (;;) { 247 244 pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16); 248 245 if (!(reg16 & PCI_EXP_LNKSTA_LT)) 249 246 break; 250 - cpu_relax(); 247 + if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) 248 + break; 249 + msleep(1); 251 250 } 252 251 /* training failed -> recover */ 253 - if ((jiffies - start_jiffies) >= HZ) { 252 + if (reg16 & PCI_EXP_LNKSTA_LT) { 254 253 dev_printk (KERN_ERR, &pdev->dev, "ASPM: Could not configure" 255 254 " common clock\n"); 256 255 i = 0;