diff options
113 files changed, 3007 insertions, 1360 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e7848a0d99e..3e69c1c4f50 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1948,8 +1948,12 @@ and is between 256 and 4096 characters. It is defined in the file | |||
1948 | IRQ routing is enabled. | 1948 | IRQ routing is enabled. |
1949 | noacpi [X86] Do not use ACPI for IRQ routing | 1949 | noacpi [X86] Do not use ACPI for IRQ routing |
1950 | or for PCI scanning. | 1950 | or for PCI scanning. |
1951 | use_crs [X86] Use _CRS for PCI resource | 1951 | use_crs [X86] Use PCI host bridge window information |
1952 | allocation. | 1952 | from ACPI. On BIOSes from 2008 or later, this |
1953 | is enabled by default. If you need to use this, | ||
1954 | please report a bug. | ||
1955 | nocrs [X86] Ignore PCI host bridge windows from ACPI. | ||
1956 | If you need to use this, please report a bug. | ||
1953 | routeirq Do IRQ routing for all PCI devices. | 1957 | routeirq Do IRQ routing for all PCI devices. |
1954 | This is normally done in pci_enable_device(), | 1958 | This is normally done in pci_enable_device(), |
1955 | so this option is a temporary workaround | 1959 | so this option is a temporary workaround |
@@ -1998,6 +2002,14 @@ and is between 256 and 4096 characters. It is defined in the file | |||
1998 | force Enable ASPM even on devices that claim not to support it. | 2002 | force Enable ASPM even on devices that claim not to support it. |
1999 | WARNING: Forcing ASPM on may cause system lockups. | 2003 | WARNING: Forcing ASPM on may cause system lockups. |
2000 | 2004 | ||
2005 | pcie_pme= [PCIE,PM] Native PCIe PME signaling options: | ||
2006 | off Do not use native PCIe PME signaling. | ||
2007 | force Use native PCIe PME signaling even if the BIOS refuses | ||
2008 | to allow the kernel to control the relevant PCIe config | ||
2009 | registers. | ||
2010 | nomsi Do not use MSI for native PCIe PME signaling (this makes | ||
2011 | all PCIe root ports use INTx for everything). | ||
2012 | |||
2001 | pcmv= [HW,PCMCIA] BadgePAD 4 | 2013 | pcmv= [HW,PCMCIA] BadgePAD 4 |
2002 | 2014 | ||
2003 | pd. [PARIDE] | 2015 | pd. [PARIDE] |
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index a91ba28999b..c9ab94ee1ca 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c | |||
@@ -126,8 +126,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final); | |||
126 | #define MB (1024*KB) | 126 | #define MB (1024*KB) |
127 | #define GB (1024*MB) | 127 | #define GB (1024*MB) |
128 | 128 | ||
129 | void | 129 | resource_size_t |
130 | pcibios_align_resource(void *data, struct resource *res, | 130 | pcibios_align_resource(void *data, const struct resource *res, |
131 | resource_size_t size, resource_size_t align) | 131 | resource_size_t size, resource_size_t align) |
132 | { | 132 | { |
133 | struct pci_dev *dev = data; | 133 | struct pci_dev *dev = data; |
@@ -184,7 +184,7 @@ pcibios_align_resource(void *data, struct resource *res, | |||
184 | } | 184 | } |
185 | } | 185 | } |
186 | 186 | ||
187 | res->start = start; | 187 | return start; |
188 | } | 188 | } |
189 | #undef KB | 189 | #undef KB |
190 | #undef MB | 190 | #undef MB |
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 809681900ec..bd397e0b663 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c | |||
@@ -616,15 +616,17 @@ char * __init pcibios_setup(char *str) | |||
616 | * but we want to try to avoid allocating at 0x2900-0x2bff | 616 | * but we want to try to avoid allocating at 0x2900-0x2bff |
617 | * which might be mirrored at 0x0100-0x03ff.. | 617 | * which might be mirrored at 0x0100-0x03ff.. |
618 | */ | 618 | */ |
619 | void pcibios_align_resource(void *data, struct resource *res, | 619 | resource_size_t pcibios_align_resource(void *data, const struct resource *res, |
620 | resource_size_t size, resource_size_t align) | 620 | resource_size_t size, resource_size_t align) |
621 | { | 621 | { |
622 | resource_size_t start = res->start; | 622 | resource_size_t start = res->start; |
623 | 623 | ||
624 | if (res->flags & IORESOURCE_IO && start & 0x300) | 624 | if (res->flags & IORESOURCE_IO && start & 0x300) |
625 | start = (start + 0x3ff) & ~0x3ff; | 625 | start = (start + 0x3ff) & ~0x3ff; |
626 | 626 | ||
627 | res->start = (start + align - 1) & ~(align - 1); | 627 | start = (start + align - 1) & ~(align - 1); |
628 | |||
629 | return start; | ||
628 | } | 630 | } |
629 | 631 | ||
630 | /** | 632 | /** |
diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c index 77ee319193c..d4b9c36ddc0 100644 --- a/arch/cris/arch-v32/drivers/pci/bios.c +++ b/arch/cris/arch-v32/drivers/pci/bios.c | |||
@@ -41,18 +41,16 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | |||
41 | return 0; | 41 | return 0; |
42 | } | 42 | } |
43 | 43 | ||
44 | void | 44 | resource_size_t |
45 | pcibios_align_resource(void *data, struct resource *res, | 45 | pcibios_align_resource(void *data, const struct resource *res, |
46 | resource_size_t size, resource_size_t align) | 46 | resource_size_t size, resource_size_t align) |
47 | { | 47 | { |
48 | if (res->flags & IORESOURCE_IO) { | 48 | resource_size_t start = res->start; |
49 | resource_size_t start = res->start; | ||
50 | 49 | ||
51 | if (start & 0x300) { | 50 | if ((res->flags & IORESOURCE_IO) && (start & 0x300)) |
52 | start = (start + 0x3ff) & ~0x3ff; | 51 | start = (start + 0x3ff) & ~0x3ff; |
53 | res->start = start; | 52 | |
54 | } | 53 | return start |
55 | } | ||
56 | } | 54 | } |
57 | 55 | ||
58 | int pcibios_enable_resources(struct pci_dev *dev, int mask) | 56 | int pcibios_enable_resources(struct pci_dev *dev, int mask) |
diff --git a/arch/frv/mb93090-mb00/pci-frv.c b/arch/frv/mb93090-mb00/pci-frv.c index 566bdeb499d..1ed15d7fea2 100644 --- a/arch/frv/mb93090-mb00/pci-frv.c +++ b/arch/frv/mb93090-mb00/pci-frv.c | |||
@@ -32,18 +32,16 @@ | |||
32 | * but we want to try to avoid allocating at 0x2900-0x2bff | 32 | * but we want to try to avoid allocating at 0x2900-0x2bff |
33 | * which might have be mirrored at 0x0100-0x03ff.. | 33 | * which might have be mirrored at 0x0100-0x03ff.. |
34 | */ | 34 | */ |
35 | void | 35 | resource_size_t |
36 | pcibios_align_resource(void *data, struct resource *res, | 36 | pcibios_align_resource(void *data, const struct resource *res, |
37 | resource_size_t size, resource_size_t align) | 37 | resource_size_t size, resource_size_t align) |
38 | { | 38 | { |
39 | if (res->flags & IORESOURCE_IO) { | 39 | resource_size_t start = res->start; |
40 | resource_size_t start = res->start; | ||
41 | 40 | ||
42 | if (start & 0x300) { | 41 | if ((res->flags & IORESOURCE_IO) && (start & 0x300)) |
43 | start = (start + 0x3ff) & ~0x3ff; | 42 | start = (start + 0x3ff) & ~0x3ff; |
44 | res->start = start; | 43 | |
45 | } | 44 | return start |
46 | } | ||
47 | } | 45 | } |
48 | 46 | ||
49 | 47 | ||
diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index e97b255d97b..93997bd5edc 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h | |||
@@ -98,6 +98,7 @@ ia64_acpi_release_global_lock (unsigned int *lock) | |||
98 | #endif | 98 | #endif |
99 | #define acpi_processor_cstate_check(x) (x) /* no idle limits on IA64 :) */ | 99 | #define acpi_processor_cstate_check(x) (x) /* no idle limits on IA64 :) */ |
100 | static inline void disable_acpi(void) { } | 100 | static inline void disable_acpi(void) { } |
101 | static inline void pci_acpi_crs_quirks(void) { } | ||
101 | 102 | ||
102 | const char *acpi_get_sysname (void); | 103 | const char *acpi_get_sysname (void); |
103 | int acpi_request_vector (u32 int_type); | 104 | int acpi_request_vector (u32 int_type); |
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index df639db779f..64aff520b89 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
@@ -320,9 +320,9 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | |||
320 | static void __devinit | 320 | static void __devinit |
321 | pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl) | 321 | pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl) |
322 | { | 322 | { |
323 | int i, j; | 323 | int i; |
324 | 324 | ||
325 | j = 0; | 325 | pci_bus_remove_resources(bus); |
326 | for (i = 0; i < ctrl->windows; i++) { | 326 | for (i = 0; i < ctrl->windows; i++) { |
327 | struct resource *res = &ctrl->window[i].resource; | 327 | struct resource *res = &ctrl->window[i].resource; |
328 | /* HP's firmware has a hack to work around a Windows bug. | 328 | /* HP's firmware has a hack to work around a Windows bug. |
@@ -330,13 +330,7 @@ pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl) | |||
330 | if ((res->flags & IORESOURCE_MEM) && | 330 | if ((res->flags & IORESOURCE_MEM) && |
331 | (res->end - res->start < 16)) | 331 | (res->end - res->start < 16)) |
332 | continue; | 332 | continue; |
333 | if (j >= PCI_BUS_NUM_RESOURCES) { | 333 | pci_bus_add_resource(bus, res, 0); |
334 | dev_warn(&bus->dev, | ||
335 | "ignoring host bridge window %pR (no space)\n", | ||
336 | res); | ||
337 | continue; | ||
338 | } | ||
339 | bus->resource[j++] = res; | ||
340 | } | 334 | } |
341 | } | 335 | } |
342 | 336 | ||
@@ -452,13 +446,12 @@ EXPORT_SYMBOL(pcibios_bus_to_resource); | |||
452 | static int __devinit is_valid_resource(struct pci_dev *dev, int idx) | 446 | static int __devinit is_valid_resource(struct pci_dev *dev, int idx) |
453 | { | 447 | { |
454 | unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; | 448 | unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; |
455 | struct resource *devr = &dev->resource[idx]; | 449 | struct resource *devr = &dev->resource[idx], *busr; |
456 | 450 | ||
457 | if (!dev->bus) | 451 | if (!dev->bus) |
458 | return 0; | 452 | return 0; |
459 | for (i=0; i<PCI_BUS_NUM_RESOURCES; i++) { | ||
460 | struct resource *busr = dev->bus->resource[i]; | ||
461 | 453 | ||
454 | pci_bus_for_each_resource(dev->bus, busr, i) { | ||
462 | if (!busr || ((busr->flags ^ devr->flags) & type_mask)) | 455 | if (!busr || ((busr->flags ^ devr->flags) & type_mask)) |
463 | continue; | 456 | continue; |
464 | if ((devr->start) && (devr->start >= busr->start) && | 457 | if ((devr->start) && (devr->start >= busr->start) && |
@@ -547,10 +540,11 @@ pcibios_disable_device (struct pci_dev *dev) | |||
547 | acpi_pci_irq_disable(dev); | 540 | acpi_pci_irq_disable(dev); |
548 | } | 541 | } |
549 | 542 | ||
550 | void | 543 | resource_size_t |
551 | pcibios_align_resource (void *data, struct resource *res, | 544 | pcibios_align_resource (void *data, const struct resource *res, |
552 | resource_size_t size, resource_size_t align) | 545 | resource_size_t size, resource_size_t align) |
553 | { | 546 | { |
547 | return res->start; | ||
554 | } | 548 | } |
555 | 549 | ||
556 | /* | 550 | /* |
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 9a11c222689..f87f5e188fa 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c | |||
@@ -49,8 +49,8 @@ static int pci_initialized; | |||
49 | * but we want to try to avoid allocating at 0x2900-0x2bff | 49 | * but we want to try to avoid allocating at 0x2900-0x2bff |
50 | * which might have be mirrored at 0x0100-0x03ff.. | 50 | * which might have be mirrored at 0x0100-0x03ff.. |
51 | */ | 51 | */ |
52 | void | 52 | resource_size_t |
53 | pcibios_align_resource(void *data, struct resource *res, | 53 | pcibios_align_resource(void *data, const struct resource *res, |
54 | resource_size_t size, resource_size_t align) | 54 | resource_size_t size, resource_size_t align) |
55 | { | 55 | { |
56 | struct pci_dev *dev = data; | 56 | struct pci_dev *dev = data; |
@@ -73,7 +73,7 @@ pcibios_align_resource(void *data, struct resource *res, | |||
73 | start = PCIBIOS_MIN_MEM + hose->mem_resource->start; | 73 | start = PCIBIOS_MIN_MEM + hose->mem_resource->start; |
74 | } | 74 | } |
75 | 75 | ||
76 | res->start = start; | 76 | return start; |
77 | } | 77 | } |
78 | 78 | ||
79 | static void __devinit pcibios_scanbus(struct pci_controller *hose) | 79 | static void __devinit pcibios_scanbus(struct pci_controller *hose) |
diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c index 678388fd34b..fd22597edb6 100644 --- a/arch/mips/pmc-sierra/yosemite/ht.c +++ b/arch/mips/pmc-sierra/yosemite/ht.c | |||
@@ -345,14 +345,13 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) | |||
345 | return pcibios_enable_resources(dev); | 345 | return pcibios_enable_resources(dev); |
346 | } | 346 | } |
347 | 347 | ||
348 | void pcibios_align_resource(void *data, struct resource *res, | 348 | resource_size_t pcibios_align_resource(void *data, const struct resource *res, |
349 | resource_size_t size, resource_size_t align) | 349 | resource_size_t size, resource_size_t align) |
350 | { | 350 | { |
351 | struct pci_dev *dev = data; | 351 | struct pci_dev *dev = data; |
352 | resource_size_t start = res->start; | ||
352 | 353 | ||
353 | if (res->flags & IORESOURCE_IO) { | 354 | if (res->flags & IORESOURCE_IO) { |
354 | resource_size_t start = res->start; | ||
355 | |||
356 | /* We need to avoid collisions with `mirrored' VGA ports | 355 | /* We need to avoid collisions with `mirrored' VGA ports |
357 | and other strange ISA hardware, so we always want the | 356 | and other strange ISA hardware, so we always want the |
358 | addresses kilobyte aligned. */ | 357 | addresses kilobyte aligned. */ |
@@ -363,8 +362,9 @@ void pcibios_align_resource(void *data, struct resource *res, | |||
363 | } | 362 | } |
364 | 363 | ||
365 | start = (start + 1024 - 1) & ~(1024 - 1); | 364 | start = (start + 1024 - 1) & ~(1024 - 1); |
366 | res->start = start; | ||
367 | } | 365 | } |
366 | |||
367 | return start; | ||
368 | } | 368 | } |
369 | 369 | ||
370 | struct pci_ops titan_pci_ops = { | 370 | struct pci_ops titan_pci_ops = { |
diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c index 78cd134ddf7..d6119b879a9 100644 --- a/arch/mn10300/unit-asb2305/pci-asb2305.c +++ b/arch/mn10300/unit-asb2305/pci-asb2305.c | |||
@@ -31,9 +31,11 @@ | |||
31 | * but we want to try to avoid allocating at 0x2900-0x2bff | 31 | * but we want to try to avoid allocating at 0x2900-0x2bff |
32 | * which might have be mirrored at 0x0100-0x03ff.. | 32 | * which might have be mirrored at 0x0100-0x03ff.. |
33 | */ | 33 | */ |
34 | void pcibios_align_resource(void *data, struct resource *res, | 34 | resource_size_t pcibios_align_resource(void *data, const struct resource *res, |
35 | resource_size_t size, resource_size_t align) | 35 | resource_size_t size, resource_size_t align) |
36 | { | 36 | { |
37 | resource_size_t start = res->start; | ||
38 | |||
37 | #if 0 | 39 | #if 0 |
38 | struct pci_dev *dev = data; | 40 | struct pci_dev *dev = data; |
39 | 41 | ||
@@ -47,14 +49,10 @@ void pcibios_align_resource(void *data, struct resource *res, | |||
47 | ); | 49 | ); |
48 | #endif | 50 | #endif |
49 | 51 | ||
50 | if (res->flags & IORESOURCE_IO) { | 52 | if ((res->flags & IORESOURCE_IO) && (start & 0x300)) |
51 | unsigned long start = res->start; | 53 | start = (start + 0x3ff) & ~0x3ff; |
52 | 54 | ||
53 | if (start & 0x300) { | 55 | return start; |
54 | start = (start + 0x3ff) & ~0x3ff; | ||
55 | res->start = start; | ||
56 | } | ||
57 | } | ||
58 | } | 56 | } |
59 | 57 | ||
60 | 58 | ||
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c index 2cb7e75ba1c..6d8720a0a59 100644 --- a/arch/mn10300/unit-asb2305/pci.c +++ b/arch/mn10300/unit-asb2305/pci.c | |||
@@ -331,12 +331,10 @@ static int __init pci_check_direct(void) | |||
331 | static int __devinit is_valid_resource(struct pci_dev *dev, int idx) | 331 | static int __devinit is_valid_resource(struct pci_dev *dev, int idx) |
332 | { | 332 | { |
333 | unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; | 333 | unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; |
334 | struct resource *devr = &dev->resource[idx]; | 334 | struct resource *devr = &dev->resource[idx], *busr; |
335 | 335 | ||
336 | if (dev->bus) { | 336 | if (dev->bus) { |
337 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 337 | pci_bus_for_each_resource(dev->bus, busr, i) { |
338 | struct resource *busr = dev->bus->resource[i]; | ||
339 | |||
340 | if (!busr || (busr->flags ^ devr->flags) & type_mask) | 338 | if (!busr || (busr->flags ^ devr->flags) & type_mask) |
341 | continue; | 339 | continue; |
342 | 340 | ||
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index 9e74bfe071d..38372e7cbb8 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c | |||
@@ -257,10 +257,10 @@ EXPORT_SYMBOL(pcibios_bus_to_resource); | |||
257 | * Since we are just checking candidates, don't use any fields other | 257 | * Since we are just checking candidates, don't use any fields other |
258 | * than res->start. | 258 | * than res->start. |
259 | */ | 259 | */ |
260 | void pcibios_align_resource(void *data, struct resource *res, | 260 | resource_size_t pcibios_align_resource(void *data, const struct resource *res, |
261 | resource_size_t size, resource_size_t alignment) | 261 | resource_size_t size, resource_size_t alignment) |
262 | { | 262 | { |
263 | resource_size_t mask, align; | 263 | resource_size_t mask, align, start = res->start; |
264 | 264 | ||
265 | DBG_RES("pcibios_align_resource(%s, (%p) [%lx,%lx]/%x, 0x%lx, 0x%lx)\n", | 265 | DBG_RES("pcibios_align_resource(%s, (%p) [%lx,%lx]/%x, 0x%lx, 0x%lx)\n", |
266 | pci_name(((struct pci_dev *) data)), | 266 | pci_name(((struct pci_dev *) data)), |
@@ -272,10 +272,10 @@ void pcibios_align_resource(void *data, struct resource *res, | |||
272 | 272 | ||
273 | /* Align to largest of MIN or input size */ | 273 | /* Align to largest of MIN or input size */ |
274 | mask = max(alignment, align) - 1; | 274 | mask = max(alignment, align) - 1; |
275 | res->start += mask; | 275 | start += mask; |
276 | res->start &= ~mask; | 276 | start &= ~mask; |
277 | 277 | ||
278 | /* The caller updates the end field, we don't. */ | 278 | return start; |
279 | } | 279 | } |
280 | 280 | ||
281 | 281 | ||
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index cadbed679fb..2597f9545d8 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -1047,10 +1047,8 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus) | |||
1047 | 1047 | ||
1048 | struct pci_dev *dev = bus->self; | 1048 | struct pci_dev *dev = bus->self; |
1049 | 1049 | ||
1050 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) { | 1050 | pci_bus_for_each_resource(bus, res, i) { |
1051 | if ((res = bus->resource[i]) == NULL) | 1051 | if (!res || !res->flags) |
1052 | continue; | ||
1053 | if (!res->flags) | ||
1054 | continue; | 1052 | continue; |
1055 | if (i >= 3 && bus->self->transparent) | 1053 | if (i >= 3 && bus->self->transparent) |
1056 | continue; | 1054 | continue; |
@@ -1181,21 +1179,20 @@ static int skip_isa_ioresource_align(struct pci_dev *dev) | |||
1181 | * but we want to try to avoid allocating at 0x2900-0x2bff | 1179 | * but we want to try to avoid allocating at 0x2900-0x2bff |
1182 | * which might have be mirrored at 0x0100-0x03ff.. | 1180 | * which might have be mirrored at 0x0100-0x03ff.. |
1183 | */ | 1181 | */ |
1184 | void pcibios_align_resource(void *data, struct resource *res, | 1182 | resource_size_t pcibios_align_resource(void *data, const struct resource *res, |
1185 | resource_size_t size, resource_size_t align) | 1183 | resource_size_t size, resource_size_t align) |
1186 | { | 1184 | { |
1187 | struct pci_dev *dev = data; | 1185 | struct pci_dev *dev = data; |
1186 | resource_size_t start = res->start; | ||
1188 | 1187 | ||
1189 | if (res->flags & IORESOURCE_IO) { | 1188 | if (res->flags & IORESOURCE_IO) { |
1190 | resource_size_t start = res->start; | ||
1191 | |||
1192 | if (skip_isa_ioresource_align(dev)) | 1189 | if (skip_isa_ioresource_align(dev)) |
1193 | return; | 1190 | return start; |
1194 | if (start & 0x300) { | 1191 | if (start & 0x300) |
1195 | start = (start + 0x3ff) & ~0x3ff; | 1192 | start = (start + 0x3ff) & ~0x3ff; |
1196 | res->start = start; | ||
1197 | } | ||
1198 | } | 1193 | } |
1194 | |||
1195 | return start; | ||
1199 | } | 1196 | } |
1200 | EXPORT_SYMBOL(pcibios_align_resource); | 1197 | EXPORT_SYMBOL(pcibios_align_resource); |
1201 | 1198 | ||
@@ -1278,9 +1275,8 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus) | |||
1278 | pr_debug("PCI: Allocating bus resources for %04x:%02x...\n", | 1275 | pr_debug("PCI: Allocating bus resources for %04x:%02x...\n", |
1279 | pci_domain_nr(bus), bus->number); | 1276 | pci_domain_nr(bus), bus->number); |
1280 | 1277 | ||
1281 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) { | 1278 | pci_bus_for_each_resource(bus, res, i) { |
1282 | if ((res = bus->resource[i]) == NULL || !res->flags | 1279 | if (!res || !res->flags || res->start > res->end || res->parent) |
1283 | || res->start > res->end || res->parent) | ||
1284 | continue; | 1280 | continue; |
1285 | if (bus->parent == NULL) | 1281 | if (bus->parent == NULL) |
1286 | pr = (res->flags & IORESOURCE_IO) ? | 1282 | pr = (res->flags & IORESOURCE_IO) ? |
diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c index fd23a1d4b39..8b0c2082a78 100644 --- a/arch/powerpc/platforms/fsl_uli1575.c +++ b/arch/powerpc/platforms/fsl_uli1575.c | |||
@@ -222,6 +222,7 @@ static void __devinit quirk_final_uli5249(struct pci_dev *dev) | |||
222 | int i; | 222 | int i; |
223 | u8 *dummy; | 223 | u8 *dummy; |
224 | struct pci_bus *bus = dev->bus; | 224 | struct pci_bus *bus = dev->bus; |
225 | struct resource *res; | ||
225 | resource_size_t end = 0; | 226 | resource_size_t end = 0; |
226 | 227 | ||
227 | for (i = PCI_BRIDGE_RESOURCES; i < PCI_BRIDGE_RESOURCES+3; i++) { | 228 | for (i = PCI_BRIDGE_RESOURCES; i < PCI_BRIDGE_RESOURCES+3; i++) { |
@@ -230,13 +231,12 @@ static void __devinit quirk_final_uli5249(struct pci_dev *dev) | |||
230 | end = pci_resource_end(dev, i); | 231 | end = pci_resource_end(dev, i); |
231 | } | 232 | } |
232 | 233 | ||
233 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 234 | pci_bus_for_each_resource(bus, res, i) { |
234 | if ((bus->resource[i]) && | 235 | if (res && res->flags & IORESOURCE_MEM) { |
235 | (bus->resource[i]->flags & IORESOURCE_MEM)) { | 236 | if (res->end == end) |
236 | if (bus->resource[i]->end == end) | 237 | dummy = ioremap(res->start, 0x4); |
237 | dummy = ioremap(bus->resource[i]->start, 0x4); | ||
238 | else | 238 | else |
239 | dummy = ioremap(bus->resource[i]->end - 3, 0x4); | 239 | dummy = ioremap(res->end - 3, 0x4); |
240 | if (dummy) { | 240 | if (dummy) { |
241 | in_8(dummy); | 241 | in_8(dummy); |
242 | iounmap(dummy); | 242 | iounmap(dummy); |
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index c481df63902..96213fd172c 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c | |||
@@ -148,8 +148,8 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) | |||
148 | * addresses to be allocated in the 0x000-0x0ff region | 148 | * addresses to be allocated in the 0x000-0x0ff region |
149 | * modulo 0x400. | 149 | * modulo 0x400. |
150 | */ | 150 | */ |
151 | void pcibios_align_resource(void *data, struct resource *res, | 151 | resource_size_t pcibios_align_resource(void *data, const struct resource *res, |
152 | resource_size_t size, resource_size_t align) | 152 | resource_size_t size, resource_size_t align) |
153 | { | 153 | { |
154 | struct pci_dev *dev = data; | 154 | struct pci_dev *dev = data; |
155 | struct pci_channel *chan = dev->sysdata; | 155 | struct pci_channel *chan = dev->sysdata; |
@@ -171,7 +171,7 @@ void pcibios_align_resource(void *data, struct resource *res, | |||
171 | start = PCIBIOS_MIN_MEM + chan->mem_resource->start; | 171 | start = PCIBIOS_MIN_MEM + chan->mem_resource->start; |
172 | } | 172 | } |
173 | 173 | ||
174 | res->start = start; | 174 | return start; |
175 | } | 175 | } |
176 | 176 | ||
177 | void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | 177 | void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, |
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index 592b03d8516..37b66c60abe 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c | |||
@@ -722,9 +722,10 @@ void pcibios_update_irq(struct pci_dev *pdev, int irq) | |||
722 | { | 722 | { |
723 | } | 723 | } |
724 | 724 | ||
725 | void pcibios_align_resource(void *data, struct resource *res, | 725 | resource_size_t pcibios_align_resource(void *data, const struct resource *res, |
726 | resource_size_t size, resource_size_t align) | 726 | resource_size_t size, resource_size_t align) |
727 | { | 727 | { |
728 | return res->start; | ||
728 | } | 729 | } |
729 | 730 | ||
730 | int pcibios_enable_device(struct pci_dev *dev, int mask) | 731 | int pcibios_enable_device(struct pci_dev *dev, int mask) |
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 4e2724ec2bb..75e88c00bca 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c | |||
@@ -768,9 +768,10 @@ char * __devinit pcibios_setup(char *str) | |||
768 | return str; | 768 | return str; |
769 | } | 769 | } |
770 | 770 | ||
771 | void pcibios_align_resource(void *data, struct resource *res, | 771 | resource_size_t pcibios_align_resource(void *data, const struct resource *res, |
772 | resource_size_t size, resource_size_t align) | 772 | resource_size_t size, resource_size_t align) |
773 | { | 773 | { |
774 | return res->start; | ||
774 | } | 775 | } |
775 | 776 | ||
776 | int pcibios_enable_device(struct pci_dev *pdev, int mask) | 777 | int pcibios_enable_device(struct pci_dev *pdev, int mask) |
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index b4bf9a942ed..05b58ccb2e8 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000 | 29 | #define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000 |
30 | #define PCI_HAS_IO_ECS 0x40000 | 30 | #define PCI_HAS_IO_ECS 0x40000 |
31 | #define PCI_NOASSIGN_ROMS 0x80000 | 31 | #define PCI_NOASSIGN_ROMS 0x80000 |
32 | #define PCI_ROOT_NO_CRS 0x100000 | ||
32 | 33 | ||
33 | extern unsigned int pci_probe; | 34 | extern unsigned int pci_probe; |
34 | extern unsigned long pirq_table_addr; | 35 | extern unsigned long pirq_table_addr; |
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 959e548a703..5f11ff6f538 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c | |||
@@ -15,6 +15,51 @@ struct pci_root_info { | |||
15 | int busnum; | 15 | int busnum; |
16 | }; | 16 | }; |
17 | 17 | ||
18 | static bool pci_use_crs = true; | ||
19 | |||
20 | static int __init set_use_crs(const struct dmi_system_id *id) | ||
21 | { | ||
22 | pci_use_crs = true; | ||
23 | return 0; | ||
24 | } | ||
25 | |||
26 | static const struct dmi_system_id pci_use_crs_table[] __initconst = { | ||
27 | /* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */ | ||
28 | { | ||
29 | .callback = set_use_crs, | ||
30 | .ident = "IBM System x3800", | ||
31 | .matches = { | ||
32 | DMI_MATCH(DMI_SYS_VENDOR, "IBM"), | ||
33 | DMI_MATCH(DMI_PRODUCT_NAME, "x3800"), | ||
34 | }, | ||
35 | }, | ||
36 | {} | ||
37 | }; | ||
38 | |||
39 | void __init pci_acpi_crs_quirks(void) | ||
40 | { | ||
41 | int year; | ||
42 | |||
43 | if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008) | ||
44 | pci_use_crs = false; | ||
45 | |||
46 | dmi_check_system(pci_use_crs_table); | ||
47 | |||
48 | /* | ||
49 | * If the user specifies "pci=use_crs" or "pci=nocrs" explicitly, that | ||
50 | * takes precedence over anything we figured out above. | ||
51 | */ | ||
52 | if (pci_probe & PCI_ROOT_NO_CRS) | ||
53 | pci_use_crs = false; | ||
54 | else if (pci_probe & PCI_USE__CRS) | ||
55 | pci_use_crs = true; | ||
56 | |||
57 | printk(KERN_INFO "PCI: %s host bridge windows from ACPI; " | ||
58 | "if necessary, use \"pci=%s\" and report a bug\n", | ||
59 | pci_use_crs ? "Using" : "Ignoring", | ||
60 | pci_use_crs ? "nocrs" : "use_crs"); | ||
61 | } | ||
62 | |||
18 | static acpi_status | 63 | static acpi_status |
19 | resource_to_addr(struct acpi_resource *resource, | 64 | resource_to_addr(struct acpi_resource *resource, |
20 | struct acpi_resource_address64 *addr) | 65 | struct acpi_resource_address64 *addr) |
@@ -45,20 +90,6 @@ count_resource(struct acpi_resource *acpi_res, void *data) | |||
45 | return AE_OK; | 90 | return AE_OK; |
46 | } | 91 | } |
47 | 92 | ||
48 | static int | ||
49 | bus_has_transparent_bridge(struct pci_bus *bus) | ||
50 | { | ||
51 | struct pci_dev *dev; | ||
52 | |||
53 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
54 | u16 class = dev->class >> 8; | ||
55 | |||
56 | if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) | ||
57 | return true; | ||
58 | } | ||
59 | return false; | ||
60 | } | ||
61 | |||
62 | static void | 93 | static void |
63 | align_resource(struct acpi_device *bridge, struct resource *res) | 94 | align_resource(struct acpi_device *bridge, struct resource *res) |
64 | { | 95 | { |
@@ -92,12 +123,8 @@ setup_resource(struct acpi_resource *acpi_res, void *data) | |||
92 | acpi_status status; | 123 | acpi_status status; |
93 | unsigned long flags; | 124 | unsigned long flags; |
94 | struct resource *root; | 125 | struct resource *root; |
95 | int max_root_bus_resources = PCI_BUS_NUM_RESOURCES; | ||
96 | u64 start, end; | 126 | u64 start, end; |
97 | 127 | ||
98 | if (bus_has_transparent_bridge(info->bus)) | ||
99 | max_root_bus_resources -= 3; | ||
100 | |||
101 | status = resource_to_addr(acpi_res, &addr); | 128 | status = resource_to_addr(acpi_res, &addr); |
102 | if (!ACPI_SUCCESS(status)) | 129 | if (!ACPI_SUCCESS(status)) |
103 | return AE_OK; | 130 | return AE_OK; |
@@ -115,15 +142,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data) | |||
115 | 142 | ||
116 | start = addr.minimum + addr.translation_offset; | 143 | start = addr.minimum + addr.translation_offset; |
117 | end = start + addr.address_length - 1; | 144 | end = start + addr.address_length - 1; |
118 | if (info->res_num >= max_root_bus_resources) { | ||
119 | if (pci_probe & PCI_USE__CRS) | ||
120 | printk(KERN_WARNING "PCI: Failed to allocate " | ||
121 | "0x%lx-0x%lx from %s for %s due to _CRS " | ||
122 | "returning more than %d resource descriptors\n", | ||
123 | (unsigned long) start, (unsigned long) end, | ||
124 | root->name, info->name, max_root_bus_resources); | ||
125 | return AE_OK; | ||
126 | } | ||
127 | 145 | ||
128 | res = &info->res[info->res_num]; | 146 | res = &info->res[info->res_num]; |
129 | res->name = info->name; | 147 | res->name = info->name; |
@@ -133,7 +151,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data) | |||
133 | res->child = NULL; | 151 | res->child = NULL; |
134 | align_resource(info->bridge, res); | 152 | align_resource(info->bridge, res); |
135 | 153 | ||
136 | if (!(pci_probe & PCI_USE__CRS)) { | 154 | if (!pci_use_crs) { |
137 | dev_printk(KERN_DEBUG, &info->bridge->dev, | 155 | dev_printk(KERN_DEBUG, &info->bridge->dev, |
138 | "host bridge window %pR (ignored)\n", res); | 156 | "host bridge window %pR (ignored)\n", res); |
139 | return AE_OK; | 157 | return AE_OK; |
@@ -143,7 +161,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data) | |||
143 | dev_err(&info->bridge->dev, | 161 | dev_err(&info->bridge->dev, |
144 | "can't allocate host bridge window %pR\n", res); | 162 | "can't allocate host bridge window %pR\n", res); |
145 | } else { | 163 | } else { |
146 | info->bus->resource[info->res_num] = res; | 164 | pci_bus_add_resource(info->bus, res, 0); |
147 | info->res_num++; | 165 | info->res_num++; |
148 | if (addr.translation_offset) | 166 | if (addr.translation_offset) |
149 | dev_info(&info->bridge->dev, "host bridge window %pR " | 167 | dev_info(&info->bridge->dev, "host bridge window %pR " |
@@ -164,10 +182,8 @@ get_current_resources(struct acpi_device *device, int busnum, | |||
164 | struct pci_root_info info; | 182 | struct pci_root_info info; |
165 | size_t size; | 183 | size_t size; |
166 | 184 | ||
167 | if (!(pci_probe & PCI_USE__CRS)) | 185 | if (pci_use_crs) |
168 | dev_info(&device->dev, | 186 | pci_bus_remove_resources(bus); |
169 | "ignoring host bridge windows from ACPI; " | ||
170 | "boot with \"pci=use_crs\" to use them\n"); | ||
171 | 187 | ||
172 | info.bridge = device; | 188 | info.bridge = device; |
173 | info.bus = bus; | 189 | info.bus = bus; |
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c index f939d603adf..12d54ff3654 100644 --- a/arch/x86/pci/bus_numa.c +++ b/arch/x86/pci/bus_numa.c | |||
@@ -36,13 +36,14 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b) | |||
36 | printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n", | 36 | printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n", |
37 | b->number); | 37 | b->number); |
38 | 38 | ||
39 | pci_bus_remove_resources(b); | ||
39 | info = &pci_root_info[i]; | 40 | info = &pci_root_info[i]; |
40 | for (j = 0; j < info->res_num; j++) { | 41 | for (j = 0; j < info->res_num; j++) { |
41 | struct resource *res; | 42 | struct resource *res; |
42 | struct resource *root; | 43 | struct resource *root; |
43 | 44 | ||
44 | res = &info->res[j]; | 45 | res = &info->res[j]; |
45 | b->resource[j] = res; | 46 | pci_bus_add_resource(b, res, 0); |
46 | if (res->flags & IORESOURCE_IO) | 47 | if (res->flags & IORESOURCE_IO) |
47 | root = &ioport_resource; | 48 | root = &ioport_resource; |
48 | else | 49 | else |
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h index adbc23fe82a..731b64ee8d8 100644 --- a/arch/x86/pci/bus_numa.h +++ b/arch/x86/pci/bus_numa.h | |||
@@ -2,8 +2,7 @@ | |||
2 | 2 | ||
3 | /* | 3 | /* |
4 | * sub bus (transparent) will use entres from 3 to store extra from | 4 | * sub bus (transparent) will use entres from 3 to store extra from |
5 | * root, so need to make sure we have enough slot there, Should we | 5 | * root, so need to make sure we have enough slot there. |
6 | * increase PCI_BUS_NUM_RESOURCES? | ||
7 | */ | 6 | */ |
8 | #define RES_NUM 16 | 7 | #define RES_NUM 16 |
9 | struct pci_root_info { | 8 | struct pci_root_info { |
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index d2552c68e94..3736176acaa 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c | |||
@@ -520,6 +520,9 @@ char * __devinit pcibios_setup(char *str) | |||
520 | } else if (!strcmp(str, "use_crs")) { | 520 | } else if (!strcmp(str, "use_crs")) { |
521 | pci_probe |= PCI_USE__CRS; | 521 | pci_probe |= PCI_USE__CRS; |
522 | return NULL; | 522 | return NULL; |
523 | } else if (!strcmp(str, "nocrs")) { | ||
524 | pci_probe |= PCI_ROOT_NO_CRS; | ||
525 | return NULL; | ||
523 | } else if (!strcmp(str, "earlydump")) { | 526 | } else if (!strcmp(str, "earlydump")) { |
524 | pci_early_dump_regs = 1; | 527 | pci_early_dump_regs = 1; |
525 | return NULL; | 528 | return NULL; |
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 5dc9e8c63fc..5a8fbf8d4ca 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c | |||
@@ -60,22 +60,20 @@ skip_isa_ioresource_align(struct pci_dev *dev) { | |||
60 | * but we want to try to avoid allocating at 0x2900-0x2bff | 60 | * but we want to try to avoid allocating at 0x2900-0x2bff |
61 | * which might have be mirrored at 0x0100-0x03ff.. | 61 | * which might have be mirrored at 0x0100-0x03ff.. |
62 | */ | 62 | */ |
63 | void | 63 | resource_size_t |
64 | pcibios_align_resource(void *data, struct resource *res, | 64 | pcibios_align_resource(void *data, const struct resource *res, |
65 | resource_size_t size, resource_size_t align) | 65 | resource_size_t size, resource_size_t align) |
66 | { | 66 | { |
67 | struct pci_dev *dev = data; | 67 | struct pci_dev *dev = data; |
68 | resource_size_t start = res->start; | ||
68 | 69 | ||
69 | if (res->flags & IORESOURCE_IO) { | 70 | if (res->flags & IORESOURCE_IO) { |
70 | resource_size_t start = res->start; | ||
71 | |||
72 | if (skip_isa_ioresource_align(dev)) | 71 | if (skip_isa_ioresource_align(dev)) |
73 | return; | 72 | return start; |
74 | if (start & 0x300) { | 73 | if (start & 0x300) |
75 | start = (start + 0x3ff) & ~0x3ff; | 74 | start = (start + 0x3ff) & ~0x3ff; |
76 | res->start = start; | ||
77 | } | ||
78 | } | 75 | } |
76 | return start; | ||
79 | } | 77 | } |
80 | EXPORT_SYMBOL(pcibios_align_resource); | 78 | EXPORT_SYMBOL(pcibios_align_resource); |
81 | 79 | ||
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 0696d506c4a..b02f6d8ac92 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c | |||
@@ -590,6 +590,8 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route | |||
590 | case PCI_DEVICE_ID_INTEL_ICH10_1: | 590 | case PCI_DEVICE_ID_INTEL_ICH10_1: |
591 | case PCI_DEVICE_ID_INTEL_ICH10_2: | 591 | case PCI_DEVICE_ID_INTEL_ICH10_2: |
592 | case PCI_DEVICE_ID_INTEL_ICH10_3: | 592 | case PCI_DEVICE_ID_INTEL_ICH10_3: |
593 | case PCI_DEVICE_ID_INTEL_CPT_LPC1: | ||
594 | case PCI_DEVICE_ID_INTEL_CPT_LPC2: | ||
593 | r->name = "PIIX/ICH"; | 595 | r->name = "PIIX/ICH"; |
594 | r->get = pirq_piix_get; | 596 | r->get = pirq_piix_get; |
595 | r->set = pirq_piix_set; | 597 | r->set = pirq_piix_set; |
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index b19d1e54201..8f3f9a50b1e 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c | |||
@@ -303,22 +303,17 @@ static void __init pci_mmcfg_check_end_bus_number(void) | |||
303 | { | 303 | { |
304 | struct pci_mmcfg_region *cfg, *cfgx; | 304 | struct pci_mmcfg_region *cfg, *cfgx; |
305 | 305 | ||
306 | /* last one*/ | 306 | /* Fixup overlaps */ |
307 | cfg = list_entry(pci_mmcfg_list.prev, typeof(*cfg), list); | ||
308 | if (cfg) | ||
309 | if (cfg->end_bus < cfg->start_bus) | ||
310 | cfg->end_bus = 255; | ||
311 | |||
312 | if (list_is_singular(&pci_mmcfg_list)) | ||
313 | return; | ||
314 | |||
315 | /* don't overlap please */ | ||
316 | list_for_each_entry(cfg, &pci_mmcfg_list, list) { | 307 | list_for_each_entry(cfg, &pci_mmcfg_list, list) { |
317 | if (cfg->end_bus < cfg->start_bus) | 308 | if (cfg->end_bus < cfg->start_bus) |
318 | cfg->end_bus = 255; | 309 | cfg->end_bus = 255; |
319 | 310 | ||
311 | /* Don't access the list head ! */ | ||
312 | if (cfg->list.next == &pci_mmcfg_list) | ||
313 | break; | ||
314 | |||
320 | cfgx = list_entry(cfg->list.next, typeof(*cfg), list); | 315 | cfgx = list_entry(cfg->list.next, typeof(*cfg), list); |
321 | if (cfg != cfgx && cfg->end_bus >= cfgx->start_bus) | 316 | if (cfg->end_bus >= cfgx->start_bus) |
322 | cfg->end_bus = cfgx->start_bus - 1; | 317 | cfg->end_bus = cfgx->start_bus - 1; |
323 | } | 318 | } |
324 | } | 319 | } |
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index b7c073484e0..cd102693120 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c | |||
@@ -69,26 +69,25 @@ static int pci_bus_count; | |||
69 | * but we want to try to avoid allocating at 0x2900-0x2bff | 69 | * but we want to try to avoid allocating at 0x2900-0x2bff |
70 | * which might have be mirrored at 0x0100-0x03ff.. | 70 | * which might have be mirrored at 0x0100-0x03ff.. |
71 | */ | 71 | */ |
72 | void | 72 | resource_size_t |
73 | pcibios_align_resource(void *data, struct resource *res, resource_size_t size, | 73 | pcibios_align_resource(void *data, const struct resource *res, |
74 | resource_size_t align) | 74 | resource_size_t size, resource_size_t align) |
75 | { | 75 | { |
76 | struct pci_dev *dev = data; | 76 | struct pci_dev *dev = data; |
77 | resource_size_t start = res->start; | ||
77 | 78 | ||
78 | if (res->flags & IORESOURCE_IO) { | 79 | if (res->flags & IORESOURCE_IO) { |
79 | resource_size_t start = res->start; | ||
80 | |||
81 | if (size > 0x100) { | 80 | if (size > 0x100) { |
82 | printk(KERN_ERR "PCI: I/O Region %s/%d too large" | 81 | printk(KERN_ERR "PCI: I/O Region %s/%d too large" |
83 | " (%ld bytes)\n", pci_name(dev), | 82 | " (%ld bytes)\n", pci_name(dev), |
84 | dev->resource - res, size); | 83 | dev->resource - res, size); |
85 | } | 84 | } |
86 | 85 | ||
87 | if (start & 0x300) { | 86 | if (start & 0x300) |
88 | start = (start + 0x3ff) & ~0x3ff; | 87 | start = (start + 0x3ff) & ~0x3ff; |
89 | res->start = start; | ||
90 | } | ||
91 | } | 88 | } |
89 | |||
90 | return start; | ||
92 | } | 91 | } |
93 | 92 | ||
94 | int | 93 | int |
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 0bba148a2c6..4ced54f7a5d 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h | |||
@@ -76,12 +76,9 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node *node, | |||
76 | * evgpe - GPE handling and dispatch | 76 | * evgpe - GPE handling and dispatch |
77 | */ | 77 | */ |
78 | acpi_status | 78 | acpi_status |
79 | acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info, | 79 | acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info); |
80 | u8 type); | ||
81 | 80 | ||
82 | acpi_status | 81 | acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); |
83 | acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info, | ||
84 | u8 write_to_hardware); | ||
85 | 82 | ||
86 | acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); | 83 | acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); |
87 | 84 | ||
@@ -122,9 +119,6 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, | |||
122 | u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list); | 119 | u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list); |
123 | 120 | ||
124 | acpi_status | 121 | acpi_status |
125 | acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type); | ||
126 | |||
127 | acpi_status | ||
128 | acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info); | 122 | acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info); |
129 | 123 | ||
130 | acpi_status acpi_ev_gpe_initialize(void); | 124 | acpi_status acpi_ev_gpe_initialize(void); |
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 81e64f47867..13cb80caacd 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h | |||
@@ -426,6 +426,8 @@ struct acpi_gpe_event_info { | |||
426 | struct acpi_gpe_register_info *register_info; /* Backpointer to register info */ | 426 | struct acpi_gpe_register_info *register_info; /* Backpointer to register info */ |
427 | u8 flags; /* Misc info about this GPE */ | 427 | u8 flags; /* Misc info about this GPE */ |
428 | u8 gpe_number; /* This GPE */ | 428 | u8 gpe_number; /* This GPE */ |
429 | u8 runtime_count; | ||
430 | u8 wakeup_count; | ||
429 | }; | 431 | }; |
430 | 432 | ||
431 | /* Information about a GPE register pair, one per each status/enable pair in an array */ | 433 | /* Information about a GPE register pair, one per each status/enable pair in an array */ |
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 64062b1be3e..07f6e2ea2ee 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h | |||
@@ -287,8 +287,10 @@ struct acpi_object_buffer_field { | |||
287 | 287 | ||
288 | struct acpi_object_notify_handler { | 288 | struct acpi_object_notify_handler { |
289 | ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Parent device */ | 289 | ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Parent device */ |
290 | u32 handler_type; | ||
290 | acpi_notify_handler handler; | 291 | acpi_notify_handler handler; |
291 | void *context; | 292 | void *context; |
293 | struct acpi_object_notify_handler *next; | ||
292 | }; | 294 | }; |
293 | 295 | ||
294 | struct acpi_object_addr_handler { | 296 | struct acpi_object_addr_handler { |
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index afacf4416c7..0b453467a5a 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c | |||
@@ -54,54 +54,9 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context); | |||
54 | 54 | ||
55 | /******************************************************************************* | 55 | /******************************************************************************* |
56 | * | 56 | * |
57 | * FUNCTION: acpi_ev_set_gpe_type | ||
58 | * | ||
59 | * PARAMETERS: gpe_event_info - GPE to set | ||
60 | * Type - New type | ||
61 | * | ||
62 | * RETURN: Status | ||
63 | * | ||
64 | * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run) | ||
65 | * | ||
66 | ******************************************************************************/ | ||
67 | |||
68 | acpi_status | ||
69 | acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type) | ||
70 | { | ||
71 | acpi_status status; | ||
72 | |||
73 | ACPI_FUNCTION_TRACE(ev_set_gpe_type); | ||
74 | |||
75 | /* Validate type and update register enable masks */ | ||
76 | |||
77 | switch (type) { | ||
78 | case ACPI_GPE_TYPE_WAKE: | ||
79 | case ACPI_GPE_TYPE_RUNTIME: | ||
80 | case ACPI_GPE_TYPE_WAKE_RUN: | ||
81 | break; | ||
82 | |||
83 | default: | ||
84 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
85 | } | ||
86 | |||
87 | /* Disable the GPE if currently enabled */ | ||
88 | |||
89 | status = acpi_ev_disable_gpe(gpe_event_info); | ||
90 | |||
91 | /* Clear the type bits and insert the new Type */ | ||
92 | |||
93 | gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; | ||
94 | gpe_event_info->flags |= type; | ||
95 | return_ACPI_STATUS(status); | ||
96 | } | ||
97 | |||
98 | /******************************************************************************* | ||
99 | * | ||
100 | * FUNCTION: acpi_ev_update_gpe_enable_masks | 57 | * FUNCTION: acpi_ev_update_gpe_enable_masks |
101 | * | 58 | * |
102 | * PARAMETERS: gpe_event_info - GPE to update | 59 | * PARAMETERS: gpe_event_info - GPE to update |
103 | * Type - What to do: ACPI_GPE_DISABLE or | ||
104 | * ACPI_GPE_ENABLE | ||
105 | * | 60 | * |
106 | * RETURN: Status | 61 | * RETURN: Status |
107 | * | 62 | * |
@@ -110,8 +65,7 @@ acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type) | |||
110 | ******************************************************************************/ | 65 | ******************************************************************************/ |
111 | 66 | ||
112 | acpi_status | 67 | acpi_status |
113 | acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info, | 68 | acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info) |
114 | u8 type) | ||
115 | { | 69 | { |
116 | struct acpi_gpe_register_info *gpe_register_info; | 70 | struct acpi_gpe_register_info *gpe_register_info; |
117 | u8 register_bit; | 71 | u8 register_bit; |
@@ -127,37 +81,14 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info, | |||
127 | (1 << | 81 | (1 << |
128 | (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number)); | 82 | (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number)); |
129 | 83 | ||
130 | /* 1) Disable case. Simply clear all enable bits */ | 84 | ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, register_bit); |
131 | 85 | ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit); | |
132 | if (type == ACPI_GPE_DISABLE) { | ||
133 | ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, | ||
134 | register_bit); | ||
135 | ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit); | ||
136 | return_ACPI_STATUS(AE_OK); | ||
137 | } | ||
138 | |||
139 | /* 2) Enable case. Set/Clear the appropriate enable bits */ | ||
140 | 86 | ||
141 | switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { | 87 | if (gpe_event_info->runtime_count) |
142 | case ACPI_GPE_TYPE_WAKE: | ||
143 | ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit); | ||
144 | ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit); | ||
145 | break; | ||
146 | |||
147 | case ACPI_GPE_TYPE_RUNTIME: | ||
148 | ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, | ||
149 | register_bit); | ||
150 | ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit); | 88 | ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit); |
151 | break; | ||
152 | 89 | ||
153 | case ACPI_GPE_TYPE_WAKE_RUN: | 90 | if (gpe_event_info->wakeup_count) |
154 | ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit); | 91 | ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit); |
155 | ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit); | ||
156 | break; | ||
157 | |||
158 | default: | ||
159 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
160 | } | ||
161 | 92 | ||
162 | return_ACPI_STATUS(AE_OK); | 93 | return_ACPI_STATUS(AE_OK); |
163 | } | 94 | } |
@@ -167,8 +98,6 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info, | |||
167 | * FUNCTION: acpi_ev_enable_gpe | 98 | * FUNCTION: acpi_ev_enable_gpe |
168 | * | 99 | * |
169 | * PARAMETERS: gpe_event_info - GPE to enable | 100 | * PARAMETERS: gpe_event_info - GPE to enable |
170 | * write_to_hardware - Enable now, or just mark data structs | ||
171 | * (WAKE GPEs should be deferred) | ||
172 | * | 101 | * |
173 | * RETURN: Status | 102 | * RETURN: Status |
174 | * | 103 | * |
@@ -176,9 +105,7 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info, | |||
176 | * | 105 | * |
177 | ******************************************************************************/ | 106 | ******************************************************************************/ |
178 | 107 | ||
179 | acpi_status | 108 | acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) |
180 | acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info, | ||
181 | u8 write_to_hardware) | ||
182 | { | 109 | { |
183 | acpi_status status; | 110 | acpi_status status; |
184 | 111 | ||
@@ -186,47 +113,20 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info, | |||
186 | 113 | ||
187 | /* Make sure HW enable masks are updated */ | 114 | /* Make sure HW enable masks are updated */ |
188 | 115 | ||
189 | status = | 116 | status = acpi_ev_update_gpe_enable_masks(gpe_event_info); |
190 | acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_ENABLE); | 117 | if (ACPI_FAILURE(status)) |
191 | if (ACPI_FAILURE(status)) { | ||
192 | return_ACPI_STATUS(status); | 118 | return_ACPI_STATUS(status); |
193 | } | ||
194 | 119 | ||
195 | /* Mark wake-enabled or HW enable, or both */ | 120 | /* Mark wake-enabled or HW enable, or both */ |
196 | 121 | ||
197 | switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { | 122 | if (gpe_event_info->runtime_count) { |
198 | case ACPI_GPE_TYPE_WAKE: | 123 | /* Clear the GPE (of stale events), then enable it */ |
199 | 124 | status = acpi_hw_clear_gpe(gpe_event_info); | |
200 | ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); | 125 | if (ACPI_FAILURE(status)) |
201 | break; | 126 | return_ACPI_STATUS(status); |
202 | |||
203 | case ACPI_GPE_TYPE_WAKE_RUN: | ||
204 | |||
205 | ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); | ||
206 | |||
207 | /*lint -fallthrough */ | ||
208 | |||
209 | case ACPI_GPE_TYPE_RUNTIME: | ||
210 | |||
211 | ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); | ||
212 | |||
213 | if (write_to_hardware) { | ||
214 | |||
215 | /* Clear the GPE (of stale events), then enable it */ | ||
216 | |||
217 | status = acpi_hw_clear_gpe(gpe_event_info); | ||
218 | if (ACPI_FAILURE(status)) { | ||
219 | return_ACPI_STATUS(status); | ||
220 | } | ||
221 | |||
222 | /* Enable the requested runtime GPE */ | ||
223 | |||
224 | status = acpi_hw_write_gpe_enable_reg(gpe_event_info); | ||
225 | } | ||
226 | break; | ||
227 | 127 | ||
228 | default: | 128 | /* Enable the requested runtime GPE */ |
229 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 129 | status = acpi_hw_write_gpe_enable_reg(gpe_event_info); |
230 | } | 130 | } |
231 | 131 | ||
232 | return_ACPI_STATUS(AE_OK); | 132 | return_ACPI_STATUS(AE_OK); |
@@ -252,34 +152,9 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
252 | 152 | ||
253 | /* Make sure HW enable masks are updated */ | 153 | /* Make sure HW enable masks are updated */ |
254 | 154 | ||
255 | status = | 155 | status = acpi_ev_update_gpe_enable_masks(gpe_event_info); |
256 | acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_DISABLE); | 156 | if (ACPI_FAILURE(status)) |
257 | if (ACPI_FAILURE(status)) { | ||
258 | return_ACPI_STATUS(status); | 157 | return_ACPI_STATUS(status); |
259 | } | ||
260 | |||
261 | /* Clear the appropriate enabled flags for this GPE */ | ||
262 | |||
263 | switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { | ||
264 | case ACPI_GPE_TYPE_WAKE: | ||
265 | ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); | ||
266 | break; | ||
267 | |||
268 | case ACPI_GPE_TYPE_WAKE_RUN: | ||
269 | ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); | ||
270 | |||
271 | /* fallthrough */ | ||
272 | |||
273 | case ACPI_GPE_TYPE_RUNTIME: | ||
274 | |||
275 | /* Disable the requested runtime GPE */ | ||
276 | |||
277 | ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); | ||
278 | break; | ||
279 | |||
280 | default: | ||
281 | break; | ||
282 | } | ||
283 | 158 | ||
284 | /* | 159 | /* |
285 | * Even if we don't know the GPE type, make sure that we always | 160 | * Even if we don't know the GPE type, make sure that we always |
@@ -521,7 +396,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) | |||
521 | 396 | ||
522 | /* Set the GPE flags for return to enabled state */ | 397 | /* Set the GPE flags for return to enabled state */ |
523 | 398 | ||
524 | (void)acpi_ev_enable_gpe(gpe_event_info, FALSE); | 399 | (void)acpi_ev_update_gpe_enable_masks(gpe_event_info); |
525 | 400 | ||
526 | /* | 401 | /* |
527 | * Take a snapshot of the GPE info for this level - we copy the info to | 402 | * Take a snapshot of the GPE info for this level - we copy the info to |
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 24792090018..3d4c4aca11c 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c | |||
@@ -258,7 +258,6 @@ acpi_ev_save_method_info(acpi_handle obj_handle, | |||
258 | u32 gpe_number; | 258 | u32 gpe_number; |
259 | char name[ACPI_NAME_SIZE + 1]; | 259 | char name[ACPI_NAME_SIZE + 1]; |
260 | u8 type; | 260 | u8 type; |
261 | acpi_status status; | ||
262 | 261 | ||
263 | ACPI_FUNCTION_TRACE(ev_save_method_info); | 262 | ACPI_FUNCTION_TRACE(ev_save_method_info); |
264 | 263 | ||
@@ -325,26 +324,20 @@ acpi_ev_save_method_info(acpi_handle obj_handle, | |||
325 | 324 | ||
326 | /* | 325 | /* |
327 | * Now we can add this information to the gpe_event_info block for use | 326 | * Now we can add this information to the gpe_event_info block for use |
328 | * during dispatch of this GPE. Default type is RUNTIME, although this may | 327 | * during dispatch of this GPE. |
329 | * change when the _PRW methods are executed later. | ||
330 | */ | 328 | */ |
331 | gpe_event_info = | 329 | gpe_event_info = |
332 | &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; | 330 | &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; |
333 | 331 | ||
334 | gpe_event_info->flags = (u8) | 332 | gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD); |
335 | (type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME); | ||
336 | 333 | ||
337 | gpe_event_info->dispatch.method_node = | 334 | gpe_event_info->dispatch.method_node = |
338 | (struct acpi_namespace_node *)obj_handle; | 335 | (struct acpi_namespace_node *)obj_handle; |
339 | 336 | ||
340 | /* Update enable mask, but don't enable the HW GPE as of yet */ | ||
341 | |||
342 | status = acpi_ev_enable_gpe(gpe_event_info, FALSE); | ||
343 | |||
344 | ACPI_DEBUG_PRINT((ACPI_DB_LOAD, | 337 | ACPI_DEBUG_PRINT((ACPI_DB_LOAD, |
345 | "Registered GPE method %s as GPE number 0x%.2X\n", | 338 | "Registered GPE method %s as GPE number 0x%.2X\n", |
346 | name, gpe_number)); | 339 | name, gpe_number)); |
347 | return_ACPI_STATUS(status); | 340 | return_ACPI_STATUS(AE_OK); |
348 | } | 341 | } |
349 | 342 | ||
350 | /******************************************************************************* | 343 | /******************************************************************************* |
@@ -454,20 +447,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, | |||
454 | gpe_block-> | 447 | gpe_block-> |
455 | block_base_number]; | 448 | block_base_number]; |
456 | 449 | ||
457 | /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */ | 450 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; |
458 | |||
459 | gpe_event_info->flags &= | ||
460 | ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED); | ||
461 | |||
462 | status = | ||
463 | acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE); | ||
464 | if (ACPI_FAILURE(status)) { | ||
465 | goto cleanup; | ||
466 | } | ||
467 | |||
468 | status = | ||
469 | acpi_ev_update_gpe_enable_masks(gpe_event_info, | ||
470 | ACPI_GPE_DISABLE); | ||
471 | } | 451 | } |
472 | 452 | ||
473 | cleanup: | 453 | cleanup: |
@@ -989,7 +969,6 @@ acpi_status | |||
989 | acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | 969 | acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, |
990 | struct acpi_gpe_block_info *gpe_block) | 970 | struct acpi_gpe_block_info *gpe_block) |
991 | { | 971 | { |
992 | acpi_status status; | ||
993 | struct acpi_gpe_event_info *gpe_event_info; | 972 | struct acpi_gpe_event_info *gpe_event_info; |
994 | struct acpi_gpe_walk_info gpe_info; | 973 | struct acpi_gpe_walk_info gpe_info; |
995 | u32 wake_gpe_count; | 974 | u32 wake_gpe_count; |
@@ -1019,42 +998,50 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | |||
1019 | gpe_info.gpe_block = gpe_block; | 998 | gpe_info.gpe_block = gpe_block; |
1020 | gpe_info.gpe_device = gpe_device; | 999 | gpe_info.gpe_device = gpe_device; |
1021 | 1000 | ||
1022 | status = | 1001 | acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
1023 | acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
1024 | ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, | 1002 | ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, |
1025 | acpi_ev_match_prw_and_gpe, NULL, | 1003 | acpi_ev_match_prw_and_gpe, NULL, |
1026 | &gpe_info, NULL); | 1004 | &gpe_info, NULL); |
1027 | } | 1005 | } |
1028 | 1006 | ||
1029 | /* | 1007 | /* |
1030 | * Enable all GPEs in this block that have these attributes: | 1008 | * Enable all GPEs that have a corresponding method and aren't |
1031 | * 1) are "runtime" or "run/wake" GPEs, and | 1009 | * capable of generating wakeups. Any other GPEs within this block |
1032 | * 2) have a corresponding _Lxx or _Exx method | 1010 | * must be enabled via the acpi_enable_gpe() interface. |
1033 | * | ||
1034 | * Any other GPEs within this block must be enabled via the | ||
1035 | * acpi_enable_gpe() external interface. | ||
1036 | */ | 1011 | */ |
1037 | wake_gpe_count = 0; | 1012 | wake_gpe_count = 0; |
1038 | gpe_enabled_count = 0; | 1013 | gpe_enabled_count = 0; |
1014 | if (gpe_device == acpi_gbl_fadt_gpe_device) | ||
1015 | gpe_device = NULL; | ||
1039 | 1016 | ||
1040 | for (i = 0; i < gpe_block->register_count; i++) { | 1017 | for (i = 0; i < gpe_block->register_count; i++) { |
1041 | for (j = 0; j < 8; j++) { | 1018 | for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { |
1019 | acpi_status status; | ||
1020 | acpi_size gpe_index; | ||
1021 | int gpe_number; | ||
1042 | 1022 | ||
1043 | /* Get the info block for this particular GPE */ | 1023 | /* Get the info block for this particular GPE */ |
1024 | gpe_index = (acpi_size)i * ACPI_GPE_REGISTER_WIDTH + j; | ||
1025 | gpe_event_info = &gpe_block->event_info[gpe_index]; | ||
1044 | 1026 | ||
1045 | gpe_event_info = &gpe_block->event_info[((acpi_size) i * | 1027 | if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) { |
1046 | ACPI_GPE_REGISTER_WIDTH) | ||
1047 | + j]; | ||
1048 | |||
1049 | if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == | ||
1050 | ACPI_GPE_DISPATCH_METHOD) && | ||
1051 | (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) { | ||
1052 | gpe_enabled_count++; | ||
1053 | } | ||
1054 | |||
1055 | if (gpe_event_info->flags & ACPI_GPE_TYPE_WAKE) { | ||
1056 | wake_gpe_count++; | 1028 | wake_gpe_count++; |
1029 | if (acpi_gbl_leave_wake_gpes_disabled) | ||
1030 | continue; | ||
1057 | } | 1031 | } |
1032 | |||
1033 | if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)) | ||
1034 | continue; | ||
1035 | |||
1036 | gpe_number = gpe_index + gpe_block->block_base_number; | ||
1037 | status = acpi_enable_gpe(gpe_device, gpe_number, | ||
1038 | ACPI_GPE_TYPE_RUNTIME); | ||
1039 | if (ACPI_FAILURE(status)) | ||
1040 | ACPI_ERROR((AE_INFO, | ||
1041 | "Failed to enable GPE %02X\n", | ||
1042 | gpe_number)); | ||
1043 | else | ||
1044 | gpe_enabled_count++; | ||
1058 | } | 1045 | } |
1059 | } | 1046 | } |
1060 | 1047 | ||
@@ -1062,15 +1049,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | |||
1062 | "Found %u Wake, Enabled %u Runtime GPEs in this block\n", | 1049 | "Found %u Wake, Enabled %u Runtime GPEs in this block\n", |
1063 | wake_gpe_count, gpe_enabled_count)); | 1050 | wake_gpe_count, gpe_enabled_count)); |
1064 | 1051 | ||
1065 | /* Enable all valid runtime GPEs found above */ | 1052 | return_ACPI_STATUS(AE_OK); |
1066 | |||
1067 | status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block, NULL); | ||
1068 | if (ACPI_FAILURE(status)) { | ||
1069 | ACPI_ERROR((AE_INFO, "Could not enable GPEs in GpeBlock %p", | ||
1070 | gpe_block)); | ||
1071 | } | ||
1072 | |||
1073 | return_ACPI_STATUS(status); | ||
1074 | } | 1053 | } |
1075 | 1054 | ||
1076 | /******************************************************************************* | 1055 | /******************************************************************************* |
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index ce224e1eaa8..8f0fac6c436 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c | |||
@@ -259,9 +259,15 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context) | |||
259 | 259 | ||
260 | handler_obj = notify_info->notify.handler_obj; | 260 | handler_obj = notify_info->notify.handler_obj; |
261 | if (handler_obj) { | 261 | if (handler_obj) { |
262 | handler_obj->notify.handler(notify_info->notify.node, | 262 | struct acpi_object_notify_handler *notifier; |
263 | notify_info->notify.value, | 263 | |
264 | handler_obj->notify.context); | 264 | notifier = &handler_obj->notify; |
265 | while (notifier) { | ||
266 | notifier->handler(notify_info->notify.node, | ||
267 | notify_info->notify.value, | ||
268 | notifier->context); | ||
269 | notifier = notifier->next; | ||
270 | } | ||
265 | } | 271 | } |
266 | 272 | ||
267 | /* All done with the info object */ | 273 | /* All done with the info object */ |
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 2fe0809d4eb..474e2cab603 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c | |||
@@ -218,6 +218,72 @@ ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler) | |||
218 | 218 | ||
219 | /******************************************************************************* | 219 | /******************************************************************************* |
220 | * | 220 | * |
221 | * FUNCTION: acpi_populate_handler_object | ||
222 | * | ||
223 | * PARAMETERS: handler_obj - Handler object to populate | ||
224 | * handler_type - The type of handler: | ||
225 | * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) | ||
226 | * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) | ||
227 | * ACPI_ALL_NOTIFY: both system and device | ||
228 | * handler - Address of the handler | ||
229 | * context - Value passed to the handler on each GPE | ||
230 | * next - Address of a handler object to link to | ||
231 | * | ||
232 | * RETURN: None | ||
233 | * | ||
234 | * DESCRIPTION: Populate a handler object. | ||
235 | * | ||
236 | ******************************************************************************/ | ||
237 | static void | ||
238 | acpi_populate_handler_object(struct acpi_object_notify_handler *handler_obj, | ||
239 | u32 handler_type, | ||
240 | acpi_notify_handler handler, void *context, | ||
241 | struct acpi_object_notify_handler *next) | ||
242 | { | ||
243 | handler_obj->handler_type = handler_type; | ||
244 | handler_obj->handler = handler; | ||
245 | handler_obj->context = context; | ||
246 | handler_obj->next = next; | ||
247 | } | ||
248 | |||
249 | /******************************************************************************* | ||
250 | * | ||
251 | * FUNCTION: acpi_add_handler_object | ||
252 | * | ||
253 | * PARAMETERS: parent_obj - Parent of the new object | ||
254 | * handler - Address of the handler | ||
255 | * context - Value passed to the handler on each GPE | ||
256 | * | ||
257 | * RETURN: Status | ||
258 | * | ||
259 | * DESCRIPTION: Create a new handler object and populate it. | ||
260 | * | ||
261 | ******************************************************************************/ | ||
262 | static acpi_status | ||
263 | acpi_add_handler_object(struct acpi_object_notify_handler *parent_obj, | ||
264 | acpi_notify_handler handler, void *context) | ||
265 | { | ||
266 | struct acpi_object_notify_handler *handler_obj; | ||
267 | |||
268 | /* The parent must not be a defice notify handler object. */ | ||
269 | if (parent_obj->handler_type & ACPI_DEVICE_NOTIFY) | ||
270 | return AE_BAD_PARAMETER; | ||
271 | |||
272 | handler_obj = ACPI_ALLOCATE_ZEROED(sizeof(*handler_obj)); | ||
273 | if (!handler_obj) | ||
274 | return AE_NO_MEMORY; | ||
275 | |||
276 | acpi_populate_handler_object(handler_obj, | ||
277 | ACPI_SYSTEM_NOTIFY, | ||
278 | handler, context, | ||
279 | parent_obj->next); | ||
280 | parent_obj->next = handler_obj; | ||
281 | |||
282 | return AE_OK; | ||
283 | } | ||
284 | |||
285 | /******************************************************************************* | ||
286 | * | ||
221 | * FUNCTION: acpi_install_notify_handler | 287 | * FUNCTION: acpi_install_notify_handler |
222 | * | 288 | * |
223 | * PARAMETERS: Device - The device for which notifies will be handled | 289 | * PARAMETERS: Device - The device for which notifies will be handled |
@@ -316,15 +382,32 @@ acpi_install_notify_handler(acpi_handle device, | |||
316 | obj_desc = acpi_ns_get_attached_object(node); | 382 | obj_desc = acpi_ns_get_attached_object(node); |
317 | if (obj_desc) { | 383 | if (obj_desc) { |
318 | 384 | ||
319 | /* Object exists - make sure there's no handler */ | 385 | /* Object exists. */ |
320 | 386 | ||
321 | if (((handler_type & ACPI_SYSTEM_NOTIFY) && | 387 | /* For a device notify, make sure there's no handler. */ |
322 | obj_desc->common_notify.system_notify) || | 388 | if ((handler_type & ACPI_DEVICE_NOTIFY) && |
323 | ((handler_type & ACPI_DEVICE_NOTIFY) && | 389 | obj_desc->common_notify.device_notify) { |
324 | obj_desc->common_notify.device_notify)) { | ||
325 | status = AE_ALREADY_EXISTS; | 390 | status = AE_ALREADY_EXISTS; |
326 | goto unlock_and_exit; | 391 | goto unlock_and_exit; |
327 | } | 392 | } |
393 | |||
394 | /* System notifies may have more handlers installed. */ | ||
395 | notify_obj = obj_desc->common_notify.system_notify; | ||
396 | |||
397 | if ((handler_type & ACPI_SYSTEM_NOTIFY) && notify_obj) { | ||
398 | struct acpi_object_notify_handler *parent_obj; | ||
399 | |||
400 | if (handler_type & ACPI_DEVICE_NOTIFY) { | ||
401 | status = AE_ALREADY_EXISTS; | ||
402 | goto unlock_and_exit; | ||
403 | } | ||
404 | |||
405 | parent_obj = ¬ify_obj->notify; | ||
406 | status = acpi_add_handler_object(parent_obj, | ||
407 | handler, | ||
408 | context); | ||
409 | goto unlock_and_exit; | ||
410 | } | ||
328 | } else { | 411 | } else { |
329 | /* Create a new object */ | 412 | /* Create a new object */ |
330 | 413 | ||
@@ -356,9 +439,10 @@ acpi_install_notify_handler(acpi_handle device, | |||
356 | goto unlock_and_exit; | 439 | goto unlock_and_exit; |
357 | } | 440 | } |
358 | 441 | ||
359 | notify_obj->notify.node = node; | 442 | acpi_populate_handler_object(¬ify_obj->notify, |
360 | notify_obj->notify.handler = handler; | 443 | handler_type, |
361 | notify_obj->notify.context = context; | 444 | handler, context, |
445 | NULL); | ||
362 | 446 | ||
363 | if (handler_type & ACPI_SYSTEM_NOTIFY) { | 447 | if (handler_type & ACPI_SYSTEM_NOTIFY) { |
364 | obj_desc->common_notify.system_notify = notify_obj; | 448 | obj_desc->common_notify.system_notify = notify_obj; |
@@ -418,6 +502,10 @@ acpi_remove_notify_handler(acpi_handle device, | |||
418 | goto exit; | 502 | goto exit; |
419 | } | 503 | } |
420 | 504 | ||
505 | |||
506 | /* Make sure all deferred tasks are completed */ | ||
507 | acpi_os_wait_events_complete(NULL); | ||
508 | |||
421 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | 509 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
422 | if (ACPI_FAILURE(status)) { | 510 | if (ACPI_FAILURE(status)) { |
423 | goto exit; | 511 | goto exit; |
@@ -445,15 +533,6 @@ acpi_remove_notify_handler(acpi_handle device, | |||
445 | goto unlock_and_exit; | 533 | goto unlock_and_exit; |
446 | } | 534 | } |
447 | 535 | ||
448 | /* Make sure all deferred tasks are completed */ | ||
449 | |||
450 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | ||
451 | acpi_os_wait_events_complete(NULL); | ||
452 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | ||
453 | if (ACPI_FAILURE(status)) { | ||
454 | goto exit; | ||
455 | } | ||
456 | |||
457 | if (handler_type & ACPI_SYSTEM_NOTIFY) { | 536 | if (handler_type & ACPI_SYSTEM_NOTIFY) { |
458 | acpi_gbl_system_notify.node = NULL; | 537 | acpi_gbl_system_notify.node = NULL; |
459 | acpi_gbl_system_notify.handler = NULL; | 538 | acpi_gbl_system_notify.handler = NULL; |
@@ -488,28 +567,60 @@ acpi_remove_notify_handler(acpi_handle device, | |||
488 | /* Object exists - make sure there's an existing handler */ | 567 | /* Object exists - make sure there's an existing handler */ |
489 | 568 | ||
490 | if (handler_type & ACPI_SYSTEM_NOTIFY) { | 569 | if (handler_type & ACPI_SYSTEM_NOTIFY) { |
570 | struct acpi_object_notify_handler *handler_obj; | ||
571 | struct acpi_object_notify_handler *parent_obj; | ||
572 | |||
491 | notify_obj = obj_desc->common_notify.system_notify; | 573 | notify_obj = obj_desc->common_notify.system_notify; |
492 | if (!notify_obj) { | 574 | if (!notify_obj) { |
493 | status = AE_NOT_EXIST; | 575 | status = AE_NOT_EXIST; |
494 | goto unlock_and_exit; | 576 | goto unlock_and_exit; |
495 | } | 577 | } |
496 | 578 | ||
497 | if (notify_obj->notify.handler != handler) { | 579 | handler_obj = ¬ify_obj->notify; |
580 | parent_obj = NULL; | ||
581 | while (handler_obj->handler != handler) { | ||
582 | if (handler_obj->next) { | ||
583 | parent_obj = handler_obj; | ||
584 | handler_obj = handler_obj->next; | ||
585 | } else { | ||
586 | break; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | if (handler_obj->handler != handler) { | ||
498 | status = AE_BAD_PARAMETER; | 591 | status = AE_BAD_PARAMETER; |
499 | goto unlock_and_exit; | 592 | goto unlock_and_exit; |
500 | } | 593 | } |
501 | /* Make sure all deferred tasks are completed */ | ||
502 | 594 | ||
503 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 595 | /* |
504 | acpi_os_wait_events_complete(NULL); | 596 | * Remove the handler. There are three possible cases. |
505 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | 597 | * First, we may need to remove a non-embedded object. |
506 | if (ACPI_FAILURE(status)) { | 598 | * Second, we may need to remove the embedded object's |
507 | goto exit; | 599 | * handler data, while non-embedded objects exist. |
600 | * Finally, we may need to remove the embedded object | ||
601 | * entirely along with its container. | ||
602 | */ | ||
603 | if (parent_obj) { | ||
604 | /* Non-embedded object is being removed. */ | ||
605 | parent_obj->next = handler_obj->next; | ||
606 | ACPI_FREE(handler_obj); | ||
607 | } else if (notify_obj->notify.next) { | ||
608 | /* | ||
609 | * The handler matches the embedded object, but | ||
610 | * there are more handler objects in the list. | ||
611 | * Replace the embedded object's data with the | ||
612 | * first next object's data and remove that | ||
613 | * object. | ||
614 | */ | ||
615 | parent_obj = ¬ify_obj->notify; | ||
616 | handler_obj = notify_obj->notify.next; | ||
617 | *parent_obj = *handler_obj; | ||
618 | ACPI_FREE(handler_obj); | ||
619 | } else { | ||
620 | /* No more handler objects in the list. */ | ||
621 | obj_desc->common_notify.system_notify = NULL; | ||
622 | acpi_ut_remove_reference(notify_obj); | ||
508 | } | 623 | } |
509 | |||
510 | /* Remove the handler */ | ||
511 | obj_desc->common_notify.system_notify = NULL; | ||
512 | acpi_ut_remove_reference(notify_obj); | ||
513 | } | 624 | } |
514 | 625 | ||
515 | if (handler_type & ACPI_DEVICE_NOTIFY) { | 626 | if (handler_type & ACPI_DEVICE_NOTIFY) { |
@@ -523,14 +634,6 @@ acpi_remove_notify_handler(acpi_handle device, | |||
523 | status = AE_BAD_PARAMETER; | 634 | status = AE_BAD_PARAMETER; |
524 | goto unlock_and_exit; | 635 | goto unlock_and_exit; |
525 | } | 636 | } |
526 | /* Make sure all deferred tasks are completed */ | ||
527 | |||
528 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | ||
529 | acpi_os_wait_events_complete(NULL); | ||
530 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | ||
531 | if (ACPI_FAILURE(status)) { | ||
532 | goto exit; | ||
533 | } | ||
534 | 637 | ||
535 | /* Remove the handler */ | 638 | /* Remove the handler */ |
536 | obj_desc->common_notify.device_notify = NULL; | 639 | obj_desc->common_notify.device_notify = NULL; |
@@ -617,13 +720,6 @@ acpi_install_gpe_handler(acpi_handle gpe_device, | |||
617 | handler->context = context; | 720 | handler->context = context; |
618 | handler->method_node = gpe_event_info->dispatch.method_node; | 721 | handler->method_node = gpe_event_info->dispatch.method_node; |
619 | 722 | ||
620 | /* Disable the GPE before installing the handler */ | ||
621 | |||
622 | status = acpi_ev_disable_gpe(gpe_event_info); | ||
623 | if (ACPI_FAILURE(status)) { | ||
624 | goto unlock_and_exit; | ||
625 | } | ||
626 | |||
627 | /* Install the handler */ | 723 | /* Install the handler */ |
628 | 724 | ||
629 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 725 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
@@ -707,13 +803,6 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, | |||
707 | goto unlock_and_exit; | 803 | goto unlock_and_exit; |
708 | } | 804 | } |
709 | 805 | ||
710 | /* Disable the GPE before removing the handler */ | ||
711 | |||
712 | status = acpi_ev_disable_gpe(gpe_event_info); | ||
713 | if (ACPI_FAILURE(status)) { | ||
714 | goto unlock_and_exit; | ||
715 | } | ||
716 | |||
717 | /* Make sure all deferred tasks are completed */ | 806 | /* Make sure all deferred tasks are completed */ |
718 | 807 | ||
719 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | 808 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); |
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index eed7a38d25f..124c157215b 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c | |||
@@ -201,23 +201,27 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event) | |||
201 | 201 | ||
202 | /******************************************************************************* | 202 | /******************************************************************************* |
203 | * | 203 | * |
204 | * FUNCTION: acpi_set_gpe_type | 204 | * FUNCTION: acpi_set_gpe |
205 | * | 205 | * |
206 | * PARAMETERS: gpe_device - Parent GPE Device | 206 | * PARAMETERS: gpe_device - Parent GPE Device |
207 | * gpe_number - GPE level within the GPE block | 207 | * gpe_number - GPE level within the GPE block |
208 | * Type - New GPE type | 208 | * action - Enable or disable |
209 | * Called from ISR or not | ||
209 | * | 210 | * |
210 | * RETURN: Status | 211 | * RETURN: Status |
211 | * | 212 | * |
212 | * DESCRIPTION: Set the type of an individual GPE | 213 | * DESCRIPTION: Enable or disable an ACPI event (general purpose) |
213 | * | 214 | * |
214 | ******************************************************************************/ | 215 | ******************************************************************************/ |
215 | acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type) | 216 | acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action) |
216 | { | 217 | { |
217 | acpi_status status = AE_OK; | 218 | acpi_status status = AE_OK; |
219 | acpi_cpu_flags flags; | ||
218 | struct acpi_gpe_event_info *gpe_event_info; | 220 | struct acpi_gpe_event_info *gpe_event_info; |
219 | 221 | ||
220 | ACPI_FUNCTION_TRACE(acpi_set_gpe_type); | 222 | ACPI_FUNCTION_TRACE(acpi_set_gpe); |
223 | |||
224 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
221 | 225 | ||
222 | /* Ensure that we have a valid GPE number */ | 226 | /* Ensure that we have a valid GPE number */ |
223 | 227 | ||
@@ -227,19 +231,29 @@ acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type) | |||
227 | goto unlock_and_exit; | 231 | goto unlock_and_exit; |
228 | } | 232 | } |
229 | 233 | ||
230 | if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) { | 234 | /* Perform the action */ |
231 | return_ACPI_STATUS(AE_OK); | 235 | |
232 | } | 236 | switch (action) { |
237 | case ACPI_GPE_ENABLE: | ||
238 | status = acpi_ev_enable_gpe(gpe_event_info); | ||
239 | break; | ||
233 | 240 | ||
234 | /* Set the new type (will disable GPE if currently enabled) */ | 241 | case ACPI_GPE_DISABLE: |
242 | status = acpi_ev_disable_gpe(gpe_event_info); | ||
243 | break; | ||
235 | 244 | ||
236 | status = acpi_ev_set_gpe_type(gpe_event_info, type); | 245 | default: |
246 | ACPI_ERROR((AE_INFO, "Invalid action\n")); | ||
247 | status = AE_BAD_PARAMETER; | ||
248 | break; | ||
249 | } | ||
237 | 250 | ||
238 | unlock_and_exit: | 251 | unlock_and_exit: |
252 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
239 | return_ACPI_STATUS(status); | 253 | return_ACPI_STATUS(status); |
240 | } | 254 | } |
241 | 255 | ||
242 | ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) | 256 | ACPI_EXPORT_SYMBOL(acpi_set_gpe) |
243 | 257 | ||
244 | /******************************************************************************* | 258 | /******************************************************************************* |
245 | * | 259 | * |
@@ -247,15 +261,14 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) | |||
247 | * | 261 | * |
248 | * PARAMETERS: gpe_device - Parent GPE Device | 262 | * PARAMETERS: gpe_device - Parent GPE Device |
249 | * gpe_number - GPE level within the GPE block | 263 | * gpe_number - GPE level within the GPE block |
250 | * Flags - Just enable, or also wake enable? | 264 | * type - Purpose the GPE will be used for |
251 | * Called from ISR or not | ||
252 | * | 265 | * |
253 | * RETURN: Status | 266 | * RETURN: Status |
254 | * | 267 | * |
255 | * DESCRIPTION: Enable an ACPI event (general purpose) | 268 | * DESCRIPTION: Take a reference to a GPE and enable it if necessary |
256 | * | 269 | * |
257 | ******************************************************************************/ | 270 | ******************************************************************************/ |
258 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) | 271 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type) |
259 | { | 272 | { |
260 | acpi_status status = AE_OK; | 273 | acpi_status status = AE_OK; |
261 | acpi_cpu_flags flags; | 274 | acpi_cpu_flags flags; |
@@ -263,6 +276,9 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) | |||
263 | 276 | ||
264 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); | 277 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); |
265 | 278 | ||
279 | if (type & ~ACPI_GPE_TYPE_WAKE_RUN) | ||
280 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
281 | |||
266 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 282 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
267 | 283 | ||
268 | /* Ensure that we have a valid GPE number */ | 284 | /* Ensure that we have a valid GPE number */ |
@@ -273,15 +289,32 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) | |||
273 | goto unlock_and_exit; | 289 | goto unlock_and_exit; |
274 | } | 290 | } |
275 | 291 | ||
276 | /* Perform the enable */ | 292 | if (type & ACPI_GPE_TYPE_RUNTIME) { |
293 | if (++gpe_event_info->runtime_count == 1) { | ||
294 | status = acpi_ev_enable_gpe(gpe_event_info); | ||
295 | if (ACPI_FAILURE(status)) | ||
296 | gpe_event_info->runtime_count--; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | if (type & ACPI_GPE_TYPE_WAKE) { | ||
301 | if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { | ||
302 | status = AE_BAD_PARAMETER; | ||
303 | goto unlock_and_exit; | ||
304 | } | ||
277 | 305 | ||
278 | status = acpi_ev_enable_gpe(gpe_event_info, TRUE); | 306 | /* |
307 | * Wake-up GPEs are only enabled right prior to putting the | ||
308 | * system into a sleep state. | ||
309 | */ | ||
310 | if (++gpe_event_info->wakeup_count == 1) | ||
311 | acpi_ev_update_gpe_enable_masks(gpe_event_info); | ||
312 | } | ||
279 | 313 | ||
280 | unlock_and_exit: | 314 | unlock_and_exit: |
281 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | 315 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
282 | return_ACPI_STATUS(status); | 316 | return_ACPI_STATUS(status); |
283 | } | 317 | } |
284 | |||
285 | ACPI_EXPORT_SYMBOL(acpi_enable_gpe) | 318 | ACPI_EXPORT_SYMBOL(acpi_enable_gpe) |
286 | 319 | ||
287 | /******************************************************************************* | 320 | /******************************************************************************* |
@@ -290,15 +323,14 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe) | |||
290 | * | 323 | * |
291 | * PARAMETERS: gpe_device - Parent GPE Device | 324 | * PARAMETERS: gpe_device - Parent GPE Device |
292 | * gpe_number - GPE level within the GPE block | 325 | * gpe_number - GPE level within the GPE block |
293 | * Flags - Just disable, or also wake disable? | 326 | * type - Purpose the GPE won't be used for any more |
294 | * Called from ISR or not | ||
295 | * | 327 | * |
296 | * RETURN: Status | 328 | * RETURN: Status |
297 | * | 329 | * |
298 | * DESCRIPTION: Disable an ACPI event (general purpose) | 330 | * DESCRIPTION: Release a reference to a GPE and disable it if necessary |
299 | * | 331 | * |
300 | ******************************************************************************/ | 332 | ******************************************************************************/ |
301 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) | 333 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type) |
302 | { | 334 | { |
303 | acpi_status status = AE_OK; | 335 | acpi_status status = AE_OK; |
304 | acpi_cpu_flags flags; | 336 | acpi_cpu_flags flags; |
@@ -306,6 +338,9 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) | |||
306 | 338 | ||
307 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); | 339 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); |
308 | 340 | ||
341 | if (type & ~ACPI_GPE_TYPE_WAKE_RUN) | ||
342 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
343 | |||
309 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 344 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
310 | /* Ensure that we have a valid GPE number */ | 345 | /* Ensure that we have a valid GPE number */ |
311 | 346 | ||
@@ -315,13 +350,24 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) | |||
315 | goto unlock_and_exit; | 350 | goto unlock_and_exit; |
316 | } | 351 | } |
317 | 352 | ||
318 | status = acpi_ev_disable_gpe(gpe_event_info); | 353 | if ((type & ACPI_GPE_TYPE_RUNTIME) && gpe_event_info->runtime_count) { |
354 | if (--gpe_event_info->runtime_count == 0) | ||
355 | status = acpi_ev_disable_gpe(gpe_event_info); | ||
356 | } | ||
357 | |||
358 | if ((type & ACPI_GPE_TYPE_WAKE) && gpe_event_info->wakeup_count) { | ||
359 | /* | ||
360 | * Wake-up GPEs are not enabled after leaving system sleep | ||
361 | * states, so we don't need to disable them here. | ||
362 | */ | ||
363 | if (--gpe_event_info->wakeup_count == 0) | ||
364 | acpi_ev_update_gpe_enable_masks(gpe_event_info); | ||
365 | } | ||
319 | 366 | ||
320 | unlock_and_exit: | 367 | unlock_and_exit: |
321 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | 368 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
322 | return_ACPI_STATUS(status); | 369 | return_ACPI_STATUS(status); |
323 | } | 370 | } |
324 | |||
325 | ACPI_EXPORT_SYMBOL(acpi_disable_gpe) | 371 | ACPI_EXPORT_SYMBOL(acpi_disable_gpe) |
326 | 372 | ||
327 | /******************************************************************************* | 373 | /******************************************************************************* |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 8a95e8329df..f53fbe307c9 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -422,11 +422,10 @@ static int acpi_button_add(struct acpi_device *device) | |||
422 | 422 | ||
423 | if (device->wakeup.flags.valid) { | 423 | if (device->wakeup.flags.valid) { |
424 | /* Button's GPE is run-wake GPE */ | 424 | /* Button's GPE is run-wake GPE */ |
425 | acpi_set_gpe_type(device->wakeup.gpe_device, | ||
426 | device->wakeup.gpe_number, | ||
427 | ACPI_GPE_TYPE_WAKE_RUN); | ||
428 | acpi_enable_gpe(device->wakeup.gpe_device, | 425 | acpi_enable_gpe(device->wakeup.gpe_device, |
429 | device->wakeup.gpe_number); | 426 | device->wakeup.gpe_number, |
427 | ACPI_GPE_TYPE_WAKE_RUN); | ||
428 | device->wakeup.run_wake_count++; | ||
430 | device->wakeup.state.enabled = 1; | 429 | device->wakeup.state.enabled = 1; |
431 | } | 430 | } |
432 | 431 | ||
@@ -446,6 +445,14 @@ static int acpi_button_remove(struct acpi_device *device, int type) | |||
446 | { | 445 | { |
447 | struct acpi_button *button = acpi_driver_data(device); | 446 | struct acpi_button *button = acpi_driver_data(device); |
448 | 447 | ||
448 | if (device->wakeup.flags.valid) { | ||
449 | acpi_disable_gpe(device->wakeup.gpe_device, | ||
450 | device->wakeup.gpe_number, | ||
451 | ACPI_GPE_TYPE_WAKE_RUN); | ||
452 | device->wakeup.run_wake_count--; | ||
453 | device->wakeup.state.enabled = 0; | ||
454 | } | ||
455 | |||
449 | acpi_button_remove_fs(device); | 456 | acpi_button_remove_fs(device); |
450 | input_unregister_device(button->input); | 457 | input_unregister_device(button->input); |
451 | kfree(button); | 458 | kfree(button); |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index d6471bb6852..27e0b92b2e3 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -307,7 +307,11 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) | |||
307 | pr_debug(PREFIX "transaction start\n"); | 307 | pr_debug(PREFIX "transaction start\n"); |
308 | /* disable GPE during transaction if storm is detected */ | 308 | /* disable GPE during transaction if storm is detected */ |
309 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | 309 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { |
310 | acpi_disable_gpe(NULL, ec->gpe); | 310 | /* |
311 | * It has to be disabled at the hardware level regardless of the | ||
312 | * GPE reference counting, so that it doesn't trigger. | ||
313 | */ | ||
314 | acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE); | ||
311 | } | 315 | } |
312 | 316 | ||
313 | status = acpi_ec_transaction_unlocked(ec, t); | 317 | status = acpi_ec_transaction_unlocked(ec, t); |
@@ -316,8 +320,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) | |||
316 | ec_check_sci_sync(ec, acpi_ec_read_status(ec)); | 320 | ec_check_sci_sync(ec, acpi_ec_read_status(ec)); |
317 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | 321 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { |
318 | msleep(1); | 322 | msleep(1); |
319 | /* it is safe to enable GPE outside of transaction */ | 323 | /* |
320 | acpi_enable_gpe(NULL, ec->gpe); | 324 | * It is safe to enable the GPE outside of the transaction. Use |
325 | * acpi_set_gpe() for that, since we used it to disable the GPE | ||
326 | * above. | ||
327 | */ | ||
328 | acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE); | ||
321 | } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { | 329 | } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { |
322 | pr_info(PREFIX "GPE storm detected, " | 330 | pr_info(PREFIX "GPE storm detected, " |
323 | "transactions will use polling mode\n"); | 331 | "transactions will use polling mode\n"); |
@@ -788,8 +796,8 @@ static int ec_install_handlers(struct acpi_ec *ec) | |||
788 | &acpi_ec_gpe_handler, ec); | 796 | &acpi_ec_gpe_handler, ec); |
789 | if (ACPI_FAILURE(status)) | 797 | if (ACPI_FAILURE(status)) |
790 | return -ENODEV; | 798 | return -ENODEV; |
791 | acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); | 799 | |
792 | acpi_enable_gpe(NULL, ec->gpe); | 800 | acpi_enable_gpe(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); |
793 | status = acpi_install_address_space_handler(ec->handle, | 801 | status = acpi_install_address_space_handler(ec->handle, |
794 | ACPI_ADR_SPACE_EC, | 802 | ACPI_ADR_SPACE_EC, |
795 | &acpi_ec_space_handler, | 803 | &acpi_ec_space_handler, |
@@ -806,6 +814,7 @@ static int ec_install_handlers(struct acpi_ec *ec) | |||
806 | } else { | 814 | } else { |
807 | acpi_remove_gpe_handler(NULL, ec->gpe, | 815 | acpi_remove_gpe_handler(NULL, ec->gpe, |
808 | &acpi_ec_gpe_handler); | 816 | &acpi_ec_gpe_handler); |
817 | acpi_disable_gpe(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); | ||
809 | return -ENODEV; | 818 | return -ENODEV; |
810 | } | 819 | } |
811 | } | 820 | } |
@@ -816,6 +825,7 @@ static int ec_install_handlers(struct acpi_ec *ec) | |||
816 | 825 | ||
817 | static void ec_remove_handlers(struct acpi_ec *ec) | 826 | static void ec_remove_handlers(struct acpi_ec *ec) |
818 | { | 827 | { |
828 | acpi_disable_gpe(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); | ||
819 | if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, | 829 | if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, |
820 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) | 830 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) |
821 | pr_err(PREFIX "failed to remove space handler\n"); | 831 | pr_err(PREFIX "failed to remove space handler\n"); |
@@ -1057,16 +1067,16 @@ error: | |||
1057 | static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) | 1067 | static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) |
1058 | { | 1068 | { |
1059 | struct acpi_ec *ec = acpi_driver_data(device); | 1069 | struct acpi_ec *ec = acpi_driver_data(device); |
1060 | /* Stop using GPE */ | 1070 | /* Stop using the GPE, but keep it reference counted. */ |
1061 | acpi_disable_gpe(NULL, ec->gpe); | 1071 | acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE); |
1062 | return 0; | 1072 | return 0; |
1063 | } | 1073 | } |
1064 | 1074 | ||
1065 | static int acpi_ec_resume(struct acpi_device *device) | 1075 | static int acpi_ec_resume(struct acpi_device *device) |
1066 | { | 1076 | { |
1067 | struct acpi_ec *ec = acpi_driver_data(device); | 1077 | struct acpi_ec *ec = acpi_driver_data(device); |
1068 | /* Enable use of GPE back */ | 1078 | /* Enable the GPE again, but don't reference count it once more. */ |
1069 | acpi_enable_gpe(NULL, ec->gpe); | 1079 | acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE); |
1070 | return 0; | 1080 | return 0; |
1071 | } | 1081 | } |
1072 | 1082 | ||
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index cb28e0502ac..9c4c962e46e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -36,8 +36,6 @@ static inline int acpi_debug_init(void) { return 0; } | |||
36 | int acpi_power_init(void); | 36 | int acpi_power_init(void); |
37 | int acpi_device_sleep_wake(struct acpi_device *dev, | 37 | int acpi_device_sleep_wake(struct acpi_device *dev, |
38 | int enable, int sleep_state, int dev_state); | 38 | int enable, int sleep_state, int dev_state); |
39 | int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state); | ||
40 | int acpi_disable_wakeup_device_power(struct acpi_device *dev); | ||
41 | int acpi_power_get_inferred_state(struct acpi_device *device); | 39 | int acpi_power_get_inferred_state(struct acpi_device *device); |
42 | int acpi_power_transition(struct acpi_device *device, int state); | 40 | int acpi_power_transition(struct acpi_device *device, int state); |
43 | extern int acpi_power_nocheck; | 41 | extern int acpi_power_nocheck; |
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index a5a77b78a72..2ef04098cc1 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c | |||
@@ -26,7 +26,9 @@ | |||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/pci-acpi.h> | ||
29 | #include <linux/acpi.h> | 30 | #include <linux/acpi.h> |
31 | #include <linux/pm_runtime.h> | ||
30 | #include <acpi/acpi_bus.h> | 32 | #include <acpi/acpi_bus.h> |
31 | #include <acpi/acpi_drivers.h> | 33 | #include <acpi/acpi_drivers.h> |
32 | 34 | ||
@@ -38,7 +40,13 @@ static int acpi_pci_unbind(struct acpi_device *device) | |||
38 | struct pci_dev *dev; | 40 | struct pci_dev *dev; |
39 | 41 | ||
40 | dev = acpi_get_pci_dev(device->handle); | 42 | dev = acpi_get_pci_dev(device->handle); |
41 | if (!dev || !dev->subordinate) | 43 | if (!dev) |
44 | goto out; | ||
45 | |||
46 | device_set_run_wake(&dev->dev, false); | ||
47 | pci_acpi_remove_pm_notifier(device); | ||
48 | |||
49 | if (!dev->subordinate) | ||
42 | goto out; | 50 | goto out; |
43 | 51 | ||
44 | acpi_pci_irq_del_prt(dev->subordinate); | 52 | acpi_pci_irq_del_prt(dev->subordinate); |
@@ -62,6 +70,10 @@ static int acpi_pci_bind(struct acpi_device *device) | |||
62 | if (!dev) | 70 | if (!dev) |
63 | return 0; | 71 | return 0; |
64 | 72 | ||
73 | pci_acpi_add_pm_notifier(device, dev); | ||
74 | if (device->wakeup.flags.run_wake) | ||
75 | device_set_run_wake(&dev->dev, true); | ||
76 | |||
65 | /* | 77 | /* |
66 | * Install the 'bind' function to facilitate callbacks for | 78 | * Install the 'bind' function to facilitate callbacks for |
67 | * children of the P2P bridge. | 79 | * children of the P2P bridge. |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 64f55b6db73..d724736d56c 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/proc_fs.h> | 30 | #include <linux/proc_fs.h> |
31 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
32 | #include <linux/pm.h> | 32 | #include <linux/pm.h> |
33 | #include <linux/pm_runtime.h> | ||
33 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
34 | #include <linux/pci-acpi.h> | 35 | #include <linux/pci-acpi.h> |
35 | #include <linux/acpi.h> | 36 | #include <linux/acpi.h> |
@@ -528,6 +529,10 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
528 | if (flags != base_flags) | 529 | if (flags != base_flags) |
529 | acpi_pci_osc_support(root, flags); | 530 | acpi_pci_osc_support(root, flags); |
530 | 531 | ||
532 | pci_acpi_add_bus_pm_notifier(device, root->bus); | ||
533 | if (device->wakeup.flags.run_wake) | ||
534 | device_set_run_wake(root->bus->bridge, true); | ||
535 | |||
531 | return 0; | 536 | return 0; |
532 | 537 | ||
533 | end: | 538 | end: |
@@ -549,6 +554,9 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) | |||
549 | { | 554 | { |
550 | struct acpi_pci_root *root = acpi_driver_data(device); | 555 | struct acpi_pci_root *root = acpi_driver_data(device); |
551 | 556 | ||
557 | device_set_run_wake(root->bus->bridge, false); | ||
558 | pci_acpi_remove_bus_pm_notifier(device); | ||
559 | |||
552 | kfree(root); | 560 | kfree(root); |
553 | return 0; | 561 | return 0; |
554 | } | 562 | } |
@@ -558,6 +566,7 @@ static int __init acpi_pci_root_init(void) | |||
558 | if (acpi_pci_disabled) | 566 | if (acpi_pci_disabled) |
559 | return 0; | 567 | return 0; |
560 | 568 | ||
569 | pci_acpi_crs_quirks(); | ||
561 | if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) | 570 | if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) |
562 | return -ENODEV; | 571 | return -ENODEV; |
563 | 572 | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 3e009674f33..fb7fc24fe72 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -741,19 +741,40 @@ acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device, | |||
741 | return AE_OK; | 741 | return AE_OK; |
742 | } | 742 | } |
743 | 743 | ||
744 | static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | 744 | static void acpi_bus_set_run_wake_flags(struct acpi_device *device) |
745 | { | 745 | { |
746 | acpi_status status = 0; | ||
747 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
748 | union acpi_object *package = NULL; | ||
749 | int psw_error; | ||
750 | |||
751 | struct acpi_device_id button_device_ids[] = { | 746 | struct acpi_device_id button_device_ids[] = { |
752 | {"PNP0C0D", 0}, | 747 | {"PNP0C0D", 0}, |
753 | {"PNP0C0C", 0}, | 748 | {"PNP0C0C", 0}, |
754 | {"PNP0C0E", 0}, | 749 | {"PNP0C0E", 0}, |
755 | {"", 0}, | 750 | {"", 0}, |
756 | }; | 751 | }; |
752 | acpi_status status; | ||
753 | acpi_event_status event_status; | ||
754 | |||
755 | device->wakeup.run_wake_count = 0; | ||
756 | device->wakeup.flags.notifier_present = 0; | ||
757 | |||
758 | /* Power button, Lid switch always enable wakeup */ | ||
759 | if (!acpi_match_device_ids(device, button_device_ids)) { | ||
760 | device->wakeup.flags.run_wake = 1; | ||
761 | device->wakeup.flags.always_enabled = 1; | ||
762 | return; | ||
763 | } | ||
764 | |||
765 | status = acpi_get_gpe_status(NULL, device->wakeup.gpe_number, | ||
766 | ACPI_NOT_ISR, &event_status); | ||
767 | if (status == AE_OK) | ||
768 | device->wakeup.flags.run_wake = | ||
769 | !!(event_status & ACPI_EVENT_FLAG_HANDLE); | ||
770 | } | ||
771 | |||
772 | static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | ||
773 | { | ||
774 | acpi_status status = 0; | ||
775 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
776 | union acpi_object *package = NULL; | ||
777 | int psw_error; | ||
757 | 778 | ||
758 | /* _PRW */ | 779 | /* _PRW */ |
759 | status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); | 780 | status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); |
@@ -773,6 +794,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
773 | 794 | ||
774 | device->wakeup.flags.valid = 1; | 795 | device->wakeup.flags.valid = 1; |
775 | device->wakeup.prepare_count = 0; | 796 | device->wakeup.prepare_count = 0; |
797 | acpi_bus_set_run_wake_flags(device); | ||
776 | /* Call _PSW/_DSW object to disable its ability to wake the sleeping | 798 | /* Call _PSW/_DSW object to disable its ability to wake the sleeping |
777 | * system for the ACPI device with the _PRW object. | 799 | * system for the ACPI device with the _PRW object. |
778 | * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. | 800 | * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. |
@@ -784,10 +806,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
784 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 806 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
785 | "error in _DSW or _PSW evaluation\n")); | 807 | "error in _DSW or _PSW evaluation\n")); |
786 | 808 | ||
787 | /* Power button, Lid switch always enable wakeup */ | ||
788 | if (!acpi_match_device_ids(device, button_device_ids)) | ||
789 | device->wakeup.flags.run_wake = 1; | ||
790 | |||
791 | end: | 809 | end: |
792 | if (ACPI_FAILURE(status)) | 810 | if (ACPI_FAILURE(status)) |
793 | device->flags.wake_capable = 0; | 811 | device->flags.wake_capable = 0; |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 79d33d908b5..3bde594a997 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -745,9 +745,18 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) | |||
745 | return -ENODEV; | 745 | return -ENODEV; |
746 | } | 746 | } |
747 | 747 | ||
748 | error = enable ? | 748 | if (enable) { |
749 | acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) : | 749 | error = acpi_enable_wakeup_device_power(adev, |
750 | acpi_disable_wakeup_device_power(adev); | 750 | acpi_target_sleep_state); |
751 | if (!error) | ||
752 | acpi_enable_gpe(adev->wakeup.gpe_device, | ||
753 | adev->wakeup.gpe_number, | ||
754 | ACPI_GPE_TYPE_WAKE); | ||
755 | } else { | ||
756 | acpi_disable_gpe(adev->wakeup.gpe_device, adev->wakeup.gpe_number, | ||
757 | ACPI_GPE_TYPE_WAKE); | ||
758 | error = acpi_disable_wakeup_device_power(adev); | ||
759 | } | ||
751 | if (!error) | 760 | if (!error) |
752 | dev_info(dev, "wake-up capability %s by ACPI\n", | 761 | dev_info(dev, "wake-up capability %s by ACPI\n", |
753 | enable ? "enabled" : "disabled"); | 762 | enable ? "enabled" : "disabled"); |
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index d11282975f3..a206a12da78 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c | |||
@@ -387,10 +387,10 @@ static ssize_t counter_set(struct kobject *kobj, | |||
387 | if (index < num_gpes) { | 387 | if (index < num_gpes) { |
388 | if (!strcmp(buf, "disable\n") && | 388 | if (!strcmp(buf, "disable\n") && |
389 | (status & ACPI_EVENT_FLAG_ENABLED)) | 389 | (status & ACPI_EVENT_FLAG_ENABLED)) |
390 | result = acpi_disable_gpe(handle, index); | 390 | result = acpi_set_gpe(handle, index, ACPI_GPE_DISABLE); |
391 | else if (!strcmp(buf, "enable\n") && | 391 | else if (!strcmp(buf, "enable\n") && |
392 | !(status & ACPI_EVENT_FLAG_ENABLED)) | 392 | !(status & ACPI_EVENT_FLAG_ENABLED)) |
393 | result = acpi_enable_gpe(handle, index); | 393 | result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE); |
394 | else if (!strcmp(buf, "clear\n") && | 394 | else if (!strcmp(buf, "clear\n") && |
395 | (status & ACPI_EVENT_FLAG_SET)) | 395 | (status & ACPI_EVENT_FLAG_SET)) |
396 | result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR); | 396 | result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR); |
diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c index e0ee0c036f5..4b9d339a6e2 100644 --- a/drivers/acpi/wakeup.c +++ b/drivers/acpi/wakeup.c | |||
@@ -21,12 +21,12 @@ | |||
21 | ACPI_MODULE_NAME("wakeup_devices") | 21 | ACPI_MODULE_NAME("wakeup_devices") |
22 | 22 | ||
23 | /** | 23 | /** |
24 | * acpi_enable_wakeup_device_prep - prepare wakeup devices | 24 | * acpi_enable_wakeup_device_prep - Prepare wake-up devices. |
25 | * @sleep_state: ACPI state | 25 | * @sleep_state: ACPI system sleep state. |
26 | * Enable all wakup devices power if the devices' wakeup level | 26 | * |
27 | * is higher than requested sleep level | 27 | * Enable all wake-up devices' power, unless the requested system sleep state is |
28 | * too deep. | ||
28 | */ | 29 | */ |
29 | |||
30 | void acpi_enable_wakeup_device_prep(u8 sleep_state) | 30 | void acpi_enable_wakeup_device_prep(u8 sleep_state) |
31 | { | 31 | { |
32 | struct list_head *node, *next; | 32 | struct list_head *node, *next; |
@@ -36,9 +36,8 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state) | |||
36 | struct acpi_device, | 36 | struct acpi_device, |
37 | wakeup_list); | 37 | wakeup_list); |
38 | 38 | ||
39 | if (!dev->wakeup.flags.valid || | 39 | if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled |
40 | !dev->wakeup.state.enabled || | 40 | || (sleep_state > (u32) dev->wakeup.sleep_state)) |
41 | (sleep_state > (u32) dev->wakeup.sleep_state)) | ||
42 | continue; | 41 | continue; |
43 | 42 | ||
44 | acpi_enable_wakeup_device_power(dev, sleep_state); | 43 | acpi_enable_wakeup_device_power(dev, sleep_state); |
@@ -46,9 +45,12 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state) | |||
46 | } | 45 | } |
47 | 46 | ||
48 | /** | 47 | /** |
49 | * acpi_enable_wakeup_device - enable wakeup devices | 48 | * acpi_enable_wakeup_device - Enable wake-up device GPEs. |
50 | * @sleep_state: ACPI state | 49 | * @sleep_state: ACPI system sleep state. |
51 | * Enable all wakup devices's GPE | 50 | * |
51 | * Enable all wake-up devices' GPEs, with the assumption that | ||
52 | * acpi_disable_all_gpes() was executed before, so we don't need to disable any | ||
53 | * GPEs here. | ||
52 | */ | 54 | */ |
53 | void acpi_enable_wakeup_device(u8 sleep_state) | 55 | void acpi_enable_wakeup_device(u8 sleep_state) |
54 | { | 56 | { |
@@ -65,29 +67,22 @@ void acpi_enable_wakeup_device(u8 sleep_state) | |||
65 | if (!dev->wakeup.flags.valid) | 67 | if (!dev->wakeup.flags.valid) |
66 | continue; | 68 | continue; |
67 | 69 | ||
68 | /* If users want to disable run-wake GPE, | ||
69 | * we only disable it for wake and leave it for runtime | ||
70 | */ | ||
71 | if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count) | 70 | if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count) |
72 | || sleep_state > (u32) dev->wakeup.sleep_state) { | 71 | || sleep_state > (u32) dev->wakeup.sleep_state) |
73 | if (dev->wakeup.flags.run_wake) { | ||
74 | /* set_gpe_type will disable GPE, leave it like that */ | ||
75 | acpi_set_gpe_type(dev->wakeup.gpe_device, | ||
76 | dev->wakeup.gpe_number, | ||
77 | ACPI_GPE_TYPE_RUNTIME); | ||
78 | } | ||
79 | continue; | 72 | continue; |
80 | } | 73 | |
81 | if (!dev->wakeup.flags.run_wake) | 74 | /* The wake-up power should have been enabled already. */ |
82 | acpi_enable_gpe(dev->wakeup.gpe_device, | 75 | acpi_set_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, |
83 | dev->wakeup.gpe_number); | 76 | ACPI_GPE_ENABLE); |
84 | } | 77 | } |
85 | } | 78 | } |
86 | 79 | ||
87 | /** | 80 | /** |
88 | * acpi_disable_wakeup_device - disable devices' wakeup capability | 81 | * acpi_disable_wakeup_device - Disable devices' wakeup capability. |
89 | * @sleep_state: ACPI state | 82 | * @sleep_state: ACPI system sleep state. |
90 | * Disable all wakup devices's GPE and wakeup capability | 83 | * |
84 | * This function only affects devices with wakeup.state.enabled set, which means | ||
85 | * that it reverses the changes made by acpi_enable_wakeup_device_prep(). | ||
91 | */ | 86 | */ |
92 | void acpi_disable_wakeup_device(u8 sleep_state) | 87 | void acpi_disable_wakeup_device(u8 sleep_state) |
93 | { | 88 | { |
@@ -97,30 +92,11 @@ void acpi_disable_wakeup_device(u8 sleep_state) | |||
97 | struct acpi_device *dev = | 92 | struct acpi_device *dev = |
98 | container_of(node, struct acpi_device, wakeup_list); | 93 | container_of(node, struct acpi_device, wakeup_list); |
99 | 94 | ||
100 | if (!dev->wakeup.flags.valid) | 95 | if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled |
101 | continue; | 96 | || (sleep_state > (u32) dev->wakeup.sleep_state)) |
102 | |||
103 | if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count) | ||
104 | || sleep_state > (u32) dev->wakeup.sleep_state) { | ||
105 | if (dev->wakeup.flags.run_wake) { | ||
106 | acpi_set_gpe_type(dev->wakeup.gpe_device, | ||
107 | dev->wakeup.gpe_number, | ||
108 | ACPI_GPE_TYPE_WAKE_RUN); | ||
109 | /* Re-enable it, since set_gpe_type will disable it */ | ||
110 | acpi_enable_gpe(dev->wakeup.gpe_device, | ||
111 | dev->wakeup.gpe_number); | ||
112 | } | ||
113 | continue; | 97 | continue; |
114 | } | ||
115 | 98 | ||
116 | acpi_disable_wakeup_device_power(dev); | 99 | acpi_disable_wakeup_device_power(dev); |
117 | /* Never disable run-wake GPE */ | ||
118 | if (!dev->wakeup.flags.run_wake) { | ||
119 | acpi_disable_gpe(dev->wakeup.gpe_device, | ||
120 | dev->wakeup.gpe_number); | ||
121 | acpi_clear_gpe(dev->wakeup.gpe_device, | ||
122 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | ||
123 | } | ||
124 | } | 100 | } |
125 | } | 101 | } |
126 | 102 | ||
@@ -134,13 +110,11 @@ int __init acpi_wakeup_device_init(void) | |||
134 | struct acpi_device, | 110 | struct acpi_device, |
135 | wakeup_list); | 111 | wakeup_list); |
136 | /* In case user doesn't load button driver */ | 112 | /* In case user doesn't load button driver */ |
137 | if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled) | 113 | if (!dev->wakeup.flags.always_enabled || |
114 | dev->wakeup.state.enabled) | ||
138 | continue; | 115 | continue; |
139 | acpi_set_gpe_type(dev->wakeup.gpe_device, | 116 | acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, |
140 | dev->wakeup.gpe_number, | 117 | ACPI_GPE_TYPE_WAKE); |
141 | ACPI_GPE_TYPE_WAKE_RUN); | ||
142 | acpi_enable_gpe(dev->wakeup.gpe_device, | ||
143 | dev->wakeup.gpe_number); | ||
144 | dev->wakeup.state.enabled = 1; | 118 | dev->wakeup.state.enabled = 1; |
145 | } | 119 | } |
146 | mutex_unlock(&acpi_device_lock); | 120 | mutex_unlock(&acpi_device_lock); |
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index 3464ebc4cdb..452fde9edf8 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig | |||
@@ -109,7 +109,7 @@ config HISAX_16_3 | |||
109 | 109 | ||
110 | config HISAX_TELESPCI | 110 | config HISAX_TELESPCI |
111 | bool "Teles PCI" | 111 | bool "Teles PCI" |
112 | depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) | 112 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
113 | help | 113 | help |
114 | This enables HiSax support for the Teles PCI. | 114 | This enables HiSax support for the Teles PCI. |
115 | See <file:Documentation/isdn/README.HiSax> on how to configure it. | 115 | See <file:Documentation/isdn/README.HiSax> on how to configure it. |
@@ -237,7 +237,7 @@ config HISAX_MIC | |||
237 | 237 | ||
238 | config HISAX_NETJET | 238 | config HISAX_NETJET |
239 | bool "NETjet card" | 239 | bool "NETjet card" |
240 | depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) | 240 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
241 | help | 241 | help |
242 | This enables HiSax support for the NetJet from Traverse | 242 | This enables HiSax support for the NetJet from Traverse |
243 | Technologies. | 243 | Technologies. |
@@ -248,7 +248,7 @@ config HISAX_NETJET | |||
248 | 248 | ||
249 | config HISAX_NETJET_U | 249 | config HISAX_NETJET_U |
250 | bool "NETspider U card" | 250 | bool "NETspider U card" |
251 | depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) | 251 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
252 | help | 252 | help |
253 | This enables HiSax support for the Netspider U interface ISDN card | 253 | This enables HiSax support for the Netspider U interface ISDN card |
254 | from Traverse Technologies. | 254 | from Traverse Technologies. |
@@ -287,7 +287,7 @@ config HISAX_HSTSAPHIR | |||
287 | 287 | ||
288 | config HISAX_BKM_A4T | 288 | config HISAX_BKM_A4T |
289 | bool "Telekom A4T card" | 289 | bool "Telekom A4T card" |
290 | depends on PCI && PCI_LEGACY | 290 | depends on PCI |
291 | help | 291 | help |
292 | This enables HiSax support for the Telekom A4T card. | 292 | This enables HiSax support for the Telekom A4T card. |
293 | 293 | ||
@@ -297,7 +297,7 @@ config HISAX_BKM_A4T | |||
297 | 297 | ||
298 | config HISAX_SCT_QUADRO | 298 | config HISAX_SCT_QUADRO |
299 | bool "Scitel Quadro card" | 299 | bool "Scitel Quadro card" |
300 | depends on PCI && PCI_LEGACY | 300 | depends on PCI |
301 | help | 301 | help |
302 | This enables HiSax support for the Scitel Quadro card. | 302 | This enables HiSax support for the Scitel Quadro card. |
303 | 303 | ||
@@ -316,7 +316,7 @@ config HISAX_GAZEL | |||
316 | 316 | ||
317 | config HISAX_HFC_PCI | 317 | config HISAX_HFC_PCI |
318 | bool "HFC PCI-Bus cards" | 318 | bool "HFC PCI-Bus cards" |
319 | depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) | 319 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
320 | help | 320 | help |
321 | This enables HiSax support for the HFC-S PCI 2BDS0 based cards. | 321 | This enables HiSax support for the HFC-S PCI 2BDS0 based cards. |
322 | 322 | ||
@@ -325,7 +325,7 @@ config HISAX_HFC_PCI | |||
325 | 325 | ||
326 | config HISAX_W6692 | 326 | config HISAX_W6692 |
327 | bool "Winbond W6692 based cards" | 327 | bool "Winbond W6692 based cards" |
328 | depends on PCI && PCI_LEGACY | 328 | depends on PCI |
329 | help | 329 | help |
330 | This enables HiSax support for Winbond W6692 based PCI ISDN cards. | 330 | This enables HiSax support for Winbond W6692 based PCI ISDN cards. |
331 | 331 | ||
@@ -341,7 +341,7 @@ config HISAX_HFC_SX | |||
341 | 341 | ||
342 | config HISAX_ENTERNOW_PCI | 342 | config HISAX_ENTERNOW_PCI |
343 | bool "Formula-n enter:now PCI card" | 343 | bool "Formula-n enter:now PCI card" |
344 | depends on HISAX_NETJET && PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) | 344 | depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
345 | help | 345 | help |
346 | This enables HiSax support for the Formula-n enter:now PCI | 346 | This enables HiSax support for the Formula-n enter:now PCI |
347 | ISDN card. | 347 | ISDN card. |
@@ -412,7 +412,7 @@ config HISAX_HFC4S8S | |||
412 | 412 | ||
413 | config HISAX_FRITZ_PCIPNP | 413 | config HISAX_FRITZ_PCIPNP |
414 | tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)" | 414 | tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)" |
415 | depends on PCI && PCI_LEGACY && EXPERIMENTAL | 415 | depends on PCI && EXPERIMENTAL |
416 | help | 416 | help |
417 | This enables the driver for the AVM Fritz!Card PCI, | 417 | This enables the driver for the AVM Fritz!Card PCI, |
418 | Fritz!Card PCI v2 and Fritz!Card PnP. | 418 | Fritz!Card PCI v2 and Fritz!Card PnP. |
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index 7cabc5a1949..14295a155e7 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c | |||
@@ -822,7 +822,7 @@ static int __devinit avm_pnp_setup(struct IsdnCardState *cs) | |||
822 | 822 | ||
823 | #endif /* __ISAPNP__ */ | 823 | #endif /* __ISAPNP__ */ |
824 | 824 | ||
825 | #ifndef CONFIG_PCI_LEGACY | 825 | #ifndef CONFIG_PCI |
826 | 826 | ||
827 | static int __devinit avm_pci_setup(struct IsdnCardState *cs) | 827 | static int __devinit avm_pci_setup(struct IsdnCardState *cs) |
828 | { | 828 | { |
@@ -835,7 +835,7 @@ static struct pci_dev *dev_avm __devinitdata = NULL; | |||
835 | 835 | ||
836 | static int __devinit avm_pci_setup(struct IsdnCardState *cs) | 836 | static int __devinit avm_pci_setup(struct IsdnCardState *cs) |
837 | { | 837 | { |
838 | if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, | 838 | if ((dev_avm = hisax_find_pci_device(PCI_VENDOR_ID_AVM, |
839 | PCI_DEVICE_ID_AVM_A1, dev_avm))) { | 839 | PCI_DEVICE_ID_AVM_A1, dev_avm))) { |
840 | 840 | ||
841 | if (pci_enable_device(dev_avm)) | 841 | if (pci_enable_device(dev_avm)) |
@@ -864,7 +864,7 @@ static int __devinit avm_pci_setup(struct IsdnCardState *cs) | |||
864 | return (1); | 864 | return (1); |
865 | } | 865 | } |
866 | 866 | ||
867 | #endif /* CONFIG_PCI_LEGACY */ | 867 | #endif /* CONFIG_PCI */ |
868 | 868 | ||
869 | int __devinit | 869 | int __devinit |
870 | setup_avm_pcipnp(struct IsdnCard *card) | 870 | setup_avm_pcipnp(struct IsdnCard *card) |
diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c index 9ca2ee54cc9..9f2009c0b69 100644 --- a/drivers/isdn/hisax/bkm_a4t.c +++ b/drivers/isdn/hisax/bkm_a4t.c | |||
@@ -340,7 +340,7 @@ setup_bkm_a4t(struct IsdnCard *card) | |||
340 | } else | 340 | } else |
341 | return (0); | 341 | return (0); |
342 | 342 | ||
343 | while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN, | 343 | while ((dev_a4t = hisax_find_pci_device(PCI_VENDOR_ID_ZORAN, |
344 | PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) { | 344 | PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) { |
345 | ret = a4t_pci_probe(dev_a4t, cs, &found, &pci_memaddr); | 345 | ret = a4t_pci_probe(dev_a4t, cs, &found, &pci_memaddr); |
346 | if (!ret) | 346 | if (!ret) |
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c index e1ff4717a8a..e775706c60e 100644 --- a/drivers/isdn/hisax/bkm_a8.c +++ b/drivers/isdn/hisax/bkm_a8.c | |||
@@ -301,7 +301,7 @@ setup_sct_quadro(struct IsdnCard *card) | |||
301 | (sub_vendor_id != PCI_VENDOR_ID_BERKOM))) | 301 | (sub_vendor_id != PCI_VENDOR_ID_BERKOM))) |
302 | return (0); | 302 | return (0); |
303 | if (cs->subtyp == SCT_1) { | 303 | if (cs->subtyp == SCT_1) { |
304 | while ((dev_a8 = pci_find_device(PCI_VENDOR_ID_PLX, | 304 | while ((dev_a8 = hisax_find_pci_device(PCI_VENDOR_ID_PLX, |
305 | PCI_DEVICE_ID_PLX_9050, dev_a8))) { | 305 | PCI_DEVICE_ID_PLX_9050, dev_a8))) { |
306 | 306 | ||
307 | sub_vendor_id = dev_a8->subsystem_vendor; | 307 | sub_vendor_id = dev_a8->subsystem_vendor; |
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index 0b0c2e5d806..780da9bda91 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c | |||
@@ -1148,7 +1148,7 @@ static int __devinit setup_diva_isapnp(struct IsdnCard *card) | |||
1148 | 1148 | ||
1149 | #endif /* ISAPNP */ | 1149 | #endif /* ISAPNP */ |
1150 | 1150 | ||
1151 | #ifdef CONFIG_PCI_LEGACY | 1151 | #ifdef CONFIG_PCI |
1152 | static struct pci_dev *dev_diva __devinitdata = NULL; | 1152 | static struct pci_dev *dev_diva __devinitdata = NULL; |
1153 | static struct pci_dev *dev_diva_u __devinitdata = NULL; | 1153 | static struct pci_dev *dev_diva_u __devinitdata = NULL; |
1154 | static struct pci_dev *dev_diva201 __devinitdata = NULL; | 1154 | static struct pci_dev *dev_diva201 __devinitdata = NULL; |
@@ -1159,21 +1159,21 @@ static int __devinit setup_diva_pci(struct IsdnCard *card) | |||
1159 | struct IsdnCardState *cs = card->cs; | 1159 | struct IsdnCardState *cs = card->cs; |
1160 | 1160 | ||
1161 | cs->subtyp = 0; | 1161 | cs->subtyp = 0; |
1162 | if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, | 1162 | if ((dev_diva = hisax_find_pci_device(PCI_VENDOR_ID_EICON, |
1163 | PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { | 1163 | PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { |
1164 | if (pci_enable_device(dev_diva)) | 1164 | if (pci_enable_device(dev_diva)) |
1165 | return(0); | 1165 | return(0); |
1166 | cs->subtyp = DIVA_PCI; | 1166 | cs->subtyp = DIVA_PCI; |
1167 | cs->irq = dev_diva->irq; | 1167 | cs->irq = dev_diva->irq; |
1168 | cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2); | 1168 | cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2); |
1169 | } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON, | 1169 | } else if ((dev_diva_u = hisax_find_pci_device(PCI_VENDOR_ID_EICON, |
1170 | PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) { | 1170 | PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) { |
1171 | if (pci_enable_device(dev_diva_u)) | 1171 | if (pci_enable_device(dev_diva_u)) |
1172 | return(0); | 1172 | return(0); |
1173 | cs->subtyp = DIVA_PCI; | 1173 | cs->subtyp = DIVA_PCI; |
1174 | cs->irq = dev_diva_u->irq; | 1174 | cs->irq = dev_diva_u->irq; |
1175 | cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2); | 1175 | cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2); |
1176 | } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON, | 1176 | } else if ((dev_diva201 = hisax_find_pci_device(PCI_VENDOR_ID_EICON, |
1177 | PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) { | 1177 | PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) { |
1178 | if (pci_enable_device(dev_diva201)) | 1178 | if (pci_enable_device(dev_diva201)) |
1179 | return(0); | 1179 | return(0); |
@@ -1183,7 +1183,7 @@ static int __devinit setup_diva_pci(struct IsdnCard *card) | |||
1183 | (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096); | 1183 | (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096); |
1184 | cs->hw.diva.cfg_reg = | 1184 | cs->hw.diva.cfg_reg = |
1185 | (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096); | 1185 | (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096); |
1186 | } else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON, | 1186 | } else if ((dev_diva202 = hisax_find_pci_device(PCI_VENDOR_ID_EICON, |
1187 | PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) { | 1187 | PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) { |
1188 | if (pci_enable_device(dev_diva202)) | 1188 | if (pci_enable_device(dev_diva202)) |
1189 | return(0); | 1189 | return(0); |
@@ -1229,14 +1229,14 @@ static int __devinit setup_diva_pci(struct IsdnCard *card) | |||
1229 | return (1); /* card found */ | 1229 | return (1); /* card found */ |
1230 | } | 1230 | } |
1231 | 1231 | ||
1232 | #else /* if !CONFIG_PCI_LEGACY */ | 1232 | #else /* if !CONFIG_PCI */ |
1233 | 1233 | ||
1234 | static int __devinit setup_diva_pci(struct IsdnCard *card) | 1234 | static int __devinit setup_diva_pci(struct IsdnCard *card) |
1235 | { | 1235 | { |
1236 | return (-1); /* card not found; continue search */ | 1236 | return (-1); /* card not found; continue search */ |
1237 | } | 1237 | } |
1238 | 1238 | ||
1239 | #endif /* CONFIG_PCI_LEGACY */ | 1239 | #endif /* CONFIG_PCI */ |
1240 | 1240 | ||
1241 | int __devinit | 1241 | int __devinit |
1242 | setup_diva(struct IsdnCard *card) | 1242 | setup_diva(struct IsdnCard *card) |
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index aa29d1cf16a..23c41fcd864 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c | |||
@@ -1025,7 +1025,7 @@ setup_elsa_pcmcia(struct IsdnCard *card) | |||
1025 | cs->irq); | 1025 | cs->irq); |
1026 | } | 1026 | } |
1027 | 1027 | ||
1028 | #ifdef CONFIG_PCI_LEGACY | 1028 | #ifdef CONFIG_PCI |
1029 | static struct pci_dev *dev_qs1000 __devinitdata = NULL; | 1029 | static struct pci_dev *dev_qs1000 __devinitdata = NULL; |
1030 | static struct pci_dev *dev_qs3000 __devinitdata = NULL; | 1030 | static struct pci_dev *dev_qs3000 __devinitdata = NULL; |
1031 | 1031 | ||
@@ -1035,7 +1035,7 @@ setup_elsa_pci(struct IsdnCard *card) | |||
1035 | struct IsdnCardState *cs = card->cs; | 1035 | struct IsdnCardState *cs = card->cs; |
1036 | 1036 | ||
1037 | cs->subtyp = 0; | 1037 | cs->subtyp = 0; |
1038 | if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, | 1038 | if ((dev_qs1000 = hisax_find_pci_device(PCI_VENDOR_ID_ELSA, |
1039 | PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { | 1039 | PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { |
1040 | if (pci_enable_device(dev_qs1000)) | 1040 | if (pci_enable_device(dev_qs1000)) |
1041 | return(0); | 1041 | return(0); |
@@ -1043,7 +1043,7 @@ setup_elsa_pci(struct IsdnCard *card) | |||
1043 | cs->irq = dev_qs1000->irq; | 1043 | cs->irq = dev_qs1000->irq; |
1044 | cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); | 1044 | cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); |
1045 | cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); | 1045 | cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); |
1046 | } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA, | 1046 | } else if ((dev_qs3000 = hisax_find_pci_device(PCI_VENDOR_ID_ELSA, |
1047 | PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { | 1047 | PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { |
1048 | if (pci_enable_device(dev_qs3000)) | 1048 | if (pci_enable_device(dev_qs3000)) |
1049 | return(0); | 1049 | return(0); |
@@ -1093,7 +1093,7 @@ setup_elsa_pci(struct IsdnCard *card) | |||
1093 | { | 1093 | { |
1094 | return (1); | 1094 | return (1); |
1095 | } | 1095 | } |
1096 | #endif /* CONFIG_PCI_LEGACY */ | 1096 | #endif /* CONFIG_PCI */ |
1097 | 1097 | ||
1098 | static int __devinit | 1098 | static int __devinit |
1099 | setup_elsa_common(struct IsdnCard *card) | 1099 | setup_elsa_common(struct IsdnCard *card) |
diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c index 39f421ed8de..26264abf1f5 100644 --- a/drivers/isdn/hisax/enternow_pci.c +++ b/drivers/isdn/hisax/enternow_pci.c | |||
@@ -406,7 +406,7 @@ setup_enternow_pci(struct IsdnCard *card) | |||
406 | 406 | ||
407 | for ( ;; ) | 407 | for ( ;; ) |
408 | { | 408 | { |
409 | if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, | 409 | if ((dev_netjet = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, |
410 | PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { | 410 | PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { |
411 | ret = en_pci_probe(dev_netjet, cs); | 411 | ret = en_pci_probe(dev_netjet, cs); |
412 | if (!ret) | 412 | if (!ret) |
diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c index 0ea3b460768..353982fc143 100644 --- a/drivers/isdn/hisax/gazel.c +++ b/drivers/isdn/hisax/gazel.c | |||
@@ -531,7 +531,7 @@ setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) | |||
531 | return (0); | 531 | return (0); |
532 | } | 532 | } |
533 | 533 | ||
534 | #ifdef CONFIG_PCI_LEGACY | 534 | #ifdef CONFIG_PCI |
535 | static struct pci_dev *dev_tel __devinitdata = NULL; | 535 | static struct pci_dev *dev_tel __devinitdata = NULL; |
536 | 536 | ||
537 | static int __devinit | 537 | static int __devinit |
@@ -546,7 +546,7 @@ setup_gazelpci(struct IsdnCardState *cs) | |||
546 | found = 0; | 546 | found = 0; |
547 | seekcard = PCI_DEVICE_ID_PLX_R685; | 547 | seekcard = PCI_DEVICE_ID_PLX_R685; |
548 | for (nbseek = 0; nbseek < 4; nbseek++) { | 548 | for (nbseek = 0; nbseek < 4; nbseek++) { |
549 | if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, | 549 | if ((dev_tel = hisax_find_pci_device(PCI_VENDOR_ID_PLX, |
550 | seekcard, dev_tel))) { | 550 | seekcard, dev_tel))) { |
551 | if (pci_enable_device(dev_tel)) | 551 | if (pci_enable_device(dev_tel)) |
552 | return 1; | 552 | return 1; |
@@ -620,7 +620,7 @@ setup_gazelpci(struct IsdnCardState *cs) | |||
620 | 620 | ||
621 | return (0); | 621 | return (0); |
622 | } | 622 | } |
623 | #endif /* CONFIG_PCI_LEGACY */ | 623 | #endif /* CONFIG_PCI */ |
624 | 624 | ||
625 | int __devinit | 625 | int __devinit |
626 | setup_gazel(struct IsdnCard *card) | 626 | setup_gazel(struct IsdnCard *card) |
@@ -640,7 +640,7 @@ setup_gazel(struct IsdnCard *card) | |||
640 | return (0); | 640 | return (0); |
641 | } else { | 641 | } else { |
642 | 642 | ||
643 | #ifdef CONFIG_PCI_LEGACY | 643 | #ifdef CONFIG_PCI |
644 | if (setup_gazelpci(cs)) | 644 | if (setup_gazelpci(cs)) |
645 | return (0); | 645 | return (0); |
646 | #else | 646 | #else |
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 10914731b30..917cc84065b 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c | |||
@@ -1658,7 +1658,7 @@ setup_hfcpci(struct IsdnCard *card) | |||
1658 | 1658 | ||
1659 | i = 0; | 1659 | i = 0; |
1660 | while (id_list[i].vendor_id) { | 1660 | while (id_list[i].vendor_id) { |
1661 | tmp_hfcpci = pci_find_device(id_list[i].vendor_id, | 1661 | tmp_hfcpci = hisax_find_pci_device(id_list[i].vendor_id, |
1662 | id_list[i].device_id, | 1662 | id_list[i].device_id, |
1663 | dev_hfcpci); | 1663 | dev_hfcpci); |
1664 | i++; | 1664 | i++; |
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 0685c194696..832a87855ff 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h | |||
@@ -1323,3 +1323,26 @@ void release_tei(struct IsdnCardState *cs); | |||
1323 | char *HiSax_getrev(const char *revision); | 1323 | char *HiSax_getrev(const char *revision); |
1324 | int TeiNew(void); | 1324 | int TeiNew(void); |
1325 | void TeiFree(void); | 1325 | void TeiFree(void); |
1326 | |||
1327 | #ifdef CONFIG_PCI | ||
1328 | |||
1329 | #include <linux/pci.h> | ||
1330 | |||
1331 | /* adaptation wrapper for old usage | ||
1332 | * WARNING! This is unfit for use in a PCI hotplug environment, | ||
1333 | * as the returned PCI device can disappear at any moment in time. | ||
1334 | * Callers should be converted to use pci_get_device() instead. | ||
1335 | */ | ||
1336 | static inline struct pci_dev *hisax_find_pci_device(unsigned int vendor, | ||
1337 | unsigned int device, | ||
1338 | struct pci_dev *from) | ||
1339 | { | ||
1340 | struct pci_dev *pdev; | ||
1341 | |||
1342 | pci_dev_get(from); | ||
1343 | pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); | ||
1344 | pci_dev_put(pdev); | ||
1345 | return pdev; | ||
1346 | } | ||
1347 | |||
1348 | #endif | ||
diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c index ef00633e1d2..ccaa6e13310 100644 --- a/drivers/isdn/hisax/niccy.c +++ b/drivers/isdn/hisax/niccy.c | |||
@@ -297,12 +297,12 @@ int __devinit setup_niccy(struct IsdnCard *card) | |||
297 | return 0; | 297 | return 0; |
298 | } | 298 | } |
299 | } else { | 299 | } else { |
300 | #ifdef CONFIG_PCI_LEGACY | 300 | #ifdef CONFIG_PCI |
301 | static struct pci_dev *niccy_dev __devinitdata; | 301 | static struct pci_dev *niccy_dev __devinitdata; |
302 | 302 | ||
303 | u_int pci_ioaddr; | 303 | u_int pci_ioaddr; |
304 | cs->subtyp = 0; | 304 | cs->subtyp = 0; |
305 | if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM, | 305 | if ((niccy_dev = hisax_find_pci_device(PCI_VENDOR_ID_SATSAGEM, |
306 | PCI_DEVICE_ID_SATSAGEM_NICCY, | 306 | PCI_DEVICE_ID_SATSAGEM_NICCY, |
307 | niccy_dev))) { | 307 | niccy_dev))) { |
308 | if (pci_enable_device(niccy_dev)) | 308 | if (pci_enable_device(niccy_dev)) |
@@ -354,7 +354,7 @@ int __devinit setup_niccy(struct IsdnCard *card) | |||
354 | printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n"); | 354 | printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n"); |
355 | printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n"); | 355 | printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n"); |
356 | return 0; | 356 | return 0; |
357 | #endif /* CONFIG_PCI_LEGACY */ | 357 | #endif /* CONFIG_PCI */ |
358 | } | 358 | } |
359 | printk(KERN_INFO "HiSax: NICCY %s config irq:%d data:0x%X ale:0x%X\n", | 359 | printk(KERN_INFO "HiSax: NICCY %s config irq:%d data:0x%X ale:0x%X\n", |
360 | (cs->subtyp == 1) ? "PnP" : "PCI", | 360 | (cs->subtyp == 1) ? "PnP" : "PCI", |
diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c index 8d36ccc87d8..2344e7b3344 100644 --- a/drivers/isdn/hisax/nj_s.c +++ b/drivers/isdn/hisax/nj_s.c | |||
@@ -276,7 +276,7 @@ setup_netjet_s(struct IsdnCard *card) | |||
276 | 276 | ||
277 | for ( ;; ) | 277 | for ( ;; ) |
278 | { | 278 | { |
279 | if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, | 279 | if ((dev_netjet = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, |
280 | PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { | 280 | PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { |
281 | ret = njs_pci_probe(dev_netjet, cs); | 281 | ret = njs_pci_probe(dev_netjet, cs); |
282 | if (!ret) | 282 | if (!ret) |
diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c index d306c946ffb..095e974aed8 100644 --- a/drivers/isdn/hisax/nj_u.c +++ b/drivers/isdn/hisax/nj_u.c | |||
@@ -240,7 +240,7 @@ setup_netjet_u(struct IsdnCard *card) | |||
240 | 240 | ||
241 | for ( ;; ) | 241 | for ( ;; ) |
242 | { | 242 | { |
243 | if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, | 243 | if ((dev_netjet = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, |
244 | PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { | 244 | PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { |
245 | ret = nju_pci_probe(dev_netjet, cs); | 245 | ret = nju_pci_probe(dev_netjet, cs); |
246 | if (!ret) | 246 | if (!ret) |
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c index 5569a522e2a..69dfc8d2901 100644 --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c | |||
@@ -598,7 +598,7 @@ setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt) | |||
598 | } | 598 | } |
599 | #endif /* __ISAPNP__ */ | 599 | #endif /* __ISAPNP__ */ |
600 | 600 | ||
601 | #ifdef CONFIG_PCI_LEGACY | 601 | #ifdef CONFIG_PCI |
602 | static struct pci_dev *dev_sedl __devinitdata = NULL; | 602 | static struct pci_dev *dev_sedl __devinitdata = NULL; |
603 | 603 | ||
604 | static int __devinit | 604 | static int __devinit |
@@ -607,7 +607,7 @@ setup_sedlbauer_pci(struct IsdnCard *card) | |||
607 | struct IsdnCardState *cs = card->cs; | 607 | struct IsdnCardState *cs = card->cs; |
608 | u16 sub_vendor_id, sub_id; | 608 | u16 sub_vendor_id, sub_id; |
609 | 609 | ||
610 | if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, | 610 | if ((dev_sedl = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, |
611 | PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { | 611 | PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { |
612 | if (pci_enable_device(dev_sedl)) | 612 | if (pci_enable_device(dev_sedl)) |
613 | return(0); | 613 | return(0); |
@@ -673,7 +673,7 @@ setup_sedlbauer_pci(struct IsdnCard *card) | |||
673 | return (1); | 673 | return (1); |
674 | } | 674 | } |
675 | 675 | ||
676 | #endif /* CONFIG_PCI_LEGACY */ | 676 | #endif /* CONFIG_PCI */ |
677 | 677 | ||
678 | int __devinit | 678 | int __devinit |
679 | setup_sedlbauer(struct IsdnCard *card) | 679 | setup_sedlbauer(struct IsdnCard *card) |
diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c index 28b08de4673..b85ceb3746c 100644 --- a/drivers/isdn/hisax/telespci.c +++ b/drivers/isdn/hisax/telespci.c | |||
@@ -300,7 +300,7 @@ setup_telespci(struct IsdnCard *card) | |||
300 | if (cs->typ != ISDN_CTYPE_TELESPCI) | 300 | if (cs->typ != ISDN_CTYPE_TELESPCI) |
301 | return (0); | 301 | return (0); |
302 | 302 | ||
303 | if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { | 303 | if ((dev_tel = hisax_find_pci_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { |
304 | if (pci_enable_device(dev_tel)) | 304 | if (pci_enable_device(dev_tel)) |
305 | return(0); | 305 | return(0); |
306 | cs->irq = dev_tel->irq; | 306 | cs->irq = dev_tel->irq; |
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c index c4d862c11a6..9d6e864023f 100644 --- a/drivers/isdn/hisax/w6692.c +++ b/drivers/isdn/hisax/w6692.c | |||
@@ -1007,7 +1007,7 @@ setup_w6692(struct IsdnCard *card) | |||
1007 | return (0); | 1007 | return (0); |
1008 | 1008 | ||
1009 | while (id_list[id_idx].vendor_id) { | 1009 | while (id_list[id_idx].vendor_id) { |
1010 | dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, | 1010 | dev_w6692 = hisax_find_pci_device(id_list[id_idx].vendor_id, |
1011 | id_list[id_idx].device_id, | 1011 | id_list[id_idx].device_id, |
1012 | dev_w6692); | 1012 | dev_w6692); |
1013 | if (dev_w6692) { | 1013 | if (dev_w6692) { |
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index b1ecefa2a23..7858a117e80 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig | |||
@@ -21,17 +21,6 @@ config PCI_MSI | |||
21 | 21 | ||
22 | If you don't know what to do here, say N. | 22 | If you don't know what to do here, say N. |
23 | 23 | ||
24 | config PCI_LEGACY | ||
25 | bool "Enable deprecated pci_find_* API" | ||
26 | depends on PCI | ||
27 | default y | ||
28 | help | ||
29 | Say Y here if you want to include support for the deprecated | ||
30 | pci_find_device() API. Most drivers have been converted over | ||
31 | to using the proper hotplug APIs, so this option serves to | ||
32 | include/exclude only a few drivers that are still using this | ||
33 | API. | ||
34 | |||
35 | config PCI_DEBUG | 24 | config PCI_DEBUG |
36 | bool "PCI Debugging" | 25 | bool "PCI Debugging" |
37 | depends on PCI && DEBUG_KERNEL | 26 | depends on PCI && DEBUG_KERNEL |
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 4df48d58eaa..8674c1ebe97 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile | |||
@@ -2,14 +2,13 @@ | |||
2 | # Makefile for the PCI bus specific drivers. | 2 | # Makefile for the PCI bus specific drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \ | 5 | obj-y += access.o bus.o probe.o remove.o pci.o \ |
6 | pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ | 6 | pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ |
7 | irq.o | 7 | irq.o |
8 | obj-$(CONFIG_PROC_FS) += proc.o | 8 | obj-$(CONFIG_PROC_FS) += proc.o |
9 | obj-$(CONFIG_SYSFS) += slot.o | 9 | obj-$(CONFIG_SYSFS) += slot.o |
10 | 10 | ||
11 | obj-$(CONFIG_PCI_LEGACY) += legacy.o | 11 | obj-$(CONFIG_PCI_QUIRKS) += quirks.o |
12 | CFLAGS_legacy.o += -Wno-deprecated-declarations | ||
13 | 12 | ||
14 | # Build PCI Express stuff if needed | 13 | # Build PCI Express stuff if needed |
15 | obj-$(CONFIG_PCIEPORTBUS) += pcie/ | 14 | obj-$(CONFIG_PCIEPORTBUS) += pcie/ |
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index cef28a79103..712250f5874 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c | |||
@@ -17,6 +17,52 @@ | |||
17 | 17 | ||
18 | #include "pci.h" | 18 | #include "pci.h" |
19 | 19 | ||
20 | void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, | ||
21 | unsigned int flags) | ||
22 | { | ||
23 | struct pci_bus_resource *bus_res; | ||
24 | |||
25 | bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL); | ||
26 | if (!bus_res) { | ||
27 | dev_err(&bus->dev, "can't add %pR resource\n", res); | ||
28 | return; | ||
29 | } | ||
30 | |||
31 | bus_res->res = res; | ||
32 | bus_res->flags = flags; | ||
33 | list_add_tail(&bus_res->list, &bus->resources); | ||
34 | } | ||
35 | |||
36 | struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n) | ||
37 | { | ||
38 | struct pci_bus_resource *bus_res; | ||
39 | |||
40 | if (n < PCI_BRIDGE_RESOURCE_NUM) | ||
41 | return bus->resource[n]; | ||
42 | |||
43 | n -= PCI_BRIDGE_RESOURCE_NUM; | ||
44 | list_for_each_entry(bus_res, &bus->resources, list) { | ||
45 | if (n-- == 0) | ||
46 | return bus_res->res; | ||
47 | } | ||
48 | return NULL; | ||
49 | } | ||
50 | EXPORT_SYMBOL_GPL(pci_bus_resource_n); | ||
51 | |||
52 | void pci_bus_remove_resources(struct pci_bus *bus) | ||
53 | { | ||
54 | struct pci_bus_resource *bus_res, *tmp; | ||
55 | int i; | ||
56 | |||
57 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) | ||
58 | bus->resource[i] = 0; | ||
59 | |||
60 | list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) { | ||
61 | list_del(&bus_res->list); | ||
62 | kfree(bus_res); | ||
63 | } | ||
64 | } | ||
65 | |||
20 | /** | 66 | /** |
21 | * pci_bus_alloc_resource - allocate a resource from a parent bus | 67 | * pci_bus_alloc_resource - allocate a resource from a parent bus |
22 | * @bus: PCI bus | 68 | * @bus: PCI bus |
@@ -36,11 +82,14 @@ int | |||
36 | pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, | 82 | pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, |
37 | resource_size_t size, resource_size_t align, | 83 | resource_size_t size, resource_size_t align, |
38 | resource_size_t min, unsigned int type_mask, | 84 | resource_size_t min, unsigned int type_mask, |
39 | void (*alignf)(void *, struct resource *, resource_size_t, | 85 | resource_size_t (*alignf)(void *, |
40 | resource_size_t), | 86 | const struct resource *, |
87 | resource_size_t, | ||
88 | resource_size_t), | ||
41 | void *alignf_data) | 89 | void *alignf_data) |
42 | { | 90 | { |
43 | int i, ret = -ENOMEM; | 91 | int i, ret = -ENOMEM; |
92 | struct resource *r; | ||
44 | resource_size_t max = -1; | 93 | resource_size_t max = -1; |
45 | 94 | ||
46 | type_mask |= IORESOURCE_IO | IORESOURCE_MEM; | 95 | type_mask |= IORESOURCE_IO | IORESOURCE_MEM; |
@@ -49,8 +98,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, | |||
49 | if (!(res->flags & IORESOURCE_MEM_64)) | 98 | if (!(res->flags & IORESOURCE_MEM_64)) |
50 | max = PCIBIOS_MAX_MEM_32; | 99 | max = PCIBIOS_MAX_MEM_32; |
51 | 100 | ||
52 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 101 | pci_bus_for_each_resource(bus, r, i) { |
53 | struct resource *r = bus->resource[i]; | ||
54 | if (!r) | 102 | if (!r) |
55 | continue; | 103 | continue; |
56 | 104 | ||
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 4dd7114964a..efa9f2de51c 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c | |||
@@ -332,8 +332,6 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) | |||
332 | slot->hotplug_slot->info->attention_status = 0; | 332 | slot->hotplug_slot->info->attention_status = 0; |
333 | slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); | 333 | slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); |
334 | slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); | 334 | slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); |
335 | slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; | ||
336 | slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; | ||
337 | 335 | ||
338 | acpiphp_slot->slot = slot; | 336 | acpiphp_slot->slot = slot; |
339 | snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun); | 337 | snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun); |
diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c index 148fb463b81..fb3f84661bd 100644 --- a/drivers/pci/hotplug/cpcihp_generic.c +++ b/drivers/pci/hotplug/cpcihp_generic.c | |||
@@ -162,6 +162,7 @@ static int __init cpcihp_generic_init(void) | |||
162 | dev = pci_get_slot(bus, PCI_DEVFN(bridge_slot, 0)); | 162 | dev = pci_get_slot(bus, PCI_DEVFN(bridge_slot, 0)); |
163 | if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { | 163 | if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { |
164 | err("Invalid bridge device %s", bridge); | 164 | err("Invalid bridge device %s", bridge); |
165 | pci_dev_put(dev); | ||
165 | return -EINVAL; | 166 | return -EINVAL; |
166 | } | 167 | } |
167 | bus = dev->subordinate; | 168 | bus = dev->subordinate; |
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index 9c6a9fd2681..d8ffc736680 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h | |||
@@ -310,8 +310,6 @@ struct controller { | |||
310 | u8 first_slot; | 310 | u8 first_slot; |
311 | u8 add_support; | 311 | u8 add_support; |
312 | u8 push_flag; | 312 | u8 push_flag; |
313 | enum pci_bus_speed speed; | ||
314 | enum pci_bus_speed speed_capability; | ||
315 | u8 push_button; /* 0 = no pushbutton, 1 = pushbutton present */ | 313 | u8 push_button; /* 0 = no pushbutton, 1 = pushbutton present */ |
316 | u8 slot_switch_type; /* 0 = no switch, 1 = switch present */ | 314 | u8 slot_switch_type; /* 0 = no switch, 1 = switch present */ |
317 | u8 defeature_PHP; /* 0 = PHP not supported, 1 = PHP supported */ | 315 | u8 defeature_PHP; /* 0 = PHP not supported, 1 = PHP supported */ |
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 075b4f4b6e0..f184d1d2ecb 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c | |||
@@ -583,30 +583,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) | |||
583 | return 0; | 583 | return 0; |
584 | } | 584 | } |
585 | 585 | ||
586 | static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | ||
587 | { | ||
588 | struct slot *slot = hotplug_slot->private; | ||
589 | struct controller *ctrl = slot->ctrl; | ||
590 | |||
591 | dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); | ||
592 | |||
593 | *value = ctrl->speed_capability; | ||
594 | |||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | ||
599 | { | ||
600 | struct slot *slot = hotplug_slot->private; | ||
601 | struct controller *ctrl = slot->ctrl; | ||
602 | |||
603 | dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); | ||
604 | |||
605 | *value = ctrl->speed; | ||
606 | |||
607 | return 0; | ||
608 | } | ||
609 | |||
610 | static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { | 586 | static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { |
611 | .set_attention_status = set_attention_status, | 587 | .set_attention_status = set_attention_status, |
612 | .enable_slot = process_SI, | 588 | .enable_slot = process_SI, |
@@ -616,8 +592,6 @@ static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { | |||
616 | .get_attention_status = get_attention_status, | 592 | .get_attention_status = get_attention_status, |
617 | .get_latch_status = get_latch_status, | 593 | .get_latch_status = get_latch_status, |
618 | .get_adapter_status = get_adapter_status, | 594 | .get_adapter_status = get_adapter_status, |
619 | .get_max_bus_speed = get_max_bus_speed, | ||
620 | .get_cur_bus_speed = get_cur_bus_speed, | ||
621 | }; | 595 | }; |
622 | 596 | ||
623 | #define SLOT_NAME_SIZE 10 | 597 | #define SLOT_NAME_SIZE 10 |
@@ -629,6 +603,7 @@ static int ctrl_slot_setup(struct controller *ctrl, | |||
629 | struct slot *slot; | 603 | struct slot *slot; |
630 | struct hotplug_slot *hotplug_slot; | 604 | struct hotplug_slot *hotplug_slot; |
631 | struct hotplug_slot_info *hotplug_slot_info; | 605 | struct hotplug_slot_info *hotplug_slot_info; |
606 | struct pci_bus *bus = ctrl->pci_bus; | ||
632 | u8 number_of_slots; | 607 | u8 number_of_slots; |
633 | u8 slot_device; | 608 | u8 slot_device; |
634 | u8 slot_number; | 609 | u8 slot_number; |
@@ -694,7 +669,7 @@ static int ctrl_slot_setup(struct controller *ctrl, | |||
694 | slot->capabilities |= PCISLOT_64_BIT_SUPPORTED; | 669 | slot->capabilities |= PCISLOT_64_BIT_SUPPORTED; |
695 | if (is_slot66mhz(slot)) | 670 | if (is_slot66mhz(slot)) |
696 | slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED; | 671 | slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED; |
697 | if (ctrl->speed == PCI_SPEED_66MHz) | 672 | if (bus->cur_bus_speed == PCI_SPEED_66MHz) |
698 | slot->capabilities |= PCISLOT_66_MHZ_OPERATION; | 673 | slot->capabilities |= PCISLOT_66_MHZ_OPERATION; |
699 | 674 | ||
700 | ctrl_slot = | 675 | ctrl_slot = |
@@ -844,6 +819,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
844 | u32 rc; | 819 | u32 rc; |
845 | struct controller *ctrl; | 820 | struct controller *ctrl; |
846 | struct pci_func *func; | 821 | struct pci_func *func; |
822 | struct pci_bus *bus; | ||
847 | int err; | 823 | int err; |
848 | 824 | ||
849 | err = pci_enable_device(pdev); | 825 | err = pci_enable_device(pdev); |
@@ -852,6 +828,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
852 | pci_name(pdev), err); | 828 | pci_name(pdev), err); |
853 | return err; | 829 | return err; |
854 | } | 830 | } |
831 | bus = pdev->subordinate; | ||
855 | 832 | ||
856 | /* Need to read VID early b/c it's used to differentiate CPQ and INTC | 833 | /* Need to read VID early b/c it's used to differentiate CPQ and INTC |
857 | * discovery | 834 | * discovery |
@@ -929,22 +906,22 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
929 | pci_read_config_byte(pdev, 0x41, &bus_cap); | 906 | pci_read_config_byte(pdev, 0x41, &bus_cap); |
930 | if (bus_cap & 0x80) { | 907 | if (bus_cap & 0x80) { |
931 | dbg("bus max supports 133MHz PCI-X\n"); | 908 | dbg("bus max supports 133MHz PCI-X\n"); |
932 | ctrl->speed_capability = PCI_SPEED_133MHz_PCIX; | 909 | bus->max_bus_speed = PCI_SPEED_133MHz_PCIX; |
933 | break; | 910 | break; |
934 | } | 911 | } |
935 | if (bus_cap & 0x40) { | 912 | if (bus_cap & 0x40) { |
936 | dbg("bus max supports 100MHz PCI-X\n"); | 913 | dbg("bus max supports 100MHz PCI-X\n"); |
937 | ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; | 914 | bus->max_bus_speed = PCI_SPEED_100MHz_PCIX; |
938 | break; | 915 | break; |
939 | } | 916 | } |
940 | if (bus_cap & 20) { | 917 | if (bus_cap & 20) { |
941 | dbg("bus max supports 66MHz PCI-X\n"); | 918 | dbg("bus max supports 66MHz PCI-X\n"); |
942 | ctrl->speed_capability = PCI_SPEED_66MHz_PCIX; | 919 | bus->max_bus_speed = PCI_SPEED_66MHz_PCIX; |
943 | break; | 920 | break; |
944 | } | 921 | } |
945 | if (bus_cap & 10) { | 922 | if (bus_cap & 10) { |
946 | dbg("bus max supports 66MHz PCI\n"); | 923 | dbg("bus max supports 66MHz PCI\n"); |
947 | ctrl->speed_capability = PCI_SPEED_66MHz; | 924 | bus->max_bus_speed = PCI_SPEED_66MHz; |
948 | break; | 925 | break; |
949 | } | 926 | } |
950 | 927 | ||
@@ -955,7 +932,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
955 | case PCI_SUB_HPC_ID: | 932 | case PCI_SUB_HPC_ID: |
956 | /* Original 6500/7000 implementation */ | 933 | /* Original 6500/7000 implementation */ |
957 | ctrl->slot_switch_type = 1; | 934 | ctrl->slot_switch_type = 1; |
958 | ctrl->speed_capability = PCI_SPEED_33MHz; | 935 | bus->max_bus_speed = PCI_SPEED_33MHz; |
959 | ctrl->push_button = 0; | 936 | ctrl->push_button = 0; |
960 | ctrl->pci_config_space = 1; | 937 | ctrl->pci_config_space = 1; |
961 | ctrl->defeature_PHP = 1; | 938 | ctrl->defeature_PHP = 1; |
@@ -966,7 +943,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
966 | /* First Pushbutton implementation */ | 943 | /* First Pushbutton implementation */ |
967 | ctrl->push_flag = 1; | 944 | ctrl->push_flag = 1; |
968 | ctrl->slot_switch_type = 1; | 945 | ctrl->slot_switch_type = 1; |
969 | ctrl->speed_capability = PCI_SPEED_33MHz; | 946 | bus->max_bus_speed = PCI_SPEED_33MHz; |
970 | ctrl->push_button = 1; | 947 | ctrl->push_button = 1; |
971 | ctrl->pci_config_space = 1; | 948 | ctrl->pci_config_space = 1; |
972 | ctrl->defeature_PHP = 1; | 949 | ctrl->defeature_PHP = 1; |
@@ -976,7 +953,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
976 | case PCI_SUB_HPC_ID_INTC: | 953 | case PCI_SUB_HPC_ID_INTC: |
977 | /* Third party (6500/7000) */ | 954 | /* Third party (6500/7000) */ |
978 | ctrl->slot_switch_type = 1; | 955 | ctrl->slot_switch_type = 1; |
979 | ctrl->speed_capability = PCI_SPEED_33MHz; | 956 | bus->max_bus_speed = PCI_SPEED_33MHz; |
980 | ctrl->push_button = 0; | 957 | ctrl->push_button = 0; |
981 | ctrl->pci_config_space = 1; | 958 | ctrl->pci_config_space = 1; |
982 | ctrl->defeature_PHP = 1; | 959 | ctrl->defeature_PHP = 1; |
@@ -987,7 +964,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
987 | /* First 66 Mhz implementation */ | 964 | /* First 66 Mhz implementation */ |
988 | ctrl->push_flag = 1; | 965 | ctrl->push_flag = 1; |
989 | ctrl->slot_switch_type = 1; | 966 | ctrl->slot_switch_type = 1; |
990 | ctrl->speed_capability = PCI_SPEED_66MHz; | 967 | bus->max_bus_speed = PCI_SPEED_66MHz; |
991 | ctrl->push_button = 1; | 968 | ctrl->push_button = 1; |
992 | ctrl->pci_config_space = 1; | 969 | ctrl->pci_config_space = 1; |
993 | ctrl->defeature_PHP = 1; | 970 | ctrl->defeature_PHP = 1; |
@@ -998,7 +975,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
998 | /* First PCI-X implementation, 100MHz */ | 975 | /* First PCI-X implementation, 100MHz */ |
999 | ctrl->push_flag = 1; | 976 | ctrl->push_flag = 1; |
1000 | ctrl->slot_switch_type = 1; | 977 | ctrl->slot_switch_type = 1; |
1001 | ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; | 978 | bus->max_bus_speed = PCI_SPEED_100MHz_PCIX; |
1002 | ctrl->push_button = 1; | 979 | ctrl->push_button = 1; |
1003 | ctrl->pci_config_space = 1; | 980 | ctrl->pci_config_space = 1; |
1004 | ctrl->defeature_PHP = 1; | 981 | ctrl->defeature_PHP = 1; |
@@ -1015,9 +992,9 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1015 | case PCI_VENDOR_ID_INTEL: | 992 | case PCI_VENDOR_ID_INTEL: |
1016 | /* Check for speed capability (0=33, 1=66) */ | 993 | /* Check for speed capability (0=33, 1=66) */ |
1017 | if (subsystem_deviceid & 0x0001) | 994 | if (subsystem_deviceid & 0x0001) |
1018 | ctrl->speed_capability = PCI_SPEED_66MHz; | 995 | bus->max_bus_speed = PCI_SPEED_66MHz; |
1019 | else | 996 | else |
1020 | ctrl->speed_capability = PCI_SPEED_33MHz; | 997 | bus->max_bus_speed = PCI_SPEED_33MHz; |
1021 | 998 | ||
1022 | /* Check for push button */ | 999 | /* Check for push button */ |
1023 | if (subsystem_deviceid & 0x0002) | 1000 | if (subsystem_deviceid & 0x0002) |
@@ -1079,7 +1056,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1079 | pdev->bus->number); | 1056 | pdev->bus->number); |
1080 | 1057 | ||
1081 | dbg("Hotplug controller capabilities:\n"); | 1058 | dbg("Hotplug controller capabilities:\n"); |
1082 | dbg(" speed_capability %d\n", ctrl->speed_capability); | 1059 | dbg(" speed_capability %d\n", bus->max_bus_speed); |
1083 | dbg(" slot_switch_type %s\n", ctrl->slot_switch_type ? | 1060 | dbg(" slot_switch_type %s\n", ctrl->slot_switch_type ? |
1084 | "switch present" : "no switch"); | 1061 | "switch present" : "no switch"); |
1085 | dbg(" defeature_PHP %s\n", ctrl->defeature_PHP ? | 1062 | dbg(" defeature_PHP %s\n", ctrl->defeature_PHP ? |
@@ -1142,7 +1119,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1142 | } | 1119 | } |
1143 | 1120 | ||
1144 | /* Check for 66Mhz operation */ | 1121 | /* Check for 66Mhz operation */ |
1145 | ctrl->speed = get_controller_speed(ctrl); | 1122 | bus->cur_bus_speed = get_controller_speed(ctrl); |
1146 | 1123 | ||
1147 | 1124 | ||
1148 | /******************************************************** | 1125 | /******************************************************** |
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 0ff689afa75..e43908d9b5d 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c | |||
@@ -1130,12 +1130,13 @@ static int is_bridge(struct pci_func * func) | |||
1130 | static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot) | 1130 | static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot) |
1131 | { | 1131 | { |
1132 | struct slot *slot; | 1132 | struct slot *slot; |
1133 | struct pci_bus *bus = ctrl->pci_bus; | ||
1133 | u8 reg; | 1134 | u8 reg; |
1134 | u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER); | 1135 | u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER); |
1135 | u16 reg16; | 1136 | u16 reg16; |
1136 | u32 leds = readl(ctrl->hpc_reg + LED_CONTROL); | 1137 | u32 leds = readl(ctrl->hpc_reg + LED_CONTROL); |
1137 | 1138 | ||
1138 | if (ctrl->speed == adapter_speed) | 1139 | if (bus->cur_bus_speed == adapter_speed) |
1139 | return 0; | 1140 | return 0; |
1140 | 1141 | ||
1141 | /* We don't allow freq/mode changes if we find another adapter running | 1142 | /* We don't allow freq/mode changes if we find another adapter running |
@@ -1152,7 +1153,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
1152 | * lower speed/mode, we allow the new adapter to function at | 1153 | * lower speed/mode, we allow the new adapter to function at |
1153 | * this rate if supported | 1154 | * this rate if supported |
1154 | */ | 1155 | */ |
1155 | if (ctrl->speed < adapter_speed) | 1156 | if (bus->cur_bus_speed < adapter_speed) |
1156 | return 0; | 1157 | return 0; |
1157 | 1158 | ||
1158 | return 1; | 1159 | return 1; |
@@ -1161,20 +1162,20 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
1161 | /* If the controller doesn't support freq/mode changes and the | 1162 | /* If the controller doesn't support freq/mode changes and the |
1162 | * controller is running at a higher mode, we bail | 1163 | * controller is running at a higher mode, we bail |
1163 | */ | 1164 | */ |
1164 | if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability)) | 1165 | if ((bus->cur_bus_speed > adapter_speed) && (!ctrl->pcix_speed_capability)) |
1165 | return 1; | 1166 | return 1; |
1166 | 1167 | ||
1167 | /* But we allow the adapter to run at a lower rate if possible */ | 1168 | /* But we allow the adapter to run at a lower rate if possible */ |
1168 | if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability)) | 1169 | if ((bus->cur_bus_speed < adapter_speed) && (!ctrl->pcix_speed_capability)) |
1169 | return 0; | 1170 | return 0; |
1170 | 1171 | ||
1171 | /* We try to set the max speed supported by both the adapter and | 1172 | /* We try to set the max speed supported by both the adapter and |
1172 | * controller | 1173 | * controller |
1173 | */ | 1174 | */ |
1174 | if (ctrl->speed_capability < adapter_speed) { | 1175 | if (bus->max_bus_speed < adapter_speed) { |
1175 | if (ctrl->speed == ctrl->speed_capability) | 1176 | if (bus->cur_bus_speed == bus->max_bus_speed) |
1176 | return 0; | 1177 | return 0; |
1177 | adapter_speed = ctrl->speed_capability; | 1178 | adapter_speed = bus->max_bus_speed; |
1178 | } | 1179 | } |
1179 | 1180 | ||
1180 | writel(0x0L, ctrl->hpc_reg + LED_CONTROL); | 1181 | writel(0x0L, ctrl->hpc_reg + LED_CONTROL); |
@@ -1229,8 +1230,8 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
1229 | pci_write_config_byte(ctrl->pci_dev, 0x43, reg); | 1230 | pci_write_config_byte(ctrl->pci_dev, 0x43, reg); |
1230 | 1231 | ||
1231 | /* Only if mode change...*/ | 1232 | /* Only if mode change...*/ |
1232 | if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) || | 1233 | if (((bus->cur_bus_speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) || |
1233 | ((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) | 1234 | ((bus->cur_bus_speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) |
1234 | set_SOGO(ctrl); | 1235 | set_SOGO(ctrl); |
1235 | 1236 | ||
1236 | wait_for_ctrl_irq(ctrl); | 1237 | wait_for_ctrl_irq(ctrl); |
@@ -1243,7 +1244,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
1243 | set_SOGO(ctrl); | 1244 | set_SOGO(ctrl); |
1244 | wait_for_ctrl_irq(ctrl); | 1245 | wait_for_ctrl_irq(ctrl); |
1245 | 1246 | ||
1246 | ctrl->speed = adapter_speed; | 1247 | bus->cur_bus_speed = adapter_speed; |
1247 | slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 1248 | slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
1248 | 1249 | ||
1249 | info("Successfully changed frequency/mode for adapter in slot %d\n", | 1250 | info("Successfully changed frequency/mode for adapter in slot %d\n", |
@@ -1269,6 +1270,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ | |||
1269 | */ | 1270 | */ |
1270 | static u32 board_replaced(struct pci_func *func, struct controller *ctrl) | 1271 | static u32 board_replaced(struct pci_func *func, struct controller *ctrl) |
1271 | { | 1272 | { |
1273 | struct pci_bus *bus = ctrl->pci_bus; | ||
1272 | u8 hp_slot; | 1274 | u8 hp_slot; |
1273 | u8 temp_byte; | 1275 | u8 temp_byte; |
1274 | u8 adapter_speed; | 1276 | u8 adapter_speed; |
@@ -1309,7 +1311,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) | |||
1309 | wait_for_ctrl_irq (ctrl); | 1311 | wait_for_ctrl_irq (ctrl); |
1310 | 1312 | ||
1311 | adapter_speed = get_adapter_speed(ctrl, hp_slot); | 1313 | adapter_speed = get_adapter_speed(ctrl, hp_slot); |
1312 | if (ctrl->speed != adapter_speed) | 1314 | if (bus->cur_bus_speed != adapter_speed) |
1313 | if (set_controller_speed(ctrl, adapter_speed, hp_slot)) | 1315 | if (set_controller_speed(ctrl, adapter_speed, hp_slot)) |
1314 | rc = WRONG_BUS_FREQUENCY; | 1316 | rc = WRONG_BUS_FREQUENCY; |
1315 | 1317 | ||
@@ -1426,6 +1428,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
1426 | u32 temp_register = 0xFFFFFFFF; | 1428 | u32 temp_register = 0xFFFFFFFF; |
1427 | u32 rc = 0; | 1429 | u32 rc = 0; |
1428 | struct pci_func *new_slot = NULL; | 1430 | struct pci_func *new_slot = NULL; |
1431 | struct pci_bus *bus = ctrl->pci_bus; | ||
1429 | struct slot *p_slot; | 1432 | struct slot *p_slot; |
1430 | struct resource_lists res_lists; | 1433 | struct resource_lists res_lists; |
1431 | 1434 | ||
@@ -1456,7 +1459,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) | |||
1456 | wait_for_ctrl_irq (ctrl); | 1459 | wait_for_ctrl_irq (ctrl); |
1457 | 1460 | ||
1458 | adapter_speed = get_adapter_speed(ctrl, hp_slot); | 1461 | adapter_speed = get_adapter_speed(ctrl, hp_slot); |
1459 | if (ctrl->speed != adapter_speed) | 1462 | if (bus->cur_bus_speed != adapter_speed) |
1460 | if (set_controller_speed(ctrl, adapter_speed, hp_slot)) | 1463 | if (set_controller_speed(ctrl, adapter_speed, hp_slot)) |
1461 | rc = WRONG_BUS_FREQUENCY; | 1464 | rc = WRONG_BUS_FREQUENCY; |
1462 | 1465 | ||
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index 7485ffda950..d934dd4fa87 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c | |||
@@ -395,89 +395,40 @@ static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value) | |||
395 | return rc; | 395 | return rc; |
396 | } | 396 | } |
397 | 397 | ||
398 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | 398 | static int get_max_bus_speed(struct slot *slot) |
399 | { | 399 | { |
400 | int rc = -ENODEV; | 400 | int rc; |
401 | struct slot *pslot; | ||
402 | u8 mode = 0; | 401 | u8 mode = 0; |
402 | enum pci_bus_speed speed; | ||
403 | struct pci_bus *bus = slot->hotplug_slot->pci_slot->bus; | ||
403 | 404 | ||
404 | debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__, | 405 | debug("%s - Entry slot[%p]\n", __func__, slot); |
405 | hotplug_slot, value); | ||
406 | 406 | ||
407 | ibmphp_lock_operations(); | 407 | ibmphp_lock_operations(); |
408 | 408 | mode = slot->supported_bus_mode; | |
409 | if (hotplug_slot) { | 409 | speed = slot->supported_speed; |
410 | pslot = hotplug_slot->private; | ||
411 | if (pslot) { | ||
412 | rc = 0; | ||
413 | mode = pslot->supported_bus_mode; | ||
414 | *value = pslot->supported_speed; | ||
415 | switch (*value) { | ||
416 | case BUS_SPEED_33: | ||
417 | break; | ||
418 | case BUS_SPEED_66: | ||
419 | if (mode == BUS_MODE_PCIX) | ||
420 | *value += 0x01; | ||
421 | break; | ||
422 | case BUS_SPEED_100: | ||
423 | case BUS_SPEED_133: | ||
424 | *value = pslot->supported_speed + 0x01; | ||
425 | break; | ||
426 | default: | ||
427 | /* Note (will need to change): there would be soon 256, 512 also */ | ||
428 | rc = -ENODEV; | ||
429 | } | ||
430 | } | ||
431 | } | ||
432 | |||
433 | ibmphp_unlock_operations(); | 410 | ibmphp_unlock_operations(); |
434 | debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value); | ||
435 | return rc; | ||
436 | } | ||
437 | 411 | ||
438 | static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | 412 | switch (speed) { |
439 | { | 413 | case BUS_SPEED_33: |
440 | int rc = -ENODEV; | 414 | break; |
441 | struct slot *pslot; | 415 | case BUS_SPEED_66: |
442 | u8 mode = 0; | 416 | if (mode == BUS_MODE_PCIX) |
443 | 417 | speed += 0x01; | |
444 | debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__, | 418 | break; |
445 | hotplug_slot, value); | 419 | case BUS_SPEED_100: |
446 | 420 | case BUS_SPEED_133: | |
447 | ibmphp_lock_operations(); | 421 | speed += 0x01; |
448 | 422 | break; | |
449 | if (hotplug_slot) { | 423 | default: |
450 | pslot = hotplug_slot->private; | 424 | /* Note (will need to change): there would be soon 256, 512 also */ |
451 | if (pslot) { | 425 | rc = -ENODEV; |
452 | rc = get_cur_bus_info(&pslot); | ||
453 | if (!rc) { | ||
454 | mode = pslot->bus_on->current_bus_mode; | ||
455 | *value = pslot->bus_on->current_speed; | ||
456 | switch (*value) { | ||
457 | case BUS_SPEED_33: | ||
458 | break; | ||
459 | case BUS_SPEED_66: | ||
460 | if (mode == BUS_MODE_PCIX) | ||
461 | *value += 0x01; | ||
462 | else if (mode == BUS_MODE_PCI) | ||
463 | ; | ||
464 | else | ||
465 | *value = PCI_SPEED_UNKNOWN; | ||
466 | break; | ||
467 | case BUS_SPEED_100: | ||
468 | case BUS_SPEED_133: | ||
469 | *value += 0x01; | ||
470 | break; | ||
471 | default: | ||
472 | /* Note of change: there would also be 256, 512 soon */ | ||
473 | rc = -ENODEV; | ||
474 | } | ||
475 | } | ||
476 | } | ||
477 | } | 426 | } |
478 | 427 | ||
479 | ibmphp_unlock_operations(); | 428 | if (!rc) |
480 | debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value); | 429 | bus->max_bus_speed = speed; |
430 | |||
431 | debug("%s - Exit rc[%d] speed[%x]\n", __func__, rc, speed); | ||
481 | return rc; | 432 | return rc; |
482 | } | 433 | } |
483 | 434 | ||
@@ -572,6 +523,7 @@ static int __init init_ops(void) | |||
572 | if (slot_cur->bus_on->current_speed == 0xFF) | 523 | if (slot_cur->bus_on->current_speed == 0xFF) |
573 | if (get_cur_bus_info(&slot_cur)) | 524 | if (get_cur_bus_info(&slot_cur)) |
574 | return -1; | 525 | return -1; |
526 | get_max_bus_speed(slot_cur); | ||
575 | 527 | ||
576 | if (slot_cur->ctrl->options == 0xFF) | 528 | if (slot_cur->ctrl->options == 0xFF) |
577 | if (get_hpc_options(slot_cur, &slot_cur->ctrl->options)) | 529 | if (get_hpc_options(slot_cur, &slot_cur->ctrl->options)) |
@@ -655,6 +607,7 @@ static int validate(struct slot *slot_cur, int opn) | |||
655 | int ibmphp_update_slot_info(struct slot *slot_cur) | 607 | int ibmphp_update_slot_info(struct slot *slot_cur) |
656 | { | 608 | { |
657 | struct hotplug_slot_info *info; | 609 | struct hotplug_slot_info *info; |
610 | struct pci_bus *bus = slot_cur->hotplug_slot->pci_slot->bus; | ||
658 | int rc; | 611 | int rc; |
659 | u8 bus_speed; | 612 | u8 bus_speed; |
660 | u8 mode; | 613 | u8 mode; |
@@ -700,8 +653,7 @@ int ibmphp_update_slot_info(struct slot *slot_cur) | |||
700 | bus_speed = PCI_SPEED_UNKNOWN; | 653 | bus_speed = PCI_SPEED_UNKNOWN; |
701 | } | 654 | } |
702 | 655 | ||
703 | info->cur_bus_speed = bus_speed; | 656 | bus->cur_bus_speed = bus_speed; |
704 | info->max_bus_speed = slot_cur->hotplug_slot->info->max_bus_speed; | ||
705 | // To do: bus_names | 657 | // To do: bus_names |
706 | 658 | ||
707 | rc = pci_hp_change_slot_info(slot_cur->hotplug_slot, info); | 659 | rc = pci_hp_change_slot_info(slot_cur->hotplug_slot, info); |
@@ -1326,8 +1278,6 @@ struct hotplug_slot_ops ibmphp_hotplug_slot_ops = { | |||
1326 | .get_attention_status = get_attention_status, | 1278 | .get_attention_status = get_attention_status, |
1327 | .get_latch_status = get_latch_status, | 1279 | .get_latch_status = get_latch_status, |
1328 | .get_adapter_status = get_adapter_present, | 1280 | .get_adapter_status = get_adapter_present, |
1329 | .get_max_bus_speed = get_max_bus_speed, | ||
1330 | .get_cur_bus_speed = get_cur_bus_speed, | ||
1331 | /* .get_max_adapter_speed = get_max_adapter_speed, | 1281 | /* .get_max_adapter_speed = get_max_adapter_speed, |
1332 | .get_bus_name_status = get_bus_name, | 1282 | .get_bus_name_status = get_bus_name, |
1333 | */ | 1283 | */ |
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c index c1abac8ab5c..5becbdee402 100644 --- a/drivers/pci/hotplug/ibmphp_ebda.c +++ b/drivers/pci/hotplug/ibmphp_ebda.c | |||
@@ -245,7 +245,7 @@ static void __init print_ebda_hpc (void) | |||
245 | 245 | ||
246 | int __init ibmphp_access_ebda (void) | 246 | int __init ibmphp_access_ebda (void) |
247 | { | 247 | { |
248 | u8 format, num_ctlrs, rio_complete, hs_complete; | 248 | u8 format, num_ctlrs, rio_complete, hs_complete, ebda_sz; |
249 | u16 ebda_seg, num_entries, next_offset, offset, blk_id, sub_addr, re, rc_id, re_id, base; | 249 | u16 ebda_seg, num_entries, next_offset, offset, blk_id, sub_addr, re, rc_id, re_id, base; |
250 | int rc = 0; | 250 | int rc = 0; |
251 | 251 | ||
@@ -260,7 +260,16 @@ int __init ibmphp_access_ebda (void) | |||
260 | iounmap (io_mem); | 260 | iounmap (io_mem); |
261 | debug ("returned ebda segment: %x\n", ebda_seg); | 261 | debug ("returned ebda segment: %x\n", ebda_seg); |
262 | 262 | ||
263 | io_mem = ioremap(ebda_seg<<4, 1024); | 263 | io_mem = ioremap(ebda_seg<<4, 1); |
264 | if (!io_mem) | ||
265 | return -ENOMEM; | ||
266 | ebda_sz = readb(io_mem); | ||
267 | iounmap(io_mem); | ||
268 | debug("ebda size: %d(KiB)\n", ebda_sz); | ||
269 | if (ebda_sz == 0) | ||
270 | return -ENOMEM; | ||
271 | |||
272 | io_mem = ioremap(ebda_seg<<4, (ebda_sz * 1024)); | ||
264 | if (!io_mem ) | 273 | if (!io_mem ) |
265 | return -ENOMEM; | 274 | return -ENOMEM; |
266 | next_offset = 0x180; | 275 | next_offset = 0x180; |
diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index c7084f0eca5..1aaf3f32d3c 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/sched.h> | 37 | #include <linux/sched.h> |
38 | #include <linux/semaphore.h> | ||
38 | #include <linux/kthread.h> | 39 | #include <linux/kthread.h> |
39 | #include "ibmphp.h" | 40 | #include "ibmphp.h" |
40 | 41 | ||
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 38183a534b6..728b119f71a 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
@@ -64,32 +64,6 @@ static int debug; | |||
64 | static LIST_HEAD(pci_hotplug_slot_list); | 64 | static LIST_HEAD(pci_hotplug_slot_list); |
65 | static DEFINE_MUTEX(pci_hp_mutex); | 65 | static DEFINE_MUTEX(pci_hp_mutex); |
66 | 66 | ||
67 | /* these strings match up with the values in pci_bus_speed */ | ||
68 | static char *pci_bus_speed_strings[] = { | ||
69 | "33 MHz PCI", /* 0x00 */ | ||
70 | "66 MHz PCI", /* 0x01 */ | ||
71 | "66 MHz PCI-X", /* 0x02 */ | ||
72 | "100 MHz PCI-X", /* 0x03 */ | ||
73 | "133 MHz PCI-X", /* 0x04 */ | ||
74 | NULL, /* 0x05 */ | ||
75 | NULL, /* 0x06 */ | ||
76 | NULL, /* 0x07 */ | ||
77 | NULL, /* 0x08 */ | ||
78 | "66 MHz PCI-X 266", /* 0x09 */ | ||
79 | "100 MHz PCI-X 266", /* 0x0a */ | ||
80 | "133 MHz PCI-X 266", /* 0x0b */ | ||
81 | NULL, /* 0x0c */ | ||
82 | NULL, /* 0x0d */ | ||
83 | NULL, /* 0x0e */ | ||
84 | NULL, /* 0x0f */ | ||
85 | NULL, /* 0x10 */ | ||
86 | "66 MHz PCI-X 533", /* 0x11 */ | ||
87 | "100 MHz PCI-X 533", /* 0x12 */ | ||
88 | "133 MHz PCI-X 533", /* 0x13 */ | ||
89 | "2.5 GT/s PCIe", /* 0x14 */ | ||
90 | "5.0 GT/s PCIe", /* 0x15 */ | ||
91 | }; | ||
92 | |||
93 | #ifdef CONFIG_HOTPLUG_PCI_CPCI | 67 | #ifdef CONFIG_HOTPLUG_PCI_CPCI |
94 | extern int cpci_hotplug_init(int debug); | 68 | extern int cpci_hotplug_init(int debug); |
95 | extern void cpci_hotplug_exit(void); | 69 | extern void cpci_hotplug_exit(void); |
@@ -118,8 +92,6 @@ GET_STATUS(power_status, u8) | |||
118 | GET_STATUS(attention_status, u8) | 92 | GET_STATUS(attention_status, u8) |
119 | GET_STATUS(latch_status, u8) | 93 | GET_STATUS(latch_status, u8) |
120 | GET_STATUS(adapter_status, u8) | 94 | GET_STATUS(adapter_status, u8) |
121 | GET_STATUS(max_bus_speed, enum pci_bus_speed) | ||
122 | GET_STATUS(cur_bus_speed, enum pci_bus_speed) | ||
123 | 95 | ||
124 | static ssize_t power_read_file(struct pci_slot *slot, char *buf) | 96 | static ssize_t power_read_file(struct pci_slot *slot, char *buf) |
125 | { | 97 | { |
@@ -263,60 +235,6 @@ static struct pci_slot_attribute hotplug_slot_attr_presence = { | |||
263 | .show = presence_read_file, | 235 | .show = presence_read_file, |
264 | }; | 236 | }; |
265 | 237 | ||
266 | static char *unknown_speed = "Unknown bus speed"; | ||
267 | |||
268 | static ssize_t max_bus_speed_read_file(struct pci_slot *slot, char *buf) | ||
269 | { | ||
270 | char *speed_string; | ||
271 | int retval; | ||
272 | enum pci_bus_speed value; | ||
273 | |||
274 | retval = get_max_bus_speed(slot->hotplug, &value); | ||
275 | if (retval) | ||
276 | goto exit; | ||
277 | |||
278 | if (value == PCI_SPEED_UNKNOWN) | ||
279 | speed_string = unknown_speed; | ||
280 | else | ||
281 | speed_string = pci_bus_speed_strings[value]; | ||
282 | |||
283 | retval = sprintf (buf, "%s\n", speed_string); | ||
284 | |||
285 | exit: | ||
286 | return retval; | ||
287 | } | ||
288 | |||
289 | static struct pci_slot_attribute hotplug_slot_attr_max_bus_speed = { | ||
290 | .attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO}, | ||
291 | .show = max_bus_speed_read_file, | ||
292 | }; | ||
293 | |||
294 | static ssize_t cur_bus_speed_read_file(struct pci_slot *slot, char *buf) | ||
295 | { | ||
296 | char *speed_string; | ||
297 | int retval; | ||
298 | enum pci_bus_speed value; | ||
299 | |||
300 | retval = get_cur_bus_speed(slot->hotplug, &value); | ||
301 | if (retval) | ||
302 | goto exit; | ||
303 | |||
304 | if (value == PCI_SPEED_UNKNOWN) | ||
305 | speed_string = unknown_speed; | ||
306 | else | ||
307 | speed_string = pci_bus_speed_strings[value]; | ||
308 | |||
309 | retval = sprintf (buf, "%s\n", speed_string); | ||
310 | |||
311 | exit: | ||
312 | return retval; | ||
313 | } | ||
314 | |||
315 | static struct pci_slot_attribute hotplug_slot_attr_cur_bus_speed = { | ||
316 | .attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO}, | ||
317 | .show = cur_bus_speed_read_file, | ||
318 | }; | ||
319 | |||
320 | static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf, | 238 | static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf, |
321 | size_t count) | 239 | size_t count) |
322 | { | 240 | { |
@@ -391,26 +309,6 @@ static bool has_adapter_file(struct pci_slot *pci_slot) | |||
391 | return false; | 309 | return false; |
392 | } | 310 | } |
393 | 311 | ||
394 | static bool has_max_bus_speed_file(struct pci_slot *pci_slot) | ||
395 | { | ||
396 | struct hotplug_slot *slot = pci_slot->hotplug; | ||
397 | if ((!slot) || (!slot->ops)) | ||
398 | return false; | ||
399 | if (slot->ops->get_max_bus_speed) | ||
400 | return true; | ||
401 | return false; | ||
402 | } | ||
403 | |||
404 | static bool has_cur_bus_speed_file(struct pci_slot *pci_slot) | ||
405 | { | ||
406 | struct hotplug_slot *slot = pci_slot->hotplug; | ||
407 | if ((!slot) || (!slot->ops)) | ||
408 | return false; | ||
409 | if (slot->ops->get_cur_bus_speed) | ||
410 | return true; | ||
411 | return false; | ||
412 | } | ||
413 | |||
414 | static bool has_test_file(struct pci_slot *pci_slot) | 312 | static bool has_test_file(struct pci_slot *pci_slot) |
415 | { | 313 | { |
416 | struct hotplug_slot *slot = pci_slot->hotplug; | 314 | struct hotplug_slot *slot = pci_slot->hotplug; |
@@ -456,20 +354,6 @@ static int fs_add_slot(struct pci_slot *slot) | |||
456 | goto exit_adapter; | 354 | goto exit_adapter; |
457 | } | 355 | } |
458 | 356 | ||
459 | if (has_max_bus_speed_file(slot)) { | ||
460 | retval = sysfs_create_file(&slot->kobj, | ||
461 | &hotplug_slot_attr_max_bus_speed.attr); | ||
462 | if (retval) | ||
463 | goto exit_max_speed; | ||
464 | } | ||
465 | |||
466 | if (has_cur_bus_speed_file(slot)) { | ||
467 | retval = sysfs_create_file(&slot->kobj, | ||
468 | &hotplug_slot_attr_cur_bus_speed.attr); | ||
469 | if (retval) | ||
470 | goto exit_cur_speed; | ||
471 | } | ||
472 | |||
473 | if (has_test_file(slot)) { | 357 | if (has_test_file(slot)) { |
474 | retval = sysfs_create_file(&slot->kobj, | 358 | retval = sysfs_create_file(&slot->kobj, |
475 | &hotplug_slot_attr_test.attr); | 359 | &hotplug_slot_attr_test.attr); |
@@ -480,14 +364,6 @@ static int fs_add_slot(struct pci_slot *slot) | |||
480 | goto exit; | 364 | goto exit; |
481 | 365 | ||
482 | exit_test: | 366 | exit_test: |
483 | if (has_cur_bus_speed_file(slot)) | ||
484 | sysfs_remove_file(&slot->kobj, | ||
485 | &hotplug_slot_attr_cur_bus_speed.attr); | ||
486 | exit_cur_speed: | ||
487 | if (has_max_bus_speed_file(slot)) | ||
488 | sysfs_remove_file(&slot->kobj, | ||
489 | &hotplug_slot_attr_max_bus_speed.attr); | ||
490 | exit_max_speed: | ||
491 | if (has_adapter_file(slot)) | 367 | if (has_adapter_file(slot)) |
492 | sysfs_remove_file(&slot->kobj, | 368 | sysfs_remove_file(&slot->kobj, |
493 | &hotplug_slot_attr_presence.attr); | 369 | &hotplug_slot_attr_presence.attr); |
@@ -523,14 +399,6 @@ static void fs_remove_slot(struct pci_slot *slot) | |||
523 | sysfs_remove_file(&slot->kobj, | 399 | sysfs_remove_file(&slot->kobj, |
524 | &hotplug_slot_attr_presence.attr); | 400 | &hotplug_slot_attr_presence.attr); |
525 | 401 | ||
526 | if (has_max_bus_speed_file(slot)) | ||
527 | sysfs_remove_file(&slot->kobj, | ||
528 | &hotplug_slot_attr_max_bus_speed.attr); | ||
529 | |||
530 | if (has_cur_bus_speed_file(slot)) | ||
531 | sysfs_remove_file(&slot->kobj, | ||
532 | &hotplug_slot_attr_cur_bus_speed.attr); | ||
533 | |||
534 | if (has_test_file(slot)) | 402 | if (has_test_file(slot)) |
535 | sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr); | 403 | sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr); |
536 | 404 | ||
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 5674b2075bd..920f820edf8 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -69,8 +69,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value); | |||
69 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); | 69 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); |
70 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); | 70 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); |
71 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); | 71 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); |
72 | static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
73 | static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
74 | 72 | ||
75 | /** | 73 | /** |
76 | * release_slot - free up the memory used by a slot | 74 | * release_slot - free up the memory used by a slot |
@@ -113,8 +111,6 @@ static int init_slot(struct controller *ctrl) | |||
113 | ops->disable_slot = disable_slot; | 111 | ops->disable_slot = disable_slot; |
114 | ops->get_power_status = get_power_status; | 112 | ops->get_power_status = get_power_status; |
115 | ops->get_adapter_status = get_adapter_status; | 113 | ops->get_adapter_status = get_adapter_status; |
116 | ops->get_max_bus_speed = get_max_bus_speed; | ||
117 | ops->get_cur_bus_speed = get_cur_bus_speed; | ||
118 | if (MRL_SENS(ctrl)) | 114 | if (MRL_SENS(ctrl)) |
119 | ops->get_latch_status = get_latch_status; | 115 | ops->get_latch_status = get_latch_status; |
120 | if (ATTN_LED(ctrl)) { | 116 | if (ATTN_LED(ctrl)) { |
@@ -227,27 +223,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) | |||
227 | return pciehp_get_adapter_status(slot, value); | 223 | return pciehp_get_adapter_status(slot, value); |
228 | } | 224 | } |
229 | 225 | ||
230 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, | ||
231 | enum pci_bus_speed *value) | ||
232 | { | ||
233 | struct slot *slot = hotplug_slot->private; | ||
234 | |||
235 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | ||
236 | __func__, slot_name(slot)); | ||
237 | |||
238 | return pciehp_get_max_link_speed(slot, value); | ||
239 | } | ||
240 | |||
241 | static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | ||
242 | { | ||
243 | struct slot *slot = hotplug_slot->private; | ||
244 | |||
245 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | ||
246 | __func__, slot_name(slot)); | ||
247 | |||
248 | return pciehp_get_cur_link_speed(slot, value); | ||
249 | } | ||
250 | |||
251 | static int pciehp_probe(struct pcie_device *dev) | 226 | static int pciehp_probe(struct pcie_device *dev) |
252 | { | 227 | { |
253 | int rc; | 228 | int rc; |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index d6ac1b261dd..9a7f247e8ac 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -341,6 +341,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) | |||
341 | p_slot->state = POWERON_STATE; | 341 | p_slot->state = POWERON_STATE; |
342 | break; | 342 | break; |
343 | default: | 343 | default: |
344 | kfree(info); | ||
344 | goto out; | 345 | goto out; |
345 | } | 346 | } |
346 | queue_work(pciehp_wq, &info->work); | 347 | queue_work(pciehp_wq, &info->work); |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 10040d58c8e..40b48f569b1 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -492,6 +492,7 @@ int pciehp_power_on_slot(struct slot * slot) | |||
492 | u16 slot_cmd; | 492 | u16 slot_cmd; |
493 | u16 cmd_mask; | 493 | u16 cmd_mask; |
494 | u16 slot_status; | 494 | u16 slot_status; |
495 | u16 lnk_status; | ||
495 | int retval = 0; | 496 | int retval = 0; |
496 | 497 | ||
497 | /* Clear sticky power-fault bit from previous power failures */ | 498 | /* Clear sticky power-fault bit from previous power failures */ |
@@ -523,6 +524,14 @@ int pciehp_power_on_slot(struct slot * slot) | |||
523 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, | 524 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
524 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); | 525 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); |
525 | 526 | ||
527 | retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); | ||
528 | if (retval) { | ||
529 | ctrl_err(ctrl, "%s: Cannot read LNKSTA register\n", | ||
530 | __func__); | ||
531 | return retval; | ||
532 | } | ||
533 | pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status); | ||
534 | |||
526 | return retval; | 535 | return retval; |
527 | } | 536 | } |
528 | 537 | ||
@@ -610,37 +619,6 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
610 | return IRQ_HANDLED; | 619 | return IRQ_HANDLED; |
611 | } | 620 | } |
612 | 621 | ||
613 | int pciehp_get_max_link_speed(struct slot *slot, enum pci_bus_speed *value) | ||
614 | { | ||
615 | struct controller *ctrl = slot->ctrl; | ||
616 | enum pcie_link_speed lnk_speed; | ||
617 | u32 lnk_cap; | ||
618 | int retval = 0; | ||
619 | |||
620 | retval = pciehp_readl(ctrl, PCI_EXP_LNKCAP, &lnk_cap); | ||
621 | if (retval) { | ||
622 | ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); | ||
623 | return retval; | ||
624 | } | ||
625 | |||
626 | switch (lnk_cap & 0x000F) { | ||
627 | case 1: | ||
628 | lnk_speed = PCIE_2_5GB; | ||
629 | break; | ||
630 | case 2: | ||
631 | lnk_speed = PCIE_5_0GB; | ||
632 | break; | ||
633 | default: | ||
634 | lnk_speed = PCIE_LNK_SPEED_UNKNOWN; | ||
635 | break; | ||
636 | } | ||
637 | |||
638 | *value = lnk_speed; | ||
639 | ctrl_dbg(ctrl, "Max link speed = %d\n", lnk_speed); | ||
640 | |||
641 | return retval; | ||
642 | } | ||
643 | |||
644 | int pciehp_get_max_lnk_width(struct slot *slot, | 622 | int pciehp_get_max_lnk_width(struct slot *slot, |
645 | enum pcie_link_width *value) | 623 | enum pcie_link_width *value) |
646 | { | 624 | { |
@@ -691,38 +669,6 @@ int pciehp_get_max_lnk_width(struct slot *slot, | |||
691 | return retval; | 669 | return retval; |
692 | } | 670 | } |
693 | 671 | ||
694 | int pciehp_get_cur_link_speed(struct slot *slot, enum pci_bus_speed *value) | ||
695 | { | ||
696 | struct controller *ctrl = slot->ctrl; | ||
697 | enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN; | ||
698 | int retval = 0; | ||
699 | u16 lnk_status; | ||
700 | |||
701 | retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); | ||
702 | if (retval) { | ||
703 | ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n", | ||
704 | __func__); | ||
705 | return retval; | ||
706 | } | ||
707 | |||
708 | switch (lnk_status & PCI_EXP_LNKSTA_CLS) { | ||
709 | case 1: | ||
710 | lnk_speed = PCIE_2_5GB; | ||
711 | break; | ||
712 | case 2: | ||
713 | lnk_speed = PCIE_5_0GB; | ||
714 | break; | ||
715 | default: | ||
716 | lnk_speed = PCIE_LNK_SPEED_UNKNOWN; | ||
717 | break; | ||
718 | } | ||
719 | |||
720 | *value = lnk_speed; | ||
721 | ctrl_dbg(ctrl, "Current link speed = %d\n", lnk_speed); | ||
722 | |||
723 | return retval; | ||
724 | } | ||
725 | |||
726 | int pciehp_get_cur_lnk_width(struct slot *slot, | 672 | int pciehp_get_cur_lnk_width(struct slot *slot, |
727 | enum pcie_link_width *value) | 673 | enum pcie_link_width *value) |
728 | { | 674 | { |
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 21733108add..0a16444c14c 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
@@ -53,17 +53,15 @@ static int __ref pciehp_add_bridge(struct pci_dev *dev) | |||
53 | busnr = pci_scan_bridge(parent, dev, busnr, pass); | 53 | busnr = pci_scan_bridge(parent, dev, busnr, pass); |
54 | if (!dev->subordinate) | 54 | if (!dev->subordinate) |
55 | return -1; | 55 | return -1; |
56 | pci_bus_size_bridges(dev->subordinate); | 56 | |
57 | pci_bus_assign_resources(parent); | ||
58 | pci_enable_bridges(parent); | ||
59 | pci_bus_add_devices(parent); | ||
60 | return 0; | 57 | return 0; |
61 | } | 58 | } |
62 | 59 | ||
63 | int pciehp_configure_device(struct slot *p_slot) | 60 | int pciehp_configure_device(struct slot *p_slot) |
64 | { | 61 | { |
65 | struct pci_dev *dev; | 62 | struct pci_dev *dev; |
66 | struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate; | 63 | struct pci_dev *bridge = p_slot->ctrl->pcie->port; |
64 | struct pci_bus *parent = bridge->subordinate; | ||
67 | int num, fn; | 65 | int num, fn; |
68 | struct controller *ctrl = p_slot->ctrl; | 66 | struct controller *ctrl = p_slot->ctrl; |
69 | 67 | ||
@@ -96,12 +94,25 @@ int pciehp_configure_device(struct slot *p_slot) | |||
96 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { | 94 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { |
97 | pciehp_add_bridge(dev); | 95 | pciehp_add_bridge(dev); |
98 | } | 96 | } |
97 | pci_dev_put(dev); | ||
98 | } | ||
99 | |||
100 | pci_assign_unassigned_bridge_resources(bridge); | ||
101 | |||
102 | for (fn = 0; fn < 8; fn++) { | ||
103 | dev = pci_get_slot(parent, PCI_DEVFN(0, fn)); | ||
104 | if (!dev) | ||
105 | continue; | ||
106 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
107 | pci_dev_put(dev); | ||
108 | continue; | ||
109 | } | ||
99 | pci_configure_slot(dev); | 110 | pci_configure_slot(dev); |
100 | pci_dev_put(dev); | 111 | pci_dev_put(dev); |
101 | } | 112 | } |
102 | 113 | ||
103 | pci_bus_assign_resources(parent); | ||
104 | pci_bus_add_devices(parent); | 114 | pci_bus_add_devices(parent); |
115 | |||
105 | return 0; | 116 | return 0; |
106 | } | 117 | } |
107 | 118 | ||
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index c159223389e..dcaae725fd7 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c | |||
@@ -130,10 +130,9 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) | |||
130 | return 0; | 130 | return 0; |
131 | } | 131 | } |
132 | 132 | ||
133 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | 133 | static enum pci_bus_speed get_max_bus_speed(struct slot *slot) |
134 | { | 134 | { |
135 | struct slot *slot = (struct slot *)hotplug_slot->private; | 135 | enum pci_bus_speed speed; |
136 | |||
137 | switch (slot->type) { | 136 | switch (slot->type) { |
138 | case 1: | 137 | case 1: |
139 | case 2: | 138 | case 2: |
@@ -141,30 +140,30 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe | |||
141 | case 4: | 140 | case 4: |
142 | case 5: | 141 | case 5: |
143 | case 6: | 142 | case 6: |
144 | *value = PCI_SPEED_33MHz; /* speed for case 1-6 */ | 143 | speed = PCI_SPEED_33MHz; /* speed for case 1-6 */ |
145 | break; | 144 | break; |
146 | case 7: | 145 | case 7: |
147 | case 8: | 146 | case 8: |
148 | *value = PCI_SPEED_66MHz; | 147 | speed = PCI_SPEED_66MHz; |
149 | break; | 148 | break; |
150 | case 11: | 149 | case 11: |
151 | case 14: | 150 | case 14: |
152 | *value = PCI_SPEED_66MHz_PCIX; | 151 | speed = PCI_SPEED_66MHz_PCIX; |
153 | break; | 152 | break; |
154 | case 12: | 153 | case 12: |
155 | case 15: | 154 | case 15: |
156 | *value = PCI_SPEED_100MHz_PCIX; | 155 | speed = PCI_SPEED_100MHz_PCIX; |
157 | break; | 156 | break; |
158 | case 13: | 157 | case 13: |
159 | case 16: | 158 | case 16: |
160 | *value = PCI_SPEED_133MHz_PCIX; | 159 | speed = PCI_SPEED_133MHz_PCIX; |
161 | break; | 160 | break; |
162 | default: | 161 | default: |
163 | *value = PCI_SPEED_UNKNOWN; | 162 | speed = PCI_SPEED_UNKNOWN; |
164 | break; | 163 | break; |
165 | |||
166 | } | 164 | } |
167 | return 0; | 165 | |
166 | return speed; | ||
168 | } | 167 | } |
169 | 168 | ||
170 | static int get_children_props(struct device_node *dn, const int **drc_indexes, | 169 | static int get_children_props(struct device_node *dn, const int **drc_indexes, |
@@ -408,6 +407,8 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) | |||
408 | slot->state = NOT_VALID; | 407 | slot->state = NOT_VALID; |
409 | return -EINVAL; | 408 | return -EINVAL; |
410 | } | 409 | } |
410 | |||
411 | slot->bus->max_bus_speed = get_max_bus_speed(slot); | ||
411 | return 0; | 412 | return 0; |
412 | } | 413 | } |
413 | 414 | ||
@@ -429,7 +430,6 @@ struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { | |||
429 | .get_power_status = get_power_status, | 430 | .get_power_status = get_power_status, |
430 | .get_attention_status = get_attention_status, | 431 | .get_attention_status = get_attention_status, |
431 | .get_adapter_status = get_adapter_status, | 432 | .get_adapter_status = get_adapter_status, |
432 | .get_max_bus_speed = get_max_bus_speed, | ||
433 | }; | 433 | }; |
434 | 434 | ||
435 | module_init(rpaphp_init); | 435 | module_init(rpaphp_init); |
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 8e210cd76e5..d2627e1c3ac 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
@@ -333,8 +333,6 @@ struct hpc_ops { | |||
333 | int (*set_attention_status)(struct slot *slot, u8 status); | 333 | int (*set_attention_status)(struct slot *slot, u8 status); |
334 | int (*get_latch_status)(struct slot *slot, u8 *status); | 334 | int (*get_latch_status)(struct slot *slot, u8 *status); |
335 | int (*get_adapter_status)(struct slot *slot, u8 *status); | 335 | int (*get_adapter_status)(struct slot *slot, u8 *status); |
336 | int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); | ||
337 | int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); | ||
338 | int (*get_adapter_speed)(struct slot *slot, enum pci_bus_speed *speed); | 336 | int (*get_adapter_speed)(struct slot *slot, enum pci_bus_speed *speed); |
339 | int (*get_mode1_ECC_cap)(struct slot *slot, u8 *mode); | 337 | int (*get_mode1_ECC_cap)(struct slot *slot, u8 *mode); |
340 | int (*get_prog_int)(struct slot *slot, u8 *prog_int); | 338 | int (*get_prog_int)(struct slot *slot, u8 *prog_int); |
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 8a520a3d0f5..a5062297f48 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c | |||
@@ -65,8 +65,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value); | |||
65 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); | 65 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); |
66 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); | 66 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); |
67 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); | 67 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); |
68 | static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
69 | static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
70 | 68 | ||
71 | static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { | 69 | static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { |
72 | .set_attention_status = set_attention_status, | 70 | .set_attention_status = set_attention_status, |
@@ -76,8 +74,6 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { | |||
76 | .get_attention_status = get_attention_status, | 74 | .get_attention_status = get_attention_status, |
77 | .get_latch_status = get_latch_status, | 75 | .get_latch_status = get_latch_status, |
78 | .get_adapter_status = get_adapter_status, | 76 | .get_adapter_status = get_adapter_status, |
79 | .get_max_bus_speed = get_max_bus_speed, | ||
80 | .get_cur_bus_speed = get_cur_bus_speed, | ||
81 | }; | 77 | }; |
82 | 78 | ||
83 | /** | 79 | /** |
@@ -279,37 +275,6 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) | |||
279 | return 0; | 275 | return 0; |
280 | } | 276 | } |
281 | 277 | ||
282 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, | ||
283 | enum pci_bus_speed *value) | ||
284 | { | ||
285 | struct slot *slot = get_slot(hotplug_slot); | ||
286 | int retval; | ||
287 | |||
288 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | ||
289 | __func__, slot_name(slot)); | ||
290 | |||
291 | retval = slot->hpc_ops->get_max_bus_speed(slot, value); | ||
292 | if (retval < 0) | ||
293 | *value = PCI_SPEED_UNKNOWN; | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | ||
299 | { | ||
300 | struct slot *slot = get_slot(hotplug_slot); | ||
301 | int retval; | ||
302 | |||
303 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | ||
304 | __func__, slot_name(slot)); | ||
305 | |||
306 | retval = slot->hpc_ops->get_cur_bus_speed(slot, value); | ||
307 | if (retval < 0) | ||
308 | *value = PCI_SPEED_UNKNOWN; | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static int is_shpc_capable(struct pci_dev *dev) | 278 | static int is_shpc_capable(struct pci_dev *dev) |
314 | { | 279 | { |
315 | if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == | 280 | if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == |
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index b8ab2796e66..3bba0c0888f 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -285,17 +285,8 @@ static int board_added(struct slot *p_slot) | |||
285 | return WRONG_BUS_FREQUENCY; | 285 | return WRONG_BUS_FREQUENCY; |
286 | } | 286 | } |
287 | 287 | ||
288 | rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp); | 288 | bsp = ctrl->pci_dev->bus->cur_bus_speed; |
289 | if (rc) { | 289 | msp = ctrl->pci_dev->bus->max_bus_speed; |
290 | ctrl_err(ctrl, "Can't get bus operation speed\n"); | ||
291 | return WRONG_BUS_FREQUENCY; | ||
292 | } | ||
293 | |||
294 | rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp); | ||
295 | if (rc) { | ||
296 | ctrl_err(ctrl, "Can't get max bus operation speed\n"); | ||
297 | msp = bsp; | ||
298 | } | ||
299 | 290 | ||
300 | /* Check if there are other slots or devices on the same bus */ | 291 | /* Check if there are other slots or devices on the same bus */ |
301 | if (!list_empty(&ctrl->pci_dev->subordinate->devices)) | 292 | if (!list_empty(&ctrl->pci_dev->subordinate->devices)) |
@@ -462,6 +453,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work) | |||
462 | p_slot->state = POWERON_STATE; | 453 | p_slot->state = POWERON_STATE; |
463 | break; | 454 | break; |
464 | default: | 455 | default: |
456 | kfree(info); | ||
465 | goto out; | 457 | goto out; |
466 | } | 458 | } |
467 | queue_work(shpchp_wq, &info->work); | 459 | queue_work(shpchp_wq, &info->work); |
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 86dc3984776..5f5e8d2e355 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -660,6 +660,75 @@ static int hpc_slot_disable(struct slot * slot) | |||
660 | return retval; | 660 | return retval; |
661 | } | 661 | } |
662 | 662 | ||
663 | static int shpc_get_cur_bus_speed(struct controller *ctrl) | ||
664 | { | ||
665 | int retval = 0; | ||
666 | struct pci_bus *bus = ctrl->pci_dev->subordinate; | ||
667 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; | ||
668 | u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG); | ||
669 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); | ||
670 | u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); | ||
671 | |||
672 | if ((pi == 1) && (speed_mode > 4)) { | ||
673 | retval = -ENODEV; | ||
674 | goto out; | ||
675 | } | ||
676 | |||
677 | switch (speed_mode) { | ||
678 | case 0x0: | ||
679 | bus_speed = PCI_SPEED_33MHz; | ||
680 | break; | ||
681 | case 0x1: | ||
682 | bus_speed = PCI_SPEED_66MHz; | ||
683 | break; | ||
684 | case 0x2: | ||
685 | bus_speed = PCI_SPEED_66MHz_PCIX; | ||
686 | break; | ||
687 | case 0x3: | ||
688 | bus_speed = PCI_SPEED_100MHz_PCIX; | ||
689 | break; | ||
690 | case 0x4: | ||
691 | bus_speed = PCI_SPEED_133MHz_PCIX; | ||
692 | break; | ||
693 | case 0x5: | ||
694 | bus_speed = PCI_SPEED_66MHz_PCIX_ECC; | ||
695 | break; | ||
696 | case 0x6: | ||
697 | bus_speed = PCI_SPEED_100MHz_PCIX_ECC; | ||
698 | break; | ||
699 | case 0x7: | ||
700 | bus_speed = PCI_SPEED_133MHz_PCIX_ECC; | ||
701 | break; | ||
702 | case 0x8: | ||
703 | bus_speed = PCI_SPEED_66MHz_PCIX_266; | ||
704 | break; | ||
705 | case 0x9: | ||
706 | bus_speed = PCI_SPEED_100MHz_PCIX_266; | ||
707 | break; | ||
708 | case 0xa: | ||
709 | bus_speed = PCI_SPEED_133MHz_PCIX_266; | ||
710 | break; | ||
711 | case 0xb: | ||
712 | bus_speed = PCI_SPEED_66MHz_PCIX_533; | ||
713 | break; | ||
714 | case 0xc: | ||
715 | bus_speed = PCI_SPEED_100MHz_PCIX_533; | ||
716 | break; | ||
717 | case 0xd: | ||
718 | bus_speed = PCI_SPEED_133MHz_PCIX_533; | ||
719 | break; | ||
720 | default: | ||
721 | retval = -ENODEV; | ||
722 | break; | ||
723 | } | ||
724 | |||
725 | out: | ||
726 | bus->cur_bus_speed = bus_speed; | ||
727 | dbg("Current bus speed = %d\n", bus_speed); | ||
728 | return retval; | ||
729 | } | ||
730 | |||
731 | |||
663 | static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) | 732 | static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) |
664 | { | 733 | { |
665 | int retval; | 734 | int retval; |
@@ -720,6 +789,8 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) | |||
720 | retval = shpc_write_cmd(slot, 0, cmd); | 789 | retval = shpc_write_cmd(slot, 0, cmd); |
721 | if (retval) | 790 | if (retval) |
722 | ctrl_err(ctrl, "%s: Write command failed!\n", __func__); | 791 | ctrl_err(ctrl, "%s: Write command failed!\n", __func__); |
792 | else | ||
793 | shpc_get_cur_bus_speed(ctrl); | ||
723 | 794 | ||
724 | return retval; | 795 | return retval; |
725 | } | 796 | } |
@@ -803,10 +874,10 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) | |||
803 | return IRQ_HANDLED; | 874 | return IRQ_HANDLED; |
804 | } | 875 | } |
805 | 876 | ||
806 | static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | 877 | static int shpc_get_max_bus_speed(struct controller *ctrl) |
807 | { | 878 | { |
808 | int retval = 0; | 879 | int retval = 0; |
809 | struct controller *ctrl = slot->ctrl; | 880 | struct pci_bus *bus = ctrl->pci_dev->subordinate; |
810 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; | 881 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; |
811 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); | 882 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); |
812 | u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); | 883 | u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); |
@@ -842,79 +913,12 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | |||
842 | retval = -ENODEV; | 913 | retval = -ENODEV; |
843 | } | 914 | } |
844 | 915 | ||
845 | *value = bus_speed; | 916 | bus->max_bus_speed = bus_speed; |
846 | ctrl_dbg(ctrl, "Max bus speed = %d\n", bus_speed); | 917 | ctrl_dbg(ctrl, "Max bus speed = %d\n", bus_speed); |
847 | 918 | ||
848 | return retval; | 919 | return retval; |
849 | } | 920 | } |
850 | 921 | ||
851 | static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) | ||
852 | { | ||
853 | int retval = 0; | ||
854 | struct controller *ctrl = slot->ctrl; | ||
855 | enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; | ||
856 | u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG); | ||
857 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); | ||
858 | u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); | ||
859 | |||
860 | if ((pi == 1) && (speed_mode > 4)) { | ||
861 | *value = PCI_SPEED_UNKNOWN; | ||
862 | return -ENODEV; | ||
863 | } | ||
864 | |||
865 | switch (speed_mode) { | ||
866 | case 0x0: | ||
867 | *value = PCI_SPEED_33MHz; | ||
868 | break; | ||
869 | case 0x1: | ||
870 | *value = PCI_SPEED_66MHz; | ||
871 | break; | ||
872 | case 0x2: | ||
873 | *value = PCI_SPEED_66MHz_PCIX; | ||
874 | break; | ||
875 | case 0x3: | ||
876 | *value = PCI_SPEED_100MHz_PCIX; | ||
877 | break; | ||
878 | case 0x4: | ||
879 | *value = PCI_SPEED_133MHz_PCIX; | ||
880 | break; | ||
881 | case 0x5: | ||
882 | *value = PCI_SPEED_66MHz_PCIX_ECC; | ||
883 | break; | ||
884 | case 0x6: | ||
885 | *value = PCI_SPEED_100MHz_PCIX_ECC; | ||
886 | break; | ||
887 | case 0x7: | ||
888 | *value = PCI_SPEED_133MHz_PCIX_ECC; | ||
889 | break; | ||
890 | case 0x8: | ||
891 | *value = PCI_SPEED_66MHz_PCIX_266; | ||
892 | break; | ||
893 | case 0x9: | ||
894 | *value = PCI_SPEED_100MHz_PCIX_266; | ||
895 | break; | ||
896 | case 0xa: | ||
897 | *value = PCI_SPEED_133MHz_PCIX_266; | ||
898 | break; | ||
899 | case 0xb: | ||
900 | *value = PCI_SPEED_66MHz_PCIX_533; | ||
901 | break; | ||
902 | case 0xc: | ||
903 | *value = PCI_SPEED_100MHz_PCIX_533; | ||
904 | break; | ||
905 | case 0xd: | ||
906 | *value = PCI_SPEED_133MHz_PCIX_533; | ||
907 | break; | ||
908 | default: | ||
909 | *value = PCI_SPEED_UNKNOWN; | ||
910 | retval = -ENODEV; | ||
911 | break; | ||
912 | } | ||
913 | |||
914 | ctrl_dbg(ctrl, "Current bus speed = %d\n", bus_speed); | ||
915 | return retval; | ||
916 | } | ||
917 | |||
918 | static struct hpc_ops shpchp_hpc_ops = { | 922 | static struct hpc_ops shpchp_hpc_ops = { |
919 | .power_on_slot = hpc_power_on_slot, | 923 | .power_on_slot = hpc_power_on_slot, |
920 | .slot_enable = hpc_slot_enable, | 924 | .slot_enable = hpc_slot_enable, |
@@ -926,8 +930,6 @@ static struct hpc_ops shpchp_hpc_ops = { | |||
926 | .get_latch_status = hpc_get_latch_status, | 930 | .get_latch_status = hpc_get_latch_status, |
927 | .get_adapter_status = hpc_get_adapter_status, | 931 | .get_adapter_status = hpc_get_adapter_status, |
928 | 932 | ||
929 | .get_max_bus_speed = hpc_get_max_bus_speed, | ||
930 | .get_cur_bus_speed = hpc_get_cur_bus_speed, | ||
931 | .get_adapter_speed = hpc_get_adapter_speed, | 933 | .get_adapter_speed = hpc_get_adapter_speed, |
932 | .get_mode1_ECC_cap = hpc_get_mode1_ECC_cap, | 934 | .get_mode1_ECC_cap = hpc_get_mode1_ECC_cap, |
933 | .get_prog_int = hpc_get_prog_int, | 935 | .get_prog_int = hpc_get_prog_int, |
@@ -1086,6 +1088,9 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) | |||
1086 | } | 1088 | } |
1087 | ctrl_dbg(ctrl, "HPC at %s irq=%x\n", pci_name(pdev), pdev->irq); | 1089 | ctrl_dbg(ctrl, "HPC at %s irq=%x\n", pci_name(pdev), pdev->irq); |
1088 | 1090 | ||
1091 | shpc_get_max_bus_speed(ctrl); | ||
1092 | shpc_get_cur_bus_speed(ctrl); | ||
1093 | |||
1089 | /* | 1094 | /* |
1090 | * If this is the first controller to be initialized, | 1095 | * If this is the first controller to be initialized, |
1091 | * initialize the shpchpd work queue | 1096 | * initialize the shpchpd work queue |
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index 29fa9d26ada..071b7dc0094 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c | |||
@@ -47,8 +47,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha | |||
47 | bus = pdev->subordinate; | 47 | bus = pdev->subordinate; |
48 | 48 | ||
49 | out += sprintf(buf, "Free resources: memory\n"); | 49 | out += sprintf(buf, "Free resources: memory\n"); |
50 | for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) { | 50 | pci_bus_for_each_resource(bus, res, index) { |
51 | res = bus->resource[index]; | ||
52 | if (res && (res->flags & IORESOURCE_MEM) && | 51 | if (res && (res->flags & IORESOURCE_MEM) && |
53 | !(res->flags & IORESOURCE_PREFETCH)) { | 52 | !(res->flags & IORESOURCE_PREFETCH)) { |
54 | out += sprintf(out, "start = %8.8llx, " | 53 | out += sprintf(out, "start = %8.8llx, " |
@@ -58,8 +57,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha | |||
58 | } | 57 | } |
59 | } | 58 | } |
60 | out += sprintf(out, "Free resources: prefetchable memory\n"); | 59 | out += sprintf(out, "Free resources: prefetchable memory\n"); |
61 | for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) { | 60 | pci_bus_for_each_resource(bus, res, index) { |
62 | res = bus->resource[index]; | ||
63 | if (res && (res->flags & IORESOURCE_MEM) && | 61 | if (res && (res->flags & IORESOURCE_MEM) && |
64 | (res->flags & IORESOURCE_PREFETCH)) { | 62 | (res->flags & IORESOURCE_PREFETCH)) { |
65 | out += sprintf(out, "start = %8.8llx, " | 63 | out += sprintf(out, "start = %8.8llx, " |
@@ -69,8 +67,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha | |||
69 | } | 67 | } |
70 | } | 68 | } |
71 | out += sprintf(out, "Free resources: IO\n"); | 69 | out += sprintf(out, "Free resources: IO\n"); |
72 | for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) { | 70 | pci_bus_for_each_resource(bus, res, index) { |
73 | res = bus->resource[index]; | ||
74 | if (res && (res->flags & IORESOURCE_IO)) { | 71 | if (res && (res->flags & IORESOURCE_IO)) { |
75 | out += sprintf(out, "start = %8.8llx, " | 72 | out += sprintf(out, "start = %8.8llx, " |
76 | "length = %8.8llx\n", | 73 | "length = %8.8llx\n", |
diff --git a/drivers/pci/legacy.c b/drivers/pci/legacy.c deleted file mode 100644 index 871f65c1593..00000000000 --- a/drivers/pci/legacy.c +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/pci.h> | ||
3 | #include <linux/module.h> | ||
4 | #include <linux/interrupt.h> | ||
5 | #include "pci.h" | ||
6 | |||
7 | /** | ||
8 | * pci_find_device - begin or continue searching for a PCI device by vendor/device id | ||
9 | * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids | ||
10 | * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids | ||
11 | * @from: Previous PCI device found in search, or %NULL for new search. | ||
12 | * | ||
13 | * Iterates through the list of known PCI devices. If a PCI device is found | ||
14 | * with a matching @vendor and @device, a pointer to its device structure is | ||
15 | * returned. Otherwise, %NULL is returned. | ||
16 | * A new search is initiated by passing %NULL as the @from argument. | ||
17 | * Otherwise if @from is not %NULL, searches continue from next device | ||
18 | * on the global list. | ||
19 | * | ||
20 | * NOTE: Do not use this function any more; use pci_get_device() instead, as | ||
21 | * the PCI device returned by this function can disappear at any moment in | ||
22 | * time. | ||
23 | */ | ||
24 | struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, | ||
25 | struct pci_dev *from) | ||
26 | { | ||
27 | struct pci_dev *pdev; | ||
28 | |||
29 | pci_dev_get(from); | ||
30 | pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); | ||
31 | pci_dev_put(pdev); | ||
32 | return pdev; | ||
33 | } | ||
34 | EXPORT_SYMBOL(pci_find_device); | ||
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 7e2829538a4..c0c73913833 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -16,8 +16,144 @@ | |||
16 | #include <acpi/acpi_bus.h> | 16 | #include <acpi/acpi_bus.h> |
17 | 17 | ||
18 | #include <linux/pci-acpi.h> | 18 | #include <linux/pci-acpi.h> |
19 | #include <linux/pm_runtime.h> | ||
19 | #include "pci.h" | 20 | #include "pci.h" |
20 | 21 | ||
22 | static DEFINE_MUTEX(pci_acpi_pm_notify_mtx); | ||
23 | |||
24 | /** | ||
25 | * pci_acpi_wake_bus - Wake-up notification handler for root buses. | ||
26 | * @handle: ACPI handle of a device the notification is for. | ||
27 | * @event: Type of the signaled event. | ||
28 | * @context: PCI root bus to wake up devices on. | ||
29 | */ | ||
30 | static void pci_acpi_wake_bus(acpi_handle handle, u32 event, void *context) | ||
31 | { | ||
32 | struct pci_bus *pci_bus = context; | ||
33 | |||
34 | if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_bus) | ||
35 | pci_pme_wakeup_bus(pci_bus); | ||
36 | } | ||
37 | |||
38 | /** | ||
39 | * pci_acpi_wake_dev - Wake-up notification handler for PCI devices. | ||
40 | * @handle: ACPI handle of a device the notification is for. | ||
41 | * @event: Type of the signaled event. | ||
42 | * @context: PCI device object to wake up. | ||
43 | */ | ||
44 | static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) | ||
45 | { | ||
46 | struct pci_dev *pci_dev = context; | ||
47 | |||
48 | if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_dev) { | ||
49 | pci_check_pme_status(pci_dev); | ||
50 | pm_runtime_resume(&pci_dev->dev); | ||
51 | if (pci_dev->subordinate) | ||
52 | pci_pme_wakeup_bus(pci_dev->subordinate); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * add_pm_notifier - Register PM notifier for given ACPI device. | ||
58 | * @dev: ACPI device to add the notifier for. | ||
59 | * @context: PCI device or bus to check for PME status if an event is signaled. | ||
60 | * | ||
61 | * NOTE: @dev need not be a run-wake or wake-up device to be a valid source of | ||
62 | * PM wake-up events. For example, wake-up events may be generated for bridges | ||
63 | * if one of the devices below the bridge is signaling PME, even if the bridge | ||
64 | * itself doesn't have a wake-up GPE associated with it. | ||
65 | */ | ||
66 | static acpi_status add_pm_notifier(struct acpi_device *dev, | ||
67 | acpi_notify_handler handler, | ||
68 | void *context) | ||
69 | { | ||
70 | acpi_status status = AE_ALREADY_EXISTS; | ||
71 | |||
72 | mutex_lock(&pci_acpi_pm_notify_mtx); | ||
73 | |||
74 | if (dev->wakeup.flags.notifier_present) | ||
75 | goto out; | ||
76 | |||
77 | status = acpi_install_notify_handler(dev->handle, | ||
78 | ACPI_SYSTEM_NOTIFY, | ||
79 | handler, context); | ||
80 | if (ACPI_FAILURE(status)) | ||
81 | goto out; | ||
82 | |||
83 | dev->wakeup.flags.notifier_present = true; | ||
84 | |||
85 | out: | ||
86 | mutex_unlock(&pci_acpi_pm_notify_mtx); | ||
87 | return status; | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * remove_pm_notifier - Unregister PM notifier from given ACPI device. | ||
92 | * @dev: ACPI device to remove the notifier from. | ||
93 | */ | ||
94 | static acpi_status remove_pm_notifier(struct acpi_device *dev, | ||
95 | acpi_notify_handler handler) | ||
96 | { | ||
97 | acpi_status status = AE_BAD_PARAMETER; | ||
98 | |||
99 | mutex_lock(&pci_acpi_pm_notify_mtx); | ||
100 | |||
101 | if (!dev->wakeup.flags.notifier_present) | ||
102 | goto out; | ||
103 | |||
104 | status = acpi_remove_notify_handler(dev->handle, | ||
105 | ACPI_SYSTEM_NOTIFY, | ||
106 | handler); | ||
107 | if (ACPI_FAILURE(status)) | ||
108 | goto out; | ||
109 | |||
110 | dev->wakeup.flags.notifier_present = false; | ||
111 | |||
112 | out: | ||
113 | mutex_unlock(&pci_acpi_pm_notify_mtx); | ||
114 | return status; | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus. | ||
119 | * @dev: ACPI device to add the notifier for. | ||
120 | * @pci_bus: PCI bus to walk checking for PME status if an event is signaled. | ||
121 | */ | ||
122 | acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, | ||
123 | struct pci_bus *pci_bus) | ||
124 | { | ||
125 | return add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus); | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * pci_acpi_remove_bus_pm_notifier - Unregister PCI bus PM notifier. | ||
130 | * @dev: ACPI device to remove the notifier from. | ||
131 | */ | ||
132 | acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) | ||
133 | { | ||
134 | return remove_pm_notifier(dev, pci_acpi_wake_bus); | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * pci_acpi_add_pm_notifier - Register PM notifier for given PCI device. | ||
139 | * @dev: ACPI device to add the notifier for. | ||
140 | * @pci_dev: PCI device to check for the PME status if an event is signaled. | ||
141 | */ | ||
142 | acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, | ||
143 | struct pci_dev *pci_dev) | ||
144 | { | ||
145 | return add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev); | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * pci_acpi_remove_pm_notifier - Unregister PCI device PM notifier. | ||
150 | * @dev: ACPI device to remove the notifier from. | ||
151 | */ | ||
152 | acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) | ||
153 | { | ||
154 | return remove_pm_notifier(dev, pci_acpi_wake_dev); | ||
155 | } | ||
156 | |||
21 | /* | 157 | /* |
22 | * _SxD returns the D-state with the highest power | 158 | * _SxD returns the D-state with the highest power |
23 | * (lowest D-state number) supported in the S-state "x". | 159 | * (lowest D-state number) supported in the S-state "x". |
@@ -131,12 +267,87 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable) | |||
131 | return 0; | 267 | return 0; |
132 | } | 268 | } |
133 | 269 | ||
270 | /** | ||
271 | * acpi_dev_run_wake - Enable/disable wake-up for given device. | ||
272 | * @phys_dev: Device to enable/disable the platform to wake-up the system for. | ||
273 | * @enable: Whether enable or disable the wake-up functionality. | ||
274 | * | ||
275 | * Find the ACPI device object corresponding to @pci_dev and try to | ||
276 | * enable/disable the GPE associated with it. | ||
277 | */ | ||
278 | static int acpi_dev_run_wake(struct device *phys_dev, bool enable) | ||
279 | { | ||
280 | struct acpi_device *dev; | ||
281 | acpi_handle handle; | ||
282 | int error = -ENODEV; | ||
283 | |||
284 | if (!device_run_wake(phys_dev)) | ||
285 | return -EINVAL; | ||
286 | |||
287 | handle = DEVICE_ACPI_HANDLE(phys_dev); | ||
288 | if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) { | ||
289 | dev_dbg(phys_dev, "ACPI handle has no context in %s!\n", | ||
290 | __func__); | ||
291 | return -ENODEV; | ||
292 | } | ||
293 | |||
294 | if (enable) { | ||
295 | if (!dev->wakeup.run_wake_count++) { | ||
296 | acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); | ||
297 | acpi_enable_gpe(dev->wakeup.gpe_device, | ||
298 | dev->wakeup.gpe_number, | ||
299 | ACPI_GPE_TYPE_RUNTIME); | ||
300 | } | ||
301 | } else if (dev->wakeup.run_wake_count > 0) { | ||
302 | if (!--dev->wakeup.run_wake_count) { | ||
303 | acpi_disable_gpe(dev->wakeup.gpe_device, | ||
304 | dev->wakeup.gpe_number, | ||
305 | ACPI_GPE_TYPE_RUNTIME); | ||
306 | acpi_disable_wakeup_device_power(dev); | ||
307 | } | ||
308 | } else { | ||
309 | error = -EALREADY; | ||
310 | } | ||
311 | |||
312 | return error; | ||
313 | } | ||
314 | |||
315 | static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable) | ||
316 | { | ||
317 | while (bus->parent) { | ||
318 | struct pci_dev *bridge = bus->self; | ||
319 | |||
320 | if (bridge->pme_interrupt) | ||
321 | return; | ||
322 | if (!acpi_dev_run_wake(&bridge->dev, enable)) | ||
323 | return; | ||
324 | bus = bus->parent; | ||
325 | } | ||
326 | |||
327 | /* We have reached the root bus. */ | ||
328 | if (bus->bridge) | ||
329 | acpi_dev_run_wake(bus->bridge, enable); | ||
330 | } | ||
331 | |||
332 | static int acpi_pci_run_wake(struct pci_dev *dev, bool enable) | ||
333 | { | ||
334 | if (dev->pme_interrupt) | ||
335 | return 0; | ||
336 | |||
337 | if (!acpi_dev_run_wake(&dev->dev, enable)) | ||
338 | return 0; | ||
339 | |||
340 | acpi_pci_propagate_run_wake(dev->bus, enable); | ||
341 | return 0; | ||
342 | } | ||
343 | |||
134 | static struct pci_platform_pm_ops acpi_pci_platform_pm = { | 344 | static struct pci_platform_pm_ops acpi_pci_platform_pm = { |
135 | .is_manageable = acpi_pci_power_manageable, | 345 | .is_manageable = acpi_pci_power_manageable, |
136 | .set_state = acpi_pci_set_power_state, | 346 | .set_state = acpi_pci_set_power_state, |
137 | .choose_state = acpi_pci_choose_state, | 347 | .choose_state = acpi_pci_choose_state, |
138 | .can_wakeup = acpi_pci_can_wakeup, | 348 | .can_wakeup = acpi_pci_can_wakeup, |
139 | .sleep_wake = acpi_pci_sleep_wake, | 349 | .sleep_wake = acpi_pci_sleep_wake, |
350 | .run_wake = acpi_pci_run_wake, | ||
140 | }; | 351 | }; |
141 | 352 | ||
142 | /* ACPI bus type */ | 353 | /* ACPI bus type */ |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index e5d47be3c6d..f9a0aec3abc 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/cpu.h> | 19 | #include <linux/cpu.h> |
20 | #include <linux/pm_runtime.h> | ||
20 | #include "pci.h" | 21 | #include "pci.h" |
21 | 22 | ||
22 | struct pci_dynid { | 23 | struct pci_dynid { |
@@ -404,6 +405,35 @@ static void pci_device_shutdown(struct device *dev) | |||
404 | pci_msix_shutdown(pci_dev); | 405 | pci_msix_shutdown(pci_dev); |
405 | } | 406 | } |
406 | 407 | ||
408 | #ifdef CONFIG_PM_OPS | ||
409 | |||
410 | /* Auxiliary functions used for system resume and run-time resume. */ | ||
411 | |||
412 | /** | ||
413 | * pci_restore_standard_config - restore standard config registers of PCI device | ||
414 | * @pci_dev: PCI device to handle | ||
415 | */ | ||
416 | static int pci_restore_standard_config(struct pci_dev *pci_dev) | ||
417 | { | ||
418 | pci_update_current_state(pci_dev, PCI_UNKNOWN); | ||
419 | |||
420 | if (pci_dev->current_state != PCI_D0) { | ||
421 | int error = pci_set_power_state(pci_dev, PCI_D0); | ||
422 | if (error) | ||
423 | return error; | ||
424 | } | ||
425 | |||
426 | return pci_restore_state(pci_dev); | ||
427 | } | ||
428 | |||
429 | static void pci_pm_default_resume_early(struct pci_dev *pci_dev) | ||
430 | { | ||
431 | pci_restore_standard_config(pci_dev); | ||
432 | pci_fixup_device(pci_fixup_resume_early, pci_dev); | ||
433 | } | ||
434 | |||
435 | #endif | ||
436 | |||
407 | #ifdef CONFIG_PM_SLEEP | 437 | #ifdef CONFIG_PM_SLEEP |
408 | 438 | ||
409 | /* | 439 | /* |
@@ -520,29 +550,6 @@ static int pci_legacy_resume(struct device *dev) | |||
520 | 550 | ||
521 | /* Auxiliary functions used by the new power management framework */ | 551 | /* Auxiliary functions used by the new power management framework */ |
522 | 552 | ||
523 | /** | ||
524 | * pci_restore_standard_config - restore standard config registers of PCI device | ||
525 | * @pci_dev: PCI device to handle | ||
526 | */ | ||
527 | static int pci_restore_standard_config(struct pci_dev *pci_dev) | ||
528 | { | ||
529 | pci_update_current_state(pci_dev, PCI_UNKNOWN); | ||
530 | |||
531 | if (pci_dev->current_state != PCI_D0) { | ||
532 | int error = pci_set_power_state(pci_dev, PCI_D0); | ||
533 | if (error) | ||
534 | return error; | ||
535 | } | ||
536 | |||
537 | return pci_restore_state(pci_dev); | ||
538 | } | ||
539 | |||
540 | static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev) | ||
541 | { | ||
542 | pci_restore_standard_config(pci_dev); | ||
543 | pci_fixup_device(pci_fixup_resume_early, pci_dev); | ||
544 | } | ||
545 | |||
546 | static void pci_pm_default_resume(struct pci_dev *pci_dev) | 553 | static void pci_pm_default_resume(struct pci_dev *pci_dev) |
547 | { | 554 | { |
548 | pci_fixup_device(pci_fixup_resume, pci_dev); | 555 | pci_fixup_device(pci_fixup_resume, pci_dev); |
@@ -581,6 +588,17 @@ static int pci_pm_prepare(struct device *dev) | |||
581 | struct device_driver *drv = dev->driver; | 588 | struct device_driver *drv = dev->driver; |
582 | int error = 0; | 589 | int error = 0; |
583 | 590 | ||
591 | /* | ||
592 | * PCI devices suspended at run time need to be resumed at this | ||
593 | * point, because in general it is necessary to reconfigure them for | ||
594 | * system suspend. Namely, if the device is supposed to wake up the | ||
595 | * system from the sleep state, we may need to reconfigure it for this | ||
596 | * purpose. In turn, if the device is not supposed to wake up the | ||
597 | * system from the sleep state, we'll have to prevent it from signaling | ||
598 | * wake-up. | ||
599 | */ | ||
600 | pm_runtime_resume(dev); | ||
601 | |||
584 | if (drv && drv->pm && drv->pm->prepare) | 602 | if (drv && drv->pm && drv->pm->prepare) |
585 | error = drv->pm->prepare(dev); | 603 | error = drv->pm->prepare(dev); |
586 | 604 | ||
@@ -595,6 +613,13 @@ static void pci_pm_complete(struct device *dev) | |||
595 | drv->pm->complete(dev); | 613 | drv->pm->complete(dev); |
596 | } | 614 | } |
597 | 615 | ||
616 | #else /* !CONFIG_PM_SLEEP */ | ||
617 | |||
618 | #define pci_pm_prepare NULL | ||
619 | #define pci_pm_complete NULL | ||
620 | |||
621 | #endif /* !CONFIG_PM_SLEEP */ | ||
622 | |||
598 | #ifdef CONFIG_SUSPEND | 623 | #ifdef CONFIG_SUSPEND |
599 | 624 | ||
600 | static int pci_pm_suspend(struct device *dev) | 625 | static int pci_pm_suspend(struct device *dev) |
@@ -681,7 +706,7 @@ static int pci_pm_resume_noirq(struct device *dev) | |||
681 | struct device_driver *drv = dev->driver; | 706 | struct device_driver *drv = dev->driver; |
682 | int error = 0; | 707 | int error = 0; |
683 | 708 | ||
684 | pci_pm_default_resume_noirq(pci_dev); | 709 | pci_pm_default_resume_early(pci_dev); |
685 | 710 | ||
686 | if (pci_has_legacy_pm_support(pci_dev)) | 711 | if (pci_has_legacy_pm_support(pci_dev)) |
687 | return pci_legacy_resume_early(dev); | 712 | return pci_legacy_resume_early(dev); |
@@ -879,7 +904,7 @@ static int pci_pm_restore_noirq(struct device *dev) | |||
879 | struct device_driver *drv = dev->driver; | 904 | struct device_driver *drv = dev->driver; |
880 | int error = 0; | 905 | int error = 0; |
881 | 906 | ||
882 | pci_pm_default_resume_noirq(pci_dev); | 907 | pci_pm_default_resume_early(pci_dev); |
883 | 908 | ||
884 | if (pci_has_legacy_pm_support(pci_dev)) | 909 | if (pci_has_legacy_pm_support(pci_dev)) |
885 | return pci_legacy_resume_early(dev); | 910 | return pci_legacy_resume_early(dev); |
@@ -931,6 +956,84 @@ static int pci_pm_restore(struct device *dev) | |||
931 | 956 | ||
932 | #endif /* !CONFIG_HIBERNATION */ | 957 | #endif /* !CONFIG_HIBERNATION */ |
933 | 958 | ||
959 | #ifdef CONFIG_PM_RUNTIME | ||
960 | |||
961 | static int pci_pm_runtime_suspend(struct device *dev) | ||
962 | { | ||
963 | struct pci_dev *pci_dev = to_pci_dev(dev); | ||
964 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
965 | pci_power_t prev = pci_dev->current_state; | ||
966 | int error; | ||
967 | |||
968 | if (!pm || !pm->runtime_suspend) | ||
969 | return -ENOSYS; | ||
970 | |||
971 | error = pm->runtime_suspend(dev); | ||
972 | suspend_report_result(pm->runtime_suspend, error); | ||
973 | if (error) | ||
974 | return error; | ||
975 | |||
976 | pci_fixup_device(pci_fixup_suspend, pci_dev); | ||
977 | |||
978 | if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 | ||
979 | && pci_dev->current_state != PCI_UNKNOWN) { | ||
980 | WARN_ONCE(pci_dev->current_state != prev, | ||
981 | "PCI PM: State of device not saved by %pF\n", | ||
982 | pm->runtime_suspend); | ||
983 | return 0; | ||
984 | } | ||
985 | |||
986 | if (!pci_dev->state_saved) | ||
987 | pci_save_state(pci_dev); | ||
988 | |||
989 | pci_finish_runtime_suspend(pci_dev); | ||
990 | |||
991 | return 0; | ||
992 | } | ||
993 | |||
994 | static int pci_pm_runtime_resume(struct device *dev) | ||
995 | { | ||
996 | struct pci_dev *pci_dev = to_pci_dev(dev); | ||
997 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
998 | |||
999 | if (!pm || !pm->runtime_resume) | ||
1000 | return -ENOSYS; | ||
1001 | |||
1002 | pci_pm_default_resume_early(pci_dev); | ||
1003 | __pci_enable_wake(pci_dev, PCI_D0, true, false); | ||
1004 | pci_fixup_device(pci_fixup_resume, pci_dev); | ||
1005 | |||
1006 | return pm->runtime_resume(dev); | ||
1007 | } | ||
1008 | |||
1009 | static int pci_pm_runtime_idle(struct device *dev) | ||
1010 | { | ||
1011 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
1012 | |||
1013 | if (!pm) | ||
1014 | return -ENOSYS; | ||
1015 | |||
1016 | if (pm->runtime_idle) { | ||
1017 | int ret = pm->runtime_idle(dev); | ||
1018 | if (ret) | ||
1019 | return ret; | ||
1020 | } | ||
1021 | |||
1022 | pm_runtime_suspend(dev); | ||
1023 | |||
1024 | return 0; | ||
1025 | } | ||
1026 | |||
1027 | #else /* !CONFIG_PM_RUNTIME */ | ||
1028 | |||
1029 | #define pci_pm_runtime_suspend NULL | ||
1030 | #define pci_pm_runtime_resume NULL | ||
1031 | #define pci_pm_runtime_idle NULL | ||
1032 | |||
1033 | #endif /* !CONFIG_PM_RUNTIME */ | ||
1034 | |||
1035 | #ifdef CONFIG_PM_OPS | ||
1036 | |||
934 | const struct dev_pm_ops pci_dev_pm_ops = { | 1037 | const struct dev_pm_ops pci_dev_pm_ops = { |
935 | .prepare = pci_pm_prepare, | 1038 | .prepare = pci_pm_prepare, |
936 | .complete = pci_pm_complete, | 1039 | .complete = pci_pm_complete, |
@@ -946,15 +1049,18 @@ const struct dev_pm_ops pci_dev_pm_ops = { | |||
946 | .thaw_noirq = pci_pm_thaw_noirq, | 1049 | .thaw_noirq = pci_pm_thaw_noirq, |
947 | .poweroff_noirq = pci_pm_poweroff_noirq, | 1050 | .poweroff_noirq = pci_pm_poweroff_noirq, |
948 | .restore_noirq = pci_pm_restore_noirq, | 1051 | .restore_noirq = pci_pm_restore_noirq, |
1052 | .runtime_suspend = pci_pm_runtime_suspend, | ||
1053 | .runtime_resume = pci_pm_runtime_resume, | ||
1054 | .runtime_idle = pci_pm_runtime_idle, | ||
949 | }; | 1055 | }; |
950 | 1056 | ||
951 | #define PCI_PM_OPS_PTR (&pci_dev_pm_ops) | 1057 | #define PCI_PM_OPS_PTR (&pci_dev_pm_ops) |
952 | 1058 | ||
953 | #else /* !CONFIG_PM_SLEEP */ | 1059 | #else /* !COMFIG_PM_OPS */ |
954 | 1060 | ||
955 | #define PCI_PM_OPS_PTR NULL | 1061 | #define PCI_PM_OPS_PTR NULL |
956 | 1062 | ||
957 | #endif /* !CONFIG_PM_SLEEP */ | 1063 | #endif /* !COMFIG_PM_OPS */ |
958 | 1064 | ||
959 | /** | 1065 | /** |
960 | * __pci_register_driver - register a new pci driver | 1066 | * __pci_register_driver - register a new pci driver |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 315fea47e78..f4a2738bf0b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -19,8 +19,8 @@ | |||
19 | #include <linux/pci-aspm.h> | 19 | #include <linux/pci-aspm.h> |
20 | #include <linux/pm_wakeup.h> | 20 | #include <linux/pm_wakeup.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ | ||
23 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/pm_runtime.h> | ||
24 | #include <asm/setup.h> | 24 | #include <asm/setup.h> |
25 | #include "pci.h" | 25 | #include "pci.h" |
26 | 26 | ||
@@ -29,6 +29,12 @@ const char *pci_power_names[] = { | |||
29 | }; | 29 | }; |
30 | EXPORT_SYMBOL_GPL(pci_power_names); | 30 | EXPORT_SYMBOL_GPL(pci_power_names); |
31 | 31 | ||
32 | int isa_dma_bridge_buggy; | ||
33 | EXPORT_SYMBOL(isa_dma_bridge_buggy); | ||
34 | |||
35 | int pci_pci_problems; | ||
36 | EXPORT_SYMBOL(pci_pci_problems); | ||
37 | |||
32 | unsigned int pci_pm_d3_delay; | 38 | unsigned int pci_pm_d3_delay; |
33 | 39 | ||
34 | static void pci_dev_d3_sleep(struct pci_dev *dev) | 40 | static void pci_dev_d3_sleep(struct pci_dev *dev) |
@@ -380,10 +386,9 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res) | |||
380 | { | 386 | { |
381 | const struct pci_bus *bus = dev->bus; | 387 | const struct pci_bus *bus = dev->bus; |
382 | int i; | 388 | int i; |
383 | struct resource *best = NULL; | 389 | struct resource *best = NULL, *r; |
384 | 390 | ||
385 | for(i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 391 | pci_bus_for_each_resource(bus, r, i) { |
386 | struct resource *r = bus->resource[i]; | ||
387 | if (!r) | 392 | if (!r) |
388 | continue; | 393 | continue; |
389 | if (res->start && !(res->start >= r->start && res->end <= r->end)) | 394 | if (res->start && !(res->start >= r->start && res->end <= r->end)) |
@@ -457,6 +462,12 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) | |||
457 | pci_platform_pm->sleep_wake(dev, enable) : -ENODEV; | 462 | pci_platform_pm->sleep_wake(dev, enable) : -ENODEV; |
458 | } | 463 | } |
459 | 464 | ||
465 | static inline int platform_pci_run_wake(struct pci_dev *dev, bool enable) | ||
466 | { | ||
467 | return pci_platform_pm ? | ||
468 | pci_platform_pm->run_wake(dev, enable) : -ENODEV; | ||
469 | } | ||
470 | |||
460 | /** | 471 | /** |
461 | * pci_raw_set_power_state - Use PCI PM registers to set the power state of | 472 | * pci_raw_set_power_state - Use PCI PM registers to set the power state of |
462 | * given PCI device | 473 | * given PCI device |
@@ -1190,6 +1201,66 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) | |||
1190 | } | 1201 | } |
1191 | 1202 | ||
1192 | /** | 1203 | /** |
1204 | * pci_check_pme_status - Check if given device has generated PME. | ||
1205 | * @dev: Device to check. | ||
1206 | * | ||
1207 | * Check the PME status of the device and if set, clear it and clear PME enable | ||
1208 | * (if set). Return 'true' if PME status and PME enable were both set or | ||
1209 | * 'false' otherwise. | ||
1210 | */ | ||
1211 | bool pci_check_pme_status(struct pci_dev *dev) | ||
1212 | { | ||
1213 | int pmcsr_pos; | ||
1214 | u16 pmcsr; | ||
1215 | bool ret = false; | ||
1216 | |||
1217 | if (!dev->pm_cap) | ||
1218 | return false; | ||
1219 | |||
1220 | pmcsr_pos = dev->pm_cap + PCI_PM_CTRL; | ||
1221 | pci_read_config_word(dev, pmcsr_pos, &pmcsr); | ||
1222 | if (!(pmcsr & PCI_PM_CTRL_PME_STATUS)) | ||
1223 | return false; | ||
1224 | |||
1225 | /* Clear PME status. */ | ||
1226 | pmcsr |= PCI_PM_CTRL_PME_STATUS; | ||
1227 | if (pmcsr & PCI_PM_CTRL_PME_ENABLE) { | ||
1228 | /* Disable PME to avoid interrupt flood. */ | ||
1229 | pmcsr &= ~PCI_PM_CTRL_PME_ENABLE; | ||
1230 | ret = true; | ||
1231 | } | ||
1232 | |||
1233 | pci_write_config_word(dev, pmcsr_pos, pmcsr); | ||
1234 | |||
1235 | return ret; | ||
1236 | } | ||
1237 | |||
1238 | /** | ||
1239 | * pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set. | ||
1240 | * @dev: Device to handle. | ||
1241 | * @ign: Ignored. | ||
1242 | * | ||
1243 | * Check if @dev has generated PME and queue a resume request for it in that | ||
1244 | * case. | ||
1245 | */ | ||
1246 | static int pci_pme_wakeup(struct pci_dev *dev, void *ign) | ||
1247 | { | ||
1248 | if (pci_check_pme_status(dev)) | ||
1249 | pm_request_resume(&dev->dev); | ||
1250 | return 0; | ||
1251 | } | ||
1252 | |||
1253 | /** | ||
1254 | * pci_pme_wakeup_bus - Walk given bus and wake up devices on it, if necessary. | ||
1255 | * @bus: Top bus of the subtree to walk. | ||
1256 | */ | ||
1257 | void pci_pme_wakeup_bus(struct pci_bus *bus) | ||
1258 | { | ||
1259 | if (bus) | ||
1260 | pci_walk_bus(bus, pci_pme_wakeup, NULL); | ||
1261 | } | ||
1262 | |||
1263 | /** | ||
1193 | * pci_pme_capable - check the capability of PCI device to generate PME# | 1264 | * pci_pme_capable - check the capability of PCI device to generate PME# |
1194 | * @dev: PCI device to handle. | 1265 | * @dev: PCI device to handle. |
1195 | * @state: PCI state from which device will issue PME#. | 1266 | * @state: PCI state from which device will issue PME#. |
@@ -1230,9 +1301,10 @@ void pci_pme_active(struct pci_dev *dev, bool enable) | |||
1230 | } | 1301 | } |
1231 | 1302 | ||
1232 | /** | 1303 | /** |
1233 | * pci_enable_wake - enable PCI device as wakeup event source | 1304 | * __pci_enable_wake - enable PCI device as wakeup event source |
1234 | * @dev: PCI device affected | 1305 | * @dev: PCI device affected |
1235 | * @state: PCI state from which device will issue wakeup events | 1306 | * @state: PCI state from which device will issue wakeup events |
1307 | * @runtime: True if the events are to be generated at run time | ||
1236 | * @enable: True to enable event generation; false to disable | 1308 | * @enable: True to enable event generation; false to disable |
1237 | * | 1309 | * |
1238 | * This enables the device as a wakeup event source, or disables it. | 1310 | * This enables the device as a wakeup event source, or disables it. |
@@ -1248,11 +1320,12 @@ void pci_pme_active(struct pci_dev *dev, bool enable) | |||
1248 | * Error code depending on the platform is returned if both the platform and | 1320 | * Error code depending on the platform is returned if both the platform and |
1249 | * the native mechanism fail to enable the generation of wake-up events | 1321 | * the native mechanism fail to enable the generation of wake-up events |
1250 | */ | 1322 | */ |
1251 | int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable) | 1323 | int __pci_enable_wake(struct pci_dev *dev, pci_power_t state, |
1324 | bool runtime, bool enable) | ||
1252 | { | 1325 | { |
1253 | int ret = 0; | 1326 | int ret = 0; |
1254 | 1327 | ||
1255 | if (enable && !device_may_wakeup(&dev->dev)) | 1328 | if (enable && !runtime && !device_may_wakeup(&dev->dev)) |
1256 | return -EINVAL; | 1329 | return -EINVAL; |
1257 | 1330 | ||
1258 | /* Don't do the same thing twice in a row for one device. */ | 1331 | /* Don't do the same thing twice in a row for one device. */ |
@@ -1272,19 +1345,24 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable) | |||
1272 | pci_pme_active(dev, true); | 1345 | pci_pme_active(dev, true); |
1273 | else | 1346 | else |
1274 | ret = 1; | 1347 | ret = 1; |
1275 | error = platform_pci_sleep_wake(dev, true); | 1348 | error = runtime ? platform_pci_run_wake(dev, true) : |
1349 | platform_pci_sleep_wake(dev, true); | ||
1276 | if (ret) | 1350 | if (ret) |
1277 | ret = error; | 1351 | ret = error; |
1278 | if (!ret) | 1352 | if (!ret) |
1279 | dev->wakeup_prepared = true; | 1353 | dev->wakeup_prepared = true; |
1280 | } else { | 1354 | } else { |
1281 | platform_pci_sleep_wake(dev, false); | 1355 | if (runtime) |
1356 | platform_pci_run_wake(dev, false); | ||
1357 | else | ||
1358 | platform_pci_sleep_wake(dev, false); | ||
1282 | pci_pme_active(dev, false); | 1359 | pci_pme_active(dev, false); |
1283 | dev->wakeup_prepared = false; | 1360 | dev->wakeup_prepared = false; |
1284 | } | 1361 | } |
1285 | 1362 | ||
1286 | return ret; | 1363 | return ret; |
1287 | } | 1364 | } |
1365 | EXPORT_SYMBOL(__pci_enable_wake); | ||
1288 | 1366 | ||
1289 | /** | 1367 | /** |
1290 | * pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold | 1368 | * pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold |
@@ -1394,6 +1472,66 @@ int pci_back_from_sleep(struct pci_dev *dev) | |||
1394 | } | 1472 | } |
1395 | 1473 | ||
1396 | /** | 1474 | /** |
1475 | * pci_finish_runtime_suspend - Carry out PCI-specific part of runtime suspend. | ||
1476 | * @dev: PCI device being suspended. | ||
1477 | * | ||
1478 | * Prepare @dev to generate wake-up events at run time and put it into a low | ||
1479 | * power state. | ||
1480 | */ | ||
1481 | int pci_finish_runtime_suspend(struct pci_dev *dev) | ||
1482 | { | ||
1483 | pci_power_t target_state = pci_target_state(dev); | ||
1484 | int error; | ||
1485 | |||
1486 | if (target_state == PCI_POWER_ERROR) | ||
1487 | return -EIO; | ||
1488 | |||
1489 | __pci_enable_wake(dev, target_state, true, pci_dev_run_wake(dev)); | ||
1490 | |||
1491 | error = pci_set_power_state(dev, target_state); | ||
1492 | |||
1493 | if (error) | ||
1494 | __pci_enable_wake(dev, target_state, true, false); | ||
1495 | |||
1496 | return error; | ||
1497 | } | ||
1498 | |||
1499 | /** | ||
1500 | * pci_dev_run_wake - Check if device can generate run-time wake-up events. | ||
1501 | * @dev: Device to check. | ||
1502 | * | ||
1503 | * Return true if the device itself is cabable of generating wake-up events | ||
1504 | * (through the platform or using the native PCIe PME) or if the device supports | ||
1505 | * PME and one of its upstream bridges can generate wake-up events. | ||
1506 | */ | ||
1507 | bool pci_dev_run_wake(struct pci_dev *dev) | ||
1508 | { | ||
1509 | struct pci_bus *bus = dev->bus; | ||
1510 | |||
1511 | if (device_run_wake(&dev->dev)) | ||
1512 | return true; | ||
1513 | |||
1514 | if (!dev->pme_support) | ||
1515 | return false; | ||
1516 | |||
1517 | while (bus->parent) { | ||
1518 | struct pci_dev *bridge = bus->self; | ||
1519 | |||
1520 | if (device_run_wake(&bridge->dev)) | ||
1521 | return true; | ||
1522 | |||
1523 | bus = bus->parent; | ||
1524 | } | ||
1525 | |||
1526 | /* We have reached the root bus. */ | ||
1527 | if (bus->bridge) | ||
1528 | return device_run_wake(bus->bridge); | ||
1529 | |||
1530 | return false; | ||
1531 | } | ||
1532 | EXPORT_SYMBOL_GPL(pci_dev_run_wake); | ||
1533 | |||
1534 | /** | ||
1397 | * pci_pm_init - Initialize PM functions of given PCI device | 1535 | * pci_pm_init - Initialize PM functions of given PCI device |
1398 | * @dev: PCI device to handle. | 1536 | * @dev: PCI device to handle. |
1399 | */ | 1537 | */ |
@@ -2871,7 +3009,6 @@ EXPORT_SYMBOL(pci_save_state); | |||
2871 | EXPORT_SYMBOL(pci_restore_state); | 3009 | EXPORT_SYMBOL(pci_restore_state); |
2872 | EXPORT_SYMBOL(pci_pme_capable); | 3010 | EXPORT_SYMBOL(pci_pme_capable); |
2873 | EXPORT_SYMBOL(pci_pme_active); | 3011 | EXPORT_SYMBOL(pci_pme_active); |
2874 | EXPORT_SYMBOL(pci_enable_wake); | ||
2875 | EXPORT_SYMBOL(pci_wake_from_d3); | 3012 | EXPORT_SYMBOL(pci_wake_from_d3); |
2876 | EXPORT_SYMBOL(pci_target_state); | 3013 | EXPORT_SYMBOL(pci_target_state); |
2877 | EXPORT_SYMBOL(pci_prepare_to_sleep); | 3014 | EXPORT_SYMBOL(pci_prepare_to_sleep); |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index fbd0e3adbca..4eb10f48d27 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -35,6 +35,10 @@ int pci_probe_reset_function(struct pci_dev *dev); | |||
35 | * | 35 | * |
36 | * @sleep_wake: enables/disables the system wake up capability of given device | 36 | * @sleep_wake: enables/disables the system wake up capability of given device |
37 | * | 37 | * |
38 | * @run_wake: enables/disables the platform to generate run-time wake-up events | ||
39 | * for given device (the device's wake-up capability has to be | ||
40 | * enabled by @sleep_wake for this feature to work) | ||
41 | * | ||
38 | * If given platform is generally capable of power managing PCI devices, all of | 42 | * If given platform is generally capable of power managing PCI devices, all of |
39 | * these callbacks are mandatory. | 43 | * these callbacks are mandatory. |
40 | */ | 44 | */ |
@@ -44,11 +48,16 @@ struct pci_platform_pm_ops { | |||
44 | pci_power_t (*choose_state)(struct pci_dev *dev); | 48 | pci_power_t (*choose_state)(struct pci_dev *dev); |
45 | bool (*can_wakeup)(struct pci_dev *dev); | 49 | bool (*can_wakeup)(struct pci_dev *dev); |
46 | int (*sleep_wake)(struct pci_dev *dev, bool enable); | 50 | int (*sleep_wake)(struct pci_dev *dev, bool enable); |
51 | int (*run_wake)(struct pci_dev *dev, bool enable); | ||
47 | }; | 52 | }; |
48 | 53 | ||
49 | extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops); | 54 | extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops); |
50 | extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state); | 55 | extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state); |
51 | extern void pci_disable_enabled_device(struct pci_dev *dev); | 56 | extern void pci_disable_enabled_device(struct pci_dev *dev); |
57 | extern bool pci_check_pme_status(struct pci_dev *dev); | ||
58 | extern int pci_finish_runtime_suspend(struct pci_dev *dev); | ||
59 | extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign); | ||
60 | extern void pci_pme_wakeup_bus(struct pci_bus *bus); | ||
52 | extern void pci_pm_init(struct pci_dev *dev); | 61 | extern void pci_pm_init(struct pci_dev *dev); |
53 | extern void platform_pci_wakeup_init(struct pci_dev *dev); | 62 | extern void platform_pci_wakeup_init(struct pci_dev *dev); |
54 | extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); | 63 | extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); |
@@ -319,6 +328,13 @@ struct pci_dev_reset_methods { | |||
319 | int (*reset)(struct pci_dev *dev, int probe); | 328 | int (*reset)(struct pci_dev *dev, int probe); |
320 | }; | 329 | }; |
321 | 330 | ||
331 | #ifdef CONFIG_PCI_QUIRKS | ||
322 | extern int pci_dev_specific_reset(struct pci_dev *dev, int probe); | 332 | extern int pci_dev_specific_reset(struct pci_dev *dev, int probe); |
333 | #else | ||
334 | static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe) | ||
335 | { | ||
336 | return -ENOTTY; | ||
337 | } | ||
338 | #endif | ||
323 | 339 | ||
324 | #endif /* DRIVERS_PCI_H */ | 340 | #endif /* DRIVERS_PCI_H */ |
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 5a0c6ad53f8..b8b494b3e0d 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig | |||
@@ -46,3 +46,7 @@ config PCIEASPM_DEBUG | |||
46 | help | 46 | help |
47 | This enables PCI Express ASPM debug support. It will add per-device | 47 | This enables PCI Express ASPM debug support. It will add per-device |
48 | interface to control ASPM. | 48 | interface to control ASPM. |
49 | |||
50 | config PCIE_PME | ||
51 | def_bool y | ||
52 | depends on PCIEPORTBUS && PM_RUNTIME && EXPERIMENTAL && ACPI | ||
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile index 11f6bb1eae2..ea654545e7c 100644 --- a/drivers/pci/pcie/Makefile +++ b/drivers/pci/pcie/Makefile | |||
@@ -11,3 +11,5 @@ obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o | |||
11 | 11 | ||
12 | # Build PCI Express AER if needed | 12 | # Build PCI Express AER if needed |
13 | obj-$(CONFIG_PCIEAER) += aer/ | 13 | obj-$(CONFIG_PCIEAER) += aer/ |
14 | |||
15 | obj-$(CONFIG_PCIE_PME) += pme/ | ||
diff --git a/drivers/pci/pcie/pme/Makefile b/drivers/pci/pcie/pme/Makefile new file mode 100644 index 00000000000..8b923805308 --- /dev/null +++ b/drivers/pci/pcie/pme/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for PCI-Express Root Port PME signaling driver | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_PCIE_PME) += pmedriver.o | ||
6 | |||
7 | pmedriver-objs := pcie_pme.o | ||
8 | pmedriver-$(CONFIG_ACPI) += pcie_pme_acpi.o | ||
diff --git a/drivers/pci/pcie/pme/pcie_pme.c b/drivers/pci/pcie/pme/pcie_pme.c new file mode 100644 index 00000000000..7b3cbff547e --- /dev/null +++ b/drivers/pci/pcie/pme/pcie_pme.c | |||
@@ -0,0 +1,505 @@ | |||
1 | /* | ||
2 | * PCIe Native PME support | ||
3 | * | ||
4 | * Copyright (C) 2007 - 2009 Intel Corp | ||
5 | * Copyright (C) 2007 - 2009 Shaohua Li <shaohua.li@intel.com> | ||
6 | * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License V2. See the file "COPYING" in the main directory of this archive | ||
10 | * for more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/pci.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/device.h> | ||
20 | #include <linux/pcieport_if.h> | ||
21 | #include <linux/acpi.h> | ||
22 | #include <linux/pci-acpi.h> | ||
23 | #include <linux/pm_runtime.h> | ||
24 | |||
25 | #include "../../pci.h" | ||
26 | #include "pcie_pme.h" | ||
27 | |||
28 | #define PCI_EXP_RTSTA_PME 0x10000 /* PME status */ | ||
29 | #define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */ | ||
30 | |||
31 | /* | ||
32 | * If set, this switch will prevent the PCIe root port PME service driver from | ||
33 | * being registered. Consequently, the interrupt-based PCIe PME signaling will | ||
34 | * not be used by any PCIe root ports in that case. | ||
35 | */ | ||
36 | static bool pcie_pme_disabled; | ||
37 | |||
38 | /* | ||
39 | * The PCI Express Base Specification 2.0, Section 6.1.8, states the following: | ||
40 | * "In order to maintain compatibility with non-PCI Express-aware system | ||
41 | * software, system power management logic must be configured by firmware to use | ||
42 | * the legacy mechanism of signaling PME by default. PCI Express-aware system | ||
43 | * software must notify the firmware prior to enabling native, interrupt-based | ||
44 | * PME signaling." However, if the platform doesn't provide us with a suitable | ||
45 | * notification mechanism or the notification fails, it is not clear whether or | ||
46 | * not we are supposed to use the interrupt-based PCIe PME signaling. The | ||
47 | * switch below can be used to indicate the desired behaviour. When set, it | ||
48 | * will make the kernel use the interrupt-based PCIe PME signaling regardless of | ||
49 | * the platform notification status, although the kernel will attempt to notify | ||
50 | * the platform anyway. When unset, it will prevent the kernel from using the | ||
51 | * the interrupt-based PCIe PME signaling if the platform notification fails, | ||
52 | * which is the default. | ||
53 | */ | ||
54 | static bool pcie_pme_force_enable; | ||
55 | |||
56 | /* | ||
57 | * If this switch is set, MSI will not be used for PCIe PME signaling. This | ||
58 | * causes the PCIe port driver to use INTx interrupts only, but it turns out | ||
59 | * that using MSI for PCIe PME signaling doesn't play well with PCIe PME-based | ||
60 | * wake-up from system sleep states. | ||
61 | */ | ||
62 | bool pcie_pme_msi_disabled; | ||
63 | |||
64 | static int __init pcie_pme_setup(char *str) | ||
65 | { | ||
66 | if (!strcmp(str, "off")) | ||
67 | pcie_pme_disabled = true; | ||
68 | else if (!strcmp(str, "force")) | ||
69 | pcie_pme_force_enable = true; | ||
70 | else if (!strcmp(str, "nomsi")) | ||
71 | pcie_pme_msi_disabled = true; | ||
72 | return 1; | ||
73 | } | ||
74 | __setup("pcie_pme=", pcie_pme_setup); | ||
75 | |||
76 | /** | ||
77 | * pcie_pme_platform_setup - Ensure that the kernel controls the PCIe PME. | ||
78 | * @srv: PCIe PME root port service to use for carrying out the check. | ||
79 | * | ||
80 | * Notify the platform that the native PCIe PME is going to be used and return | ||
81 | * 'true' if the control of the PCIe PME registers has been acquired from the | ||
82 | * platform. | ||
83 | */ | ||
84 | static bool pcie_pme_platform_setup(struct pcie_device *srv) | ||
85 | { | ||
86 | if (!pcie_pme_platform_notify(srv)) | ||
87 | return true; | ||
88 | return pcie_pme_force_enable; | ||
89 | } | ||
90 | |||
91 | struct pcie_pme_service_data { | ||
92 | spinlock_t lock; | ||
93 | struct pcie_device *srv; | ||
94 | struct work_struct work; | ||
95 | bool noirq; /* Don't enable the PME interrupt used by this service. */ | ||
96 | }; | ||
97 | |||
98 | /** | ||
99 | * pcie_pme_interrupt_enable - Enable/disable PCIe PME interrupt generation. | ||
100 | * @dev: PCIe root port or event collector. | ||
101 | * @enable: Enable or disable the interrupt. | ||
102 | */ | ||
103 | static void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) | ||
104 | { | ||
105 | int rtctl_pos; | ||
106 | u16 rtctl; | ||
107 | |||
108 | rtctl_pos = pci_pcie_cap(dev) + PCI_EXP_RTCTL; | ||
109 | |||
110 | pci_read_config_word(dev, rtctl_pos, &rtctl); | ||
111 | if (enable) | ||
112 | rtctl |= PCI_EXP_RTCTL_PMEIE; | ||
113 | else | ||
114 | rtctl &= ~PCI_EXP_RTCTL_PMEIE; | ||
115 | pci_write_config_word(dev, rtctl_pos, rtctl); | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * pcie_pme_clear_status - Clear root port PME interrupt status. | ||
120 | * @dev: PCIe root port or event collector. | ||
121 | */ | ||
122 | static void pcie_pme_clear_status(struct pci_dev *dev) | ||
123 | { | ||
124 | int rtsta_pos; | ||
125 | u32 rtsta; | ||
126 | |||
127 | rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA; | ||
128 | |||
129 | pci_read_config_dword(dev, rtsta_pos, &rtsta); | ||
130 | rtsta |= PCI_EXP_RTSTA_PME; | ||
131 | pci_write_config_dword(dev, rtsta_pos, rtsta); | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * pcie_pme_walk_bus - Scan a PCI bus for devices asserting PME#. | ||
136 | * @bus: PCI bus to scan. | ||
137 | * | ||
138 | * Scan given PCI bus and all buses under it for devices asserting PME#. | ||
139 | */ | ||
140 | static bool pcie_pme_walk_bus(struct pci_bus *bus) | ||
141 | { | ||
142 | struct pci_dev *dev; | ||
143 | bool ret = false; | ||
144 | |||
145 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
146 | /* Skip PCIe devices in case we started from a root port. */ | ||
147 | if (!pci_is_pcie(dev) && pci_check_pme_status(dev)) { | ||
148 | pm_request_resume(&dev->dev); | ||
149 | ret = true; | ||
150 | } | ||
151 | |||
152 | if (dev->subordinate && pcie_pme_walk_bus(dev->subordinate)) | ||
153 | ret = true; | ||
154 | } | ||
155 | |||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * pcie_pme_from_pci_bridge - Check if PCIe-PCI bridge generated a PME. | ||
161 | * @bus: Secondary bus of the bridge. | ||
162 | * @devfn: Device/function number to check. | ||
163 | * | ||
164 | * PME from PCI devices under a PCIe-PCI bridge may be converted to an in-band | ||
165 | * PCIe PME message. In such that case the bridge should use the Requester ID | ||
166 | * of device/function number 0 on its secondary bus. | ||
167 | */ | ||
168 | static bool pcie_pme_from_pci_bridge(struct pci_bus *bus, u8 devfn) | ||
169 | { | ||
170 | struct pci_dev *dev; | ||
171 | bool found = false; | ||
172 | |||
173 | if (devfn) | ||
174 | return false; | ||
175 | |||
176 | dev = pci_dev_get(bus->self); | ||
177 | if (!dev) | ||
178 | return false; | ||
179 | |||
180 | if (pci_is_pcie(dev) && dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) { | ||
181 | down_read(&pci_bus_sem); | ||
182 | if (pcie_pme_walk_bus(bus)) | ||
183 | found = true; | ||
184 | up_read(&pci_bus_sem); | ||
185 | } | ||
186 | |||
187 | pci_dev_put(dev); | ||
188 | return found; | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * pcie_pme_handle_request - Find device that generated PME and handle it. | ||
193 | * @port: Root port or event collector that generated the PME interrupt. | ||
194 | * @req_id: PCIe Requester ID of the device that generated the PME. | ||
195 | */ | ||
196 | static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id) | ||
197 | { | ||
198 | u8 busnr = req_id >> 8, devfn = req_id & 0xff; | ||
199 | struct pci_bus *bus; | ||
200 | struct pci_dev *dev; | ||
201 | bool found = false; | ||
202 | |||
203 | /* First, check if the PME is from the root port itself. */ | ||
204 | if (port->devfn == devfn && port->bus->number == busnr) { | ||
205 | if (pci_check_pme_status(port)) { | ||
206 | pm_request_resume(&port->dev); | ||
207 | found = true; | ||
208 | } else { | ||
209 | /* | ||
210 | * Apparently, the root port generated the PME on behalf | ||
211 | * of a non-PCIe device downstream. If this is done by | ||
212 | * a root port, the Requester ID field in its status | ||
213 | * register may contain either the root port's, or the | ||
214 | * source device's information (PCI Express Base | ||
215 | * Specification, Rev. 2.0, Section 6.1.9). | ||
216 | */ | ||
217 | down_read(&pci_bus_sem); | ||
218 | found = pcie_pme_walk_bus(port->subordinate); | ||
219 | up_read(&pci_bus_sem); | ||
220 | } | ||
221 | goto out; | ||
222 | } | ||
223 | |||
224 | /* Second, find the bus the source device is on. */ | ||
225 | bus = pci_find_bus(pci_domain_nr(port->bus), busnr); | ||
226 | if (!bus) | ||
227 | goto out; | ||
228 | |||
229 | /* Next, check if the PME is from a PCIe-PCI bridge. */ | ||
230 | found = pcie_pme_from_pci_bridge(bus, devfn); | ||
231 | if (found) | ||
232 | goto out; | ||
233 | |||
234 | /* Finally, try to find the PME source on the bus. */ | ||
235 | down_read(&pci_bus_sem); | ||
236 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
237 | pci_dev_get(dev); | ||
238 | if (dev->devfn == devfn) { | ||
239 | found = true; | ||
240 | break; | ||
241 | } | ||
242 | pci_dev_put(dev); | ||
243 | } | ||
244 | up_read(&pci_bus_sem); | ||
245 | |||
246 | if (found) { | ||
247 | /* The device is there, but we have to check its PME status. */ | ||
248 | found = pci_check_pme_status(dev); | ||
249 | if (found) | ||
250 | pm_request_resume(&dev->dev); | ||
251 | pci_dev_put(dev); | ||
252 | } else if (devfn) { | ||
253 | /* | ||
254 | * The device is not there, but we can still try to recover by | ||
255 | * assuming that the PME was reported by a PCIe-PCI bridge that | ||
256 | * used devfn different from zero. | ||
257 | */ | ||
258 | dev_dbg(&port->dev, "PME interrupt generated for " | ||
259 | "non-existent device %02x:%02x.%d\n", | ||
260 | busnr, PCI_SLOT(devfn), PCI_FUNC(devfn)); | ||
261 | found = pcie_pme_from_pci_bridge(bus, 0); | ||
262 | } | ||
263 | |||
264 | out: | ||
265 | if (!found) | ||
266 | dev_dbg(&port->dev, "Spurious native PME interrupt!\n"); | ||
267 | } | ||
268 | |||
269 | /** | ||
270 | * pcie_pme_work_fn - Work handler for PCIe PME interrupt. | ||
271 | * @work: Work structure giving access to service data. | ||
272 | */ | ||
273 | static void pcie_pme_work_fn(struct work_struct *work) | ||
274 | { | ||
275 | struct pcie_pme_service_data *data = | ||
276 | container_of(work, struct pcie_pme_service_data, work); | ||
277 | struct pci_dev *port = data->srv->port; | ||
278 | int rtsta_pos; | ||
279 | u32 rtsta; | ||
280 | |||
281 | rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA; | ||
282 | |||
283 | spin_lock_irq(&data->lock); | ||
284 | |||
285 | for (;;) { | ||
286 | if (data->noirq) | ||
287 | break; | ||
288 | |||
289 | pci_read_config_dword(port, rtsta_pos, &rtsta); | ||
290 | if (rtsta & PCI_EXP_RTSTA_PME) { | ||
291 | /* | ||
292 | * Clear PME status of the port. If there are other | ||
293 | * pending PMEs, the status will be set again. | ||
294 | */ | ||
295 | pcie_pme_clear_status(port); | ||
296 | |||
297 | spin_unlock_irq(&data->lock); | ||
298 | pcie_pme_handle_request(port, rtsta & 0xffff); | ||
299 | spin_lock_irq(&data->lock); | ||
300 | |||
301 | continue; | ||
302 | } | ||
303 | |||
304 | /* No need to loop if there are no more PMEs pending. */ | ||
305 | if (!(rtsta & PCI_EXP_RTSTA_PENDING)) | ||
306 | break; | ||
307 | |||
308 | spin_unlock_irq(&data->lock); | ||
309 | cpu_relax(); | ||
310 | spin_lock_irq(&data->lock); | ||
311 | } | ||
312 | |||
313 | if (!data->noirq) | ||
314 | pcie_pme_interrupt_enable(port, true); | ||
315 | |||
316 | spin_unlock_irq(&data->lock); | ||
317 | } | ||
318 | |||
319 | /** | ||
320 | * pcie_pme_irq - Interrupt handler for PCIe root port PME interrupt. | ||
321 | * @irq: Interrupt vector. | ||
322 | * @context: Interrupt context pointer. | ||
323 | */ | ||
324 | static irqreturn_t pcie_pme_irq(int irq, void *context) | ||
325 | { | ||
326 | struct pci_dev *port; | ||
327 | struct pcie_pme_service_data *data; | ||
328 | int rtsta_pos; | ||
329 | u32 rtsta; | ||
330 | unsigned long flags; | ||
331 | |||
332 | port = ((struct pcie_device *)context)->port; | ||
333 | data = get_service_data((struct pcie_device *)context); | ||
334 | |||
335 | rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA; | ||
336 | |||
337 | spin_lock_irqsave(&data->lock, flags); | ||
338 | pci_read_config_dword(port, rtsta_pos, &rtsta); | ||
339 | |||
340 | if (!(rtsta & PCI_EXP_RTSTA_PME)) { | ||
341 | spin_unlock_irqrestore(&data->lock, flags); | ||
342 | return IRQ_NONE; | ||
343 | } | ||
344 | |||
345 | pcie_pme_interrupt_enable(port, false); | ||
346 | spin_unlock_irqrestore(&data->lock, flags); | ||
347 | |||
348 | /* We don't use pm_wq, because it's freezable. */ | ||
349 | schedule_work(&data->work); | ||
350 | |||
351 | return IRQ_HANDLED; | ||
352 | } | ||
353 | |||
354 | /** | ||
355 | * pcie_pme_set_native - Set the PME interrupt flag for given device. | ||
356 | * @dev: PCI device to handle. | ||
357 | * @ign: Ignored. | ||
358 | */ | ||
359 | static int pcie_pme_set_native(struct pci_dev *dev, void *ign) | ||
360 | { | ||
361 | dev_info(&dev->dev, "Signaling PME through PCIe PME interrupt\n"); | ||
362 | |||
363 | device_set_run_wake(&dev->dev, true); | ||
364 | dev->pme_interrupt = true; | ||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | /** | ||
369 | * pcie_pme_mark_devices - Set the PME interrupt flag for devices below a port. | ||
370 | * @port: PCIe root port or event collector to handle. | ||
371 | * | ||
372 | * For each device below given root port, including the port itself (or for each | ||
373 | * root complex integrated endpoint if @port is a root complex event collector) | ||
374 | * set the flag indicating that it can signal run-time wake-up events via PCIe | ||
375 | * PME interrupts. | ||
376 | */ | ||
377 | static void pcie_pme_mark_devices(struct pci_dev *port) | ||
378 | { | ||
379 | pcie_pme_set_native(port, NULL); | ||
380 | if (port->subordinate) { | ||
381 | pci_walk_bus(port->subordinate, pcie_pme_set_native, NULL); | ||
382 | } else { | ||
383 | struct pci_bus *bus = port->bus; | ||
384 | struct pci_dev *dev; | ||
385 | |||
386 | /* Check if this is a root port event collector. */ | ||
387 | if (port->pcie_type != PCI_EXP_TYPE_RC_EC || !bus) | ||
388 | return; | ||
389 | |||
390 | down_read(&pci_bus_sem); | ||
391 | list_for_each_entry(dev, &bus->devices, bus_list) | ||
392 | if (pci_is_pcie(dev) | ||
393 | && dev->pcie_type == PCI_EXP_TYPE_RC_END) | ||
394 | pcie_pme_set_native(dev, NULL); | ||
395 | up_read(&pci_bus_sem); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | /** | ||
400 | * pcie_pme_probe - Initialize PCIe PME service for given root port. | ||
401 | * @srv: PCIe service to initialize. | ||
402 | */ | ||
403 | static int pcie_pme_probe(struct pcie_device *srv) | ||
404 | { | ||
405 | struct pci_dev *port; | ||
406 | struct pcie_pme_service_data *data; | ||
407 | int ret; | ||
408 | |||
409 | if (!pcie_pme_platform_setup(srv)) | ||
410 | return -EACCES; | ||
411 | |||
412 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
413 | if (!data) | ||
414 | return -ENOMEM; | ||
415 | |||
416 | spin_lock_init(&data->lock); | ||
417 | INIT_WORK(&data->work, pcie_pme_work_fn); | ||
418 | data->srv = srv; | ||
419 | set_service_data(srv, data); | ||
420 | |||
421 | port = srv->port; | ||
422 | pcie_pme_interrupt_enable(port, false); | ||
423 | pcie_pme_clear_status(port); | ||
424 | |||
425 | ret = request_irq(srv->irq, pcie_pme_irq, IRQF_SHARED, "PCIe PME", srv); | ||
426 | if (ret) { | ||
427 | kfree(data); | ||
428 | } else { | ||
429 | pcie_pme_mark_devices(port); | ||
430 | pcie_pme_interrupt_enable(port, true); | ||
431 | } | ||
432 | |||
433 | return ret; | ||
434 | } | ||
435 | |||
436 | /** | ||
437 | * pcie_pme_suspend - Suspend PCIe PME service device. | ||
438 | * @srv: PCIe service device to suspend. | ||
439 | */ | ||
440 | static int pcie_pme_suspend(struct pcie_device *srv) | ||
441 | { | ||
442 | struct pcie_pme_service_data *data = get_service_data(srv); | ||
443 | struct pci_dev *port = srv->port; | ||
444 | |||
445 | spin_lock_irq(&data->lock); | ||
446 | pcie_pme_interrupt_enable(port, false); | ||
447 | pcie_pme_clear_status(port); | ||
448 | data->noirq = true; | ||
449 | spin_unlock_irq(&data->lock); | ||
450 | |||
451 | synchronize_irq(srv->irq); | ||
452 | |||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | /** | ||
457 | * pcie_pme_resume - Resume PCIe PME service device. | ||
458 | * @srv - PCIe service device to resume. | ||
459 | */ | ||
460 | static int pcie_pme_resume(struct pcie_device *srv) | ||
461 | { | ||
462 | struct pcie_pme_service_data *data = get_service_data(srv); | ||
463 | struct pci_dev *port = srv->port; | ||
464 | |||
465 | spin_lock_irq(&data->lock); | ||
466 | data->noirq = false; | ||
467 | pcie_pme_clear_status(port); | ||
468 | pcie_pme_interrupt_enable(port, true); | ||
469 | spin_unlock_irq(&data->lock); | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | /** | ||
475 | * pcie_pme_remove - Prepare PCIe PME service device for removal. | ||
476 | * @srv - PCIe service device to resume. | ||
477 | */ | ||
478 | static void pcie_pme_remove(struct pcie_device *srv) | ||
479 | { | ||
480 | pcie_pme_suspend(srv); | ||
481 | free_irq(srv->irq, srv); | ||
482 | kfree(get_service_data(srv)); | ||
483 | } | ||
484 | |||
485 | static struct pcie_port_service_driver pcie_pme_driver = { | ||
486 | .name = "pcie_pme", | ||
487 | .port_type = PCI_EXP_TYPE_ROOT_PORT, | ||
488 | .service = PCIE_PORT_SERVICE_PME, | ||
489 | |||
490 | .probe = pcie_pme_probe, | ||
491 | .suspend = pcie_pme_suspend, | ||
492 | .resume = pcie_pme_resume, | ||
493 | .remove = pcie_pme_remove, | ||
494 | }; | ||
495 | |||
496 | /** | ||
497 | * pcie_pme_service_init - Register the PCIe PME service driver. | ||
498 | */ | ||
499 | static int __init pcie_pme_service_init(void) | ||
500 | { | ||
501 | return pcie_pme_disabled ? | ||
502 | -ENODEV : pcie_port_service_register(&pcie_pme_driver); | ||
503 | } | ||
504 | |||
505 | module_init(pcie_pme_service_init); | ||
diff --git a/drivers/pci/pcie/pme/pcie_pme.h b/drivers/pci/pcie/pme/pcie_pme.h new file mode 100644 index 00000000000..b30d2b7c977 --- /dev/null +++ b/drivers/pci/pcie/pme/pcie_pme.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * drivers/pci/pcie/pme/pcie_pme.h | ||
3 | * | ||
4 | * PCI Express Root Port PME signaling support | ||
5 | * | ||
6 | * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
7 | */ | ||
8 | |||
9 | #ifndef _PCIE_PME_H_ | ||
10 | #define _PCIE_PME_H_ | ||
11 | |||
12 | struct pcie_device; | ||
13 | |||
14 | #ifdef CONFIG_ACPI | ||
15 | extern int pcie_pme_acpi_setup(struct pcie_device *srv); | ||
16 | |||
17 | static inline int pcie_pme_platform_notify(struct pcie_device *srv) | ||
18 | { | ||
19 | return pcie_pme_acpi_setup(srv); | ||
20 | } | ||
21 | #else /* !CONFIG_ACPI */ | ||
22 | static inline int pcie_pme_platform_notify(struct pcie_device *srv) | ||
23 | { | ||
24 | return 0; | ||
25 | } | ||
26 | #endif /* !CONFIG_ACPI */ | ||
27 | |||
28 | #endif | ||
diff --git a/drivers/pci/pcie/pme/pcie_pme_acpi.c b/drivers/pci/pcie/pme/pcie_pme_acpi.c new file mode 100644 index 00000000000..83ab2287ae3 --- /dev/null +++ b/drivers/pci/pcie/pme/pcie_pme_acpi.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * PCIe Native PME support, ACPI-related part | ||
3 | * | ||
4 | * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License V2. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/pci.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/acpi.h> | ||
15 | #include <linux/pci-acpi.h> | ||
16 | #include <linux/pcieport_if.h> | ||
17 | |||
18 | /** | ||
19 | * pcie_pme_acpi_setup - Request the ACPI BIOS to release control over PCIe PME. | ||
20 | * @srv - PCIe PME service for a root port or event collector. | ||
21 | * | ||
22 | * Invoked when the PCIe bus type loads PCIe PME service driver. To avoid | ||
23 | * conflict with the BIOS PCIe support requires the BIOS to yield PCIe PME | ||
24 | * control to the kernel. | ||
25 | */ | ||
26 | int pcie_pme_acpi_setup(struct pcie_device *srv) | ||
27 | { | ||
28 | acpi_status status = AE_NOT_FOUND; | ||
29 | struct pci_dev *port = srv->port; | ||
30 | acpi_handle handle; | ||
31 | int error = 0; | ||
32 | |||
33 | if (acpi_pci_disabled) | ||
34 | return -ENOSYS; | ||
35 | |||
36 | dev_info(&port->dev, "Requesting control of PCIe PME from ACPI BIOS\n"); | ||
37 | |||
38 | handle = acpi_find_root_bridge_handle(port); | ||
39 | if (!handle) | ||
40 | return -EINVAL; | ||
41 | |||
42 | status = acpi_pci_osc_control_set(handle, | ||
43 | OSC_PCI_EXPRESS_PME_CONTROL | | ||
44 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | ||
45 | if (ACPI_FAILURE(status)) { | ||
46 | dev_info(&port->dev, | ||
47 | "Failed to receive control of PCIe PME service: %s\n", | ||
48 | (status == AE_SUPPORT || status == AE_NOT_FOUND) ? | ||
49 | "no _OSC support" : "ACPI _OSC failed"); | ||
50 | error = -ENODEV; | ||
51 | } | ||
52 | |||
53 | return error; | ||
54 | } | ||
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index aaeb9d21cba..813a5c3427b 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h | |||
@@ -30,4 +30,21 @@ extern void pcie_port_device_remove(struct pci_dev *dev); | |||
30 | extern int __must_check pcie_port_bus_register(void); | 30 | extern int __must_check pcie_port_bus_register(void); |
31 | extern void pcie_port_bus_unregister(void); | 31 | extern void pcie_port_bus_unregister(void); |
32 | 32 | ||
33 | #ifdef CONFIG_PCIE_PME | ||
34 | extern bool pcie_pme_msi_disabled; | ||
35 | |||
36 | static inline void pcie_pme_disable_msi(void) | ||
37 | { | ||
38 | pcie_pme_msi_disabled = true; | ||
39 | } | ||
40 | |||
41 | static inline bool pcie_pme_no_msi(void) | ||
42 | { | ||
43 | return pcie_pme_msi_disabled; | ||
44 | } | ||
45 | #else /* !CONFIG_PCIE_PME */ | ||
46 | static inline void pcie_pme_disable_msi(void) {} | ||
47 | static inline bool pcie_pme_no_msi(void) { return false; } | ||
48 | #endif /* !CONFIG_PCIE_PME */ | ||
49 | |||
33 | #endif /* _PORTDRV_H_ */ | 50 | #endif /* _PORTDRV_H_ */ |
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index b174188ac12..0d34ff41539 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
@@ -186,16 +186,24 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask) | |||
186 | */ | 186 | */ |
187 | static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask) | 187 | static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask) |
188 | { | 188 | { |
189 | int i, irq; | 189 | int i, irq = -1; |
190 | |||
191 | /* We have to use INTx if MSI cannot be used for PCIe PME. */ | ||
192 | if ((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi()) { | ||
193 | if (dev->pin) | ||
194 | irq = dev->irq; | ||
195 | goto no_msi; | ||
196 | } | ||
190 | 197 | ||
191 | /* Try to use MSI-X if supported */ | 198 | /* Try to use MSI-X if supported */ |
192 | if (!pcie_port_enable_msix(dev, irqs, mask)) | 199 | if (!pcie_port_enable_msix(dev, irqs, mask)) |
193 | return 0; | 200 | return 0; |
201 | |||
194 | /* We're not going to use MSI-X, so try MSI and fall back to INTx */ | 202 | /* We're not going to use MSI-X, so try MSI and fall back to INTx */ |
195 | irq = -1; | ||
196 | if (!pci_enable_msi(dev) || dev->pin) | 203 | if (!pci_enable_msi(dev) || dev->pin) |
197 | irq = dev->irq; | 204 | irq = dev->irq; |
198 | 205 | ||
206 | no_msi: | ||
199 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) | 207 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) |
200 | irqs[i] = irq; | 208 | irqs[i] = irq; |
201 | irqs[PCIE_PORT_SERVICE_VC_SHIFT] = -1; | 209 | irqs[PCIE_PORT_SERVICE_VC_SHIFT] = -1; |
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 13c8972886e..127e8f169d9 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/pcieport_if.h> | 16 | #include <linux/pcieport_if.h> |
17 | #include <linux/aer.h> | 17 | #include <linux/aer.h> |
18 | #include <linux/dmi.h> | ||
18 | 19 | ||
19 | #include "portdrv.h" | 20 | #include "portdrv.h" |
20 | #include "aer/aerdrv.h" | 21 | #include "aer/aerdrv.h" |
@@ -273,10 +274,36 @@ static struct pci_driver pcie_portdriver = { | |||
273 | .driver.pm = PCIE_PORTDRV_PM_OPS, | 274 | .driver.pm = PCIE_PORTDRV_PM_OPS, |
274 | }; | 275 | }; |
275 | 276 | ||
277 | static int __init dmi_pcie_pme_disable_msi(const struct dmi_system_id *d) | ||
278 | { | ||
279 | pr_notice("%s detected: will not use MSI for PCIe PME signaling\n", | ||
280 | d->ident); | ||
281 | pcie_pme_disable_msi(); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static struct dmi_system_id __initdata pcie_portdrv_dmi_table[] = { | ||
286 | /* | ||
287 | * Boxes that should not use MSI for PCIe PME signaling. | ||
288 | */ | ||
289 | { | ||
290 | .callback = dmi_pcie_pme_disable_msi, | ||
291 | .ident = "MSI Wind U-100", | ||
292 | .matches = { | ||
293 | DMI_MATCH(DMI_SYS_VENDOR, | ||
294 | "MICRO-STAR INTERNATIONAL CO., LTD"), | ||
295 | DMI_MATCH(DMI_PRODUCT_NAME, "U-100"), | ||
296 | }, | ||
297 | }, | ||
298 | {} | ||
299 | }; | ||
300 | |||
276 | static int __init pcie_portdrv_init(void) | 301 | static int __init pcie_portdrv_init(void) |
277 | { | 302 | { |
278 | int retval; | 303 | int retval; |
279 | 304 | ||
305 | dmi_check_system(pcie_portdrv_dmi_table); | ||
306 | |||
280 | retval = pcie_port_bus_register(); | 307 | retval = pcie_port_bus_register(); |
281 | if (retval) { | 308 | if (retval) { |
282 | printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval); | 309 | printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval); |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 446e4a94d7d..270d069819f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -89,6 +89,7 @@ static void release_pcibus_dev(struct device *dev) | |||
89 | 89 | ||
90 | if (pci_bus->bridge) | 90 | if (pci_bus->bridge) |
91 | put_device(pci_bus->bridge); | 91 | put_device(pci_bus->bridge); |
92 | pci_bus_remove_resources(pci_bus); | ||
92 | kfree(pci_bus); | 93 | kfree(pci_bus); |
93 | } | 94 | } |
94 | 95 | ||
@@ -281,26 +282,12 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) | |||
281 | } | 282 | } |
282 | } | 283 | } |
283 | 284 | ||
284 | void __devinit pci_read_bridge_bases(struct pci_bus *child) | 285 | static void __devinit pci_read_bridge_io(struct pci_bus *child) |
285 | { | 286 | { |
286 | struct pci_dev *dev = child->self; | 287 | struct pci_dev *dev = child->self; |
287 | u8 io_base_lo, io_limit_lo; | 288 | u8 io_base_lo, io_limit_lo; |
288 | u16 mem_base_lo, mem_limit_lo; | ||
289 | unsigned long base, limit; | 289 | unsigned long base, limit; |
290 | struct resource *res; | 290 | struct resource *res; |
291 | int i; | ||
292 | |||
293 | if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */ | ||
294 | return; | ||
295 | |||
296 | dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n", | ||
297 | child->secondary, child->subordinate, | ||
298 | dev->transparent ? " (subtractive decode)": ""); | ||
299 | |||
300 | if (dev->transparent) { | ||
301 | for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++) | ||
302 | child->resource[i] = child->parent->resource[i - 3]; | ||
303 | } | ||
304 | 291 | ||
305 | res = child->resource[0]; | 292 | res = child->resource[0]; |
306 | pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); | 293 | pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); |
@@ -316,26 +303,50 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) | |||
316 | limit |= (io_limit_hi << 16); | 303 | limit |= (io_limit_hi << 16); |
317 | } | 304 | } |
318 | 305 | ||
319 | if (base <= limit) { | 306 | if (base && base <= limit) { |
320 | res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; | 307 | res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; |
321 | if (!res->start) | 308 | if (!res->start) |
322 | res->start = base; | 309 | res->start = base; |
323 | if (!res->end) | 310 | if (!res->end) |
324 | res->end = limit + 0xfff; | 311 | res->end = limit + 0xfff; |
325 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); | 312 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); |
313 | } else { | ||
314 | dev_printk(KERN_DEBUG, &dev->dev, | ||
315 | " bridge window [io %04lx - %04lx] reg reading\n", | ||
316 | base, limit); | ||
326 | } | 317 | } |
318 | } | ||
319 | |||
320 | static void __devinit pci_read_bridge_mmio(struct pci_bus *child) | ||
321 | { | ||
322 | struct pci_dev *dev = child->self; | ||
323 | u16 mem_base_lo, mem_limit_lo; | ||
324 | unsigned long base, limit; | ||
325 | struct resource *res; | ||
327 | 326 | ||
328 | res = child->resource[1]; | 327 | res = child->resource[1]; |
329 | pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo); | 328 | pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo); |
330 | pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo); | 329 | pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo); |
331 | base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16; | 330 | base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16; |
332 | limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16; | 331 | limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16; |
333 | if (base <= limit) { | 332 | if (base && base <= limit) { |
334 | res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; | 333 | res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; |
335 | res->start = base; | 334 | res->start = base; |
336 | res->end = limit + 0xfffff; | 335 | res->end = limit + 0xfffff; |
337 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); | 336 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); |
337 | } else { | ||
338 | dev_printk(KERN_DEBUG, &dev->dev, | ||
339 | " bridge window [mem 0x%08lx - 0x%08lx] reg reading\n", | ||
340 | base, limit + 0xfffff); | ||
338 | } | 341 | } |
342 | } | ||
343 | |||
344 | static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child) | ||
345 | { | ||
346 | struct pci_dev *dev = child->self; | ||
347 | u16 mem_base_lo, mem_limit_lo; | ||
348 | unsigned long base, limit; | ||
349 | struct resource *res; | ||
339 | 350 | ||
340 | res = child->resource[2]; | 351 | res = child->resource[2]; |
341 | pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); | 352 | pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); |
@@ -366,7 +377,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) | |||
366 | #endif | 377 | #endif |
367 | } | 378 | } |
368 | } | 379 | } |
369 | if (base <= limit) { | 380 | if (base && base <= limit) { |
370 | res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | | 381 | res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | |
371 | IORESOURCE_MEM | IORESOURCE_PREFETCH; | 382 | IORESOURCE_MEM | IORESOURCE_PREFETCH; |
372 | if (res->flags & PCI_PREF_RANGE_TYPE_64) | 383 | if (res->flags & PCI_PREF_RANGE_TYPE_64) |
@@ -374,6 +385,44 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) | |||
374 | res->start = base; | 385 | res->start = base; |
375 | res->end = limit + 0xfffff; | 386 | res->end = limit + 0xfffff; |
376 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); | 387 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); |
388 | } else { | ||
389 | dev_printk(KERN_DEBUG, &dev->dev, | ||
390 | " bridge window [mem 0x%08lx - %08lx pref] reg reading\n", | ||
391 | base, limit + 0xfffff); | ||
392 | } | ||
393 | } | ||
394 | |||
395 | void __devinit pci_read_bridge_bases(struct pci_bus *child) | ||
396 | { | ||
397 | struct pci_dev *dev = child->self; | ||
398 | struct resource *res; | ||
399 | int i; | ||
400 | |||
401 | if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */ | ||
402 | return; | ||
403 | |||
404 | dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n", | ||
405 | child->secondary, child->subordinate, | ||
406 | dev->transparent ? " (subtractive decode)" : ""); | ||
407 | |||
408 | pci_bus_remove_resources(child); | ||
409 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) | ||
410 | child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i]; | ||
411 | |||
412 | pci_read_bridge_io(child); | ||
413 | pci_read_bridge_mmio(child); | ||
414 | pci_read_bridge_mmio_pref(child); | ||
415 | |||
416 | if (dev->transparent) { | ||
417 | pci_bus_for_each_resource(child->parent, res, i) { | ||
418 | if (res) { | ||
419 | pci_bus_add_resource(child, res, | ||
420 | PCI_SUBTRACTIVE_DECODE); | ||
421 | dev_printk(KERN_DEBUG, &dev->dev, | ||
422 | " bridge window %pR (subtractive decode)\n", | ||
423 | res); | ||
424 | } | ||
425 | } | ||
377 | } | 426 | } |
378 | } | 427 | } |
379 | 428 | ||
@@ -387,10 +436,147 @@ static struct pci_bus * pci_alloc_bus(void) | |||
387 | INIT_LIST_HEAD(&b->children); | 436 | INIT_LIST_HEAD(&b->children); |
388 | INIT_LIST_HEAD(&b->devices); | 437 | INIT_LIST_HEAD(&b->devices); |
389 | INIT_LIST_HEAD(&b->slots); | 438 | INIT_LIST_HEAD(&b->slots); |
439 | INIT_LIST_HEAD(&b->resources); | ||
440 | b->max_bus_speed = PCI_SPEED_UNKNOWN; | ||
441 | b->cur_bus_speed = PCI_SPEED_UNKNOWN; | ||
390 | } | 442 | } |
391 | return b; | 443 | return b; |
392 | } | 444 | } |
393 | 445 | ||
446 | static unsigned char pcix_bus_speed[] = { | ||
447 | PCI_SPEED_UNKNOWN, /* 0 */ | ||
448 | PCI_SPEED_66MHz_PCIX, /* 1 */ | ||
449 | PCI_SPEED_100MHz_PCIX, /* 2 */ | ||
450 | PCI_SPEED_133MHz_PCIX, /* 3 */ | ||
451 | PCI_SPEED_UNKNOWN, /* 4 */ | ||
452 | PCI_SPEED_66MHz_PCIX_ECC, /* 5 */ | ||
453 | PCI_SPEED_100MHz_PCIX_ECC, /* 6 */ | ||
454 | PCI_SPEED_133MHz_PCIX_ECC, /* 7 */ | ||
455 | PCI_SPEED_UNKNOWN, /* 8 */ | ||
456 | PCI_SPEED_66MHz_PCIX_266, /* 9 */ | ||
457 | PCI_SPEED_100MHz_PCIX_266, /* A */ | ||
458 | PCI_SPEED_133MHz_PCIX_266, /* B */ | ||
459 | PCI_SPEED_UNKNOWN, /* C */ | ||
460 | PCI_SPEED_66MHz_PCIX_533, /* D */ | ||
461 | PCI_SPEED_100MHz_PCIX_533, /* E */ | ||
462 | PCI_SPEED_133MHz_PCIX_533 /* F */ | ||
463 | }; | ||
464 | |||
465 | static unsigned char pcie_link_speed[] = { | ||
466 | PCI_SPEED_UNKNOWN, /* 0 */ | ||
467 | PCIE_SPEED_2_5GT, /* 1 */ | ||
468 | PCIE_SPEED_5_0GT, /* 2 */ | ||
469 | PCIE_SPEED_8_0GT, /* 3 */ | ||
470 | PCI_SPEED_UNKNOWN, /* 4 */ | ||
471 | PCI_SPEED_UNKNOWN, /* 5 */ | ||
472 | PCI_SPEED_UNKNOWN, /* 6 */ | ||
473 | PCI_SPEED_UNKNOWN, /* 7 */ | ||
474 | PCI_SPEED_UNKNOWN, /* 8 */ | ||
475 | PCI_SPEED_UNKNOWN, /* 9 */ | ||
476 | PCI_SPEED_UNKNOWN, /* A */ | ||
477 | PCI_SPEED_UNKNOWN, /* B */ | ||
478 | PCI_SPEED_UNKNOWN, /* C */ | ||
479 | PCI_SPEED_UNKNOWN, /* D */ | ||
480 | PCI_SPEED_UNKNOWN, /* E */ | ||
481 | PCI_SPEED_UNKNOWN /* F */ | ||
482 | }; | ||
483 | |||
484 | void pcie_update_link_speed(struct pci_bus *bus, u16 linksta) | ||
485 | { | ||
486 | bus->cur_bus_speed = pcie_link_speed[linksta & 0xf]; | ||
487 | } | ||
488 | EXPORT_SYMBOL_GPL(pcie_update_link_speed); | ||
489 | |||
490 | static unsigned char agp_speeds[] = { | ||
491 | AGP_UNKNOWN, | ||
492 | AGP_1X, | ||
493 | AGP_2X, | ||
494 | AGP_4X, | ||
495 | AGP_8X | ||
496 | }; | ||
497 | |||
498 | static enum pci_bus_speed agp_speed(int agp3, int agpstat) | ||
499 | { | ||
500 | int index = 0; | ||
501 | |||
502 | if (agpstat & 4) | ||
503 | index = 3; | ||
504 | else if (agpstat & 2) | ||
505 | index = 2; | ||
506 | else if (agpstat & 1) | ||
507 | index = 1; | ||
508 | else | ||
509 | goto out; | ||
510 | |||
511 | if (agp3) { | ||
512 | index += 2; | ||
513 | if (index == 5) | ||
514 | index = 0; | ||
515 | } | ||
516 | |||
517 | out: | ||
518 | return agp_speeds[index]; | ||
519 | } | ||
520 | |||
521 | |||
522 | static void pci_set_bus_speed(struct pci_bus *bus) | ||
523 | { | ||
524 | struct pci_dev *bridge = bus->self; | ||
525 | int pos; | ||
526 | |||
527 | pos = pci_find_capability(bridge, PCI_CAP_ID_AGP); | ||
528 | if (!pos) | ||
529 | pos = pci_find_capability(bridge, PCI_CAP_ID_AGP3); | ||
530 | if (pos) { | ||
531 | u32 agpstat, agpcmd; | ||
532 | |||
533 | pci_read_config_dword(bridge, pos + PCI_AGP_STATUS, &agpstat); | ||
534 | bus->max_bus_speed = agp_speed(agpstat & 8, agpstat & 7); | ||
535 | |||
536 | pci_read_config_dword(bridge, pos + PCI_AGP_COMMAND, &agpcmd); | ||
537 | bus->cur_bus_speed = agp_speed(agpstat & 8, agpcmd & 7); | ||
538 | } | ||
539 | |||
540 | pos = pci_find_capability(bridge, PCI_CAP_ID_PCIX); | ||
541 | if (pos) { | ||
542 | u16 status; | ||
543 | enum pci_bus_speed max; | ||
544 | pci_read_config_word(bridge, pos + 2, &status); | ||
545 | |||
546 | if (status & 0x8000) { | ||
547 | max = PCI_SPEED_133MHz_PCIX_533; | ||
548 | } else if (status & 0x4000) { | ||
549 | max = PCI_SPEED_133MHz_PCIX_266; | ||
550 | } else if (status & 0x0002) { | ||
551 | if (((status >> 12) & 0x3) == 2) { | ||
552 | max = PCI_SPEED_133MHz_PCIX_ECC; | ||
553 | } else { | ||
554 | max = PCI_SPEED_133MHz_PCIX; | ||
555 | } | ||
556 | } else { | ||
557 | max = PCI_SPEED_66MHz_PCIX; | ||
558 | } | ||
559 | |||
560 | bus->max_bus_speed = max; | ||
561 | bus->cur_bus_speed = pcix_bus_speed[(status >> 6) & 0xf]; | ||
562 | |||
563 | return; | ||
564 | } | ||
565 | |||
566 | pos = pci_find_capability(bridge, PCI_CAP_ID_EXP); | ||
567 | if (pos) { | ||
568 | u32 linkcap; | ||
569 | u16 linksta; | ||
570 | |||
571 | pci_read_config_dword(bridge, pos + PCI_EXP_LNKCAP, &linkcap); | ||
572 | bus->max_bus_speed = pcie_link_speed[linkcap & 0xf]; | ||
573 | |||
574 | pci_read_config_word(bridge, pos + PCI_EXP_LNKSTA, &linksta); | ||
575 | pcie_update_link_speed(bus, linksta); | ||
576 | } | ||
577 | } | ||
578 | |||
579 | |||
394 | static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, | 580 | static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, |
395 | struct pci_dev *bridge, int busnr) | 581 | struct pci_dev *bridge, int busnr) |
396 | { | 582 | { |
@@ -430,6 +616,8 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, | |||
430 | child->self = bridge; | 616 | child->self = bridge; |
431 | child->bridge = get_device(&bridge->dev); | 617 | child->bridge = get_device(&bridge->dev); |
432 | 618 | ||
619 | pci_set_bus_speed(child); | ||
620 | |||
433 | /* Set up default resource pointers and names.. */ | 621 | /* Set up default resource pointers and names.. */ |
434 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) { | 622 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) { |
435 | child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i]; | 623 | child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i]; |
@@ -1081,6 +1269,45 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn) | |||
1081 | } | 1269 | } |
1082 | EXPORT_SYMBOL(pci_scan_single_device); | 1270 | EXPORT_SYMBOL(pci_scan_single_device); |
1083 | 1271 | ||
1272 | static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn) | ||
1273 | { | ||
1274 | u16 cap; | ||
1275 | unsigned pos, next_fn; | ||
1276 | |||
1277 | if (!dev) | ||
1278 | return 0; | ||
1279 | |||
1280 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); | ||
1281 | if (!pos) | ||
1282 | return 0; | ||
1283 | pci_read_config_word(dev, pos + 4, &cap); | ||
1284 | next_fn = cap >> 8; | ||
1285 | if (next_fn <= fn) | ||
1286 | return 0; | ||
1287 | return next_fn; | ||
1288 | } | ||
1289 | |||
1290 | static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn) | ||
1291 | { | ||
1292 | return (fn + 1) % 8; | ||
1293 | } | ||
1294 | |||
1295 | static unsigned no_next_fn(struct pci_dev *dev, unsigned fn) | ||
1296 | { | ||
1297 | return 0; | ||
1298 | } | ||
1299 | |||
1300 | static int only_one_child(struct pci_bus *bus) | ||
1301 | { | ||
1302 | struct pci_dev *parent = bus->self; | ||
1303 | if (!parent || !pci_is_pcie(parent)) | ||
1304 | return 0; | ||
1305 | if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT || | ||
1306 | parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) | ||
1307 | return 1; | ||
1308 | return 0; | ||
1309 | } | ||
1310 | |||
1084 | /** | 1311 | /** |
1085 | * pci_scan_slot - scan a PCI slot on a bus for devices. | 1312 | * pci_scan_slot - scan a PCI slot on a bus for devices. |
1086 | * @bus: PCI bus to scan | 1313 | * @bus: PCI bus to scan |
@@ -1094,21 +1321,30 @@ EXPORT_SYMBOL(pci_scan_single_device); | |||
1094 | */ | 1321 | */ |
1095 | int pci_scan_slot(struct pci_bus *bus, int devfn) | 1322 | int pci_scan_slot(struct pci_bus *bus, int devfn) |
1096 | { | 1323 | { |
1097 | int fn, nr = 0; | 1324 | unsigned fn, nr = 0; |
1098 | struct pci_dev *dev; | 1325 | struct pci_dev *dev; |
1326 | unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn; | ||
1327 | |||
1328 | if (only_one_child(bus) && (devfn > 0)) | ||
1329 | return 0; /* Already scanned the entire slot */ | ||
1099 | 1330 | ||
1100 | dev = pci_scan_single_device(bus, devfn); | 1331 | dev = pci_scan_single_device(bus, devfn); |
1101 | if (dev && !dev->is_added) /* new device? */ | 1332 | if (!dev) |
1333 | return 0; | ||
1334 | if (!dev->is_added) | ||
1102 | nr++; | 1335 | nr++; |
1103 | 1336 | ||
1104 | if (dev && dev->multifunction) { | 1337 | if (pci_ari_enabled(bus)) |
1105 | for (fn = 1; fn < 8; fn++) { | 1338 | next_fn = next_ari_fn; |
1106 | dev = pci_scan_single_device(bus, devfn + fn); | 1339 | else if (dev->multifunction) |
1107 | if (dev) { | 1340 | next_fn = next_trad_fn; |
1108 | if (!dev->is_added) | 1341 | |
1109 | nr++; | 1342 | for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) { |
1110 | dev->multifunction = 1; | 1343 | dev = pci_scan_single_device(bus, devfn + fn); |
1111 | } | 1344 | if (dev) { |
1345 | if (!dev->is_added) | ||
1346 | nr++; | ||
1347 | dev->multifunction = 1; | ||
1112 | } | 1348 | } |
1113 | } | 1349 | } |
1114 | 1350 | ||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d58b94030ef..790eb69a4aa 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -25,14 +25,9 @@ | |||
25 | #include <linux/dmi.h> | 25 | #include <linux/dmi.h> |
26 | #include <linux/pci-aspm.h> | 26 | #include <linux/pci-aspm.h> |
27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
28 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ | ||
28 | #include "pci.h" | 29 | #include "pci.h" |
29 | 30 | ||
30 | int isa_dma_bridge_buggy; | ||
31 | EXPORT_SYMBOL(isa_dma_bridge_buggy); | ||
32 | int pci_pci_problems; | ||
33 | EXPORT_SYMBOL(pci_pci_problems); | ||
34 | |||
35 | #ifdef CONFIG_PCI_QUIRKS | ||
36 | /* | 31 | /* |
37 | * This quirk function disables memory decoding and releases memory resources | 32 | * This quirk function disables memory decoding and releases memory resources |
38 | * of the device specified by kernel's boot parameter 'pci=resource_alignment='. | 33 | * of the device specified by kernel's boot parameter 'pci=resource_alignment='. |
@@ -2612,6 +2607,7 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) | |||
2612 | } | 2607 | } |
2613 | pci_do_fixups(dev, start, end); | 2608 | pci_do_fixups(dev, start, end); |
2614 | } | 2609 | } |
2610 | EXPORT_SYMBOL(pci_fixup_device); | ||
2615 | 2611 | ||
2616 | static int __init pci_apply_final_quirks(void) | 2612 | static int __init pci_apply_final_quirks(void) |
2617 | { | 2613 | { |
@@ -2723,9 +2719,3 @@ int pci_dev_specific_reset(struct pci_dev *dev, int probe) | |||
2723 | 2719 | ||
2724 | return -ENOTTY; | 2720 | return -ENOTTY; |
2725 | } | 2721 | } |
2726 | |||
2727 | #else | ||
2728 | void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {} | ||
2729 | int pci_dev_specific_reset(struct pci_dev *dev, int probe) { return -ENOTTY; } | ||
2730 | #endif | ||
2731 | EXPORT_SYMBOL(pci_fixup_device); | ||
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index c48cd377b3f..bf32f07c4ef 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -27,37 +27,83 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include "pci.h" | 28 | #include "pci.h" |
29 | 29 | ||
30 | static void pbus_assign_resources_sorted(const struct pci_bus *bus) | 30 | struct resource_list_x { |
31 | { | 31 | struct resource_list_x *next; |
32 | struct pci_dev *dev; | ||
33 | struct resource *res; | 32 | struct resource *res; |
34 | struct resource_list head, *list, *tmp; | 33 | struct pci_dev *dev; |
35 | int idx; | 34 | resource_size_t start; |
35 | resource_size_t end; | ||
36 | unsigned long flags; | ||
37 | }; | ||
36 | 38 | ||
37 | head.next = NULL; | 39 | static void add_to_failed_list(struct resource_list_x *head, |
38 | list_for_each_entry(dev, &bus->devices, bus_list) { | 40 | struct pci_dev *dev, struct resource *res) |
39 | u16 class = dev->class >> 8; | 41 | { |
42 | struct resource_list_x *list = head; | ||
43 | struct resource_list_x *ln = list->next; | ||
44 | struct resource_list_x *tmp; | ||
40 | 45 | ||
41 | /* Don't touch classless devices or host bridges or ioapics. */ | 46 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); |
42 | if (class == PCI_CLASS_NOT_DEFINED || | 47 | if (!tmp) { |
43 | class == PCI_CLASS_BRIDGE_HOST) | 48 | pr_warning("add_to_failed_list: kmalloc() failed!\n"); |
44 | continue; | 49 | return; |
50 | } | ||
45 | 51 | ||
46 | /* Don't touch ioapic devices already enabled by firmware */ | 52 | tmp->next = ln; |
47 | if (class == PCI_CLASS_SYSTEM_PIC) { | 53 | tmp->res = res; |
48 | u16 command; | 54 | tmp->dev = dev; |
49 | pci_read_config_word(dev, PCI_COMMAND, &command); | 55 | tmp->start = res->start; |
50 | if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | 56 | tmp->end = res->end; |
51 | continue; | 57 | tmp->flags = res->flags; |
52 | } | 58 | list->next = tmp; |
59 | } | ||
60 | |||
61 | static void free_failed_list(struct resource_list_x *head) | ||
62 | { | ||
63 | struct resource_list_x *list, *tmp; | ||
53 | 64 | ||
54 | pdev_sort_resources(dev, &head); | 65 | for (list = head->next; list;) { |
66 | tmp = list; | ||
67 | list = list->next; | ||
68 | kfree(tmp); | ||
55 | } | 69 | } |
56 | 70 | ||
57 | for (list = head.next; list;) { | 71 | head->next = NULL; |
72 | } | ||
73 | |||
74 | static void __dev_sort_resources(struct pci_dev *dev, | ||
75 | struct resource_list *head) | ||
76 | { | ||
77 | u16 class = dev->class >> 8; | ||
78 | |||
79 | /* Don't touch classless devices or host bridges or ioapics. */ | ||
80 | if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST) | ||
81 | return; | ||
82 | |||
83 | /* Don't touch ioapic devices already enabled by firmware */ | ||
84 | if (class == PCI_CLASS_SYSTEM_PIC) { | ||
85 | u16 command; | ||
86 | pci_read_config_word(dev, PCI_COMMAND, &command); | ||
87 | if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | pdev_sort_resources(dev, head); | ||
92 | } | ||
93 | |||
94 | static void __assign_resources_sorted(struct resource_list *head, | ||
95 | struct resource_list_x *fail_head) | ||
96 | { | ||
97 | struct resource *res; | ||
98 | struct resource_list *list, *tmp; | ||
99 | int idx; | ||
100 | |||
101 | for (list = head->next; list;) { | ||
58 | res = list->res; | 102 | res = list->res; |
59 | idx = res - &list->dev->resource[0]; | 103 | idx = res - &list->dev->resource[0]; |
60 | if (pci_assign_resource(list->dev, idx)) { | 104 | if (pci_assign_resource(list->dev, idx)) { |
105 | if (fail_head && !pci_is_root_bus(list->dev->bus)) | ||
106 | add_to_failed_list(fail_head, list->dev, res); | ||
61 | res->start = 0; | 107 | res->start = 0; |
62 | res->end = 0; | 108 | res->end = 0; |
63 | res->flags = 0; | 109 | res->flags = 0; |
@@ -68,6 +114,30 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus) | |||
68 | } | 114 | } |
69 | } | 115 | } |
70 | 116 | ||
117 | static void pdev_assign_resources_sorted(struct pci_dev *dev, | ||
118 | struct resource_list_x *fail_head) | ||
119 | { | ||
120 | struct resource_list head; | ||
121 | |||
122 | head.next = NULL; | ||
123 | __dev_sort_resources(dev, &head); | ||
124 | __assign_resources_sorted(&head, fail_head); | ||
125 | |||
126 | } | ||
127 | |||
128 | static void pbus_assign_resources_sorted(const struct pci_bus *bus, | ||
129 | struct resource_list_x *fail_head) | ||
130 | { | ||
131 | struct pci_dev *dev; | ||
132 | struct resource_list head; | ||
133 | |||
134 | head.next = NULL; | ||
135 | list_for_each_entry(dev, &bus->devices, bus_list) | ||
136 | __dev_sort_resources(dev, &head); | ||
137 | |||
138 | __assign_resources_sorted(&head, fail_head); | ||
139 | } | ||
140 | |||
71 | void pci_setup_cardbus(struct pci_bus *bus) | 141 | void pci_setup_cardbus(struct pci_bus *bus) |
72 | { | 142 | { |
73 | struct pci_dev *bridge = bus->self; | 143 | struct pci_dev *bridge = bus->self; |
@@ -134,18 +204,12 @@ EXPORT_SYMBOL(pci_setup_cardbus); | |||
134 | config space writes, so it's quite possible that an I/O window of | 204 | config space writes, so it's quite possible that an I/O window of |
135 | the bridge will have some undesirable address (e.g. 0) after the | 205 | the bridge will have some undesirable address (e.g. 0) after the |
136 | first write. Ditto 64-bit prefetchable MMIO. */ | 206 | first write. Ditto 64-bit prefetchable MMIO. */ |
137 | static void pci_setup_bridge(struct pci_bus *bus) | 207 | static void pci_setup_bridge_io(struct pci_bus *bus) |
138 | { | 208 | { |
139 | struct pci_dev *bridge = bus->self; | 209 | struct pci_dev *bridge = bus->self; |
140 | struct resource *res; | 210 | struct resource *res; |
141 | struct pci_bus_region region; | 211 | struct pci_bus_region region; |
142 | u32 l, bu, lu, io_upper16; | 212 | u32 l, io_upper16; |
143 | |||
144 | if (pci_is_enabled(bridge)) | ||
145 | return; | ||
146 | |||
147 | dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", | ||
148 | bus->secondary, bus->subordinate); | ||
149 | 213 | ||
150 | /* Set up the top and bottom of the PCI I/O segment for this bus. */ | 214 | /* Set up the top and bottom of the PCI I/O segment for this bus. */ |
151 | res = bus->resource[0]; | 215 | res = bus->resource[0]; |
@@ -158,8 +222,7 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
158 | /* Set up upper 16 bits of I/O base/limit. */ | 222 | /* Set up upper 16 bits of I/O base/limit. */ |
159 | io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); | 223 | io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); |
160 | dev_info(&bridge->dev, " bridge window %pR\n", res); | 224 | dev_info(&bridge->dev, " bridge window %pR\n", res); |
161 | } | 225 | } else { |
162 | else { | ||
163 | /* Clear upper 16 bits of I/O base/limit. */ | 226 | /* Clear upper 16 bits of I/O base/limit. */ |
164 | io_upper16 = 0; | 227 | io_upper16 = 0; |
165 | l = 0x00f0; | 228 | l = 0x00f0; |
@@ -171,21 +234,35 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
171 | pci_write_config_dword(bridge, PCI_IO_BASE, l); | 234 | pci_write_config_dword(bridge, PCI_IO_BASE, l); |
172 | /* Update upper 16 bits of I/O base/limit. */ | 235 | /* Update upper 16 bits of I/O base/limit. */ |
173 | pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16); | 236 | pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16); |
237 | } | ||
174 | 238 | ||
175 | /* Set up the top and bottom of the PCI Memory segment | 239 | static void pci_setup_bridge_mmio(struct pci_bus *bus) |
176 | for this bus. */ | 240 | { |
241 | struct pci_dev *bridge = bus->self; | ||
242 | struct resource *res; | ||
243 | struct pci_bus_region region; | ||
244 | u32 l; | ||
245 | |||
246 | /* Set up the top and bottom of the PCI Memory segment for this bus. */ | ||
177 | res = bus->resource[1]; | 247 | res = bus->resource[1]; |
178 | pcibios_resource_to_bus(bridge, ®ion, res); | 248 | pcibios_resource_to_bus(bridge, ®ion, res); |
179 | if (res->flags & IORESOURCE_MEM) { | 249 | if (res->flags & IORESOURCE_MEM) { |
180 | l = (region.start >> 16) & 0xfff0; | 250 | l = (region.start >> 16) & 0xfff0; |
181 | l |= region.end & 0xfff00000; | 251 | l |= region.end & 0xfff00000; |
182 | dev_info(&bridge->dev, " bridge window %pR\n", res); | 252 | dev_info(&bridge->dev, " bridge window %pR\n", res); |
183 | } | 253 | } else { |
184 | else { | ||
185 | l = 0x0000fff0; | 254 | l = 0x0000fff0; |
186 | dev_info(&bridge->dev, " bridge window [mem disabled]\n"); | 255 | dev_info(&bridge->dev, " bridge window [mem disabled]\n"); |
187 | } | 256 | } |
188 | pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); | 257 | pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); |
258 | } | ||
259 | |||
260 | static void pci_setup_bridge_mmio_pref(struct pci_bus *bus) | ||
261 | { | ||
262 | struct pci_dev *bridge = bus->self; | ||
263 | struct resource *res; | ||
264 | struct pci_bus_region region; | ||
265 | u32 l, bu, lu; | ||
189 | 266 | ||
190 | /* Clear out the upper 32 bits of PREF limit. | 267 | /* Clear out the upper 32 bits of PREF limit. |
191 | If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily | 268 | If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily |
@@ -204,8 +281,7 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
204 | lu = upper_32_bits(region.end); | 281 | lu = upper_32_bits(region.end); |
205 | } | 282 | } |
206 | dev_info(&bridge->dev, " bridge window %pR\n", res); | 283 | dev_info(&bridge->dev, " bridge window %pR\n", res); |
207 | } | 284 | } else { |
208 | else { | ||
209 | l = 0x0000fff0; | 285 | l = 0x0000fff0; |
210 | dev_info(&bridge->dev, " bridge window [mem pref disabled]\n"); | 286 | dev_info(&bridge->dev, " bridge window [mem pref disabled]\n"); |
211 | } | 287 | } |
@@ -214,10 +290,35 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
214 | /* Set the upper 32 bits of PREF base & limit. */ | 290 | /* Set the upper 32 bits of PREF base & limit. */ |
215 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); | 291 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); |
216 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); | 292 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); |
293 | } | ||
294 | |||
295 | static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type) | ||
296 | { | ||
297 | struct pci_dev *bridge = bus->self; | ||
298 | |||
299 | dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", | ||
300 | bus->secondary, bus->subordinate); | ||
301 | |||
302 | if (type & IORESOURCE_IO) | ||
303 | pci_setup_bridge_io(bus); | ||
304 | |||
305 | if (type & IORESOURCE_MEM) | ||
306 | pci_setup_bridge_mmio(bus); | ||
307 | |||
308 | if (type & IORESOURCE_PREFETCH) | ||
309 | pci_setup_bridge_mmio_pref(bus); | ||
217 | 310 | ||
218 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); | 311 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); |
219 | } | 312 | } |
220 | 313 | ||
314 | static void pci_setup_bridge(struct pci_bus *bus) | ||
315 | { | ||
316 | unsigned long type = IORESOURCE_IO | IORESOURCE_MEM | | ||
317 | IORESOURCE_PREFETCH; | ||
318 | |||
319 | __pci_setup_bridge(bus, type); | ||
320 | } | ||
321 | |||
221 | /* Check whether the bridge supports optional I/O and | 322 | /* Check whether the bridge supports optional I/O and |
222 | prefetchable memory ranges. If not, the respective | 323 | prefetchable memory ranges. If not, the respective |
223 | base/limit registers must be read-only and read as 0. */ | 324 | base/limit registers must be read-only and read as 0. */ |
@@ -253,8 +354,11 @@ static void pci_bridge_check_ranges(struct pci_bus *bus) | |||
253 | } | 354 | } |
254 | if (pmem) { | 355 | if (pmem) { |
255 | b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; | 356 | b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; |
256 | if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) | 357 | if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == |
358 | PCI_PREF_RANGE_TYPE_64) { | ||
257 | b_res[2].flags |= IORESOURCE_MEM_64; | 359 | b_res[2].flags |= IORESOURCE_MEM_64; |
360 | b_res[2].flags |= PCI_PREF_RANGE_TYPE_64; | ||
361 | } | ||
258 | } | 362 | } |
259 | 363 | ||
260 | /* double check if bridge does support 64 bit pref */ | 364 | /* double check if bridge does support 64 bit pref */ |
@@ -283,8 +387,7 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon | |||
283 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | 387 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | |
284 | IORESOURCE_PREFETCH; | 388 | IORESOURCE_PREFETCH; |
285 | 389 | ||
286 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 390 | pci_bus_for_each_resource(bus, r, i) { |
287 | r = bus->resource[i]; | ||
288 | if (r == &ioport_resource || r == &iomem_resource) | 391 | if (r == &ioport_resource || r == &iomem_resource) |
289 | continue; | 392 | continue; |
290 | if (r && (r->flags & type_mask) == type && !r->parent) | 393 | if (r && (r->flags & type_mask) == type && !r->parent) |
@@ -301,7 +404,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | |||
301 | { | 404 | { |
302 | struct pci_dev *dev; | 405 | struct pci_dev *dev; |
303 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); | 406 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); |
304 | unsigned long size = 0, size1 = 0; | 407 | unsigned long size = 0, size1 = 0, old_size; |
305 | 408 | ||
306 | if (!b_res) | 409 | if (!b_res) |
307 | return; | 410 | return; |
@@ -326,12 +429,17 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | |||
326 | } | 429 | } |
327 | if (size < min_size) | 430 | if (size < min_size) |
328 | size = min_size; | 431 | size = min_size; |
432 | old_size = resource_size(b_res); | ||
433 | if (old_size == 1) | ||
434 | old_size = 0; | ||
329 | /* To be fixed in 2.5: we should have sort of HAVE_ISA | 435 | /* To be fixed in 2.5: we should have sort of HAVE_ISA |
330 | flag in the struct pci_bus. */ | 436 | flag in the struct pci_bus. */ |
331 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) | 437 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) |
332 | size = (size & 0xff) + ((size & ~0xffUL) << 2); | 438 | size = (size & 0xff) + ((size & ~0xffUL) << 2); |
333 | #endif | 439 | #endif |
334 | size = ALIGN(size + size1, 4096); | 440 | size = ALIGN(size + size1, 4096); |
441 | if (size < old_size) | ||
442 | size = old_size; | ||
335 | if (!size) { | 443 | if (!size) { |
336 | if (b_res->start || b_res->end) | 444 | if (b_res->start || b_res->end) |
337 | dev_info(&bus->self->dev, "disabling bridge window " | 445 | dev_info(&bus->self->dev, "disabling bridge window " |
@@ -352,7 +460,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
352 | unsigned long type, resource_size_t min_size) | 460 | unsigned long type, resource_size_t min_size) |
353 | { | 461 | { |
354 | struct pci_dev *dev; | 462 | struct pci_dev *dev; |
355 | resource_size_t min_align, align, size; | 463 | resource_size_t min_align, align, size, old_size; |
356 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ | 464 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ |
357 | int order, max_order; | 465 | int order, max_order; |
358 | struct resource *b_res = find_free_bus_resource(bus, type); | 466 | struct resource *b_res = find_free_bus_resource(bus, type); |
@@ -402,6 +510,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
402 | } | 510 | } |
403 | if (size < min_size) | 511 | if (size < min_size) |
404 | size = min_size; | 512 | size = min_size; |
513 | old_size = resource_size(b_res); | ||
514 | if (old_size == 1) | ||
515 | old_size = 0; | ||
516 | if (size < old_size) | ||
517 | size = old_size; | ||
405 | 518 | ||
406 | align = 0; | 519 | align = 0; |
407 | min_align = 0; | 520 | min_align = 0; |
@@ -538,23 +651,25 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
538 | } | 651 | } |
539 | EXPORT_SYMBOL(pci_bus_size_bridges); | 652 | EXPORT_SYMBOL(pci_bus_size_bridges); |
540 | 653 | ||
541 | void __ref pci_bus_assign_resources(const struct pci_bus *bus) | 654 | static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, |
655 | struct resource_list_x *fail_head) | ||
542 | { | 656 | { |
543 | struct pci_bus *b; | 657 | struct pci_bus *b; |
544 | struct pci_dev *dev; | 658 | struct pci_dev *dev; |
545 | 659 | ||
546 | pbus_assign_resources_sorted(bus); | 660 | pbus_assign_resources_sorted(bus, fail_head); |
547 | 661 | ||
548 | list_for_each_entry(dev, &bus->devices, bus_list) { | 662 | list_for_each_entry(dev, &bus->devices, bus_list) { |
549 | b = dev->subordinate; | 663 | b = dev->subordinate; |
550 | if (!b) | 664 | if (!b) |
551 | continue; | 665 | continue; |
552 | 666 | ||
553 | pci_bus_assign_resources(b); | 667 | __pci_bus_assign_resources(b, fail_head); |
554 | 668 | ||
555 | switch (dev->class >> 8) { | 669 | switch (dev->class >> 8) { |
556 | case PCI_CLASS_BRIDGE_PCI: | 670 | case PCI_CLASS_BRIDGE_PCI: |
557 | pci_setup_bridge(b); | 671 | if (!pci_is_enabled(dev)) |
672 | pci_setup_bridge(b); | ||
558 | break; | 673 | break; |
559 | 674 | ||
560 | case PCI_CLASS_BRIDGE_CARDBUS: | 675 | case PCI_CLASS_BRIDGE_CARDBUS: |
@@ -568,15 +683,130 @@ void __ref pci_bus_assign_resources(const struct pci_bus *bus) | |||
568 | } | 683 | } |
569 | } | 684 | } |
570 | } | 685 | } |
686 | |||
687 | void __ref pci_bus_assign_resources(const struct pci_bus *bus) | ||
688 | { | ||
689 | __pci_bus_assign_resources(bus, NULL); | ||
690 | } | ||
571 | EXPORT_SYMBOL(pci_bus_assign_resources); | 691 | EXPORT_SYMBOL(pci_bus_assign_resources); |
572 | 692 | ||
693 | static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge, | ||
694 | struct resource_list_x *fail_head) | ||
695 | { | ||
696 | struct pci_bus *b; | ||
697 | |||
698 | pdev_assign_resources_sorted((struct pci_dev *)bridge, fail_head); | ||
699 | |||
700 | b = bridge->subordinate; | ||
701 | if (!b) | ||
702 | return; | ||
703 | |||
704 | __pci_bus_assign_resources(b, fail_head); | ||
705 | |||
706 | switch (bridge->class >> 8) { | ||
707 | case PCI_CLASS_BRIDGE_PCI: | ||
708 | pci_setup_bridge(b); | ||
709 | break; | ||
710 | |||
711 | case PCI_CLASS_BRIDGE_CARDBUS: | ||
712 | pci_setup_cardbus(b); | ||
713 | break; | ||
714 | |||
715 | default: | ||
716 | dev_info(&bridge->dev, "not setting up bridge for bus " | ||
717 | "%04x:%02x\n", pci_domain_nr(b), b->number); | ||
718 | break; | ||
719 | } | ||
720 | } | ||
721 | static void pci_bridge_release_resources(struct pci_bus *bus, | ||
722 | unsigned long type) | ||
723 | { | ||
724 | int idx; | ||
725 | bool changed = false; | ||
726 | struct pci_dev *dev; | ||
727 | struct resource *r; | ||
728 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
729 | IORESOURCE_PREFETCH; | ||
730 | |||
731 | dev = bus->self; | ||
732 | for (idx = PCI_BRIDGE_RESOURCES; idx <= PCI_BRIDGE_RESOURCE_END; | ||
733 | idx++) { | ||
734 | r = &dev->resource[idx]; | ||
735 | if ((r->flags & type_mask) != type) | ||
736 | continue; | ||
737 | if (!r->parent) | ||
738 | continue; | ||
739 | /* | ||
740 | * if there are children under that, we should release them | ||
741 | * all | ||
742 | */ | ||
743 | release_child_resources(r); | ||
744 | if (!release_resource(r)) { | ||
745 | dev_printk(KERN_DEBUG, &dev->dev, | ||
746 | "resource %d %pR released\n", idx, r); | ||
747 | /* keep the old size */ | ||
748 | r->end = resource_size(r) - 1; | ||
749 | r->start = 0; | ||
750 | r->flags = 0; | ||
751 | changed = true; | ||
752 | } | ||
753 | } | ||
754 | |||
755 | if (changed) { | ||
756 | /* avoiding touch the one without PREF */ | ||
757 | if (type & IORESOURCE_PREFETCH) | ||
758 | type = IORESOURCE_PREFETCH; | ||
759 | __pci_setup_bridge(bus, type); | ||
760 | } | ||
761 | } | ||
762 | |||
763 | enum release_type { | ||
764 | leaf_only, | ||
765 | whole_subtree, | ||
766 | }; | ||
767 | /* | ||
768 | * try to release pci bridge resources that is from leaf bridge, | ||
769 | * so we can allocate big new one later | ||
770 | */ | ||
771 | static void __ref pci_bus_release_bridge_resources(struct pci_bus *bus, | ||
772 | unsigned long type, | ||
773 | enum release_type rel_type) | ||
774 | { | ||
775 | struct pci_dev *dev; | ||
776 | bool is_leaf_bridge = true; | ||
777 | |||
778 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
779 | struct pci_bus *b = dev->subordinate; | ||
780 | if (!b) | ||
781 | continue; | ||
782 | |||
783 | is_leaf_bridge = false; | ||
784 | |||
785 | if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) | ||
786 | continue; | ||
787 | |||
788 | if (rel_type == whole_subtree) | ||
789 | pci_bus_release_bridge_resources(b, type, | ||
790 | whole_subtree); | ||
791 | } | ||
792 | |||
793 | if (pci_is_root_bus(bus)) | ||
794 | return; | ||
795 | |||
796 | if ((bus->self->class >> 8) != PCI_CLASS_BRIDGE_PCI) | ||
797 | return; | ||
798 | |||
799 | if ((rel_type == whole_subtree) || is_leaf_bridge) | ||
800 | pci_bridge_release_resources(bus, type); | ||
801 | } | ||
802 | |||
573 | static void pci_bus_dump_res(struct pci_bus *bus) | 803 | static void pci_bus_dump_res(struct pci_bus *bus) |
574 | { | 804 | { |
575 | int i; | 805 | struct resource *res; |
806 | int i; | ||
576 | 807 | ||
577 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 808 | pci_bus_for_each_resource(bus, res, i) { |
578 | struct resource *res = bus->resource[i]; | 809 | if (!res || !res->end || !res->flags) |
579 | if (!res || !res->end) | ||
580 | continue; | 810 | continue; |
581 | 811 | ||
582 | dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res); | 812 | dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res); |
@@ -600,11 +830,65 @@ static void pci_bus_dump_resources(struct pci_bus *bus) | |||
600 | } | 830 | } |
601 | } | 831 | } |
602 | 832 | ||
833 | static int __init pci_bus_get_depth(struct pci_bus *bus) | ||
834 | { | ||
835 | int depth = 0; | ||
836 | struct pci_dev *dev; | ||
837 | |||
838 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
839 | int ret; | ||
840 | struct pci_bus *b = dev->subordinate; | ||
841 | if (!b) | ||
842 | continue; | ||
843 | |||
844 | ret = pci_bus_get_depth(b); | ||
845 | if (ret + 1 > depth) | ||
846 | depth = ret + 1; | ||
847 | } | ||
848 | |||
849 | return depth; | ||
850 | } | ||
851 | static int __init pci_get_max_depth(void) | ||
852 | { | ||
853 | int depth = 0; | ||
854 | struct pci_bus *bus; | ||
855 | |||
856 | list_for_each_entry(bus, &pci_root_buses, node) { | ||
857 | int ret; | ||
858 | |||
859 | ret = pci_bus_get_depth(bus); | ||
860 | if (ret > depth) | ||
861 | depth = ret; | ||
862 | } | ||
863 | |||
864 | return depth; | ||
865 | } | ||
866 | |||
867 | /* | ||
868 | * first try will not touch pci bridge res | ||
869 | * second and later try will clear small leaf bridge res | ||
870 | * will stop till to the max deepth if can not find good one | ||
871 | */ | ||
603 | void __init | 872 | void __init |
604 | pci_assign_unassigned_resources(void) | 873 | pci_assign_unassigned_resources(void) |
605 | { | 874 | { |
606 | struct pci_bus *bus; | 875 | struct pci_bus *bus; |
876 | int tried_times = 0; | ||
877 | enum release_type rel_type = leaf_only; | ||
878 | struct resource_list_x head, *list; | ||
879 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
880 | IORESOURCE_PREFETCH; | ||
881 | unsigned long failed_type; | ||
882 | int max_depth = pci_get_max_depth(); | ||
883 | int pci_try_num; | ||
607 | 884 | ||
885 | head.next = NULL; | ||
886 | |||
887 | pci_try_num = max_depth + 1; | ||
888 | printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n", | ||
889 | max_depth, pci_try_num); | ||
890 | |||
891 | again: | ||
608 | /* Depth first, calculate sizes and alignments of all | 892 | /* Depth first, calculate sizes and alignments of all |
609 | subordinate buses. */ | 893 | subordinate buses. */ |
610 | list_for_each_entry(bus, &pci_root_buses, node) { | 894 | list_for_each_entry(bus, &pci_root_buses, node) { |
@@ -612,12 +896,130 @@ pci_assign_unassigned_resources(void) | |||
612 | } | 896 | } |
613 | /* Depth last, allocate resources and update the hardware. */ | 897 | /* Depth last, allocate resources and update the hardware. */ |
614 | list_for_each_entry(bus, &pci_root_buses, node) { | 898 | list_for_each_entry(bus, &pci_root_buses, node) { |
615 | pci_bus_assign_resources(bus); | 899 | __pci_bus_assign_resources(bus, &head); |
616 | pci_enable_bridges(bus); | ||
617 | } | 900 | } |
901 | tried_times++; | ||
902 | |||
903 | /* any device complain? */ | ||
904 | if (!head.next) | ||
905 | goto enable_and_dump; | ||
906 | failed_type = 0; | ||
907 | for (list = head.next; list;) { | ||
908 | failed_type |= list->flags; | ||
909 | list = list->next; | ||
910 | } | ||
911 | /* | ||
912 | * io port are tight, don't try extra | ||
913 | * or if reach the limit, don't want to try more | ||
914 | */ | ||
915 | failed_type &= type_mask; | ||
916 | if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) { | ||
917 | free_failed_list(&head); | ||
918 | goto enable_and_dump; | ||
919 | } | ||
920 | |||
921 | printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", | ||
922 | tried_times + 1); | ||
923 | |||
924 | /* third times and later will not check if it is leaf */ | ||
925 | if ((tried_times + 1) > 2) | ||
926 | rel_type = whole_subtree; | ||
927 | |||
928 | /* | ||
929 | * Try to release leaf bridge's resources that doesn't fit resource of | ||
930 | * child device under that bridge | ||
931 | */ | ||
932 | for (list = head.next; list;) { | ||
933 | bus = list->dev->bus; | ||
934 | pci_bus_release_bridge_resources(bus, list->flags & type_mask, | ||
935 | rel_type); | ||
936 | list = list->next; | ||
937 | } | ||
938 | /* restore size and flags */ | ||
939 | for (list = head.next; list;) { | ||
940 | struct resource *res = list->res; | ||
941 | |||
942 | res->start = list->start; | ||
943 | res->end = list->end; | ||
944 | res->flags = list->flags; | ||
945 | if (list->dev->subordinate) | ||
946 | res->flags = 0; | ||
947 | |||
948 | list = list->next; | ||
949 | } | ||
950 | free_failed_list(&head); | ||
951 | |||
952 | goto again; | ||
953 | |||
954 | enable_and_dump: | ||
955 | /* Depth last, update the hardware. */ | ||
956 | list_for_each_entry(bus, &pci_root_buses, node) | ||
957 | pci_enable_bridges(bus); | ||
618 | 958 | ||
619 | /* dump the resource on buses */ | 959 | /* dump the resource on buses */ |
620 | list_for_each_entry(bus, &pci_root_buses, node) { | 960 | list_for_each_entry(bus, &pci_root_buses, node) { |
621 | pci_bus_dump_resources(bus); | 961 | pci_bus_dump_resources(bus); |
622 | } | 962 | } |
623 | } | 963 | } |
964 | |||
965 | void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) | ||
966 | { | ||
967 | struct pci_bus *parent = bridge->subordinate; | ||
968 | int tried_times = 0; | ||
969 | struct resource_list_x head, *list; | ||
970 | int retval; | ||
971 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
972 | IORESOURCE_PREFETCH; | ||
973 | |||
974 | head.next = NULL; | ||
975 | |||
976 | again: | ||
977 | pci_bus_size_bridges(parent); | ||
978 | __pci_bridge_assign_resources(bridge, &head); | ||
979 | retval = pci_reenable_device(bridge); | ||
980 | pci_set_master(bridge); | ||
981 | pci_enable_bridges(parent); | ||
982 | |||
983 | tried_times++; | ||
984 | |||
985 | if (!head.next) | ||
986 | return; | ||
987 | |||
988 | if (tried_times >= 2) { | ||
989 | /* still fail, don't need to try more */ | ||
990 | free_failed_list(&head); | ||
991 | return; | ||
992 | } | ||
993 | |||
994 | printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", | ||
995 | tried_times + 1); | ||
996 | |||
997 | /* | ||
998 | * Try to release leaf bridge's resources that doesn't fit resource of | ||
999 | * child device under that bridge | ||
1000 | */ | ||
1001 | for (list = head.next; list;) { | ||
1002 | struct pci_bus *bus = list->dev->bus; | ||
1003 | unsigned long flags = list->flags; | ||
1004 | |||
1005 | pci_bus_release_bridge_resources(bus, flags & type_mask, | ||
1006 | whole_subtree); | ||
1007 | list = list->next; | ||
1008 | } | ||
1009 | /* restore size and flags */ | ||
1010 | for (list = head.next; list;) { | ||
1011 | struct resource *res = list->res; | ||
1012 | |||
1013 | res->start = list->start; | ||
1014 | res->end = list->end; | ||
1015 | res->flags = list->flags; | ||
1016 | if (list->dev->subordinate) | ||
1017 | res->flags = 0; | ||
1018 | |||
1019 | list = list->next; | ||
1020 | } | ||
1021 | free_failed_list(&head); | ||
1022 | |||
1023 | goto again; | ||
1024 | } | ||
1025 | EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); | ||
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index 8c02b6c53bd..49c9e6c9779 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c | |||
@@ -47,6 +47,55 @@ static ssize_t address_read_file(struct pci_slot *slot, char *buf) | |||
47 | slot->number); | 47 | slot->number); |
48 | } | 48 | } |
49 | 49 | ||
50 | /* these strings match up with the values in pci_bus_speed */ | ||
51 | static char *pci_bus_speed_strings[] = { | ||
52 | "33 MHz PCI", /* 0x00 */ | ||
53 | "66 MHz PCI", /* 0x01 */ | ||
54 | "66 MHz PCI-X", /* 0x02 */ | ||
55 | "100 MHz PCI-X", /* 0x03 */ | ||
56 | "133 MHz PCI-X", /* 0x04 */ | ||
57 | NULL, /* 0x05 */ | ||
58 | NULL, /* 0x06 */ | ||
59 | NULL, /* 0x07 */ | ||
60 | NULL, /* 0x08 */ | ||
61 | "66 MHz PCI-X 266", /* 0x09 */ | ||
62 | "100 MHz PCI-X 266", /* 0x0a */ | ||
63 | "133 MHz PCI-X 266", /* 0x0b */ | ||
64 | "Unknown AGP", /* 0x0c */ | ||
65 | "1x AGP", /* 0x0d */ | ||
66 | "2x AGP", /* 0x0e */ | ||
67 | "4x AGP", /* 0x0f */ | ||
68 | "8x AGP", /* 0x10 */ | ||
69 | "66 MHz PCI-X 533", /* 0x11 */ | ||
70 | "100 MHz PCI-X 533", /* 0x12 */ | ||
71 | "133 MHz PCI-X 533", /* 0x13 */ | ||
72 | "2.5 GT/s PCIe", /* 0x14 */ | ||
73 | "5.0 GT/s PCIe", /* 0x15 */ | ||
74 | "8.0 GT/s PCIe", /* 0x16 */ | ||
75 | }; | ||
76 | |||
77 | static ssize_t bus_speed_read(enum pci_bus_speed speed, char *buf) | ||
78 | { | ||
79 | const char *speed_string; | ||
80 | |||
81 | if (speed < ARRAY_SIZE(pci_bus_speed_strings)) | ||
82 | speed_string = pci_bus_speed_strings[speed]; | ||
83 | else | ||
84 | speed_string = "Unknown"; | ||
85 | |||
86 | return sprintf(buf, "%s\n", speed_string); | ||
87 | } | ||
88 | |||
89 | static ssize_t max_speed_read_file(struct pci_slot *slot, char *buf) | ||
90 | { | ||
91 | return bus_speed_read(slot->bus->max_bus_speed, buf); | ||
92 | } | ||
93 | |||
94 | static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf) | ||
95 | { | ||
96 | return bus_speed_read(slot->bus->cur_bus_speed, buf); | ||
97 | } | ||
98 | |||
50 | static void pci_slot_release(struct kobject *kobj) | 99 | static void pci_slot_release(struct kobject *kobj) |
51 | { | 100 | { |
52 | struct pci_dev *dev; | 101 | struct pci_dev *dev; |
@@ -66,9 +115,15 @@ static void pci_slot_release(struct kobject *kobj) | |||
66 | 115 | ||
67 | static struct pci_slot_attribute pci_slot_attr_address = | 116 | static struct pci_slot_attribute pci_slot_attr_address = |
68 | __ATTR(address, (S_IFREG | S_IRUGO), address_read_file, NULL); | 117 | __ATTR(address, (S_IFREG | S_IRUGO), address_read_file, NULL); |
118 | static struct pci_slot_attribute pci_slot_attr_max_speed = | ||
119 | __ATTR(max_bus_speed, (S_IFREG | S_IRUGO), max_speed_read_file, NULL); | ||
120 | static struct pci_slot_attribute pci_slot_attr_cur_speed = | ||
121 | __ATTR(cur_bus_speed, (S_IFREG | S_IRUGO), cur_speed_read_file, NULL); | ||
69 | 122 | ||
70 | static struct attribute *pci_slot_default_attrs[] = { | 123 | static struct attribute *pci_slot_default_attrs[] = { |
71 | &pci_slot_attr_address.attr, | 124 | &pci_slot_attr_address.attr, |
125 | &pci_slot_attr_max_speed.attr, | ||
126 | &pci_slot_attr_cur_speed.attr, | ||
72 | NULL, | 127 | NULL, |
73 | }; | 128 | }; |
74 | 129 | ||
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index 52db17263d8..f8401a0ef89 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c | |||
@@ -114,22 +114,21 @@ struct pcmcia_align_data { | |||
114 | unsigned long offset; | 114 | unsigned long offset; |
115 | }; | 115 | }; |
116 | 116 | ||
117 | static void pcmcia_align(void *align_data, struct resource *res, | 117 | static resource_size_t pcmcia_align(void *align_data, |
118 | unsigned long size, unsigned long align) | 118 | const struct resource *res, |
119 | resource_size_t size, resource_size_t align) | ||
119 | { | 120 | { |
120 | struct pcmcia_align_data *data = align_data; | 121 | struct pcmcia_align_data *data = align_data; |
121 | unsigned long start; | 122 | resource_size_t start; |
122 | 123 | ||
123 | start = (res->start & ~data->mask) + data->offset; | 124 | start = (res->start & ~data->mask) + data->offset; |
124 | if (start < res->start) | 125 | if (start < res->start) |
125 | start += data->mask + 1; | 126 | start += data->mask + 1; |
126 | res->start = start; | ||
127 | 127 | ||
128 | #ifdef CONFIG_X86 | 128 | #ifdef CONFIG_X86 |
129 | if (res->flags & IORESOURCE_IO) { | 129 | if (res->flags & IORESOURCE_IO) { |
130 | if (start & 0x300) { | 130 | if (start & 0x300) { |
131 | start = (start + 0x3ff) & ~0x3ff; | 131 | start = (start + 0x3ff) & ~0x3ff; |
132 | res->start = start; | ||
133 | } | 132 | } |
134 | } | 133 | } |
135 | #endif | 134 | #endif |
@@ -137,9 +136,11 @@ static void pcmcia_align(void *align_data, struct resource *res, | |||
137 | #ifdef CONFIG_M68K | 136 | #ifdef CONFIG_M68K |
138 | if (res->flags & IORESOURCE_IO) { | 137 | if (res->flags & IORESOURCE_IO) { |
139 | if ((res->start + size - 1) >= 1024) | 138 | if ((res->start + size - 1) >= 1024) |
140 | res->start = res->end; | 139 | start = res->end; |
141 | } | 140 | } |
142 | #endif | 141 | #endif |
142 | |||
143 | return start; | ||
143 | } | 144 | } |
144 | 145 | ||
145 | 146 | ||
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 9b0dc433a8c..c67638fe691 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c | |||
@@ -533,8 +533,8 @@ struct pcmcia_align_data { | |||
533 | struct resource_map *map; | 533 | struct resource_map *map; |
534 | }; | 534 | }; |
535 | 535 | ||
536 | static void | 536 | static resource_size_t |
537 | pcmcia_common_align(void *align_data, struct resource *res, | 537 | pcmcia_common_align(void *align_data, const struct resource *res, |
538 | resource_size_t size, resource_size_t align) | 538 | resource_size_t size, resource_size_t align) |
539 | { | 539 | { |
540 | struct pcmcia_align_data *data = align_data; | 540 | struct pcmcia_align_data *data = align_data; |
@@ -545,17 +545,18 @@ pcmcia_common_align(void *align_data, struct resource *res, | |||
545 | start = (res->start & ~data->mask) + data->offset; | 545 | start = (res->start & ~data->mask) + data->offset; |
546 | if (start < res->start) | 546 | if (start < res->start) |
547 | start += data->mask + 1; | 547 | start += data->mask + 1; |
548 | res->start = start; | 548 | return start; |
549 | } | 549 | } |
550 | 550 | ||
551 | static void | 551 | static resource_size_t |
552 | pcmcia_align(void *align_data, struct resource *res, resource_size_t size, | 552 | pcmcia_align(void *align_data, const struct resource *res, |
553 | resource_size_t align) | 553 | resource_size_t size, resource_size_t align) |
554 | { | 554 | { |
555 | struct pcmcia_align_data *data = align_data; | 555 | struct pcmcia_align_data *data = align_data; |
556 | struct resource_map *m; | 556 | struct resource_map *m; |
557 | resource_size_t start; | ||
557 | 558 | ||
558 | pcmcia_common_align(data, res, size, align); | 559 | start = pcmcia_common_align(data, res, size, align); |
559 | 560 | ||
560 | for (m = data->map->next; m != data->map; m = m->next) { | 561 | for (m = data->map->next; m != data->map; m = m->next) { |
561 | unsigned long start = m->base; | 562 | unsigned long start = m->base; |
@@ -567,8 +568,7 @@ pcmcia_align(void *align_data, struct resource *res, resource_size_t size, | |||
567 | * fit here. | 568 | * fit here. |
568 | */ | 569 | */ |
569 | if (res->start < start) { | 570 | if (res->start < start) { |
570 | res->start = start; | 571 | start = pcmcia_common_align(data, res, size, align); |
571 | pcmcia_common_align(data, res, size, align); | ||
572 | } | 572 | } |
573 | 573 | ||
574 | /* | 574 | /* |
@@ -586,7 +586,9 @@ pcmcia_align(void *align_data, struct resource *res, resource_size_t size, | |||
586 | * If we failed to find something suitable, ensure we fail. | 586 | * If we failed to find something suitable, ensure we fail. |
587 | */ | 587 | */ |
588 | if (m == data->map) | 588 | if (m == data->map) |
589 | res->start = res->end; | 589 | start = res->end; |
590 | |||
591 | return start; | ||
590 | } | 592 | } |
591 | 593 | ||
592 | /* | 594 | /* |
@@ -801,8 +803,7 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s) | |||
801 | return -EINVAL; | 803 | return -EINVAL; |
802 | #endif | 804 | #endif |
803 | 805 | ||
804 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 806 | pci_bus_for_each_resource(s->cb_dev->bus, res, i) { |
805 | res = s->cb_dev->bus->resource[i]; | ||
806 | if (!res) | 807 | if (!res) |
807 | continue; | 808 | continue; |
808 | 809 | ||
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index e4d12acdd52..1f2039d5e96 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
@@ -649,9 +649,10 @@ static int yenta_search_one_res(struct resource *root, struct resource *res, | |||
649 | static int yenta_search_res(struct yenta_socket *socket, struct resource *res, | 649 | static int yenta_search_res(struct yenta_socket *socket, struct resource *res, |
650 | u32 min) | 650 | u32 min) |
651 | { | 651 | { |
652 | struct resource *root; | ||
652 | int i; | 653 | int i; |
653 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 654 | |
654 | struct resource *root = socket->dev->bus->resource[i]; | 655 | pci_bus_for_each_resource(socket->dev->bus, root, i) { |
655 | if (!root) | 656 | if (!root) |
656 | continue; | 657 | continue; |
657 | 658 | ||
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 3cd9ccdcbd8..54508ccea02 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -242,6 +242,8 @@ struct acpi_device_perf { | |||
242 | struct acpi_device_wakeup_flags { | 242 | struct acpi_device_wakeup_flags { |
243 | u8 valid:1; /* Can successfully enable wakeup? */ | 243 | u8 valid:1; /* Can successfully enable wakeup? */ |
244 | u8 run_wake:1; /* Run-Wake GPE devices */ | 244 | u8 run_wake:1; /* Run-Wake GPE devices */ |
245 | u8 always_enabled:1; /* Run-wake devices that are always enabled */ | ||
246 | u8 notifier_present:1; /* Wake-up notify handler has been installed */ | ||
245 | }; | 247 | }; |
246 | 248 | ||
247 | struct acpi_device_wakeup_state { | 249 | struct acpi_device_wakeup_state { |
@@ -256,6 +258,7 @@ struct acpi_device_wakeup { | |||
256 | struct acpi_device_wakeup_state state; | 258 | struct acpi_device_wakeup_state state; |
257 | struct acpi_device_wakeup_flags flags; | 259 | struct acpi_device_wakeup_flags flags; |
258 | int prepare_count; | 260 | int prepare_count; |
261 | int run_wake_count; | ||
259 | }; | 262 | }; |
260 | 263 | ||
261 | /* Device */ | 264 | /* Device */ |
@@ -386,6 +389,9 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); | |||
386 | struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); | 389 | struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); |
387 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) | 390 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) |
388 | 391 | ||
392 | int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); | ||
393 | int acpi_disable_wakeup_device_power(struct acpi_device *dev); | ||
394 | |||
389 | #ifdef CONFIG_PM_SLEEP | 395 | #ifdef CONFIG_PM_SLEEP |
390 | int acpi_pm_device_sleep_state(struct device *, int *); | 396 | int acpi_pm_device_sleep_state(struct device *, int *); |
391 | int acpi_pm_device_sleep_wake(struct device *, bool); | 397 | int acpi_pm_device_sleep_wake(struct device *, bool); |
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index f4906f6568d..3a4767c01c5 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h | |||
@@ -104,6 +104,7 @@ int acpi_pci_bind_root(struct acpi_device *device); | |||
104 | 104 | ||
105 | struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain, | 105 | struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain, |
106 | int bus); | 106 | int bus); |
107 | void pci_acpi_crs_quirks(void); | ||
107 | 108 | ||
108 | /* -------------------------------------------------------------------------- | 109 | /* -------------------------------------------------------------------------- |
109 | Processor | 110 | Processor |
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 86e9735a96b..3988f93b9c6 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h | |||
@@ -281,11 +281,11 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status); | |||
281 | /* | 281 | /* |
282 | * GPE Interfaces | 282 | * GPE Interfaces |
283 | */ | 283 | */ |
284 | acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type); | 284 | acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action); |
285 | 285 | ||
286 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number); | 286 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type); |
287 | 287 | ||
288 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number); | 288 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type); |
289 | 289 | ||
290 | acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); | 290 | acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); |
291 | 291 | ||
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 153f12dc337..73af4086337 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h | |||
@@ -668,15 +668,16 @@ typedef u32 acpi_event_status; | |||
668 | 668 | ||
669 | /* | 669 | /* |
670 | * GPE info flags - Per GPE | 670 | * GPE info flags - Per GPE |
671 | * +-+-+-+---+---+-+ | 671 | * +-+-+-+---+-+-+-+ |
672 | * |7|6|5|4:3|2:1|0| | 672 | * |7|6|5|4:3|2|1|0| |
673 | * +-+-+-+---+---+-+ | 673 | * +-+-+-+---+-+-+-+ |
674 | * | | | | | | | 674 | * | | | | | | | |
675 | * | | | | | +--- Interrupt type: Edge or Level Triggered | 675 | * | | | | | | +--- Interrupt type: Edge or Level Triggered |
676 | * | | | | +--- Type: Wake-only, Runtime-only, or wake/runtime | 676 | * | | | | | +--- GPE can wake the system |
677 | * | | | | +--- Unused | ||
677 | * | | | +--- Type of dispatch -- to method, handler, or none | 678 | * | | | +--- Type of dispatch -- to method, handler, or none |
678 | * | | +--- Enabled for runtime? | 679 | * | | +--- Unused |
679 | * | +--- Enabled for wake? | 680 | * | +--- Unused |
680 | * +--- Unused | 681 | * +--- Unused |
681 | */ | 682 | */ |
682 | #define ACPI_GPE_XRUPT_TYPE_MASK (u8) 0x01 | 683 | #define ACPI_GPE_XRUPT_TYPE_MASK (u8) 0x01 |
@@ -687,22 +688,13 @@ typedef u32 acpi_event_status; | |||
687 | #define ACPI_GPE_TYPE_WAKE_RUN (u8) 0x06 | 688 | #define ACPI_GPE_TYPE_WAKE_RUN (u8) 0x06 |
688 | #define ACPI_GPE_TYPE_WAKE (u8) 0x02 | 689 | #define ACPI_GPE_TYPE_WAKE (u8) 0x02 |
689 | #define ACPI_GPE_TYPE_RUNTIME (u8) 0x04 /* Default */ | 690 | #define ACPI_GPE_TYPE_RUNTIME (u8) 0x04 /* Default */ |
691 | #define ACPI_GPE_CAN_WAKE (u8) 0x02 | ||
690 | 692 | ||
691 | #define ACPI_GPE_DISPATCH_MASK (u8) 0x18 | 693 | #define ACPI_GPE_DISPATCH_MASK (u8) 0x18 |
692 | #define ACPI_GPE_DISPATCH_HANDLER (u8) 0x08 | 694 | #define ACPI_GPE_DISPATCH_HANDLER (u8) 0x08 |
693 | #define ACPI_GPE_DISPATCH_METHOD (u8) 0x10 | 695 | #define ACPI_GPE_DISPATCH_METHOD (u8) 0x10 |
694 | #define ACPI_GPE_DISPATCH_NOT_USED (u8) 0x00 /* Default */ | 696 | #define ACPI_GPE_DISPATCH_NOT_USED (u8) 0x00 /* Default */ |
695 | 697 | ||
696 | #define ACPI_GPE_RUN_ENABLE_MASK (u8) 0x20 | ||
697 | #define ACPI_GPE_RUN_ENABLED (u8) 0x20 | ||
698 | #define ACPI_GPE_RUN_DISABLED (u8) 0x00 /* Default */ | ||
699 | |||
700 | #define ACPI_GPE_WAKE_ENABLE_MASK (u8) 0x40 | ||
701 | #define ACPI_GPE_WAKE_ENABLED (u8) 0x40 | ||
702 | #define ACPI_GPE_WAKE_DISABLED (u8) 0x00 /* Default */ | ||
703 | |||
704 | #define ACPI_GPE_ENABLE_MASK (u8) 0x60 /* Both run/wake */ | ||
705 | |||
706 | /* | 698 | /* |
707 | * Flags for GPE and Lock interfaces | 699 | * Flags for GPE and Lock interfaces |
708 | */ | 700 | */ |
diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 7129504e053..dda98410d58 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h | |||
@@ -112,6 +112,7 @@ extern struct resource iomem_resource; | |||
112 | 112 | ||
113 | extern int request_resource(struct resource *root, struct resource *new); | 113 | extern int request_resource(struct resource *root, struct resource *new); |
114 | extern int release_resource(struct resource *new); | 114 | extern int release_resource(struct resource *new); |
115 | void release_child_resources(struct resource *new); | ||
115 | extern void reserve_region_with_split(struct resource *root, | 116 | extern void reserve_region_with_split(struct resource *root, |
116 | resource_size_t start, resource_size_t end, | 117 | resource_size_t start, resource_size_t end, |
117 | const char *name); | 118 | const char *name); |
@@ -120,8 +121,10 @@ extern void insert_resource_expand_to_fit(struct resource *root, struct resource | |||
120 | extern int allocate_resource(struct resource *root, struct resource *new, | 121 | extern int allocate_resource(struct resource *root, struct resource *new, |
121 | resource_size_t size, resource_size_t min, | 122 | resource_size_t size, resource_size_t min, |
122 | resource_size_t max, resource_size_t align, | 123 | resource_size_t max, resource_size_t align, |
123 | void (*alignf)(void *, struct resource *, | 124 | resource_size_t (*alignf)(void *, |
124 | resource_size_t, resource_size_t), | 125 | const struct resource *, |
126 | resource_size_t, | ||
127 | resource_size_t), | ||
125 | void *alignf_data); | 128 | void *alignf_data); |
126 | int adjust_resource(struct resource *res, resource_size_t start, | 129 | int adjust_resource(struct resource *res, resource_size_t start, |
127 | resource_size_t size); | 130 | resource_size_t size); |
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 93a7c08f869..c8b6473c5f4 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h | |||
@@ -11,6 +11,13 @@ | |||
11 | #include <linux/acpi.h> | 11 | #include <linux/acpi.h> |
12 | 12 | ||
13 | #ifdef CONFIG_ACPI | 13 | #ifdef CONFIG_ACPI |
14 | extern acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, | ||
15 | struct pci_bus *pci_bus); | ||
16 | extern acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev); | ||
17 | extern acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, | ||
18 | struct pci_dev *pci_dev); | ||
19 | extern acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev); | ||
20 | |||
14 | static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev) | 21 | static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev) |
15 | { | 22 | { |
16 | struct pci_bus *pbus = pdev->bus; | 23 | struct pci_bus *pbus = pdev->bus; |
diff --git a/include/linux/pci.h b/include/linux/pci.h index c1968f464c3..e19a69613d8 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -187,6 +187,33 @@ enum pci_bus_flags { | |||
187 | PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2, | 187 | PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2, |
188 | }; | 188 | }; |
189 | 189 | ||
190 | /* Based on the PCI Hotplug Spec, but some values are made up by us */ | ||
191 | enum pci_bus_speed { | ||
192 | PCI_SPEED_33MHz = 0x00, | ||
193 | PCI_SPEED_66MHz = 0x01, | ||
194 | PCI_SPEED_66MHz_PCIX = 0x02, | ||
195 | PCI_SPEED_100MHz_PCIX = 0x03, | ||
196 | PCI_SPEED_133MHz_PCIX = 0x04, | ||
197 | PCI_SPEED_66MHz_PCIX_ECC = 0x05, | ||
198 | PCI_SPEED_100MHz_PCIX_ECC = 0x06, | ||
199 | PCI_SPEED_133MHz_PCIX_ECC = 0x07, | ||
200 | PCI_SPEED_66MHz_PCIX_266 = 0x09, | ||
201 | PCI_SPEED_100MHz_PCIX_266 = 0x0a, | ||
202 | PCI_SPEED_133MHz_PCIX_266 = 0x0b, | ||
203 | AGP_UNKNOWN = 0x0c, | ||
204 | AGP_1X = 0x0d, | ||
205 | AGP_2X = 0x0e, | ||
206 | AGP_4X = 0x0f, | ||
207 | AGP_8X = 0x10, | ||
208 | PCI_SPEED_66MHz_PCIX_533 = 0x11, | ||
209 | PCI_SPEED_100MHz_PCIX_533 = 0x12, | ||
210 | PCI_SPEED_133MHz_PCIX_533 = 0x13, | ||
211 | PCIE_SPEED_2_5GT = 0x14, | ||
212 | PCIE_SPEED_5_0GT = 0x15, | ||
213 | PCIE_SPEED_8_0GT = 0x16, | ||
214 | PCI_SPEED_UNKNOWN = 0xff, | ||
215 | }; | ||
216 | |||
190 | struct pci_cap_saved_state { | 217 | struct pci_cap_saved_state { |
191 | struct hlist_node next; | 218 | struct hlist_node next; |
192 | char cap_nr; | 219 | char cap_nr; |
@@ -239,6 +266,7 @@ struct pci_dev { | |||
239 | configuration space */ | 266 | configuration space */ |
240 | unsigned int pme_support:5; /* Bitmask of states from which PME# | 267 | unsigned int pme_support:5; /* Bitmask of states from which PME# |
241 | can be generated */ | 268 | can be generated */ |
269 | unsigned int pme_interrupt:1; | ||
242 | unsigned int d1_support:1; /* Low power state D1 is supported */ | 270 | unsigned int d1_support:1; /* Low power state D1 is supported */ |
243 | unsigned int d2_support:1; /* Low power state D2 is supported */ | 271 | unsigned int d2_support:1; /* Low power state D2 is supported */ |
244 | unsigned int no_d1d2:1; /* Only allow D0 and D3 */ | 272 | unsigned int no_d1d2:1; /* Only allow D0 and D3 */ |
@@ -275,7 +303,8 @@ struct pci_dev { | |||
275 | unsigned int msix_enabled:1; | 303 | unsigned int msix_enabled:1; |
276 | unsigned int ari_enabled:1; /* ARI forwarding */ | 304 | unsigned int ari_enabled:1; /* ARI forwarding */ |
277 | unsigned int is_managed:1; | 305 | unsigned int is_managed:1; |
278 | unsigned int is_pcie:1; | 306 | unsigned int is_pcie:1; /* Obsolete. Will be removed. |
307 | Use pci_is_pcie() instead */ | ||
279 | unsigned int needs_freset:1; /* Dev requires fundamental reset */ | 308 | unsigned int needs_freset:1; /* Dev requires fundamental reset */ |
280 | unsigned int state_saved:1; | 309 | unsigned int state_saved:1; |
281 | unsigned int is_physfn:1; | 310 | unsigned int is_physfn:1; |
@@ -335,9 +364,26 @@ static inline void pci_add_saved_cap(struct pci_dev *pci_dev, | |||
335 | hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space); | 364 | hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space); |
336 | } | 365 | } |
337 | 366 | ||
338 | #ifndef PCI_BUS_NUM_RESOURCES | 367 | /* |
339 | #define PCI_BUS_NUM_RESOURCES 16 | 368 | * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond |
340 | #endif | 369 | * to P2P or CardBus bridge windows) go in a table. Additional ones (for |
370 | * buses below host bridges or subtractive decode bridges) go in the list. | ||
371 | * Use pci_bus_for_each_resource() to iterate through all the resources. | ||
372 | */ | ||
373 | |||
374 | /* | ||
375 | * PCI_SUBTRACTIVE_DECODE means the bridge forwards the window implicitly | ||
376 | * and there's no way to program the bridge with the details of the window. | ||
377 | * This does not apply to ACPI _CRS windows, even with the _DEC subtractive- | ||
378 | * decode bit set, because they are explicit and can be programmed with _SRS. | ||
379 | */ | ||
380 | #define PCI_SUBTRACTIVE_DECODE 0x1 | ||
381 | |||
382 | struct pci_bus_resource { | ||
383 | struct list_head list; | ||
384 | struct resource *res; | ||
385 | unsigned int flags; | ||
386 | }; | ||
341 | 387 | ||
342 | #define PCI_REGION_FLAG_MASK 0x0fU /* These bits of resource flags tell us the PCI region flags */ | 388 | #define PCI_REGION_FLAG_MASK 0x0fU /* These bits of resource flags tell us the PCI region flags */ |
343 | 389 | ||
@@ -348,8 +394,8 @@ struct pci_bus { | |||
348 | struct list_head devices; /* list of devices on this bus */ | 394 | struct list_head devices; /* list of devices on this bus */ |
349 | struct pci_dev *self; /* bridge device as seen by parent */ | 395 | struct pci_dev *self; /* bridge device as seen by parent */ |
350 | struct list_head slots; /* list of slots on this bus */ | 396 | struct list_head slots; /* list of slots on this bus */ |
351 | struct resource *resource[PCI_BUS_NUM_RESOURCES]; | 397 | struct resource *resource[PCI_BRIDGE_RESOURCE_NUM]; |
352 | /* address space routed to this bus */ | 398 | struct list_head resources; /* address space routed to this bus */ |
353 | 399 | ||
354 | struct pci_ops *ops; /* configuration access functions */ | 400 | struct pci_ops *ops; /* configuration access functions */ |
355 | void *sysdata; /* hook for sys-specific extension */ | 401 | void *sysdata; /* hook for sys-specific extension */ |
@@ -359,6 +405,8 @@ struct pci_bus { | |||
359 | unsigned char primary; /* number of primary bridge */ | 405 | unsigned char primary; /* number of primary bridge */ |
360 | unsigned char secondary; /* number of secondary bridge */ | 406 | unsigned char secondary; /* number of secondary bridge */ |
361 | unsigned char subordinate; /* max number of subordinate buses */ | 407 | unsigned char subordinate; /* max number of subordinate buses */ |
408 | unsigned char max_bus_speed; /* enum pci_bus_speed */ | ||
409 | unsigned char cur_bus_speed; /* enum pci_bus_speed */ | ||
362 | 410 | ||
363 | char name[48]; | 411 | char name[48]; |
364 | 412 | ||
@@ -563,7 +611,8 @@ int __must_check pcibios_enable_device(struct pci_dev *, int mask); | |||
563 | char *pcibios_setup(char *str); | 611 | char *pcibios_setup(char *str); |
564 | 612 | ||
565 | /* Used only when drivers/pci/setup.c is used */ | 613 | /* Used only when drivers/pci/setup.c is used */ |
566 | void pcibios_align_resource(void *, struct resource *, resource_size_t, | 614 | resource_size_t pcibios_align_resource(void *, const struct resource *, |
615 | resource_size_t, | ||
567 | resource_size_t); | 616 | resource_size_t); |
568 | void pcibios_update_irq(struct pci_dev *, int irq); | 617 | void pcibios_update_irq(struct pci_dev *, int irq); |
569 | 618 | ||
@@ -589,6 +638,7 @@ struct pci_bus *pci_create_bus(struct device *parent, int bus, | |||
589 | struct pci_ops *ops, void *sysdata); | 638 | struct pci_ops *ops, void *sysdata); |
590 | struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, | 639 | struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, |
591 | int busnr); | 640 | int busnr); |
641 | void pcie_update_link_speed(struct pci_bus *bus, u16 link_status); | ||
592 | struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, | 642 | struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, |
593 | const char *name, | 643 | const char *name, |
594 | struct hotplug_slot *hotplug); | 644 | struct hotplug_slot *hotplug); |
@@ -615,12 +665,6 @@ extern void pci_sort_breadthfirst(void); | |||
615 | 665 | ||
616 | /* Generic PCI functions exported to card drivers */ | 666 | /* Generic PCI functions exported to card drivers */ |
617 | 667 | ||
618 | #ifdef CONFIG_PCI_LEGACY | ||
619 | struct pci_dev __deprecated *pci_find_device(unsigned int vendor, | ||
620 | unsigned int device, | ||
621 | struct pci_dev *from); | ||
622 | #endif /* CONFIG_PCI_LEGACY */ | ||
623 | |||
624 | enum pci_lost_interrupt_reason { | 668 | enum pci_lost_interrupt_reason { |
625 | PCI_LOST_IRQ_NO_INFORMATION = 0, | 669 | PCI_LOST_IRQ_NO_INFORMATION = 0, |
626 | PCI_LOST_IRQ_DISABLE_MSI, | 670 | PCI_LOST_IRQ_DISABLE_MSI, |
@@ -750,11 +794,19 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state); | |||
750 | pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); | 794 | pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); |
751 | bool pci_pme_capable(struct pci_dev *dev, pci_power_t state); | 795 | bool pci_pme_capable(struct pci_dev *dev, pci_power_t state); |
752 | void pci_pme_active(struct pci_dev *dev, bool enable); | 796 | void pci_pme_active(struct pci_dev *dev, bool enable); |
753 | int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable); | 797 | int __pci_enable_wake(struct pci_dev *dev, pci_power_t state, |
798 | bool runtime, bool enable); | ||
754 | int pci_wake_from_d3(struct pci_dev *dev, bool enable); | 799 | int pci_wake_from_d3(struct pci_dev *dev, bool enable); |
755 | pci_power_t pci_target_state(struct pci_dev *dev); | 800 | pci_power_t pci_target_state(struct pci_dev *dev); |
756 | int pci_prepare_to_sleep(struct pci_dev *dev); | 801 | int pci_prepare_to_sleep(struct pci_dev *dev); |
757 | int pci_back_from_sleep(struct pci_dev *dev); | 802 | int pci_back_from_sleep(struct pci_dev *dev); |
803 | bool pci_dev_run_wake(struct pci_dev *dev); | ||
804 | |||
805 | static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, | ||
806 | bool enable) | ||
807 | { | ||
808 | return __pci_enable_wake(dev, state, false, enable); | ||
809 | } | ||
758 | 810 | ||
759 | /* For use by arch with custom probe code */ | 811 | /* For use by arch with custom probe code */ |
760 | void set_pcie_port_type(struct pci_dev *pdev); | 812 | void set_pcie_port_type(struct pci_dev *pdev); |
@@ -776,6 +828,7 @@ void pci_bus_assign_resources(const struct pci_bus *bus); | |||
776 | void pci_bus_size_bridges(struct pci_bus *bus); | 828 | void pci_bus_size_bridges(struct pci_bus *bus); |
777 | int pci_claim_resource(struct pci_dev *, int); | 829 | int pci_claim_resource(struct pci_dev *, int); |
778 | void pci_assign_unassigned_resources(void); | 830 | void pci_assign_unassigned_resources(void); |
831 | void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge); | ||
779 | void pdev_enable_device(struct pci_dev *); | 832 | void pdev_enable_device(struct pci_dev *); |
780 | void pdev_sort_resources(struct pci_dev *, struct resource_list *); | 833 | void pdev_sort_resources(struct pci_dev *, struct resource_list *); |
781 | int pci_enable_resources(struct pci_dev *, int mask); | 834 | int pci_enable_resources(struct pci_dev *, int mask); |
@@ -793,12 +846,23 @@ int pci_request_selected_regions_exclusive(struct pci_dev *, int, const char *); | |||
793 | void pci_release_selected_regions(struct pci_dev *, int); | 846 | void pci_release_selected_regions(struct pci_dev *, int); |
794 | 847 | ||
795 | /* drivers/pci/bus.c */ | 848 | /* drivers/pci/bus.c */ |
849 | void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, unsigned int flags); | ||
850 | struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n); | ||
851 | void pci_bus_remove_resources(struct pci_bus *bus); | ||
852 | |||
853 | #define pci_bus_for_each_resource(bus, res, i) \ | ||
854 | for (i = 0; \ | ||
855 | (res = pci_bus_resource_n(bus, i)) || i < PCI_BRIDGE_RESOURCE_NUM; \ | ||
856 | i++) | ||
857 | |||
796 | int __must_check pci_bus_alloc_resource(struct pci_bus *bus, | 858 | int __must_check pci_bus_alloc_resource(struct pci_bus *bus, |
797 | struct resource *res, resource_size_t size, | 859 | struct resource *res, resource_size_t size, |
798 | resource_size_t align, resource_size_t min, | 860 | resource_size_t align, resource_size_t min, |
799 | unsigned int type_mask, | 861 | unsigned int type_mask, |
800 | void (*alignf)(void *, struct resource *, | 862 | resource_size_t (*alignf)(void *, |
801 | resource_size_t, resource_size_t), | 863 | const struct resource *, |
864 | resource_size_t, | ||
865 | resource_size_t), | ||
802 | void *alignf_data); | 866 | void *alignf_data); |
803 | void pci_enable_bridges(struct pci_bus *bus); | 867 | void pci_enable_bridges(struct pci_bus *bus); |
804 | 868 | ||
@@ -977,13 +1041,6 @@ static inline int pci_proc_domain(struct pci_bus *bus) | |||
977 | _PCI_NOP_ALL(read, *) | 1041 | _PCI_NOP_ALL(read, *) |
978 | _PCI_NOP_ALL(write,) | 1042 | _PCI_NOP_ALL(write,) |
979 | 1043 | ||
980 | static inline struct pci_dev *pci_find_device(unsigned int vendor, | ||
981 | unsigned int device, | ||
982 | struct pci_dev *from) | ||
983 | { | ||
984 | return NULL; | ||
985 | } | ||
986 | |||
987 | static inline struct pci_dev *pci_get_device(unsigned int vendor, | 1044 | static inline struct pci_dev *pci_get_device(unsigned int vendor, |
988 | unsigned int device, | 1045 | unsigned int device, |
989 | struct pci_dev *from) | 1046 | struct pci_dev *from) |
@@ -1241,8 +1298,12 @@ enum pci_fixup_pass { | |||
1241 | DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend, \ | 1298 | DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend, \ |
1242 | suspend##vendor##device##hook, vendor, device, hook) | 1299 | suspend##vendor##device##hook, vendor, device, hook) |
1243 | 1300 | ||
1244 | 1301 | #ifdef CONFIG_PCI_QUIRKS | |
1245 | void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); | 1302 | void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); |
1303 | #else | ||
1304 | static inline void pci_fixup_device(enum pci_fixup_pass pass, | ||
1305 | struct pci_dev *dev) {} | ||
1306 | #endif | ||
1246 | 1307 | ||
1247 | void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen); | 1308 | void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen); |
1248 | void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr); | 1309 | void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr); |
diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h index 652ba797696..5d09cbafa7d 100644 --- a/include/linux/pci_hotplug.h +++ b/include/linux/pci_hotplug.h | |||
@@ -28,26 +28,6 @@ | |||
28 | #ifndef _PCI_HOTPLUG_H | 28 | #ifndef _PCI_HOTPLUG_H |
29 | #define _PCI_HOTPLUG_H | 29 | #define _PCI_HOTPLUG_H |
30 | 30 | ||
31 | |||
32 | /* These values come from the PCI Hotplug Spec */ | ||
33 | enum pci_bus_speed { | ||
34 | PCI_SPEED_33MHz = 0x00, | ||
35 | PCI_SPEED_66MHz = 0x01, | ||
36 | PCI_SPEED_66MHz_PCIX = 0x02, | ||
37 | PCI_SPEED_100MHz_PCIX = 0x03, | ||
38 | PCI_SPEED_133MHz_PCIX = 0x04, | ||
39 | PCI_SPEED_66MHz_PCIX_ECC = 0x05, | ||
40 | PCI_SPEED_100MHz_PCIX_ECC = 0x06, | ||
41 | PCI_SPEED_133MHz_PCIX_ECC = 0x07, | ||
42 | PCI_SPEED_66MHz_PCIX_266 = 0x09, | ||
43 | PCI_SPEED_100MHz_PCIX_266 = 0x0a, | ||
44 | PCI_SPEED_133MHz_PCIX_266 = 0x0b, | ||
45 | PCI_SPEED_66MHz_PCIX_533 = 0x11, | ||
46 | PCI_SPEED_100MHz_PCIX_533 = 0x12, | ||
47 | PCI_SPEED_133MHz_PCIX_533 = 0x13, | ||
48 | PCI_SPEED_UNKNOWN = 0xff, | ||
49 | }; | ||
50 | |||
51 | /* These values come from the PCI Express Spec */ | 31 | /* These values come from the PCI Express Spec */ |
52 | enum pcie_link_width { | 32 | enum pcie_link_width { |
53 | PCIE_LNK_WIDTH_RESRV = 0x00, | 33 | PCIE_LNK_WIDTH_RESRV = 0x00, |
@@ -61,12 +41,6 @@ enum pcie_link_width { | |||
61 | PCIE_LNK_WIDTH_UNKNOWN = 0xFF, | 41 | PCIE_LNK_WIDTH_UNKNOWN = 0xFF, |
62 | }; | 42 | }; |
63 | 43 | ||
64 | enum pcie_link_speed { | ||
65 | PCIE_2_5GB = 0x14, | ||
66 | PCIE_5_0GB = 0x15, | ||
67 | PCIE_LNK_SPEED_UNKNOWN = 0xFF, | ||
68 | }; | ||
69 | |||
70 | /** | 44 | /** |
71 | * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use | 45 | * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use |
72 | * @owner: The module owner of this structure | 46 | * @owner: The module owner of this structure |
@@ -89,12 +63,6 @@ enum pcie_link_speed { | |||
89 | * @get_adapter_status: Called to get see if an adapter is present in the slot or not. | 63 | * @get_adapter_status: Called to get see if an adapter is present in the slot or not. |
90 | * If this field is NULL, the value passed in the struct hotplug_slot_info | 64 | * If this field is NULL, the value passed in the struct hotplug_slot_info |
91 | * will be used when this value is requested by a user. | 65 | * will be used when this value is requested by a user. |
92 | * @get_max_bus_speed: Called to get the max bus speed for a slot. | ||
93 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
94 | * will be used when this value is requested by a user. | ||
95 | * @get_cur_bus_speed: Called to get the current bus speed for a slot. | ||
96 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
97 | * will be used when this value is requested by a user. | ||
98 | * | 66 | * |
99 | * The table of function pointers that is passed to the hotplug pci core by a | 67 | * The table of function pointers that is passed to the hotplug pci core by a |
100 | * hotplug pci driver. These functions are called by the hotplug pci core when | 68 | * hotplug pci driver. These functions are called by the hotplug pci core when |
@@ -112,17 +80,14 @@ struct hotplug_slot_ops { | |||
112 | int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); | 80 | int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); |
113 | int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); | 81 | int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); |
114 | int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); | 82 | int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); |
115 | int (*get_max_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
116 | int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
117 | }; | 83 | }; |
118 | 84 | ||
119 | /** | 85 | /** |
120 | * struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot | 86 | * struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot |
121 | * @power: if power is enabled or not (1/0) | 87 | * @power_status: if power is enabled or not (1/0) |
122 | * @attention_status: if the attention light is enabled or not (1/0) | 88 | * @attention_status: if the attention light is enabled or not (1/0) |
123 | * @latch_status: if the latch (if any) is open or closed (1/0) | 89 | * @latch_status: if the latch (if any) is open or closed (1/0) |
124 | * @adapter_present: if there is a pci board present in the slot or not (1/0) | 90 | * @adapter_status: if there is a pci board present in the slot or not (1/0) |
125 | * @address: (domain << 16 | bus << 8 | dev) | ||
126 | * | 91 | * |
127 | * Used to notify the hotplug pci core of the status of a specific slot. | 92 | * Used to notify the hotplug pci core of the status of a specific slot. |
128 | */ | 93 | */ |
@@ -131,8 +96,6 @@ struct hotplug_slot_info { | |||
131 | u8 attention_status; | 96 | u8 attention_status; |
132 | u8 latch_status; | 97 | u8 latch_status; |
133 | u8 adapter_status; | 98 | u8 adapter_status; |
134 | enum pci_bus_speed max_bus_speed; | ||
135 | enum pci_bus_speed cur_bus_speed; | ||
136 | }; | 99 | }; |
137 | 100 | ||
138 | /** | 101 | /** |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index cca8a044e2b..0be82432058 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -2417,6 +2417,9 @@ | |||
2417 | #define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21 | 2417 | #define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21 |
2418 | #define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30 | 2418 | #define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30 |
2419 | #define PCI_DEVICE_ID_INTEL_IOAT 0x1a38 | 2419 | #define PCI_DEVICE_ID_INTEL_IOAT 0x1a38 |
2420 | #define PCI_DEVICE_ID_INTEL_CPT_SMBUS 0x1c22 | ||
2421 | #define PCI_DEVICE_ID_INTEL_CPT_LPC1 0x1c42 | ||
2422 | #define PCI_DEVICE_ID_INTEL_CPT_LPC2 0x1c43 | ||
2420 | #define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 | 2423 | #define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 |
2421 | #define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411 | 2424 | #define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411 |
2422 | #define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413 | 2425 | #define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413 |
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 91e09d3b2eb..4c9cffcf69c 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -222,3 +222,8 @@ config PM_RUNTIME | |||
222 | and the bus type drivers of the buses the devices are on are | 222 | and the bus type drivers of the buses the devices are on are |
223 | responsible for the actual handling of the autosuspend requests and | 223 | responsible for the actual handling of the autosuspend requests and |
224 | wake-up events. | 224 | wake-up events. |
225 | |||
226 | config PM_OPS | ||
227 | bool | ||
228 | depends on PM_SLEEP || PM_RUNTIME | ||
229 | default y | ||
diff --git a/kernel/resource.c b/kernel/resource.c index af96c1e4b54..24e9e60c145 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
@@ -188,6 +188,36 @@ static int __release_resource(struct resource *old) | |||
188 | return -EINVAL; | 188 | return -EINVAL; |
189 | } | 189 | } |
190 | 190 | ||
191 | static void __release_child_resources(struct resource *r) | ||
192 | { | ||
193 | struct resource *tmp, *p; | ||
194 | resource_size_t size; | ||
195 | |||
196 | p = r->child; | ||
197 | r->child = NULL; | ||
198 | while (p) { | ||
199 | tmp = p; | ||
200 | p = p->sibling; | ||
201 | |||
202 | tmp->parent = NULL; | ||
203 | tmp->sibling = NULL; | ||
204 | __release_child_resources(tmp); | ||
205 | |||
206 | printk(KERN_DEBUG "release child resource %pR\n", tmp); | ||
207 | /* need to restore size, and keep flags */ | ||
208 | size = resource_size(tmp); | ||
209 | tmp->start = 0; | ||
210 | tmp->end = size - 1; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | void release_child_resources(struct resource *r) | ||
215 | { | ||
216 | write_lock(&resource_lock); | ||
217 | __release_child_resources(r); | ||
218 | write_unlock(&resource_lock); | ||
219 | } | ||
220 | |||
191 | /** | 221 | /** |
192 | * request_resource - request and reserve an I/O or memory resource | 222 | * request_resource - request and reserve an I/O or memory resource |
193 | * @root: root resource descriptor | 223 | * @root: root resource descriptor |
@@ -303,8 +333,10 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, | |||
303 | static int find_resource(struct resource *root, struct resource *new, | 333 | static int find_resource(struct resource *root, struct resource *new, |
304 | resource_size_t size, resource_size_t min, | 334 | resource_size_t size, resource_size_t min, |
305 | resource_size_t max, resource_size_t align, | 335 | resource_size_t max, resource_size_t align, |
306 | void (*alignf)(void *, struct resource *, | 336 | resource_size_t (*alignf)(void *, |
307 | resource_size_t, resource_size_t), | 337 | const struct resource *, |
338 | resource_size_t, | ||
339 | resource_size_t), | ||
308 | void *alignf_data) | 340 | void *alignf_data) |
309 | { | 341 | { |
310 | struct resource *this = root->child; | 342 | struct resource *this = root->child; |
@@ -330,7 +362,7 @@ static int find_resource(struct resource *root, struct resource *new, | |||
330 | tmp.end = max; | 362 | tmp.end = max; |
331 | tmp.start = ALIGN(tmp.start, align); | 363 | tmp.start = ALIGN(tmp.start, align); |
332 | if (alignf) | 364 | if (alignf) |
333 | alignf(alignf_data, &tmp, size, align); | 365 | tmp.start = alignf(alignf_data, &tmp, size, align); |
334 | if (tmp.start < tmp.end && tmp.end - tmp.start >= size - 1) { | 366 | if (tmp.start < tmp.end && tmp.end - tmp.start >= size - 1) { |
335 | new->start = tmp.start; | 367 | new->start = tmp.start; |
336 | new->end = tmp.start + size - 1; | 368 | new->end = tmp.start + size - 1; |
@@ -358,8 +390,10 @@ static int find_resource(struct resource *root, struct resource *new, | |||
358 | int allocate_resource(struct resource *root, struct resource *new, | 390 | int allocate_resource(struct resource *root, struct resource *new, |
359 | resource_size_t size, resource_size_t min, | 391 | resource_size_t size, resource_size_t min, |
360 | resource_size_t max, resource_size_t align, | 392 | resource_size_t max, resource_size_t align, |
361 | void (*alignf)(void *, struct resource *, | 393 | resource_size_t (*alignf)(void *, |
362 | resource_size_t, resource_size_t), | 394 | const struct resource *, |
395 | resource_size_t, | ||
396 | resource_size_t), | ||
363 | void *alignf_data) | 397 | void *alignf_data) |
364 | { | 398 | { |
365 | int err; | 399 | int err; |