diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-20 16:40:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-20 16:40:47 -0400 |
commit | a0bfb673dca8a2b4324fe11e678ec6d6a9ad67e0 (patch) | |
tree | b5a473c95d671e6a62fc4520d01a7a4721820794 /arch | |
parent | 92b29b86fe2e183d44eb467e5e74a5f718ef2e43 (diff) | |
parent | 96499871f45b9126157b1a5c512d6e30f1635225 (diff) |
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (41 commits)
PCI: fix pci_ioremap_bar() on s390
PCI: fix AER capability check
PCI: use pci_find_ext_capability everywhere
PCI: remove #ifdef DEBUG around dev_dbg call
PCI hotplug: fix get_##name return value problem
PCI: document the pcie_aspm kernel parameter
PCI: introduce an pci_ioremap(pdev, barnr) function
powerpc/PCI: Add legacy PCI access via sysfs
PCI: Add ability to mmap legacy_io on some platforms
PCI: probing debug message uniformization
PCI: support PCIe ARI capability
PCI: centralize the capabilities code in probe.c
PCI: centralize the capabilities code in pci-sysfs.c
PCI: fix 64-vbit prefetchable memory resource BARs
PCI: replace cfg space size (256/4096) by macros.
PCI: use resource_size() everywhere.
PCI: use same arg names in PCI_VDEVICE comment
PCI hotplug: rpaphp: make debug var unique
PCI: use %pF instead of print_fn_descriptor_symbol() in quirks.c
PCI: fix hotplug get_##name return value problem
...
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ia64/include/asm/pci.h | 12 | ||||
-rw-r--r-- | arch/ia64/pci/pci.c | 7 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pci-bridge.h | 7 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pci.h | 11 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 136 | ||||
-rw-r--r-- | arch/x86/pci/irq.c | 19 |
6 files changed, 174 insertions, 18 deletions
diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h index 0149097b736d..ce342fb74246 100644 --- a/arch/ia64/include/asm/pci.h +++ b/arch/ia64/include/asm/pci.h | |||
@@ -95,16 +95,8 @@ extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, | |||
95 | enum pci_mmap_state mmap_state, int write_combine); | 95 | enum pci_mmap_state mmap_state, int write_combine); |
96 | #define HAVE_PCI_LEGACY | 96 | #define HAVE_PCI_LEGACY |
97 | extern int pci_mmap_legacy_page_range(struct pci_bus *bus, | 97 | extern int pci_mmap_legacy_page_range(struct pci_bus *bus, |
98 | struct vm_area_struct *vma); | 98 | struct vm_area_struct *vma, |
99 | extern ssize_t pci_read_legacy_io(struct kobject *kobj, | 99 | enum pci_mmap_state mmap_state); |
100 | struct bin_attribute *bin_attr, | ||
101 | char *buf, loff_t off, size_t count); | ||
102 | extern ssize_t pci_write_legacy_io(struct kobject *kobj, | ||
103 | struct bin_attribute *bin_attr, | ||
104 | char *buf, loff_t off, size_t count); | ||
105 | extern int pci_mmap_legacy_mem(struct kobject *kobj, | ||
106 | struct bin_attribute *attr, | ||
107 | struct vm_area_struct *vma); | ||
108 | 100 | ||
109 | #define pci_get_legacy_mem platform_pci_get_legacy_mem | 101 | #define pci_get_legacy_mem platform_pci_get_legacy_mem |
110 | #define pci_legacy_read platform_pci_legacy_read | 102 | #define pci_legacy_read platform_pci_legacy_read |
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 7545037a8625..211fcfd115f9 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
@@ -614,12 +614,17 @@ char *ia64_pci_get_legacy_mem(struct pci_bus *bus) | |||
614 | * vector to get the base address. | 614 | * vector to get the base address. |
615 | */ | 615 | */ |
616 | int | 616 | int |
617 | pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma) | 617 | pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma, |
618 | enum pci_mmap_state mmap_state) | ||
618 | { | 619 | { |
619 | unsigned long size = vma->vm_end - vma->vm_start; | 620 | unsigned long size = vma->vm_end - vma->vm_start; |
620 | pgprot_t prot; | 621 | pgprot_t prot; |
621 | char *addr; | 622 | char *addr; |
622 | 623 | ||
624 | /* We only support mmap'ing of legacy memory space */ | ||
625 | if (mmap_state != pci_mmap_mem) | ||
626 | return -ENOSYS; | ||
627 | |||
623 | /* | 628 | /* |
624 | * Avoid attribute aliasing. See Documentation/ia64/aliasing.txt | 629 | * Avoid attribute aliasing. See Documentation/ia64/aliasing.txt |
625 | * for more details. | 630 | * for more details. |
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index ae2ea803a0f2..9047af7baa69 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h | |||
@@ -74,6 +74,13 @@ struct pci_controller { | |||
74 | unsigned long pci_io_size; | 74 | unsigned long pci_io_size; |
75 | #endif | 75 | #endif |
76 | 76 | ||
77 | /* Some machines have a special region to forward the ISA | ||
78 | * "memory" cycles such as VGA memory regions. Left to 0 | ||
79 | * if unsupported | ||
80 | */ | ||
81 | resource_size_t isa_mem_phys; | ||
82 | resource_size_t isa_mem_size; | ||
83 | |||
77 | struct pci_ops *ops; | 84 | struct pci_ops *ops; |
78 | unsigned int __iomem *cfg_addr; | 85 | unsigned int __iomem *cfg_addr; |
79 | void __iomem *cfg_data; | 86 | void __iomem *cfg_data; |
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h index 0e52c7828ea4..39d547fde956 100644 --- a/arch/powerpc/include/asm/pci.h +++ b/arch/powerpc/include/asm/pci.h | |||
@@ -123,6 +123,16 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, | |||
123 | /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */ | 123 | /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */ |
124 | #define HAVE_PCI_MMAP 1 | 124 | #define HAVE_PCI_MMAP 1 |
125 | 125 | ||
126 | extern int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val, | ||
127 | size_t count); | ||
128 | extern int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val, | ||
129 | size_t count); | ||
130 | extern int pci_mmap_legacy_page_range(struct pci_bus *bus, | ||
131 | struct vm_area_struct *vma, | ||
132 | enum pci_mmap_state mmap_state); | ||
133 | |||
134 | #define HAVE_PCI_LEGACY 1 | ||
135 | |||
126 | #if defined(CONFIG_PPC64) || defined(CONFIG_NOT_COHERENT_CACHE) | 136 | #if defined(CONFIG_PPC64) || defined(CONFIG_NOT_COHERENT_CACHE) |
127 | /* | 137 | /* |
128 | * For 64-bit kernels, pci_unmap_{single,page} is not a nop. | 138 | * For 64-bit kernels, pci_unmap_{single,page} is not a nop. |
@@ -226,5 +236,6 @@ extern void pci_resource_to_user(const struct pci_dev *dev, int bar, | |||
226 | extern void pcibios_do_bus_setup(struct pci_bus *bus); | 236 | extern void pcibios_do_bus_setup(struct pci_bus *bus); |
227 | extern void pcibios_fixup_of_probed_bus(struct pci_bus *bus); | 237 | extern void pcibios_fixup_of_probed_bus(struct pci_bus *bus); |
228 | 238 | ||
239 | |||
229 | #endif /* __KERNEL__ */ | 240 | #endif /* __KERNEL__ */ |
230 | #endif /* __ASM_POWERPC_PCI_H */ | 241 | #endif /* __ASM_POWERPC_PCI_H */ |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 01ce8c38bae6..3815d84a1ef4 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -451,7 +451,8 @@ pgprot_t pci_phys_mem_access_prot(struct file *file, | |||
451 | pci_dev_put(pdev); | 451 | pci_dev_put(pdev); |
452 | } | 452 | } |
453 | 453 | ||
454 | DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | 454 | DBG("non-PCI map for %llx, prot: %lx\n", |
455 | (unsigned long long)offset, prot); | ||
455 | 456 | ||
456 | return __pgprot(prot); | 457 | return __pgprot(prot); |
457 | } | 458 | } |
@@ -490,6 +491,131 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | |||
490 | return ret; | 491 | return ret; |
491 | } | 492 | } |
492 | 493 | ||
494 | /* This provides legacy IO read access on a bus */ | ||
495 | int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val, size_t size) | ||
496 | { | ||
497 | unsigned long offset; | ||
498 | struct pci_controller *hose = pci_bus_to_host(bus); | ||
499 | struct resource *rp = &hose->io_resource; | ||
500 | void __iomem *addr; | ||
501 | |||
502 | /* Check if port can be supported by that bus. We only check | ||
503 | * the ranges of the PHB though, not the bus itself as the rules | ||
504 | * for forwarding legacy cycles down bridges are not our problem | ||
505 | * here. So if the host bridge supports it, we do it. | ||
506 | */ | ||
507 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
508 | offset += port; | ||
509 | |||
510 | if (!(rp->flags & IORESOURCE_IO)) | ||
511 | return -ENXIO; | ||
512 | if (offset < rp->start || (offset + size) > rp->end) | ||
513 | return -ENXIO; | ||
514 | addr = hose->io_base_virt + port; | ||
515 | |||
516 | switch(size) { | ||
517 | case 1: | ||
518 | *((u8 *)val) = in_8(addr); | ||
519 | return 1; | ||
520 | case 2: | ||
521 | if (port & 1) | ||
522 | return -EINVAL; | ||
523 | *((u16 *)val) = in_le16(addr); | ||
524 | return 2; | ||
525 | case 4: | ||
526 | if (port & 3) | ||
527 | return -EINVAL; | ||
528 | *((u32 *)val) = in_le32(addr); | ||
529 | return 4; | ||
530 | } | ||
531 | return -EINVAL; | ||
532 | } | ||
533 | |||
534 | /* This provides legacy IO write access on a bus */ | ||
535 | int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val, size_t size) | ||
536 | { | ||
537 | unsigned long offset; | ||
538 | struct pci_controller *hose = pci_bus_to_host(bus); | ||
539 | struct resource *rp = &hose->io_resource; | ||
540 | void __iomem *addr; | ||
541 | |||
542 | /* Check if port can be supported by that bus. We only check | ||
543 | * the ranges of the PHB though, not the bus itself as the rules | ||
544 | * for forwarding legacy cycles down bridges are not our problem | ||
545 | * here. So if the host bridge supports it, we do it. | ||
546 | */ | ||
547 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
548 | offset += port; | ||
549 | |||
550 | if (!(rp->flags & IORESOURCE_IO)) | ||
551 | return -ENXIO; | ||
552 | if (offset < rp->start || (offset + size) > rp->end) | ||
553 | return -ENXIO; | ||
554 | addr = hose->io_base_virt + port; | ||
555 | |||
556 | /* WARNING: The generic code is idiotic. It gets passed a pointer | ||
557 | * to what can be a 1, 2 or 4 byte quantity and always reads that | ||
558 | * as a u32, which means that we have to correct the location of | ||
559 | * the data read within those 32 bits for size 1 and 2 | ||
560 | */ | ||
561 | switch(size) { | ||
562 | case 1: | ||
563 | out_8(addr, val >> 24); | ||
564 | return 1; | ||
565 | case 2: | ||
566 | if (port & 1) | ||
567 | return -EINVAL; | ||
568 | out_le16(addr, val >> 16); | ||
569 | return 2; | ||
570 | case 4: | ||
571 | if (port & 3) | ||
572 | return -EINVAL; | ||
573 | out_le32(addr, val); | ||
574 | return 4; | ||
575 | } | ||
576 | return -EINVAL; | ||
577 | } | ||
578 | |||
579 | /* This provides legacy IO or memory mmap access on a bus */ | ||
580 | int pci_mmap_legacy_page_range(struct pci_bus *bus, | ||
581 | struct vm_area_struct *vma, | ||
582 | enum pci_mmap_state mmap_state) | ||
583 | { | ||
584 | struct pci_controller *hose = pci_bus_to_host(bus); | ||
585 | resource_size_t offset = | ||
586 | ((resource_size_t)vma->vm_pgoff) << PAGE_SHIFT; | ||
587 | resource_size_t size = vma->vm_end - vma->vm_start; | ||
588 | struct resource *rp; | ||
589 | |||
590 | pr_debug("pci_mmap_legacy_page_range(%04x:%02x, %s @%llx..%llx)\n", | ||
591 | pci_domain_nr(bus), bus->number, | ||
592 | mmap_state == pci_mmap_mem ? "MEM" : "IO", | ||
593 | (unsigned long long)offset, | ||
594 | (unsigned long long)(offset + size - 1)); | ||
595 | |||
596 | if (mmap_state == pci_mmap_mem) { | ||
597 | if ((offset + size) > hose->isa_mem_size) | ||
598 | return -ENXIO; | ||
599 | offset += hose->isa_mem_phys; | ||
600 | } else { | ||
601 | unsigned long io_offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
602 | unsigned long roffset = offset + io_offset; | ||
603 | rp = &hose->io_resource; | ||
604 | if (!(rp->flags & IORESOURCE_IO)) | ||
605 | return -ENXIO; | ||
606 | if (roffset < rp->start || (roffset + size) > rp->end) | ||
607 | return -ENXIO; | ||
608 | offset += hose->io_base_phys; | ||
609 | } | ||
610 | pr_debug(" -> mapping phys %llx\n", (unsigned long long)offset); | ||
611 | |||
612 | vma->vm_pgoff = offset >> PAGE_SHIFT; | ||
613 | vma->vm_page_prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||
614 | return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||
615 | vma->vm_end - vma->vm_start, | ||
616 | vma->vm_page_prot); | ||
617 | } | ||
618 | |||
493 | void pci_resource_to_user(const struct pci_dev *dev, int bar, | 619 | void pci_resource_to_user(const struct pci_dev *dev, int bar, |
494 | const struct resource *rsrc, | 620 | const struct resource *rsrc, |
495 | resource_size_t *start, resource_size_t *end) | 621 | resource_size_t *start, resource_size_t *end) |
@@ -592,6 +718,12 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
592 | cpu_addr = of_translate_address(dev, ranges + 3); | 718 | cpu_addr = of_translate_address(dev, ranges + 3); |
593 | size = of_read_number(ranges + pna + 3, 2); | 719 | size = of_read_number(ranges + pna + 3, 2); |
594 | ranges += np; | 720 | ranges += np; |
721 | |||
722 | /* If we failed translation or got a zero-sized region | ||
723 | * (some FW try to feed us with non sensical zero sized regions | ||
724 | * such as power3 which look like some kind of attempt at exposing | ||
725 | * the VGA memory hole) | ||
726 | */ | ||
595 | if (cpu_addr == OF_BAD_ADDR || size == 0) | 727 | if (cpu_addr == OF_BAD_ADDR || size == 0) |
596 | continue; | 728 | continue; |
597 | 729 | ||
@@ -665,6 +797,8 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
665 | isa_hole = memno; | 797 | isa_hole = memno; |
666 | if (primary || isa_mem_base == 0) | 798 | if (primary || isa_mem_base == 0) |
667 | isa_mem_base = cpu_addr; | 799 | isa_mem_base = cpu_addr; |
800 | hose->isa_mem_phys = cpu_addr; | ||
801 | hose->isa_mem_size = size; | ||
668 | } | 802 | } |
669 | 803 | ||
670 | /* We get the PCI/Mem offset from the first range or | 804 | /* We get the PCI/Mem offset from the first range or |
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 006599db0dc7..bf69dbe08bff 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c | |||
@@ -493,7 +493,7 @@ static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq | |||
493 | if (pirq <= 4) | 493 | if (pirq <= 4) |
494 | irq = read_config_nybble(router, 0x56, pirq - 1); | 494 | irq = read_config_nybble(router, 0x56, pirq - 1); |
495 | dev_info(&dev->dev, | 495 | dev_info(&dev->dev, |
496 | "AMD756: dev [%04x/%04x], router PIRQ %d get IRQ %d\n", | 496 | "AMD756: dev [%04x:%04x], router PIRQ %d get IRQ %d\n", |
497 | dev->vendor, dev->device, pirq, irq); | 497 | dev->vendor, dev->device, pirq, irq); |
498 | return irq; | 498 | return irq; |
499 | } | 499 | } |
@@ -501,7 +501,7 @@ static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq | |||
501 | static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | 501 | static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) |
502 | { | 502 | { |
503 | dev_info(&dev->dev, | 503 | dev_info(&dev->dev, |
504 | "AMD756: dev [%04x/%04x], router PIRQ %d set IRQ %d\n", | 504 | "AMD756: dev [%04x:%04x], router PIRQ %d set IRQ %d\n", |
505 | dev->vendor, dev->device, pirq, irq); | 505 | dev->vendor, dev->device, pirq, irq); |
506 | if (pirq <= 4) | 506 | if (pirq <= 4) |
507 | write_config_nybble(router, 0x56, pirq - 1, irq); | 507 | write_config_nybble(router, 0x56, pirq - 1, irq); |
@@ -590,13 +590,20 @@ 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_PCH_0: | ||
594 | case PCI_DEVICE_ID_INTEL_PCH_1: | ||
595 | r->name = "PIIX/ICH"; | 593 | r->name = "PIIX/ICH"; |
596 | r->get = pirq_piix_get; | 594 | r->get = pirq_piix_get; |
597 | r->set = pirq_piix_set; | 595 | r->set = pirq_piix_set; |
598 | return 1; | 596 | return 1; |
599 | } | 597 | } |
598 | |||
599 | if ((device >= PCI_DEVICE_ID_INTEL_PCH_LPC_MIN) && | ||
600 | (device <= PCI_DEVICE_ID_INTEL_PCH_LPC_MAX)) { | ||
601 | r->name = "PIIX/ICH"; | ||
602 | r->get = pirq_piix_get; | ||
603 | r->set = pirq_piix_set; | ||
604 | return 1; | ||
605 | } | ||
606 | |||
600 | return 0; | 607 | return 0; |
601 | } | 608 | } |
602 | 609 | ||
@@ -823,7 +830,7 @@ static void __init pirq_find_router(struct irq_router *r) | |||
823 | r->get = NULL; | 830 | r->get = NULL; |
824 | r->set = NULL; | 831 | r->set = NULL; |
825 | 832 | ||
826 | DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for %04x:%04x\n", | 833 | DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for [%04x:%04x]\n", |
827 | rt->rtr_vendor, rt->rtr_device); | 834 | rt->rtr_vendor, rt->rtr_device); |
828 | 835 | ||
829 | pirq_router_dev = pci_get_bus_and_slot(rt->rtr_bus, rt->rtr_devfn); | 836 | pirq_router_dev = pci_get_bus_and_slot(rt->rtr_bus, rt->rtr_devfn); |
@@ -843,7 +850,7 @@ static void __init pirq_find_router(struct irq_router *r) | |||
843 | h->probe(r, pirq_router_dev, pirq_router_dev->device)) | 850 | h->probe(r, pirq_router_dev, pirq_router_dev->device)) |
844 | break; | 851 | break; |
845 | } | 852 | } |
846 | dev_info(&pirq_router_dev->dev, "%s IRQ router [%04x/%04x]\n", | 853 | dev_info(&pirq_router_dev->dev, "%s IRQ router [%04x:%04x]\n", |
847 | pirq_router.name, | 854 | pirq_router.name, |
848 | pirq_router_dev->vendor, pirq_router_dev->device); | 855 | pirq_router_dev->vendor, pirq_router_dev->device); |
849 | 856 | ||