diff options
author | Jiang Liu <jiang.liu@huawei.com> | 2012-07-24 05:20:12 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2012-08-23 12:11:12 -0400 |
commit | f12eb72a268ba57d23fa5afd987210521cfe73e6 (patch) | |
tree | 4a0461213c585f13fdb836c8ba9613c10d5c1852 /drivers/pci | |
parent | 43bd4ee89f748111d2a0443e6ef58f08ceb359aa (diff) |
PCI/ASPM: Use PCI Express Capability accessors
Use PCI Express Capability access functions to simplify PCIe ASPM.
Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Signed-off-by: Yijing Wang <wangyijing@huawei.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pcie/aspm.c | 77 |
1 files changed, 26 insertions, 51 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 25916034c0ae..213753b283a6 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -125,21 +125,16 @@ static int policy_to_clkpm_state(struct pcie_link_state *link) | |||
125 | 125 | ||
126 | static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable) | 126 | static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable) |
127 | { | 127 | { |
128 | int pos; | ||
129 | u16 reg16; | ||
130 | struct pci_dev *child; | 128 | struct pci_dev *child; |
131 | struct pci_bus *linkbus = link->pdev->subordinate; | 129 | struct pci_bus *linkbus = link->pdev->subordinate; |
132 | 130 | ||
133 | list_for_each_entry(child, &linkbus->devices, bus_list) { | 131 | list_for_each_entry(child, &linkbus->devices, bus_list) { |
134 | pos = pci_pcie_cap(child); | ||
135 | if (!pos) | ||
136 | return; | ||
137 | pci_read_config_word(child, pos + PCI_EXP_LNKCTL, ®16); | ||
138 | if (enable) | 132 | if (enable) |
139 | reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN; | 133 | pcie_capability_set_word(child, PCI_EXP_LNKCTL, |
134 | PCI_EXP_LNKCTL_CLKREQ_EN); | ||
140 | else | 135 | else |
141 | reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN; | 136 | pcie_capability_clear_word(child, PCI_EXP_LNKCTL, |
142 | pci_write_config_word(child, pos + PCI_EXP_LNKCTL, reg16); | 137 | PCI_EXP_LNKCTL_CLKREQ_EN); |
143 | } | 138 | } |
144 | link->clkpm_enabled = !!enable; | 139 | link->clkpm_enabled = !!enable; |
145 | } | 140 | } |
@@ -157,7 +152,7 @@ static void pcie_set_clkpm(struct pcie_link_state *link, int enable) | |||
157 | 152 | ||
158 | static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) | 153 | static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) |
159 | { | 154 | { |
160 | int pos, capable = 1, enabled = 1; | 155 | int capable = 1, enabled = 1; |
161 | u32 reg32; | 156 | u32 reg32; |
162 | u16 reg16; | 157 | u16 reg16; |
163 | struct pci_dev *child; | 158 | struct pci_dev *child; |
@@ -165,16 +160,13 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) | |||
165 | 160 | ||
166 | /* All functions should have the same cap and state, take the worst */ | 161 | /* All functions should have the same cap and state, take the worst */ |
167 | list_for_each_entry(child, &linkbus->devices, bus_list) { | 162 | list_for_each_entry(child, &linkbus->devices, bus_list) { |
168 | pos = pci_pcie_cap(child); | 163 | pcie_capability_read_dword(child, PCI_EXP_LNKCAP, ®32); |
169 | if (!pos) | ||
170 | return; | ||
171 | pci_read_config_dword(child, pos + PCI_EXP_LNKCAP, ®32); | ||
172 | if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) { | 164 | if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) { |
173 | capable = 0; | 165 | capable = 0; |
174 | enabled = 0; | 166 | enabled = 0; |
175 | break; | 167 | break; |
176 | } | 168 | } |
177 | pci_read_config_word(child, pos + PCI_EXP_LNKCTL, ®16); | 169 | pcie_capability_read_word(child, PCI_EXP_LNKCTL, ®16); |
178 | if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN)) | 170 | if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN)) |
179 | enabled = 0; | 171 | enabled = 0; |
180 | } | 172 | } |
@@ -190,7 +182,7 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) | |||
190 | */ | 182 | */ |
191 | static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) | 183 | static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) |
192 | { | 184 | { |
193 | int ppos, cpos, same_clock = 1; | 185 | int same_clock = 1; |
194 | u16 reg16, parent_reg, child_reg[8]; | 186 | u16 reg16, parent_reg, child_reg[8]; |
195 | unsigned long start_jiffies; | 187 | unsigned long start_jiffies; |
196 | struct pci_dev *child, *parent = link->pdev; | 188 | struct pci_dev *child, *parent = link->pdev; |
@@ -203,46 +195,43 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) | |||
203 | BUG_ON(!pci_is_pcie(child)); | 195 | BUG_ON(!pci_is_pcie(child)); |
204 | 196 | ||
205 | /* Check downstream component if bit Slot Clock Configuration is 1 */ | 197 | /* Check downstream component if bit Slot Clock Configuration is 1 */ |
206 | cpos = pci_pcie_cap(child); | 198 | pcie_capability_read_word(child, PCI_EXP_LNKSTA, ®16); |
207 | pci_read_config_word(child, cpos + PCI_EXP_LNKSTA, ®16); | ||
208 | if (!(reg16 & PCI_EXP_LNKSTA_SLC)) | 199 | if (!(reg16 & PCI_EXP_LNKSTA_SLC)) |
209 | same_clock = 0; | 200 | same_clock = 0; |
210 | 201 | ||
211 | /* Check upstream component if bit Slot Clock Configuration is 1 */ | 202 | /* Check upstream component if bit Slot Clock Configuration is 1 */ |
212 | ppos = pci_pcie_cap(parent); | 203 | pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16); |
213 | pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, ®16); | ||
214 | if (!(reg16 & PCI_EXP_LNKSTA_SLC)) | 204 | if (!(reg16 & PCI_EXP_LNKSTA_SLC)) |
215 | same_clock = 0; | 205 | same_clock = 0; |
216 | 206 | ||
217 | /* Configure downstream component, all functions */ | 207 | /* Configure downstream component, all functions */ |
218 | list_for_each_entry(child, &linkbus->devices, bus_list) { | 208 | list_for_each_entry(child, &linkbus->devices, bus_list) { |
219 | cpos = pci_pcie_cap(child); | 209 | pcie_capability_read_word(child, PCI_EXP_LNKCTL, ®16); |
220 | pci_read_config_word(child, cpos + PCI_EXP_LNKCTL, ®16); | ||
221 | child_reg[PCI_FUNC(child->devfn)] = reg16; | 210 | child_reg[PCI_FUNC(child->devfn)] = reg16; |
222 | if (same_clock) | 211 | if (same_clock) |
223 | reg16 |= PCI_EXP_LNKCTL_CCC; | 212 | reg16 |= PCI_EXP_LNKCTL_CCC; |
224 | else | 213 | else |
225 | reg16 &= ~PCI_EXP_LNKCTL_CCC; | 214 | reg16 &= ~PCI_EXP_LNKCTL_CCC; |
226 | pci_write_config_word(child, cpos + PCI_EXP_LNKCTL, reg16); | 215 | pcie_capability_write_word(child, PCI_EXP_LNKCTL, reg16); |
227 | } | 216 | } |
228 | 217 | ||
229 | /* Configure upstream component */ | 218 | /* Configure upstream component */ |
230 | pci_read_config_word(parent, ppos + PCI_EXP_LNKCTL, ®16); | 219 | pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16); |
231 | parent_reg = reg16; | 220 | parent_reg = reg16; |
232 | if (same_clock) | 221 | if (same_clock) |
233 | reg16 |= PCI_EXP_LNKCTL_CCC; | 222 | reg16 |= PCI_EXP_LNKCTL_CCC; |
234 | else | 223 | else |
235 | reg16 &= ~PCI_EXP_LNKCTL_CCC; | 224 | reg16 &= ~PCI_EXP_LNKCTL_CCC; |
236 | pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, reg16); | 225 | pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); |
237 | 226 | ||
238 | /* Retrain link */ | 227 | /* Retrain link */ |
239 | reg16 |= PCI_EXP_LNKCTL_RL; | 228 | reg16 |= PCI_EXP_LNKCTL_RL; |
240 | pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, reg16); | 229 | pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); |
241 | 230 | ||
242 | /* Wait for link training end. Break out after waiting for timeout */ | 231 | /* Wait for link training end. Break out after waiting for timeout */ |
243 | start_jiffies = jiffies; | 232 | start_jiffies = jiffies; |
244 | for (;;) { | 233 | for (;;) { |
245 | pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, ®16); | 234 | pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16); |
246 | if (!(reg16 & PCI_EXP_LNKSTA_LT)) | 235 | if (!(reg16 & PCI_EXP_LNKSTA_LT)) |
247 | break; | 236 | break; |
248 | if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) | 237 | if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) |
@@ -255,12 +244,10 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) | |||
255 | /* Training failed. Restore common clock configurations */ | 244 | /* Training failed. Restore common clock configurations */ |
256 | dev_printk(KERN_ERR, &parent->dev, | 245 | dev_printk(KERN_ERR, &parent->dev, |
257 | "ASPM: Could not configure common clock\n"); | 246 | "ASPM: Could not configure common clock\n"); |
258 | list_for_each_entry(child, &linkbus->devices, bus_list) { | 247 | list_for_each_entry(child, &linkbus->devices, bus_list) |
259 | cpos = pci_pcie_cap(child); | 248 | pcie_capability_write_word(child, PCI_EXP_LNKCTL, |
260 | pci_write_config_word(child, cpos + PCI_EXP_LNKCTL, | 249 | child_reg[PCI_FUNC(child->devfn)]); |
261 | child_reg[PCI_FUNC(child->devfn)]); | 250 | pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); |
262 | } | ||
263 | pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, parent_reg); | ||
264 | } | 251 | } |
265 | 252 | ||
266 | /* Convert L0s latency encoding to ns */ | 253 | /* Convert L0s latency encoding to ns */ |
@@ -305,16 +292,14 @@ struct aspm_register_info { | |||
305 | static void pcie_get_aspm_reg(struct pci_dev *pdev, | 292 | static void pcie_get_aspm_reg(struct pci_dev *pdev, |
306 | struct aspm_register_info *info) | 293 | struct aspm_register_info *info) |
307 | { | 294 | { |
308 | int pos; | ||
309 | u16 reg16; | 295 | u16 reg16; |
310 | u32 reg32; | 296 | u32 reg32; |
311 | 297 | ||
312 | pos = pci_pcie_cap(pdev); | 298 | pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, ®32); |
313 | pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, ®32); | ||
314 | info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10; | 299 | info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10; |
315 | info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12; | 300 | info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12; |
316 | info->latency_encoding_l1 = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15; | 301 | info->latency_encoding_l1 = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15; |
317 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); | 302 | pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, ®16); |
318 | info->enabled = reg16 & PCI_EXP_LNKCTL_ASPMC; | 303 | info->enabled = reg16 & PCI_EXP_LNKCTL_ASPMC; |
319 | } | 304 | } |
320 | 305 | ||
@@ -420,7 +405,6 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | |||
420 | 405 | ||
421 | /* Get and check endpoint acceptable latencies */ | 406 | /* Get and check endpoint acceptable latencies */ |
422 | list_for_each_entry(child, &linkbus->devices, bus_list) { | 407 | list_for_each_entry(child, &linkbus->devices, bus_list) { |
423 | int pos; | ||
424 | u32 reg32, encoding; | 408 | u32 reg32, encoding; |
425 | struct aspm_latency *acceptable = | 409 | struct aspm_latency *acceptable = |
426 | &link->acceptable[PCI_FUNC(child->devfn)]; | 410 | &link->acceptable[PCI_FUNC(child->devfn)]; |
@@ -429,8 +413,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | |||
429 | pci_pcie_type(child) != PCI_EXP_TYPE_LEG_END) | 413 | pci_pcie_type(child) != PCI_EXP_TYPE_LEG_END) |
430 | continue; | 414 | continue; |
431 | 415 | ||
432 | pos = pci_pcie_cap(child); | 416 | pcie_capability_read_dword(child, PCI_EXP_DEVCAP, ®32); |
433 | pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, ®32); | ||
434 | /* Calculate endpoint L0s acceptable latency */ | 417 | /* Calculate endpoint L0s acceptable latency */ |
435 | encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; | 418 | encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; |
436 | acceptable->l0s = calc_l0s_acceptable(encoding); | 419 | acceptable->l0s = calc_l0s_acceptable(encoding); |
@@ -444,13 +427,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | |||
444 | 427 | ||
445 | static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) | 428 | static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) |
446 | { | 429 | { |
447 | u16 reg16; | 430 | pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, 0x3, val); |
448 | int pos = pci_pcie_cap(pdev); | ||
449 | |||
450 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); | ||
451 | reg16 &= ~0x3; | ||
452 | reg16 |= val; | ||
453 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); | ||
454 | } | 431 | } |
455 | 432 | ||
456 | static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) | 433 | static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) |
@@ -505,7 +482,6 @@ static void free_link_state(struct pcie_link_state *link) | |||
505 | static int pcie_aspm_sanity_check(struct pci_dev *pdev) | 482 | static int pcie_aspm_sanity_check(struct pci_dev *pdev) |
506 | { | 483 | { |
507 | struct pci_dev *child; | 484 | struct pci_dev *child; |
508 | int pos; | ||
509 | u32 reg32; | 485 | u32 reg32; |
510 | 486 | ||
511 | /* | 487 | /* |
@@ -513,8 +489,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) | |||
513 | * very strange. Disable ASPM for the whole slot | 489 | * very strange. Disable ASPM for the whole slot |
514 | */ | 490 | */ |
515 | list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { | 491 | list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { |
516 | pos = pci_pcie_cap(child); | 492 | if (!pci_is_pcie(child)) |
517 | if (!pos) | ||
518 | return -EINVAL; | 493 | return -EINVAL; |
519 | 494 | ||
520 | /* | 495 | /* |
@@ -530,7 +505,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) | |||
530 | * Disable ASPM for pre-1.1 PCIe device, we follow MS to use | 505 | * Disable ASPM for pre-1.1 PCIe device, we follow MS to use |
531 | * RBER bit to determine if a function is 1.1 version device | 506 | * RBER bit to determine if a function is 1.1 version device |
532 | */ | 507 | */ |
533 | pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, ®32); | 508 | pcie_capability_read_dword(child, PCI_EXP_DEVCAP, ®32); |
534 | if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) { | 509 | if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) { |
535 | dev_printk(KERN_INFO, &child->dev, "disabling ASPM" | 510 | dev_printk(KERN_INFO, &child->dev, "disabling ASPM" |
536 | " on pre-1.1 PCIe device. You can enable it" | 511 | " on pre-1.1 PCIe device. You can enable it" |