diff options
| -rw-r--r-- | drivers/pci/host/pcie-altera.c | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c index 2b7837650db8..58eef9963752 100644 --- a/drivers/pci/host/pcie-altera.c +++ b/drivers/pci/host/pcie-altera.c | |||
| @@ -61,7 +61,8 @@ | |||
| 61 | #define TLP_LOOP 500 | 61 | #define TLP_LOOP 500 |
| 62 | #define RP_DEVFN 0 | 62 | #define RP_DEVFN 0 |
| 63 | 63 | ||
| 64 | #define LINK_UP_TIMEOUT 5000 | 64 | #define LINK_UP_TIMEOUT HZ |
| 65 | #define LINK_RETRAIN_TIMEOUT HZ | ||
| 65 | 66 | ||
| 66 | #define INTX_NUM 4 | 67 | #define INTX_NUM 4 |
| 67 | 68 | ||
| @@ -99,11 +100,44 @@ static bool altera_pcie_link_is_up(struct altera_pcie *pcie) | |||
| 99 | return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); | 100 | return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); |
| 100 | } | 101 | } |
| 101 | 102 | ||
| 103 | static void altera_wait_link_retrain(struct pci_dev *dev) | ||
| 104 | { | ||
| 105 | u16 reg16; | ||
| 106 | unsigned long start_jiffies; | ||
| 107 | struct altera_pcie *pcie = dev->bus->sysdata; | ||
| 108 | |||
| 109 | /* Wait for link training end. */ | ||
| 110 | start_jiffies = jiffies; | ||
| 111 | for (;;) { | ||
| 112 | pcie_capability_read_word(dev, PCI_EXP_LNKSTA, ®16); | ||
| 113 | if (!(reg16 & PCI_EXP_LNKSTA_LT)) | ||
| 114 | break; | ||
| 115 | |||
| 116 | if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) { | ||
| 117 | dev_err(&pcie->pdev->dev, "link retrain timeout\n"); | ||
| 118 | break; | ||
| 119 | } | ||
| 120 | udelay(100); | ||
| 121 | } | ||
| 122 | |||
| 123 | /* Wait for link is up */ | ||
| 124 | start_jiffies = jiffies; | ||
| 125 | for (;;) { | ||
| 126 | if (altera_pcie_link_is_up(pcie)) | ||
| 127 | break; | ||
| 128 | |||
| 129 | if (time_after(jiffies, start_jiffies + LINK_UP_TIMEOUT)) { | ||
| 130 | dev_err(&pcie->pdev->dev, "link up timeout\n"); | ||
| 131 | break; | ||
| 132 | } | ||
| 133 | udelay(100); | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 102 | static void altera_pcie_retrain(struct pci_dev *dev) | 137 | static void altera_pcie_retrain(struct pci_dev *dev) |
| 103 | { | 138 | { |
| 104 | u16 linkcap, linkstat; | 139 | u16 linkcap, linkstat; |
| 105 | struct altera_pcie *pcie = dev->bus->sysdata; | 140 | struct altera_pcie *pcie = dev->bus->sysdata; |
| 106 | int timeout = 0; | ||
| 107 | 141 | ||
| 108 | if (!altera_pcie_link_is_up(pcie)) | 142 | if (!altera_pcie_link_is_up(pcie)) |
| 109 | return; | 143 | return; |
| @@ -121,12 +155,7 @@ static void altera_pcie_retrain(struct pci_dev *dev) | |||
| 121 | if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) { | 155 | if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) { |
| 122 | pcie_capability_set_word(dev, PCI_EXP_LNKCTL, | 156 | pcie_capability_set_word(dev, PCI_EXP_LNKCTL, |
| 123 | PCI_EXP_LNKCTL_RL); | 157 | PCI_EXP_LNKCTL_RL); |
| 124 | while (!altera_pcie_link_is_up(pcie)) { | 158 | altera_wait_link_retrain(dev); |
| 125 | timeout++; | ||
| 126 | if (timeout > LINK_UP_TIMEOUT) | ||
| 127 | break; | ||
| 128 | udelay(5); | ||
| 129 | } | ||
| 130 | } | 159 | } |
| 131 | } | 160 | } |
| 132 | DECLARE_PCI_FIXUP_EARLY(0x1172, PCI_ANY_ID, altera_pcie_retrain); | 161 | DECLARE_PCI_FIXUP_EARLY(0x1172, PCI_ANY_ID, altera_pcie_retrain); |
