diff options
author | Tony Luck <tony.luck@intel.com> | 2005-01-10 19:50:58 -0800 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2005-01-10 19:50:58 -0800 |
commit | 3c6c37215e29e6e58171e775b15deda1f2f167c6 (patch) | |
tree | 94c433032fbc7bfaacf0cfbbc08ec8c17cc1cbd2 /arch | |
parent | 307bc76b2bd60b153e529090680c1dceb4fc3498 (diff) | |
parent | 872a9465d098476c5cf2e21c53deb70be31b3270 (diff) | |
download | history-3c6c37215e29e6e58171e775b15deda1f2f167c6.tar.gz |
Merge intel.com:/data/home/aegl/BK/Linus
into intel.com:/data/home/aegl/BK/linux-ia64-release-2.6.11
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ia64/Kconfig | 24 | ||||
-rw-r--r-- | arch/ia64/Kconfig.debug | 2 | ||||
-rw-r--r-- | arch/ia64/Makefile | 2 | ||||
-rw-r--r-- | arch/ia64/hp/common/Makefile | 2 | ||||
-rw-r--r-- | arch/ia64/hp/zx1/Makefile | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/acpi.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/setup.c | 25 | ||||
-rw-r--r-- | arch/ia64/lib/swiotlb.c | 16 | ||||
-rw-r--r-- | arch/ia64/pci/pci.c | 114 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pci_dma.c | 64 |
11 files changed, 239 insertions, 15 deletions
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 0b87da9d55b57a..bd846b6596d2fd 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -61,11 +61,12 @@ config IA64_GENERIC will run on any supported IA-64 system. However, if you configure a kernel for your specific system, it will be faster and smaller. - generic For any supported IA-64 system - DIG-compliant For DIG ("Developer's Interface Guide") compliant systems - HP-zx1/sx1000 For HP systems - SGI-SN2 For SGI Altix systems - Ski-simulator For the HP simulator <http://www.hpl.hp.com/research/linux/ski/> + generic For any supported IA-64 system + DIG-compliant For DIG ("Developer's Interface Guide") compliant systems + HP-zx1/sx1000 For HP systems + HP-zx1/sx1000+swiotlb For HP systems with (broken) DMA-constrained devices. + SGI-SN2 For SGI Altix systems + Ski-simulator For the HP simulator <http://www.hpl.hp.com/research/linux/ski/> If you don't know what to do, choose "generic". @@ -78,6 +79,15 @@ config IA64_HP_ZX1 Build a kernel that runs on HP zx1 and sx1000 systems. This adds support for the HP I/O MMU. +config IA64_HP_ZX1_SWIOTLB + bool "HP-zx1/sx1000 with software I/O TLB" + help + Build a kernel that runs on HP zx1 and sx1000 systems even when they + have broken PCI devices which cannot DMA to full 32 bits. Apart + from support for the HP I/O MMU, this includes support for the software + I/O TLB, which allows supporting the broken devices at the expense of + wasting some kernel memory (about 2MB by default). + config IA64_SGI_SN2 bool "SGI-SN2" help @@ -188,7 +198,7 @@ config HOLES_IN_ZONE config DISCONTIGMEM bool "Discontiguous memory support" - depends on (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1) && NUMA && VIRTUAL_MEM_MAP + depends on (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB) && NUMA && VIRTUAL_MEM_MAP default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA help Say Y to support efficient handling of discontiguous physical memory, @@ -326,7 +336,7 @@ menu "Power management and ACPI" config PM bool "Power Management support" - depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 + depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB default y help "Power Management" means that parts of your computer are shut diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug index 19edc8b2c61d8c..de9d507ba0fd46 100644 --- a/arch/ia64/Kconfig.debug +++ b/arch/ia64/Kconfig.debug @@ -16,7 +16,7 @@ config IA64_GRANULE_16MB config IA64_GRANULE_64MB bool "64MB" - depends on !(IA64_GENERIC || IA64_HP_ZX1 || IA64_SGI_SN2) + depends on !(IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_SGI_SN2) endchoice diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 2932ac71bd0b0f..c0b3d95d0f81fe 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -57,11 +57,13 @@ core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/ core-$(CONFIG_IA64_DIG) += arch/ia64/dig/ core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ +core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/ core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ +drivers-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ arch/ia64/sn/ drivers-$(CONFIG_OPROFILE) += arch/ia64/oprofile/ diff --git a/arch/ia64/hp/common/Makefile b/arch/ia64/hp/common/Makefile index e7c7133c7ca773..f61a60057ff7dd 100644 --- a/arch/ia64/hp/common/Makefile +++ b/arch/ia64/hp/common/Makefile @@ -6,3 +6,5 @@ # obj-y := sba_iommu.o +obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += hwsw_iommu.o +obj-$(CONFIG_IA64_GENERIC) += hwsw_iommu.o diff --git a/arch/ia64/hp/zx1/Makefile b/arch/ia64/hp/zx1/Makefile index 64e39aa82a3fd9..61e878729d1ed2 100644 --- a/arch/ia64/hp/zx1/Makefile +++ b/arch/ia64/hp/zx1/Makefile @@ -5,4 +5,4 @@ # Copyright (C) Alex Williamson (alex_williamson@hp.com) # -obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o +obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o hpzx1_swiotlb_machvec.o diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 12d8bf976cc254..c1a02bbc252c7b 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -12,6 +12,7 @@ obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o i obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o obj-$(CONFIG_IA64_HP_ZX1) += acpi-ext.o +obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += acpi-ext.o obj-$(CONFIG_IA64_PALINFO) += palinfo.o obj-$(CONFIG_IOSAPIC) += iosapic.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index baa9c1eee662a5..ca062b9628ab3c 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -113,6 +113,8 @@ acpi_get_sysname (void) return "hpsim"; # elif defined (CONFIG_IA64_HP_ZX1) return "hpzx1"; +# elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB) + return "hpzx1_swiotlb"; # elif defined (CONFIG_IA64_SGI_SN2) return "sn2"; # elif defined (CONFIG_IA64_DIG) diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 7b2033bf09546b..d35bda31d23847 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -1,7 +1,7 @@ /* * Architecture-specific setup. * - * Copyright (C) 1998-2001, 2003 Hewlett-Packard Co + * Copyright (C) 1998-2001, 2003-2004 Hewlett-Packard Co * David Mosberger-Tang <davidm@hpl.hp.com> * Stephane Eranian <eranian@hpl.hp.com> * Copyright (C) 2000, Rohit Seth <rohit.seth@intel.com> @@ -312,7 +312,28 @@ setup_arch (char **cmdline_p) io_port_init(); #ifdef CONFIG_IA64_GENERIC - machvec_init(acpi_get_sysname()); + { + const char *mvec_name = strstr (*cmdline_p, "machvec="); + char str[64]; + + if (mvec_name) { + const char *end; + size_t len; + + mvec_name += 8; + end = strchr (mvec_name, ' '); + if (end) + len = end - mvec_name; + else + len = strlen (mvec_name); + len = min(len, sizeof (str) - 1); + strncpy (str, mvec_name, len); + str[len] = '\0'; + mvec_name = str; + } else + mvec_name = acpi_get_sysname(); + machvec_init(mvec_name); + } #endif if (early_console_setup(*cmdline_p) == 0) diff --git a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c index e4770828db5971..d38b01538184bd 100644 --- a/arch/ia64/lib/swiotlb.c +++ b/arch/ia64/lib/swiotlb.c @@ -61,9 +61,8 @@ static char *io_tlb_start, *io_tlb_end; /* * The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and * io_tlb_end. This is command line adjustable via setup_io_tlb_npages. - * Default to 64MB. */ -static unsigned long io_tlb_nslabs = 32768; +static unsigned long io_tlb_nslabs; /* * When the IOMMU overflows we return a fallback buffer. This sets the size. @@ -113,10 +112,15 @@ __setup("swiotlb=", setup_io_tlb_npages); * structures for the software IO TLB used to implement the PCI DMA API. */ void -swiotlb_init(void) +swiotlb_init_with_default_size (size_t default_size) { unsigned long i; + if (!io_tlb_nslabs) { + io_tlb_nslabs = (default_size >> PAGE_SHIFT); + io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE); + } + /* * Get IO TLB memory from the low pages */ @@ -145,6 +149,12 @@ swiotlb_init(void) virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end)); } +void +swiotlb_init (void) +{ + swiotlb_init_with_default_size(64 * (1<<20)); /* default to 64MB */ +} + static inline int address_needs_mapping(struct device *hwdev, dma_addr_t addr) { diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 01f8eabf3636be..edc8915bb4159b 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -6,6 +6,7 @@ * Copyright (C) 2002 Hewlett-Packard Co * David Mosberger-Tang <davidm@hpl.hp.com> * Bjorn Helgaas <bjorn_helgaas@hp.com> + * Copyright (C) 2004 Silicon Graphics, Inc. * * Note: Above list of copyright holders is incomplete... */ @@ -526,7 +527,7 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, * Leave vm_pgoff as-is, the PCI space address is the physical * address on this platform. */ - vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO); + vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO); if (write_combine) vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); @@ -541,6 +542,117 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, } /** + * pci_mmap_legacy_page_range - map legacy memory space to userland + * @bus: bus whose legacy space we're mapping + * @vma: vma passed in by mmap + * + * Map legacy memory space for this device back to userspace using a machine + * vector to get the base address. + */ +int +pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma) +{ + char *addr; + + addr = pci_get_legacy_mem(bus); + if (IS_ERR(addr)) + return PTR_ERR(addr); + + vma->vm_pgoff += (unsigned long)addr >> PAGE_SHIFT; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO); + + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) + return -EAGAIN; + + return 0; +} + +/** + * ia64_pci_get_legacy_mem - generic legacy mem routine + * @bus: bus to get legacy memory base address for + * + * Find the base of legacy memory for @bus. This is typically the first + * megabyte of bus address space for @bus or is simply 0 on platforms whose + * chipsets support legacy I/O and memory routing. Returns the base address + * or an error pointer if an error occurred. + * + * This is the ia64 generic version of this routine. Other platforms + * are free to override it with a machine vector. + */ +char *ia64_pci_get_legacy_mem(struct pci_bus *bus) +{ + return (char *)__IA64_UNCACHED_OFFSET; +} + +/** + * ia64_pci_legacy_read - read from legacy I/O space + * @bus: bus to read + * @port: legacy port value + * @val: caller allocated storage for returned value + * @size: number of bytes to read + * + * Simply reads @size bytes from @port and puts the result in @val. + * + * Again, this (and the write routine) are generic versions that can be + * overridden by the platform. This is necessary on platforms that don't + * support legacy I/O routing or that hard fail on legacy I/O timeouts. + */ +int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size) +{ + int ret = size; + + switch (size) { + case 1: + *val = inb(port); + break; + case 2: + *val = inw(port); + break; + case 4: + *val = inl(port); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * ia64_pci_legacy_write - perform a legacy I/O write + * @bus: bus pointer + * @port: port to write + * @val: value to write + * @size: number of bytes to write from @val + * + * Simply writes @size bytes of @val to @port. + */ +int ia64_pci_legacy_write(struct pci_dev *bus, u16 port, u32 val, u8 size) +{ + int ret = 0; + + switch (size) { + case 1: + outb(val, port); + break; + case 2: + outw(val, port); + break; + case 4: + outl(val, port); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** * pci_cacheline_size - determine cacheline size for PCI devices * @dev: void * diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index 71f311dc04c3bd..4187f920d26d17 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -475,3 +475,67 @@ EXPORT_SYMBOL(sn_pci_alloc_consistent); EXPORT_SYMBOL(sn_pci_free_consistent); EXPORT_SYMBOL(sn_pci_dma_supported); EXPORT_SYMBOL(sn_dma_mapping_error); + +char *sn_pci_get_legacy_mem(struct pci_bus *bus) +{ + if (!SN_PCIBUS_BUSSOFT(bus)) + return ERR_PTR(-ENODEV); + + return (char *)(SN_PCIBUS_BUSSOFT(bus)->bs_legacy_mem | __IA64_UNCACHED_OFFSET); +} + +int sn_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size) +{ + unsigned long addr; + int ret; + + if (!SN_PCIBUS_BUSSOFT(bus)) + return -ENODEV; + + addr = SN_PCIBUS_BUSSOFT(bus)->bs_legacy_io | __IA64_UNCACHED_OFFSET; + addr += port; + + ret = ia64_sn_probe_mem(addr, (long)size, (void *)val); + + if (ret == 2) + return -EINVAL; + + if (ret == 1) + *val = -1; + + return size; +} + +int sn_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size) +{ + int ret = size; + unsigned long paddr; + unsigned long *addr; + + if (!SN_PCIBUS_BUSSOFT(bus)) { + ret = -ENODEV; + goto out; + } + + /* Put the phys addr in uncached space */ + paddr = SN_PCIBUS_BUSSOFT(bus)->bs_legacy_io | __IA64_UNCACHED_OFFSET; + paddr += port; + addr = (unsigned long *)paddr; + + switch (size) { + case 1: + *(volatile u8 *)(addr) = (u8)(val); + break; + case 2: + *(volatile u16 *)(addr) = (u16)(val); + break; + case 4: + *(volatile u32 *)(addr) = (u32)(val); + break; + default: + ret = -EINVAL; + break; + } + out: + return ret; +} |