aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-20 16:40:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-20 16:40:47 -0400
commita0bfb673dca8a2b4324fe11e678ec6d6a9ad67e0 (patch)
treeb5a473c95d671e6a62fc4520d01a7a4721820794 /arch
parent92b29b86fe2e183d44eb467e5e74a5f718ef2e43 (diff)
parent96499871f45b9126157b1a5c512d6e30f1635225 (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.h12
-rw-r--r--arch/ia64/pci/pci.c7
-rw-r--r--arch/powerpc/include/asm/pci-bridge.h7
-rw-r--r--arch/powerpc/include/asm/pci.h11
-rw-r--r--arch/powerpc/kernel/pci-common.c136
-rw-r--r--arch/x86/pci/irq.c19
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
97extern int pci_mmap_legacy_page_range(struct pci_bus *bus, 97extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
98 struct vm_area_struct *vma); 98 struct vm_area_struct *vma,
99extern 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);
102extern ssize_t pci_write_legacy_io(struct kobject *kobj,
103 struct bin_attribute *bin_attr,
104 char *buf, loff_t off, size_t count);
105extern 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 */
616int 616int
617pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma) 617pci_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
126extern int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val,
127 size_t count);
128extern int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val,
129 size_t count);
130extern 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,
226extern void pcibios_do_bus_setup(struct pci_bus *bus); 236extern void pcibios_do_bus_setup(struct pci_bus *bus);
227extern void pcibios_fixup_of_probed_bus(struct pci_bus *bus); 237extern 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 */
495int 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 */
535int 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 */
580int 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
493void pci_resource_to_user(const struct pci_dev *dev, int bar, 619void 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
501static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) 501static 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