aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorAndrew Patterson <andrew.patterson@hp.com>2009-01-05 18:21:04 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-01-07 14:13:28 -0500
commit987a4c783a8bbf3baf554e6b8ff588b26e06e020 (patch)
tree68cae4e999c8f318bf3f95ff703d36699b2061ab /drivers/pci
parentd9347371c538544a7309d5b6475ec011d98d40e6 (diff)
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>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pcie/aspm.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 4d8e2c7b2ad1..586b6f75910d 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -17,6 +17,7 @@
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/jiffies.h> 19#include <linux/jiffies.h>
20#include <linux/delay.h>
20#include <linux/pci-aspm.h> 21#include <linux/pci-aspm.h>
21#include "../pci.h" 22#include "../pci.h"
22 23
@@ -75,6 +76,8 @@ static const char *policy_str[] = {
75 [POLICY_POWERSAVE] = "powersave" 76 [POLICY_POWERSAVE] = "powersave"
76}; 77};
77 78
79#define LINK_RETRAIN_TIMEOUT HZ
80
78static int policy_to_aspm_state(struct pci_dev *pdev) 81static int policy_to_aspm_state(struct pci_dev *pdev)
79{ 82{
80 struct pcie_link_state *link_state = pdev->link_state; 83 struct pcie_link_state *link_state = pdev->link_state;
@@ -238,16 +241,18 @@ static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
238 pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); 241 pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
239 242
240 /* Wait for link training end */ 243 /* Wait for link training end */
241 /* break out after waiting for 1 second */ 244 /* break out after waiting for timeout */
242 start_jiffies = jiffies; 245 start_jiffies = jiffies;
243 while ((jiffies - start_jiffies) < HZ) { 246 for (;;) {
244 pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16); 247 pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
245 if (!(reg16 & PCI_EXP_LNKSTA_LT)) 248 if (!(reg16 & PCI_EXP_LNKSTA_LT))
246 break; 249 break;
247 cpu_relax(); 250 if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT))
251 break;
252 msleep(1);
248 } 253 }
249 /* training failed -> recover */ 254 /* training failed -> recover */
250 if ((jiffies - start_jiffies) >= HZ) { 255 if (reg16 & PCI_EXP_LNKSTA_LT) {
251 dev_printk (KERN_ERR, &pdev->dev, "ASPM: Could not configure" 256 dev_printk (KERN_ERR, &pdev->dev, "ASPM: Could not configure"
252 " common clock\n"); 257 " common clock\n");
253 i = 0; 258 i = 0;