diff options
| author | Olof Johansson <olof@lixom.net> | 2012-09-13 01:00:07 -0400 |
|---|---|---|
| committer | Olof Johansson <olof@lixom.net> | 2012-09-13 01:00:07 -0400 |
| commit | 2bc733e8b443e77db5bb18e1bb8f1c535a92eb8c (patch) | |
| tree | a6985ec4a761efbf2bdbaf7e75110669bf52bc15 /drivers/pci | |
| parent | f5a60d4efc7a3928d6e7d37202a8560ce76cb838 (diff) | |
| parent | 48540058612786d365602f3324ed97f9071092de (diff) | |
Merge tag 'imx-fixes' of git://git.pengutronix.de/git/imx/linux-2.6 into fixes
ARM: i.MX: Fix SSI clock associations for i.MX25/i.MX35
* tag 'imx-fixes' of git://git.pengutronix.de/git/imx/linux-2.6:
ARM: clk-imx35: Fix SSI clock registration
ARM: clk-imx25: Fix SSI clock registration
+ Linux 3.6-rc5
Diffstat (limited to 'drivers/pci')
| -rw-r--r-- | drivers/pci/pci-driver.c | 6 | ||||
| -rw-r--r-- | drivers/pci/pci-sysfs.c | 42 | ||||
| -rw-r--r-- | drivers/pci/pci.c | 1 | ||||
| -rw-r--r-- | drivers/pci/pcie/portdrv_pci.c | 14 | ||||
| -rw-r--r-- | drivers/pci/probe.c | 31 |
5 files changed, 80 insertions, 14 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 5270f1a99328..d6fd6b6d9d4b 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
| @@ -280,8 +280,12 @@ static long local_pci_probe(void *_ddi) | |||
| 280 | { | 280 | { |
| 281 | struct drv_dev_and_id *ddi = _ddi; | 281 | struct drv_dev_and_id *ddi = _ddi; |
| 282 | struct device *dev = &ddi->dev->dev; | 282 | struct device *dev = &ddi->dev->dev; |
| 283 | struct device *parent = dev->parent; | ||
| 283 | int rc; | 284 | int rc; |
| 284 | 285 | ||
| 286 | /* The parent bridge must be in active state when probing */ | ||
| 287 | if (parent) | ||
| 288 | pm_runtime_get_sync(parent); | ||
| 285 | /* Unbound PCI devices are always set to disabled and suspended. | 289 | /* Unbound PCI devices are always set to disabled and suspended. |
| 286 | * During probe, the device is set to enabled and active and the | 290 | * During probe, the device is set to enabled and active and the |
| 287 | * usage count is incremented. If the driver supports runtime PM, | 291 | * usage count is incremented. If the driver supports runtime PM, |
| @@ -298,6 +302,8 @@ static long local_pci_probe(void *_ddi) | |||
| 298 | pm_runtime_set_suspended(dev); | 302 | pm_runtime_set_suspended(dev); |
| 299 | pm_runtime_put_noidle(dev); | 303 | pm_runtime_put_noidle(dev); |
| 300 | } | 304 | } |
| 305 | if (parent) | ||
| 306 | pm_runtime_put(parent); | ||
| 301 | return rc; | 307 | return rc; |
| 302 | } | 308 | } |
| 303 | 309 | ||
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 6869009c7393..02d107b15281 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
| @@ -458,6 +458,40 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
| 458 | } | 458 | } |
| 459 | struct device_attribute vga_attr = __ATTR_RO(boot_vga); | 459 | struct device_attribute vga_attr = __ATTR_RO(boot_vga); |
| 460 | 460 | ||
| 461 | static void | ||
| 462 | pci_config_pm_runtime_get(struct pci_dev *pdev) | ||
| 463 | { | ||
| 464 | struct device *dev = &pdev->dev; | ||
| 465 | struct device *parent = dev->parent; | ||
| 466 | |||
| 467 | if (parent) | ||
| 468 | pm_runtime_get_sync(parent); | ||
| 469 | pm_runtime_get_noresume(dev); | ||
| 470 | /* | ||
| 471 | * pdev->current_state is set to PCI_D3cold during suspending, | ||
| 472 | * so wait until suspending completes | ||
| 473 | */ | ||
| 474 | pm_runtime_barrier(dev); | ||
| 475 | /* | ||
| 476 | * Only need to resume devices in D3cold, because config | ||
| 477 | * registers are still accessible for devices suspended but | ||
| 478 | * not in D3cold. | ||
| 479 | */ | ||
| 480 | if (pdev->current_state == PCI_D3cold) | ||
| 481 | pm_runtime_resume(dev); | ||
| 482 | } | ||
| 483 | |||
| 484 | static void | ||
| 485 | pci_config_pm_runtime_put(struct pci_dev *pdev) | ||
| 486 | { | ||
| 487 | struct device *dev = &pdev->dev; | ||
| 488 | struct device *parent = dev->parent; | ||
| 489 | |||
| 490 | pm_runtime_put(dev); | ||
| 491 | if (parent) | ||
| 492 | pm_runtime_put_sync(parent); | ||
| 493 | } | ||
| 494 | |||
| 461 | static ssize_t | 495 | static ssize_t |
| 462 | pci_read_config(struct file *filp, struct kobject *kobj, | 496 | pci_read_config(struct file *filp, struct kobject *kobj, |
| 463 | struct bin_attribute *bin_attr, | 497 | struct bin_attribute *bin_attr, |
| @@ -484,6 +518,8 @@ pci_read_config(struct file *filp, struct kobject *kobj, | |||
| 484 | size = count; | 518 | size = count; |
| 485 | } | 519 | } |
| 486 | 520 | ||
| 521 | pci_config_pm_runtime_get(dev); | ||
| 522 | |||
| 487 | if ((off & 1) && size) { | 523 | if ((off & 1) && size) { |
| 488 | u8 val; | 524 | u8 val; |
| 489 | pci_user_read_config_byte(dev, off, &val); | 525 | pci_user_read_config_byte(dev, off, &val); |
| @@ -529,6 +565,8 @@ pci_read_config(struct file *filp, struct kobject *kobj, | |||
| 529 | --size; | 565 | --size; |
| 530 | } | 566 | } |
| 531 | 567 | ||
| 568 | pci_config_pm_runtime_put(dev); | ||
| 569 | |||
| 532 | return count; | 570 | return count; |
| 533 | } | 571 | } |
| 534 | 572 | ||
| @@ -549,6 +587,8 @@ pci_write_config(struct file* filp, struct kobject *kobj, | |||
| 549 | count = size; | 587 | count = size; |
| 550 | } | 588 | } |
| 551 | 589 | ||
| 590 | pci_config_pm_runtime_get(dev); | ||
| 591 | |||
| 552 | if ((off & 1) && size) { | 592 | if ((off & 1) && size) { |
| 553 | pci_user_write_config_byte(dev, off, data[off - init_off]); | 593 | pci_user_write_config_byte(dev, off, data[off - init_off]); |
| 554 | off++; | 594 | off++; |
| @@ -587,6 +627,8 @@ pci_write_config(struct file* filp, struct kobject *kobj, | |||
| 587 | --size; | 627 | --size; |
| 588 | } | 628 | } |
| 589 | 629 | ||
| 630 | pci_config_pm_runtime_put(dev); | ||
| 631 | |||
| 590 | return count; | 632 | return count; |
| 591 | } | 633 | } |
| 592 | 634 | ||
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f3ea977a5b1b..ab4bf5a4c2f1 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -1941,6 +1941,7 @@ void pci_pm_init(struct pci_dev *dev) | |||
| 1941 | dev->pm_cap = pm; | 1941 | dev->pm_cap = pm; |
| 1942 | dev->d3_delay = PCI_PM_D3_WAIT; | 1942 | dev->d3_delay = PCI_PM_D3_WAIT; |
| 1943 | dev->d3cold_delay = PCI_PM_D3COLD_WAIT; | 1943 | dev->d3cold_delay = PCI_PM_D3COLD_WAIT; |
| 1944 | dev->d3cold_allowed = true; | ||
| 1944 | 1945 | ||
| 1945 | dev->d1_support = false; | 1946 | dev->d1_support = false; |
| 1946 | dev->d2_support = false; | 1947 | dev->d2_support = false; |
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 3a7eefcb270a..e76b44777dbf 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
| @@ -140,9 +140,17 @@ static int pcie_port_runtime_resume(struct device *dev) | |||
| 140 | { | 140 | { |
| 141 | return 0; | 141 | return 0; |
| 142 | } | 142 | } |
| 143 | |||
| 144 | static int pcie_port_runtime_idle(struct device *dev) | ||
| 145 | { | ||
| 146 | /* Delay for a short while to prevent too frequent suspend/resume */ | ||
| 147 | pm_schedule_suspend(dev, 10); | ||
| 148 | return -EBUSY; | ||
| 149 | } | ||
| 143 | #else | 150 | #else |
| 144 | #define pcie_port_runtime_suspend NULL | 151 | #define pcie_port_runtime_suspend NULL |
| 145 | #define pcie_port_runtime_resume NULL | 152 | #define pcie_port_runtime_resume NULL |
| 153 | #define pcie_port_runtime_idle NULL | ||
| 146 | #endif | 154 | #endif |
| 147 | 155 | ||
| 148 | static const struct dev_pm_ops pcie_portdrv_pm_ops = { | 156 | static const struct dev_pm_ops pcie_portdrv_pm_ops = { |
| @@ -155,6 +163,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { | |||
| 155 | .resume_noirq = pcie_port_resume_noirq, | 163 | .resume_noirq = pcie_port_resume_noirq, |
| 156 | .runtime_suspend = pcie_port_runtime_suspend, | 164 | .runtime_suspend = pcie_port_runtime_suspend, |
| 157 | .runtime_resume = pcie_port_runtime_resume, | 165 | .runtime_resume = pcie_port_runtime_resume, |
| 166 | .runtime_idle = pcie_port_runtime_idle, | ||
| 158 | }; | 167 | }; |
| 159 | 168 | ||
| 160 | #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) | 169 | #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) |
| @@ -200,6 +209,11 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, | |||
| 200 | return status; | 209 | return status; |
| 201 | 210 | ||
| 202 | pci_save_state(dev); | 211 | pci_save_state(dev); |
| 212 | /* | ||
| 213 | * D3cold may not work properly on some PCIe port, so disable | ||
| 214 | * it by default. | ||
| 215 | */ | ||
| 216 | dev->d3cold_allowed = false; | ||
| 203 | if (!pci_match_id(port_runtime_pm_black_list, dev)) | 217 | if (!pci_match_id(port_runtime_pm_black_list, dev)) |
| 204 | pm_runtime_put_noidle(&dev->dev); | 218 | pm_runtime_put_noidle(&dev->dev); |
| 205 | 219 | ||
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6c143b4497ca..9f8a6b79a8ec 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
| @@ -144,15 +144,13 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar) | |||
| 144 | case PCI_BASE_ADDRESS_MEM_TYPE_32: | 144 | case PCI_BASE_ADDRESS_MEM_TYPE_32: |
| 145 | break; | 145 | break; |
| 146 | case PCI_BASE_ADDRESS_MEM_TYPE_1M: | 146 | case PCI_BASE_ADDRESS_MEM_TYPE_1M: |
| 147 | dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n"); | 147 | /* 1M mem BAR treated as 32-bit BAR */ |
| 148 | break; | 148 | break; |
| 149 | case PCI_BASE_ADDRESS_MEM_TYPE_64: | 149 | case PCI_BASE_ADDRESS_MEM_TYPE_64: |
| 150 | flags |= IORESOURCE_MEM_64; | 150 | flags |= IORESOURCE_MEM_64; |
| 151 | break; | 151 | break; |
| 152 | default: | 152 | default: |
| 153 | dev_warn(&dev->dev, | 153 | /* mem unknown type treated as 32-bit BAR */ |
| 154 | "mem unknown type %x treated as 32-bit BAR\n", | ||
| 155 | mem_type); | ||
| 156 | break; | 154 | break; |
| 157 | } | 155 | } |
| 158 | return flags; | 156 | return flags; |
| @@ -173,9 +171,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
| 173 | u32 l, sz, mask; | 171 | u32 l, sz, mask; |
| 174 | u16 orig_cmd; | 172 | u16 orig_cmd; |
| 175 | struct pci_bus_region region; | 173 | struct pci_bus_region region; |
| 174 | bool bar_too_big = false, bar_disabled = false; | ||
| 176 | 175 | ||
| 177 | mask = type ? PCI_ROM_ADDRESS_MASK : ~0; | 176 | mask = type ? PCI_ROM_ADDRESS_MASK : ~0; |
| 178 | 177 | ||
| 178 | /* No printks while decoding is disabled! */ | ||
| 179 | if (!dev->mmio_always_on) { | 179 | if (!dev->mmio_always_on) { |
| 180 | pci_read_config_word(dev, PCI_COMMAND, &orig_cmd); | 180 | pci_read_config_word(dev, PCI_COMMAND, &orig_cmd); |
| 181 | pci_write_config_word(dev, PCI_COMMAND, | 181 | pci_write_config_word(dev, PCI_COMMAND, |
| @@ -240,8 +240,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
| 240 | goto fail; | 240 | goto fail; |
| 241 | 241 | ||
| 242 | if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) { | 242 | if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) { |
| 243 | dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", | 243 | bar_too_big = true; |
| 244 | pos); | ||
| 245 | goto fail; | 244 | goto fail; |
| 246 | } | 245 | } |
| 247 | 246 | ||
| @@ -252,12 +251,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
| 252 | region.start = 0; | 251 | region.start = 0; |
| 253 | region.end = sz64; | 252 | region.end = sz64; |
| 254 | pcibios_bus_to_resource(dev, res, ®ion); | 253 | pcibios_bus_to_resource(dev, res, ®ion); |
| 254 | bar_disabled = true; | ||
| 255 | } else { | 255 | } else { |
| 256 | region.start = l64; | 256 | region.start = l64; |
| 257 | region.end = l64 + sz64; | 257 | region.end = l64 + sz64; |
| 258 | pcibios_bus_to_resource(dev, res, ®ion); | 258 | pcibios_bus_to_resource(dev, res, ®ion); |
| 259 | dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", | ||
| 260 | pos, res); | ||
| 261 | } | 259 | } |
| 262 | } else { | 260 | } else { |
| 263 | sz = pci_size(l, sz, mask); | 261 | sz = pci_size(l, sz, mask); |
| @@ -268,18 +266,23 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
| 268 | region.start = l; | 266 | region.start = l; |
| 269 | region.end = l + sz; | 267 | region.end = l + sz; |
| 270 | pcibios_bus_to_resource(dev, res, ®ion); | 268 | pcibios_bus_to_resource(dev, res, ®ion); |
| 271 | |||
| 272 | dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); | ||
| 273 | } | 269 | } |
| 274 | 270 | ||
| 275 | out: | 271 | goto out; |
| 272 | |||
| 273 | |||
| 274 | fail: | ||
| 275 | res->flags = 0; | ||
| 276 | out: | ||
| 276 | if (!dev->mmio_always_on) | 277 | if (!dev->mmio_always_on) |
| 277 | pci_write_config_word(dev, PCI_COMMAND, orig_cmd); | 278 | pci_write_config_word(dev, PCI_COMMAND, orig_cmd); |
| 278 | 279 | ||
| 280 | if (bar_too_big) | ||
| 281 | dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos); | ||
| 282 | if (res->flags && !bar_disabled) | ||
| 283 | dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); | ||
| 284 | |||
| 279 | return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; | 285 | return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; |
| 280 | fail: | ||
| 281 | res->flags = 0; | ||
| 282 | goto out; | ||
| 283 | } | 286 | } |
| 284 | 287 | ||
| 285 | static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) | 288 | static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) |
