From 4fb416f4abe28a060a5a5b6aba60af0924e0f27c Mon Sep 17 00:00:00 2001 From: Andi Kleen <ak@suse.de> Date: Sun, 15 Jun 2003 20:10:50 -0700 Subject: [PATCH] [PATCH] x86-64 merge Lots of small fixes and I merged the PCI subsystem with i386 again because it was mostly identical. This makes the patch quite big, but it only removes files. - Merge PCI subsystem with i386. This changes the initialization order of PCI and IOMMU slightly. It didn't see any problems yet, but it could cause some in theory. It re-adds some code that used to be removed, but it's only small stuff and it should hopefully cause less mainteance overhead longer term. - Fix warnings - Merge cpuid.c with i386.c - Sync msr.c with i386 - Consolidate externs in asm/proto.h - sysfs/sysdev fixes for apic/nmi (Bryan O'Sullivan) - Fix /proc/kcore access - Add real kern_addr_valid (used for above). - Support consistent dma_mask in IOMMU - Fix double print of AMD for CPU model. - Remove unused wakeup.S file. - Remove obsolete CONFIG_SIMNOW ifdef. - Support ptrace access for 32bit vsyscalls. - Fix warnings in 32bit boot code compilation. --- arch/x86_64/Makefile | 1 - arch/x86_64/ia32/vsyscall.S | 2 +- arch/x86_64/kernel/Makefile | 4 +- arch/x86_64/kernel/aperture.c | 2 - arch/x86_64/kernel/apic.c | 34 +- arch/x86_64/kernel/bluesmoke.c | 3 +- arch/x86_64/kernel/cpuid.c | 178 --------- arch/x86_64/kernel/ldt.c | 3 +- arch/x86_64/kernel/msr.c | 24 +- arch/x86_64/kernel/nmi.c | 44 +-- arch/x86_64/kernel/pci-gart.c | 34 +- arch/x86_64/kernel/pci-nommu.c | 3 +- arch/x86_64/kernel/process.c | 2 - arch/x86_64/kernel/setup.c | 2 +- arch/x86_64/kernel/signal.c | 2 - arch/x86_64/kernel/smpboot.c | 12 +- arch/x86_64/kernel/time.c | 4 +- arch/x86_64/kernel/traps.c | 9 +- arch/x86_64/kernel/wakeup.S | 306 ---------------- arch/x86_64/lib/delay.c | 2 - arch/x86_64/mm/init.c | 43 ++- arch/x86_64/pci/Makefile | 23 +- arch/x86_64/pci/acpi.c | 27 -- arch/x86_64/pci/changelog | 1 - arch/x86_64/pci/common.c | 212 ----------- arch/x86_64/pci/direct.c | 281 --------------- arch/x86_64/pci/fixup.c | 48 --- arch/x86_64/pci/irq.c | 639 --------------------------------- arch/x86_64/pci/legacy.c | 68 ---- arch/x86_64/pci/pci.h | 75 ---- arch/x86_64/pci/x86-64.c | 299 --------------- include/asm-x86_64/fixmap.h | 5 + include/asm-x86_64/io.h | 2 +- include/asm-x86_64/mmzone.h | 14 - include/asm-x86_64/page.h | 2 + include/asm-x86_64/pci.h | 1 - include/asm-x86_64/pgtable.h | 11 +- include/asm-x86_64/proto.h | 22 +- 38 files changed, 178 insertions(+), 2266 deletions(-) delete mode 100644 arch/x86_64/kernel/cpuid.c delete mode 100644 arch/x86_64/kernel/wakeup.S delete mode 100644 arch/x86_64/pci/acpi.c delete mode 100644 arch/x86_64/pci/changelog delete mode 100644 arch/x86_64/pci/common.c delete mode 100644 arch/x86_64/pci/direct.c delete mode 100644 arch/x86_64/pci/fixup.c delete mode 100644 arch/x86_64/pci/irq.c delete mode 100644 arch/x86_64/pci/legacy.c delete mode 100644 arch/x86_64/pci/pci.h delete mode 100644 arch/x86_64/pci/x86-64.c diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index 1faa3f4937ab..35447c84d97c 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile @@ -42,7 +42,6 @@ CFLAGS += -mno-red-zone CFLAGS += -mcmodel=kernel CFLAGS += -pipe # this makes reading assembly source easier, but produces worse code -# disable for production kernel CFLAGS += -fno-reorder-blocks # should lower this a lot and see how much .text is saves CFLAGS += -finline-limit=2000 diff --git a/arch/x86_64/ia32/vsyscall.S b/arch/x86_64/ia32/vsyscall.S index c7af4f64d9e8..1cde011239ce 100644 --- a/arch/x86_64/ia32/vsyscall.S +++ b/arch/x86_64/ia32/vsyscall.S @@ -35,7 +35,7 @@ __kernel_sigreturn: .section .text.rtsigreturn,"ax" .balign 32 - .globl __kernel_rt_sigreturn,"ax" + .globl __kernel_rt_sigreturn .type __kernel_rt_sigreturn,@function __kernel_rt_sigreturn: .LSTART_rt_sigreturn: diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index 765fa7d91c80..128cd3867de8 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile @@ -24,6 +24,8 @@ obj-$(CONFIG_MODULES) += module.o $(obj)/bootflag.c: @ln -sf ../../i386/kernel/bootflag.c $(obj)/bootflag.c +$(obj)/cpuid.c: + @ln -sf ../../i386/kernel/cpuid.c $(obj)/cpuid.c -clean-files += bootflag.c +clean-files += bootflag.c cpuid.c diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c index 871394fa7547..aedd584b7ae0 100644 --- a/arch/x86_64/kernel/aperture.c +++ b/arch/x86_64/kernel/aperture.c @@ -25,8 +25,6 @@ int fallback_aper_order __initdata = 1; /* 64MB */ int fallback_aper_force __initdata = 0; -extern int no_iommu, force_mmu; - /* This code runs before the PCI subsystem is initialized, so just access the northbridge directly. */ diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 1addbb749ec2..f4e2169b1508 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -25,6 +25,7 @@ #include <linux/interrupt.h> #include <linux/mc146818rtc.h> #include <linux/kernel_stat.h> +#include <linux/sysdev.h> #include <asm/atomic.h> #include <asm/smp.h> @@ -464,13 +465,11 @@ static struct { unsigned int apic_thmr; } apic_pm_state; -static int lapic_suspend(struct device *dev, u32 state, u32 level) +static int lapic_suspend(struct sys_device *dev, u32 state) { unsigned int l, h; unsigned long flags; - if (level != SUSPEND_POWER_DOWN) - return 0; if (!apic_pm_state.active) return 0; @@ -497,13 +496,11 @@ static int lapic_suspend(struct device *dev, u32 state, u32 level) return 0; } -static int lapic_resume(struct device *dev, u32 level) +static int lapic_resume(struct sys_device *dev) { unsigned int l, h; unsigned long flags; - if (level != RESUME_POWER_ON) - return 0; if (!apic_pm_state.active) return 0; @@ -537,38 +534,35 @@ static int lapic_resume(struct device *dev, u32 level) return 0; } -static struct device_driver lapic_driver = { - .name = "lapic", - .bus = &system_bus_type, +static struct sysdev_class lapic_sysclass = { + set_kset_name("lapic"), .resume = lapic_resume, .suspend = lapic_suspend, }; /* not static, needed by child devices */ -struct sys_device device_lapic = { - .name = "lapic", +static struct sys_device device_lapic = { .id = 0, - .dev = { - .name = "lapic", - .driver = &lapic_driver, - }, + .cls = &lapic_sysclass, }; -EXPORT_SYMBOL(device_lapic); static void __init apic_pm_activate(void) { apic_pm_state.active = 1; } -static int __init init_lapic_devicefs(void) +static int __init init_lapic_sysfs(void) { + int error; if (!cpu_has_apic) return 0; /* XXX: remove suspend/resume procs if !apic_pm_state.active? */ - driver_register(&lapic_driver); - return sys_device_register(&device_lapic); + error = sysdev_class_register(&lapic_sysclass); + if (!error) + error = sys_device_register(&device_lapic); + return error; } -device_initcall(init_lapic_devicefs); +device_initcall(init_lapic_sysfs); #else /* CONFIG_PM */ diff --git a/arch/x86_64/kernel/bluesmoke.c b/arch/x86_64/kernel/bluesmoke.c index 392b8bab96ee..bd71684c0e6e 100644 --- a/arch/x86_64/kernel/bluesmoke.c +++ b/arch/x86_64/kernel/bluesmoke.c @@ -303,7 +303,7 @@ static void k8_machine_check(struct pt_regs * regs, long error_code) wrmsrl(MSR_IA32_MCG_STATUS, 0); if (regs && (status & (1<<1))) - printk(KERN_EMERG "MCE at EIP %lx ESP %lx\n", regs->rip, regs->rsp); + printk(KERN_EMERG "MCE at RIP %lx RSP %lx\n", regs->rip, regs->rsp); others: generic_machine_check(regs, error_code); @@ -352,7 +352,6 @@ static void __init k8_mcheck_init(struct cpuinfo_x86 *c) { u64 cap; int i; - struct pci_dev *nb; if (!test_bit(X86_FEATURE_MCE, &c->x86_capability) || !test_bit(X86_FEATURE_MCA, &c->x86_capability)) diff --git a/arch/x86_64/kernel/cpuid.c b/arch/x86_64/kernel/cpuid.c deleted file mode 100644 index c8f38e2e9f9c..000000000000 --- a/arch/x86_64/kernel/cpuid.c +++ /dev/null @@ -1,178 +0,0 @@ -#ident "$Id: cpuid.c,v 1.4 2001/10/24 23:58:53 ak Exp $" -/* ----------------------------------------------------------------------- * - * - * Copyright 2000 H. Peter Anvin - All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, - * USA; either version 2 of the License, or (at your option) any later - * version; incorporated herein by reference. - * - * ----------------------------------------------------------------------- */ - - -/* - * cpuid.c - * - * x86 CPUID access device - * - * This device is accessed by lseek() to the appropriate CPUID level - * and then read in chunks of 16 bytes. A larger size means multiple - * reads of consecutive levels. - * - * This driver uses /dev/cpu/%d/cpuid where %d is the minor number, and on - * an SMP box will direct the access to CPU %d. - */ - -#include <linux/module.h> -#include <linux/config.h> - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/fcntl.h> -#include <linux/init.h> -#include <linux/poll.h> -#include <linux/smp.h> -#include <linux/major.h> -#include <linux/fs.h> -#include <linux/smp_lock.h> -#include <linux/fs.h> - -#include <asm/processor.h> -#include <asm/msr.h> -#include <asm/uaccess.h> -#include <asm/system.h> - -#ifdef CONFIG_SMP - -struct cpuid_command { - int cpu; - u32 reg; - u32 *data; -}; - -static void cpuid_smp_cpuid(void *cmd_block) -{ - struct cpuid_command *cmd = (struct cpuid_command *) cmd_block; - - if ( cmd->cpu == smp_processor_id() ) - cpuid(cmd->reg, &cmd->data[0], &cmd->data[1], &cmd->data[2], &cmd->data[3]); -} - -static inline void do_cpuid(int cpu, u32 reg, u32 *data) -{ - struct cpuid_command cmd; - - preempt_disable(); - if ( cpu == smp_processor_id() ) { - cpuid(reg, &data[0], &data[1], &data[2], &data[3]); - } else { - cmd.cpu = cpu; - cmd.reg = reg; - cmd.data = data; - - smp_call_function(cpuid_smp_cpuid, &cmd, 1, 1); - } - preempt_enable(); -} -#else /* ! CONFIG_SMP */ - -static inline void do_cpuid(int cpu, u32 reg, u32 *data) -{ - cpuid(reg, &data[0], &data[1], &data[2], &data[3]); -} - -#endif /* ! CONFIG_SMP */ - -static loff_t cpuid_seek(struct file *file, loff_t offset, int orig) -{ - loff_t ret; - - lock_kernel(); - - switch (orig) { - case 0: - file->f_pos = offset; - ret = file->f_pos; - break; - case 1: - file->f_pos += offset; - ret = file->f_pos; - break; - default: - ret = -EINVAL; - } - - unlock_kernel(); - return ret; -} - -static ssize_t cpuid_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - u32 *tmp = (u32 *)buf; - u32 data[4]; - size_t rv; - u32 reg = *ppos; - int cpu = minor(file->f_dentry->d_inode->i_rdev); - - if ( count % 16 ) - return -EINVAL; /* Invalid chunk size */ - - for ( rv = 0 ; count ; count -= 16 ) { - do_cpuid(cpu, reg, data); - if ( copy_to_user(tmp,&data,16) ) - return -EFAULT; - tmp += 4; - *ppos = reg++; - } - - return ((char *)tmp) - buf; -} - -static int cpuid_open(struct inode *inode, struct file *file) -{ - int cpu = minor(file->f_dentry->d_inode->i_rdev); - struct cpuinfo_x86 *c = &(cpu_data)[cpu]; - - if ( !(cpu_online_map & (1UL << cpu)) ) - return -ENXIO; /* No such CPU */ - if ( c->cpuid_level < 0 ) - return -EIO; /* CPUID not supported */ - - return 0; -} - -/* - * File operations we support - */ -static struct file_operations cpuid_fops = { - .owner = THIS_MODULE, - .llseek = cpuid_seek, - .read = cpuid_read, - .open = cpuid_open, -}; - -int __init cpuid_init(void) -{ - if (register_chrdev(CPUID_MAJOR, "cpu/cpuid", &cpuid_fops)) { - printk(KERN_ERR "cpuid: unable to get major %d for cpuid\n", - CPUID_MAJOR); - return -EBUSY; - } - - return 0; -} - -void __exit cpuid_exit(void) -{ - unregister_chrdev(CPUID_MAJOR, "cpu/cpuid"); -} - -module_init(cpuid_init); -module_exit(cpuid_exit) - -MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>"); -MODULE_DESCRIPTION("x86 generic CPUID driver"); -MODULE_LICENSE("GPL"); diff --git a/arch/x86_64/kernel/ldt.c b/arch/x86_64/kernel/ldt.c index 1b7c821593b9..cd14f4b67b4e 100644 --- a/arch/x86_64/kernel/ldt.c +++ b/arch/x86_64/kernel/ldt.c @@ -21,8 +21,7 @@ #include <asm/system.h> #include <asm/ldt.h> #include <asm/desc.h> - -extern void load_gs_index(unsigned gs); +#include <asm/proto.h> #ifdef CONFIG_SMP /* avoids "defined but not used" warnig */ static void flush_ldt(void *null) diff --git a/arch/x86_64/kernel/msr.c b/arch/x86_64/kernel/msr.c index bf1cbac3cdf5..52e21f71d403 100644 --- a/arch/x86_64/kernel/msr.c +++ b/arch/x86_64/kernel/msr.c @@ -1,4 +1,4 @@ -#ident "$Id: msr.c,v 1.6 2001/10/24 23:58:53 ak Exp $" +#ident "$Id$" /* ----------------------------------------------------------------------- * * * Copyright 2000 H. Peter Anvin - All Rights Reserved @@ -22,9 +22,6 @@ * * This driver uses /dev/cpu/%d/msr where %d is the minor number, and on * an SMP box will direct the access to CPU %d. - -RED-PEN: need to get power management for S3 restore - */ #include <linux/module.h> @@ -44,7 +41,6 @@ RED-PEN: need to get power management for S3 restore #include <asm/msr.h> #include <asm/uaccess.h> #include <asm/system.h> -#include <asm/cpufeature.h> /* Note: "err" is handled in a funny way below. Otherwise one version of gcc or another breaks. */ @@ -119,12 +115,11 @@ static void msr_smp_rdmsr(void *cmd_block) static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx) { struct msr_command cmd; + int ret; preempt_disable(); if ( cpu == smp_processor_id() ) { - int ret = wrmsr_eio(reg, eax, edx); - preempt_enable(); - return ret; + ret = wrmsr_eio(reg, eax, edx); } else { cmd.cpu = cpu; cmd.reg = reg; @@ -132,17 +127,20 @@ static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx) cmd.data[1] = edx; smp_call_function(msr_smp_wrmsr, &cmd, 1, 1); - preempt_enable(); - return cmd.err; + ret = cmd.err; } + preempt_enable(); + return ret; } static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx) { struct msr_command cmd; + int ret; + preempt_disable(); if ( cpu == smp_processor_id() ) { - return rdmsr_eio(reg, eax, edx); + ret = rdmsr_eio(reg, eax, edx); } else { cmd.cpu = cpu; cmd.reg = reg; @@ -152,8 +150,10 @@ static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx) *eax = cmd.data[0]; *edx = cmd.data[1]; - return cmd.err; + ret = cmd.err; } + preempt_enable(); + return ret; } #else /* ! CONFIG_SMP */ diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index 8ab7bb0af3ef..34e3a58da168 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -22,6 +22,7 @@ #include <linux/mc146818rtc.h> #include <linux/kernel_stat.h> #include <linux/module.h> +#include <linux/sysdev.h> #include <asm/smp.h> #include <asm/mtrr.h> @@ -152,50 +153,45 @@ void enable_lapic_nmi_watchdog(void) #include <linux/device.h> -static int lapic_nmi_suspend(struct device *dev, u32 state, u32 level) - { - if (level != SUSPEND_POWER_DOWN) - return 0; +static int lapic_nmi_suspend(struct sys_device *dev, u32 state) +{ disable_lapic_nmi_watchdog(); return 0; - } +} -static int lapic_nmi_resume(struct device *dev, u32 level) - { - if (level != RESUME_POWER_ON) - return 0; +static int lapic_nmi_resume(struct sys_device *dev) +{ #if 0 enable_lapic_nmi_watchdog(); #endif return 0; - } +} -static struct device_driver lapic_nmi_driver = { - .name = "lapic_nmi", - .bus = &system_bus_type, +static struct sysdev_class nmi_sysclass = { + set_kset_name("lapic_nmi"), .resume = lapic_nmi_resume, .suspend = lapic_nmi_suspend, }; static struct sys_device device_lapic_nmi = { - .name = "lapic_nmi", .id = 0, - .dev = { - .name = "lapic_nmi", - .driver = &lapic_nmi_driver, - .parent = &device_lapic.dev, - }, + .cls = &nmi_sysclass, }; -static int __init init_lapic_nmi_devicefs(void) +static int __init init_lapic_nmi_sysfs(void) { + int error; + if (nmi_active == 0) return 0; - driver_register(&lapic_nmi_driver); - return sys_device_register(&device_lapic_nmi); + + error = sysdev_class_register(&nmi_sysclass); + if (!error) + error = sys_device_register(&device_lapic_nmi); + return error; } /* must come after the local APIC's device_initcall() */ -late_initcall(init_lapic_nmi_devicefs); +late_initcall(init_lapic_nmi_sysfs); #endif /* CONFIG_PM */ @@ -332,13 +328,11 @@ asmlinkage void do_nmi(struct pt_regs * regs, long error_code) { int cpu = safe_smp_processor_id(); - init_tss[cpu].ist[NMI_STACK] -= 2048; /* this shouldn't be needed. */ nmi_enter(); add_pda(__nmi_count,1); if (!nmi_callback(regs, cpu)) default_do_nmi(regs); nmi_exit(); - init_tss[cpu].ist[NMI_STACK] += 2048; } void set_nmi_callback(nmi_callback_t callback) diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index 12047fff5230..b8679513563a 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c @@ -38,6 +38,8 @@ possible future tuning: #include <asm/pgtable.h> #include <asm/proto.h> #include <asm/cacheflush.h> +#include <asm/kdebug.h> +#include <asm/proto.h> unsigned long iommu_bus_base; /* GART remapping area (physical) */ static unsigned long iommu_size; /* size of remapping area bytes */ @@ -53,9 +55,6 @@ int force_mmu = 1; int force_mmu = 0; #endif -extern int fallback_aper_order; -extern int fallback_aper_force; - /* Allocation bitmap for the remapping area */ static spinlock_t iommu_bitmap_lock = SPIN_LOCK_UNLOCKED; static unsigned long *iommu_gart_bitmap; /* guarded by iommu_bitmap_lock */ @@ -135,10 +134,19 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, void *memory; int gfp = GFP_ATOMIC; int i; - unsigned long iommu_page; int flush = 0; + unsigned long iommu_page; + unsigned long dma_mask; - if (hwdev == NULL || hwdev->dma_mask < 0xffffffff || no_iommu) + if (hwdev == NULL) { + gfp |= GFP_DMA; + dma_mask = 0xffffffff; + } else { + dma_mask = hwdev->consistent_dma_mask; + } + if (dma_mask == 0) + dma_mask = 0xffffffff; + if (dma_mask < 0xffffffff || no_iommu) gfp |= GFP_DMA; /* @@ -151,7 +159,7 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, return NULL; } else { int high = 0, mmu; - if (((unsigned long)virt_to_bus(memory) + size) > 0xffffffffUL) + if (((unsigned long)virt_to_bus(memory) + size) > dma_mask) high = 1; mmu = 1; if (force_mmu && !(gfp & GFP_DMA)) @@ -222,7 +230,6 @@ void pci_free_consistent(struct pci_dev *hwdev, size_t size, static void **iommu_leak_tab; static int leak_trace; int iommu_leak_pages = 20; -extern unsigned long printk_address(unsigned long); void dump_leak(void) { int i; @@ -459,7 +466,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info) extern int agp_amdk8_init(void); -void __init pci_iommu_init(void) +int __init pci_iommu_init(void) { struct agp_kern_info info; unsigned long aper_size; @@ -468,6 +475,7 @@ void __init pci_iommu_init(void) #ifndef CONFIG_AGP_AMD_8151 no_agp = 1; #else + /* Makefile puts PCI initialization via subsys_initcall first. */ /* Add other K8 AGP bridge drivers here */ no_agp = no_agp || (agp_amdk8_init() < 0) || @@ -477,7 +485,7 @@ void __init pci_iommu_init(void) if (no_iommu || (!force_mmu && end_pfn < 0xffffffff>>PAGE_SHIFT)) { printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); no_iommu = 1; - return; + return -1; } if (no_agp) { @@ -489,7 +497,7 @@ void __init pci_iommu_init(void) if (err < 0) { printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); no_iommu = 1; - return; + return -1; } } @@ -540,8 +548,13 @@ void __init pci_iommu_init(void) clear_kernel_mapping((unsigned long)__va(iommu_bus_base), iommu_size); flush_gart(); + + return 0; } +/* Must execute after PCI subsystem */ +fs_initcall(pci_iommu_init); + /* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]] size set size of iommu (in bytes) noagp don't initialize the AGP driver and use full aperture. @@ -589,4 +602,3 @@ __init int iommu_setup(char *opt) } return 1; } - diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c index 4e163f83f881..8240e5557f89 100644 --- a/arch/x86_64/kernel/pci-nommu.c +++ b/arch/x86_64/kernel/pci-nommu.c @@ -2,13 +2,12 @@ #include <linux/init.h> #include <linux/pci.h> #include <linux/string.h> +#include <asm/proto.h> /* * Dummy IO MMU functions */ -extern unsigned long end_pfn; - void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) { diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 5a5b2fe81e6c..dc6b48b58dbb 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -200,8 +200,6 @@ void show_regs(struct pt_regs *regs) show_trace(®s->rsp); } -extern void load_gs_index(unsigned); - /* * Free current thread data structures etc.. */ diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index e04b3912f17e..fafd7d063ef8 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -585,7 +585,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c) void __init print_cpu_info(struct cpuinfo_x86 *c) { if (c->x86_model_id[0]) - printk("AMD %s", c->x86_model_id); + printk("%s", c->x86_model_id); if (c->x86_mask || c->cpuid_level >= 0) printk(" stepping %02x\n", c->x86_mask); diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c index 2bd0172ef482..6ae0e7077e09 100644 --- a/arch/x86_64/kernel/signal.c +++ b/arch/x86_64/kernel/signal.c @@ -475,8 +475,6 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, __u32 thread_info_ do_signal(regs,oldset); } -extern int exception_trace; - void signal_fault(struct pt_regs *regs, void *frame, char *where) { struct task_struct *me = current; diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 00ee45c7a21b..034ffc0efeb8 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -51,8 +51,7 @@ #include <asm/desc.h> #include <asm/kdebug.h> #include <asm/tlbflush.h> - -extern int disable_apic; +#include <asm/proto.h> /* Bitmask of currently online CPUs */ unsigned long cpu_online_map = 1; @@ -67,8 +66,6 @@ struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; /* Set when the idlers are all forked */ int smp_threads_ready; -extern void time_init_smp(void); - /* * Trampoline 80x86 program as an array. */ @@ -128,7 +125,6 @@ static void __init synchronize_tsc_bp (void) long long delta; long one_usec; int buggy = 0; - extern unsigned cpu_khz; printk(KERN_INFO "checking TSC synchronization across %u CPUs: ",num_booting_cpus()); @@ -242,8 +238,6 @@ static void __init synchronize_tsc_ap (void) } #undef NR_LOOPS -extern void calibrate_delay(void); - static atomic_t init_deasserted; void __init smp_callin(void) @@ -337,8 +331,6 @@ void __init smp_callin(void) int cpucount; -extern int cpu_idle(void); - /* * Activate a secondary processor. */ @@ -560,8 +552,6 @@ static int __init wakeup_secondary_via_INIT(int phys_apicid, unsigned int start_ return (send_status | accept_status); } -extern unsigned long cpu_initialized; - static void __init do_boot_cpu (int apicid) { struct task_struct *idle; diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 02286a052580..f558d43822bf 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -27,6 +27,7 @@ #include <asm/pgtable.h> #include <asm/vsyscall.h> #include <asm/timex.h> +#include <asm/proto.h> #ifdef CONFIG_X86_LOCAL_APIC #include <asm/apic.h> #endif @@ -38,9 +39,6 @@ extern int using_apic_timer; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED; -extern int using_apic_timer; -extern void smp_local_timer_interrupt(struct pt_regs * regs); - #undef HPET_HACK_ENABLE_DANGEROUS diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 24d5862bdcd7..3c8c0ff57cde 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -41,13 +41,10 @@ #include <asm/smp.h> #include <asm/pgalloc.h> #include <asm/pda.h> +#include <asm/proto.h> #include <linux/irq.h> -asmlinkage int system_call(void); -asmlinkage int kernel_syscall(void); -extern void ia32_syscall(void); - extern struct gate_struct idt_table[256]; asmlinkage void divide_error(void); @@ -73,8 +70,6 @@ asmlinkage void machine_check(void); asmlinkage void spurious_interrupt_bug(void); asmlinkage void call_debug(void); -extern int exception_trace; - struct notifier_block *die_chain; static inline void conditional_sti(struct pt_regs *regs) @@ -457,8 +452,6 @@ DO_ERROR(12, SIGBUS, "stack segment", stack_segment) DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2()) DO_ERROR(18, SIGSEGV, "reserved", reserved) -extern void dump_pagetable(unsigned long); - asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) { conditional_sti(regs); diff --git a/arch/x86_64/kernel/wakeup.S b/arch/x86_64/kernel/wakeup.S deleted file mode 100644 index 8fe49f037515..000000000000 --- a/arch/x86_64/kernel/wakeup.S +++ /dev/null @@ -1,306 +0,0 @@ -/* - * ACPI S3 entry/exit handling. - * - * Notes: - * Relies on kernel being loaded below 4GB. - * Needs restore_low_mappings called before. - * - * Copyright 2003 by Andi Kleen, SuSE Labs. - * - * Long mode entry loosely based on example code in chapter 14 of the x86-64 system - * programmer's manual. - * - * Notebook: - - FIXME need to interface with suspend.c properly. do_magic. check i386. rename to suspend64.S - - Need to fix vgacon,mtrr,bluesmoke to do resume - - Interrupts should be off until the io-apic code has reinited the APIC. - Need support for that in the pm frame work or a special hack? - - SMP support is non existent. Need to somehow restart the other CPUs again. - If CPU hotplug was working it could be used. Save/Restore needs to run on the same CPU. - - Should check magic like i386 code - - suspend code copies something. check what it is. - */ - -#include <linux/linkage.h> - -#include <asm/msr.h> -#include <asm/segment.h> -#include <asm/page.h> - -#define O(x) (x-acpi_wakeup) - - .text - .code16 -ENTRY(acpi_wakeup) - /* 16bit real mode entered from ACPI BIOS */ - /* The machine is just through BIOS setup after power down and everything set up - by Linux needs to be restored. */ - /* The code here needs to be position independent or manually relocated, - because it is copied to a <1MB page for real mode execution */ - - /* A20 enabled (according to ACPI spec) */ - /* cs = acpi_wakeup >> 4 ; eip = acpi_wakeup & 0xF */ - - movw %cs,%ax - movw %ax,%ds /* make %ds point to acpi_wakeup */ - movw %ax,%ss - movw $O(wakeup_stack),%sp /* setup stack */ - - pushl $0 - popfl /* clear EFLAGS */ - - lgdt %ds:O(pGDT) /* load kernel GDT */ - - movl $0x1,%eax /* enable protected mode */ - movl %eax,%cr0 - - movl %ds:O(wakeup_page_table),%edi - ljmpl $__KERNEL16_CS,$0 /* -> s3_prot16 (filled in earlier by caller) */ - - /* patched by s3_restore_state below */ -pGDT: - .short 0 - .quad 0 - - .align 4 - .globl wakeup_page_table -wakeup_page_table: - .long 0 - - .align 8 -wakeup_stack: - .fill 128,1,0 - .globl acpi_wakeup_end -acpi_wakeup_end: - /* end of real mode trampoline */ - - /* pointed to by __KERNEL16_CS:0 */ - .code16 -ENTRY(s3_prot16) - /* Now in 16bit protected mode, still no paging, stack/data segments invalid */ - - /* Prepare everything for 64bit paging, but still keep it turned off */ - movl %cr4,%eax - bts $5,%eax /* set PAE bit */ - movl %eax,%cr4 - - movl %edi,%cr3 /* load kernel page table */ - - movl $0x80000001,%eax - cpuid /* no execute supported ? */ - movl %edx,%esi - - movl $MSR_EFER,%ecx - rdmsr - bts $8,%eax /* long mode */ - bt $20,%esi /* NX supported ? */ - jnc 1f - bt $_EFER_NX,%eax -1: - wrmsr /* set temporary efer - real one is restored a bit later */ - - movl %cr0,%eax - bts $31,%eax /* paging */ - movl %eax,%cr0 - - /* running in identity mapping now */ - - /* go to 64bit code segment */ - ljmpl $__KERNEL_CS,$s3_restore_state-__START_KERNEL_map - - .code64 - .macro SAVEMSR msr,target - movl $\msr,%ecx - rdmsr - shlq $32,%rdx - orq %rax,%rdx - movq %rdx,\target(%rip) - .endm - - .macro RESTMSR msr,src - movl $\msr,%ecx - movq \src(%rip),%rax - movq %rax,%rdx - shrq $32,%rdx - wrmsr - .endm - - .macro SAVECTL reg - movq %\reg,%rax - movq %rax,saved_\reg(%rip) - .endm - - .macro RESTCTL reg - movq saved_\reg(%rip),%rax - movq %rax,%\reg - .endm - - /* Running in identity mapping, long mode */ -s3_restore_state_low: - movq $s3_restore_state,%rax - jmpq *%rax - - /* Running in real kernel mapping now */ -s3_restore_state: - xorl %eax,%eax - movl %eax,%ds - movq saved_rsp(%rip),%rsp - movw saved_ss(%rip),%ss - movw saved_fs(%rip),%fs - movw saved_gs(%rip),%gs - movw saved_es(%rip),%es - movw saved_ds(%rip),%ds - - lidt saved_idt - ltr saved_tr - lldt saved_ldt - /* gdt is already loaded */ - - RESTCTL cr0 - RESTCTL cr4 - /* cr3 is already loaded */ - - RESTMSR MSR_EFER,saved_efer - RESTMSR MSR_LSTAR,saved_lstar - RESTMSR MSR_CSTAR,saved_cstar - RESTMSR MSR_FS_BASE,saved_fs_base - RESTMSR MSR_GS_BASE,saved_gs_base - RESTMSR MSR_KERNEL_GS_BASE,saved_kernel_gs_base - RESTMSR MSR_SYSCALL_MASK,saved_syscall_mask - - fxrstor fpustate(%rip) - - RESTCTL dr0 - RESTCTL dr1 - RESTCTL dr2 - RESTCTL dr3 - RESTCTL dr6 - RESTCTL dr7 - - movq saved_rflags(%rip),%rax - pushq %rax - popfq - - movq saved_rbp(%rip),%rbp - movq saved_rbx(%rip),%rbx - movq saved_r12(%rip),%r12 - movq saved_r13(%rip),%r13 - movq saved_r14(%rip),%r14 - movq saved_r15(%rip),%r15 - ret - -ENTRY(acpi_prepare_wakeup) - sgdt saved_gdt - - /* copy gdt descr and page table to low level wakeup code so that it can - reload them early. */ - movq acpi_wakeup_address(%rip),%rax - movw saved_gdt+8(%rip),%cx - movw %cx,O(pGDT)+8(%rax) - movq saved_gdt(%rip),%rcx - movq %rcx,O(pGDT)(%rax) - - movq %cr3,%rdi - movl %edi,O(wakeup_page_table)(%rax) - ret - - /* Save CPU state. */ - /* Everything saved here needs to be restored above. */ -ENTRY(do_suspend_lowlevel) - testl %edi,%edi - jnz s3_restore_state - - SAVECTL cr0 - SAVECTL cr4 - SAVECTL cr3 - - str saved_tr - sidt saved_idt - sgdt saved_gdt - sldt saved_ldt - - SAVEMSR MSR_EFER,saved_efer - SAVEMSR MSR_LSTAR,saved_lstar - SAVEMSR MSR_CSTAR,saved_cstar - SAVEMSR MSR_FS_BASE,saved_fs_base - SAVEMSR MSR_GS_BASE,saved_gs_base - SAVEMSR MSR_KERNEL_GS_BASE,saved_kernel_gs_base - SAVEMSR MSR_SYSCALL_MASK,saved_syscall_mask - - movw %ds,saved_ds(%rip) - movw %es,saved_es(%rip) - movw %fs,saved_fs(%rip) - movw %gs,saved_gs(%rip) - movw %ss,saved_ss(%rip) - movq %rsp,saved_rsp(%rip) - - pushfq - popq %rax - movq %rax,saved_rflags(%rip) - - SAVECTL dr0 - SAVECTL dr1 - SAVECTL dr2 - SAVECTL dr3 - SAVECTL dr6 - SAVECTL dr7 - - fxsave fpustate(%rip) - - /* finally save callee saved registers */ - movq %rbp,saved_rbp(%rip) - movq %rbx,saved_rbx(%rip) - movq %r12,saved_r12(%rip) - movq %r13,saved_r13(%rip) - movq %r14,saved_r14(%rip) - movq %r15,saved_r15(%rip) - movq $3,%rdi - call acpi_enter_sleep_state - ret /* should not happen */ - - .data - .align 8 -saved_efer: .quad 0 -saved_lstar: .quad 0 -saved_cstar: .quad 0 -saved_cr4: .quad 0 -saved_cr3: .quad 0 -saved_cr0: .quad 0 -saved_rbp: .quad 0 -saved_rbx: .quad 0 -saved_rsp: .quad 0 -saved_r12: .quad 0 -saved_r13: .quad 0 -saved_r14: .quad 0 -saved_r15: .quad 0 -saved_rflags: .quad 0 -saved_gs_base: .quad 0 -saved_fs_base: .quad 0 -saved_kernel_gs_base: .quad 0 -saved_syscall_mask: .quad 0 -saved_dr0: .quad 0 -saved_dr1: .quad 0 -saved_dr2: .quad 0 -saved_dr3: .quad 0 -saved_dr6: .quad 0 -saved_dr7: .quad 0 -saved_ds: .short 0 -saved_fs: .short 0 -saved_gs: .short 0 -saved_es: .short 0 -saved_ss: .short 0 -saved_idt: .short 0 - .quad 0 -saved_ldt: .short 0 -saved_gdt: .short 0 - .quad 0 -saved_tr: .short 0 - - .align 16 -fpustate: .fill 512,1,0 diff --git a/arch/x86_64/lib/delay.c b/arch/x86_64/lib/delay.c index 16a8d8bcdada..9fcdb2d2d4cd 100644 --- a/arch/x86_64/lib/delay.c +++ b/arch/x86_64/lib/delay.c @@ -21,7 +21,6 @@ int x86_udelay_tsc = 0; /* Delay via TSC */ void __delay(unsigned long loops) { -#ifndef CONFIG_SIMNOW unsigned long bclock, now; rdtscl(bclock); @@ -31,7 +30,6 @@ void __delay(unsigned long loops) rdtscl(now); } while((now-bclock) < loops); -#endif } inline void __const_udelay(unsigned long xloops) diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index dee5a42a2e9f..3be6a8e4b679 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -24,6 +24,7 @@ #endif #include <linux/pagemap.h> #include <linux/bootmem.h> +#include <linux/proc_fs.h> #include <asm/processor.h> #include <asm/system.h> @@ -41,6 +42,8 @@ #define Dprintk(x...) +extern char _stext; + DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); /* @@ -393,6 +396,9 @@ static inline int page_is_ram (unsigned long pagenr) return 0; } +static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules, + kcore_vsyscall; + void __init mem_init(void) { int codesize, reservedpages, datasize, initsize; @@ -434,6 +440,15 @@ void __init mem_init(void) datasize = (unsigned long) &_edata - (unsigned long) &_etext; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; + /* Register memory areas for /proc/kcore */ + kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); + kclist_add(&kcore_vmalloc, (void *)VMALLOC_START, + VMALLOC_END-VMALLOC_START); + kclist_add(&kcore_kernel, &_stext, &_end - &_stext); + kclist_add(&kcore_modules, (void *)MODULES_VADDR, MODULES_LEN); + kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START, + VSYSCALL_END - VSYSCALL_START); + printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n", (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), end_pfn << (PAGE_SHIFT-10), @@ -462,7 +477,7 @@ void free_initmem(void) ClearPageReserved(virt_to_page(addr)); set_page_count(virt_to_page(addr), 1); #ifdef CONFIG_INIT_DEBUG - memset(addr & ~(PAGE_SIZE-1), 0xcc, PAGE_SIZE); + memset((void *)(addr & ~(PAGE_SIZE-1)), 0xcc, PAGE_SIZE); #endif free_page(addr); totalram_pages++; @@ -497,3 +512,29 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len) reserve_bootmem(phys, len); #endif } + +int kern_addr_valid(unsigned long addr) +{ + unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT; + if (above != 0 && above != -1UL) + return 0; + + pml4_t *pml4 = pml4_offset_k(addr); + if (pml4_none(*pml4)) + return 0; + + pgd_t *pgd = pgd_offset_k(addr); + if (pgd_none(*pgd)) + return 0; + + pmd_t *pmd = pmd_offset(pgd, addr); + if (pmd_none(*pmd)) + return 0; + if (pmd_large(*pmd)) + return pfn_valid(pmd_pfn(*pmd)); + + pte_t *pte = pte_offset_kernel(pmd, addr); + if (pte_none(*pte)) + return 0; + return pfn_valid(pte_pfn(*pte)); +} diff --git a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile index d113570fe828..f673692e643d 100644 --- a/arch/x86_64/pci/Makefile +++ b/arch/x86_64/pci/Makefile @@ -1,8 +1,29 @@ # # Makefile for X86_64 specific PCI routines # -obj-y := x86-64.o +# Reuse the i386 PCI subsystem using symlinks +# +obj-y := i386.o obj-$(CONFIG_PCI_DIRECT)+= direct.o obj-y += fixup.o obj-$(CONFIG_ACPI_PCI) += acpi.o obj-y += legacy.o irq.o common.o + +$(obj)/direct.c: $(obj)/pci.h + @ln -sf ../../i386/pci/direct.c $(obj)/direct.c +$(obj)/legacy.c: $(obj)/pci.h + @ln -sf ../../i386/pci/legacy.c $(obj)/legacy.c +$(obj)/common.c: $(obj)/pci.h + @ln -sf ../../i386/pci/common.c $(obj)/common.c +$(obj)/acpi.c: $(obj)/pci.h + @ln -sf ../../i386/pci/acpi.c $(obj)/acpi.c +$(obj)/pci.h: + @ln -sf ../../i386/pci/pci.h $(obj)/pci.h +$(obj)/irq.c: $(obj)/pci.h + @ln -sf ../../i386/pci/irq.c $(obj)/irq.c +$(obj)/fixup.c: $(obj)/pci.h + @ln -sf ../../i386/pci/fixup.c $(obj)/fixup.c +$(obj)/i386.c: $(obj)/pci.h + @ln -sf ../../i386/pci/i386.c $(obj)/i386.c + +clean-files += i386.c legacy.c fixup.c acpi.c irq.c pci.h common.c direct.c diff --git a/arch/x86_64/pci/acpi.c b/arch/x86_64/pci/acpi.c deleted file mode 100644 index 2c21bc493ce4..000000000000 --- a/arch/x86_64/pci/acpi.c +++ /dev/null @@ -1,27 +0,0 @@ -#include <linux/pci.h> -#include <linux/acpi.h> -#include <linux/init.h> -#include "pci.h" - -static int __init pci_acpi_init(void) -{ - if (pcibios_scanned) - return 0; - - if (!(pci_probe & PCI_NO_ACPI_ROUTING)) { - if (!acpi_pci_irq_init()) { - printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); - printk(KERN_INFO "PCI: if you experience problems, try using option 'pci=noacpi'\n"); - pcibios_scanned++; - pcibios_enable_irq = acpi_pci_irq_enable; - } else - printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n"); - - /* still scan manually in case ACPI forgot some bus */ - pcibios_fixup_peer_bridges(); - } - - return 0; -} - -subsys_initcall(pci_acpi_init); diff --git a/arch/x86_64/pci/changelog b/arch/x86_64/pci/changelog deleted file mode 100644 index fcf2f4d7c0c9..000000000000 --- a/arch/x86_64/pci/changelog +++ /dev/null @@ -1 +0,0 @@ -See arch/i386/pci/changelog for early changelog. diff --git a/arch/x86_64/pci/common.c b/arch/x86_64/pci/common.c deleted file mode 100644 index 8a189e818ef1..000000000000 --- a/arch/x86_64/pci/common.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Low-Level PCI Support for PC - * - * (c) 1999--2000 Martin Mares <mj@ucw.cz> - - Note: on x86-64 there is no PCI BIOS so there is no way to sort in the - same order as 32bit Linux. This could cause grief for dualbooting because - devices may wander. May want to use ACPI for sorting eventually. - - */ - -#include <linux/sched.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/ioport.h> - -#include <asm/segment.h> -#include <asm/io.h> -#include <asm/smp.h> -#include <asm/cache.h> - -#include "pci.h" - -unsigned int pci_probe = PCI_PROBE_CONF1 | PCI_PROBE_CONF2; - -int pcibios_last_bus = 0xff; /* XXX */ -struct pci_bus *pci_root_bus = NULL; -struct pci_ops *pci_root_ops = NULL; - -int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL; -int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL; - -/* - * legacy, numa, and acpi all want to call pcibios_scan_root - * from their initcalls. This flag prevents that. - */ -int pcibios_scanned; - -/* - * This interrupt-safe spinlock protects all accesses to PCI - * configuration space. - */ -spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED; - -/* - * Several buggy motherboards address only 16 devices and mirror - * them to next 16 IDs. We try to detect this `feature' on all - * primary buses (those containing host bridges as they are - * expected to be unique) and remove the ghost devices. - */ - -static void __devinit pcibios_fixup_ghosts(struct pci_bus *b) -{ - struct list_head *ln, *mn; - struct pci_dev *d, *e; - int mirror = PCI_DEVFN(16,0); - int seen_host_bridge = 0; - int i; - - DBG("PCI: Scanning for ghost devices on bus %d\n", b->number); - for (ln=b->devices.next; ln != &b->devices; ln=ln->next) { - d = pci_dev_b(ln); - if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST) - seen_host_bridge++; - for (mn=ln->next; mn != &b->devices; mn=mn->next) { - e = pci_dev_b(mn); - if (e->devfn != d->devfn + mirror || - e->vendor != d->vendor || - e->device != d->device || - e->class != d->class) - continue; - for(i=0; i<PCI_NUM_RESOURCES; i++) - if (e->resource[i].start != d->resource[i].start || - e->resource[i].end != d->resource[i].end || - e->resource[i].flags != d->resource[i].flags) - continue; - break; - } - if (mn == &b->devices) - return; - } - if (!seen_host_bridge) - return; - printk(KERN_WARNING "PCI: Ignoring ghost devices on bus %02x\n", b->number); - - ln = &b->devices; - while (ln->next != &b->devices) { - d = pci_dev_b(ln->next); - if (d->devfn >= mirror) { - list_del(&d->global_list); - list_del(&d->bus_list); - kfree(d); - } else - ln = ln->next; - } -} - -struct pbus_set_ranges_data; - -void __devinit -pcibios_fixup_pbus_ranges (struct pci_bus *bus, struct pbus_set_ranges_data *ranges) -{ -} - -/* - * Called after each bus is probed, but before its children - * are examined. - */ - -void __devinit pcibios_fixup_bus(struct pci_bus *b) -{ - pcibios_fixup_ghosts(b); - pci_read_bridge_bases(b); -} - - -struct pci_bus * __devinit pcibios_scan_root(int busnum) -{ - struct list_head *list; - struct pci_bus *bus; - - list_for_each(list, &pci_root_buses) { - bus = pci_bus_b(list); - if (bus->number == busnum) { - /* Already scanned */ - return bus; - } - } - - printk("PCI: Probing PCI hardware (bus %02x)\n", busnum); - - return pci_scan_bus(busnum, pci_root_ops, NULL); -} - -extern u8 pci_cache_line_size; - -static int __init pcibios_init(void) -{ - if (!pci_root_ops) { - printk("PCI: System does not support PCI\n"); - return 0; - } - - pci_cache_line_size = boot_cpu_data.x86_clflush_size >> 2; - - pcibios_resource_survey(); - -#ifdef CONFIG_GART_IOMMU - pci_iommu_init(); -#endif - - /* may eventually need to do ACPI sort here. */ - return 0; -} - -subsys_initcall(pcibios_init); - -char * __devinit pcibios_setup(char *str) -{ - if (!strcmp(str, "off")) { - pci_probe = 0; - return NULL; - } -#ifdef CONFIG_PCI_DIRECT - else if (!strcmp(str, "conf1")) { - pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS; - return NULL; - } - else if (!strcmp(str, "conf2")) { - pci_probe = PCI_PROBE_CONF2 | PCI_NO_CHECKS; - return NULL; - } -#endif -#ifdef CONFIG_ACPI_PCI - else if (!strcmp(str, "noacpi")) { - pci_probe |= PCI_NO_ACPI_ROUTING; - return NULL; - } -#endif - else if (!strcmp(str, "rom")) { - pci_probe |= PCI_ASSIGN_ROMS; - return NULL; - } else if (!strcmp(str, "assign-busses")) { - pci_probe |= PCI_ASSIGN_ALL_BUSSES; - return NULL; - } else if (!strcmp(str, "usepirqmask")) { - pci_probe |= PCI_USE_PIRQ_MASK; - return NULL; - } else if (!strncmp(str, "irqmask=", 8)) { - pcibios_irq_mask = simple_strtol(str+8, NULL, 0); - return NULL; - } else if (!strncmp(str, "lastbus=", 8)) { - pcibios_last_bus = simple_strtol(str+8, NULL, 0); - return NULL; - } - return str; -} - -unsigned int pcibios_assign_all_busses(void) -{ - return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; -} - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - int err; - - if ((err = pcibios_enable_resources(dev, mask)) < 0) - return err; - - return pcibios_enable_irq(dev); -} diff --git a/arch/x86_64/pci/direct.c b/arch/x86_64/pci/direct.c deleted file mode 100644 index a5971a01cdb5..000000000000 --- a/arch/x86_64/pci/direct.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * direct.c - Low-level direct PCI config space access - */ - -#include <linux/pci.h> -#include <linux/init.h> -#include "pci.h" - -/* - * Functions for accessing PCI configuration space with type 1 accesses - */ - -#define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \ - (0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) - -static int __pci_conf1_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) -{ - unsigned long flags; - - if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) - return -EINVAL; - - spin_lock_irqsave(&pci_config_lock, flags); - - outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8); - - switch (len) { - case 1: - *value = inb(0xCFC + (reg & 3)); - break; - case 2: - *value = inw(0xCFC + (reg & 2)); - break; - case 4: - *value = inl(0xCFC); - break; - } - - spin_unlock_irqrestore(&pci_config_lock, flags); - - return 0; -} - -static int __pci_conf1_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) -{ - unsigned long flags; - - if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) - return -EINVAL; - - spin_lock_irqsave(&pci_config_lock, flags); - - outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8); - - switch (len) { - case 1: - outb((u8)value, 0xCFC + (reg & 3)); - break; - case 2: - outw((u16)value, 0xCFC + (reg & 2)); - break; - case 4: - outl((u32)value, 0xCFC); - break; - } - - spin_unlock_irqrestore(&pci_config_lock, flags); - - return 0; -} - -#undef PCI_CONF1_ADDRESS - -static int pci_conf1_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) -{ - return __pci_conf1_read(0, bus->number, PCI_SLOT(devfn), - PCI_FUNC(devfn), where, size, value); -} - -static int pci_conf1_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) -{ - return __pci_conf1_write(0, bus->number, PCI_SLOT(devfn), - PCI_FUNC(devfn), where, size, value); -} - -static struct pci_ops pci_direct_conf1 = { - .read = pci_conf1_read, - .write = pci_conf1_write, -}; - - -/* - * Functions for accessing PCI configuration space with type 2 accesses - */ - -#define PCI_CONF2_ADDRESS(dev, reg) (u16)(0xC000 | (dev << 8) | reg) - -static int __pci_conf2_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) -{ - unsigned long flags; - - if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) - return -EINVAL; - - if (dev & 0x10) - return PCIBIOS_DEVICE_NOT_FOUND; - - spin_lock_irqsave(&pci_config_lock, flags); - - outb((u8)(0xF0 | (fn << 1)), 0xCF8); - outb((u8)bus, 0xCFA); - - switch (len) { - case 1: - *value = inb(PCI_CONF2_ADDRESS(dev, reg)); - break; - case 2: - *value = inw(PCI_CONF2_ADDRESS(dev, reg)); - break; - case 4: - *value = inl(PCI_CONF2_ADDRESS(dev, reg)); - break; - } - - outb (0, 0xCF8); - - spin_unlock_irqrestore(&pci_config_lock, flags); - - return 0; -} - -static int __pci_conf2_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) -{ - unsigned long flags; - - if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) - return -EINVAL; - - if (dev & 0x10) - return PCIBIOS_DEVICE_NOT_FOUND; - - spin_lock_irqsave(&pci_config_lock, flags); - - outb((u8)(0xF0 | (fn << 1)), 0xCF8); - outb((u8)bus, 0xCFA); - - switch (len) { - case 1: - outb ((u8)value, PCI_CONF2_ADDRESS(dev, reg)); - break; - case 2: - outw ((u16)value, PCI_CONF2_ADDRESS(dev, reg)); - break; - case 4: - outl ((u32)value, PCI_CONF2_ADDRESS(dev, reg)); - break; - } - - outb (0, 0xCF8); - - spin_unlock_irqrestore(&pci_config_lock, flags); - - return 0; -} - -#undef PCI_CONF2_ADDRESS - -static int pci_conf2_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) -{ - return __pci_conf2_read(0, bus->number, PCI_SLOT(devfn), - PCI_FUNC(devfn), where, size, value); -} - -static int pci_conf2_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) -{ - return __pci_conf2_write(0, bus->number, PCI_SLOT(devfn), - PCI_FUNC(devfn), where, size, value); -} - -static struct pci_ops pci_direct_conf2 = { - .read = pci_conf2_read, - .write = pci_conf2_write, -}; - - -/* - * Before we decide to use direct hardware access mechanisms, we try to do some - * trivial checks to ensure it at least _seems_ to be working -- we just test - * whether bus 00 contains a host bridge (this is similar to checking - * techniques used in XFree86, but ours should be more reliable since we - * attempt to make use of direct access hints provided by the PCI BIOS). - * - * This should be close to trivial, but it isn't, because there are buggy - * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID. - */ -static int __devinit pci_sanity_check(struct pci_ops *o) -{ - u32 x = 0; - int retval = 0; - struct pci_bus *bus; /* Fake bus and device */ - struct pci_dev *dev; - - if (pci_probe & PCI_NO_CHECKS) - return 1; - - bus = kmalloc(sizeof(*bus), GFP_ATOMIC); - dev = kmalloc(sizeof(*dev), GFP_ATOMIC); - if (!bus || !dev) { - printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__); - goto exit; - } - - bus->number = 0; - dev->bus = bus; - for(dev->devfn=0; dev->devfn < 0x100; dev->devfn++) - if ((!o->read(bus, dev->devfn, PCI_CLASS_DEVICE, 2, &x) && - (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) || - (!o->read(bus, dev->devfn, PCI_VENDOR_ID, 2, &x) && - (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ))) { - retval = 1; - goto exit; - } - DBG("PCI: Sanity check failed\n"); -exit: - kfree(dev); - kfree(bus); - return retval; -} - -static int __init pci_direct_init(void) -{ - unsigned int tmp; - unsigned long flags; - - local_irq_save(flags); - - /* - * Check if configuration type 1 works. - */ - if (pci_probe & PCI_PROBE_CONF1) { - outb (0x01, 0xCFB); - tmp = inl (0xCF8); - outl (0x80000000, 0xCF8); - if (inl (0xCF8) == 0x80000000 && - pci_sanity_check(&pci_direct_conf1)) { - outl (tmp, 0xCF8); - local_irq_restore(flags); - printk(KERN_INFO "PCI: Using configuration type 1\n"); - if (!request_region(0xCF8, 8, "PCI conf1")) - pci_root_ops = NULL; - else - pci_root_ops = &pci_direct_conf1; - return 0; - } - outl (tmp, 0xCF8); - } - - /* - * Check if configuration type 2 works. - */ - if (pci_probe & PCI_PROBE_CONF2) { - outb (0x00, 0xCFB); - outb (0x00, 0xCF8); - outb (0x00, 0xCFA); - if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00 && - pci_sanity_check(&pci_direct_conf2)) { - local_irq_restore(flags); - printk(KERN_INFO "PCI: Using configuration type 2\n"); - if (!request_region(0xCF8, 4, "PCI conf2")) - pci_root_ops = NULL; - else - pci_root_ops = &pci_direct_conf2; - return 0; - } - } - - local_irq_restore(flags); - return 0; -} - -arch_initcall(pci_direct_init); diff --git a/arch/x86_64/pci/fixup.c b/arch/x86_64/pci/fixup.c deleted file mode 100644 index 6f6aee48b601..000000000000 --- a/arch/x86_64/pci/fixup.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Exceptions for specific devices. Usually work-arounds for fatal design flaws. - * - -Short list on x86-64........so far. - - */ - -#include <linux/pci.h> -#include <linux/init.h> -#include "pci.h" - -static void __devinit pci_fixup_ncr53c810(struct pci_dev *d) -{ - /* - * NCR 53C810 returns class code 0 (at least on some systems). - * Fix class to be PCI_CLASS_STORAGE_SCSI - */ - if (!d->class) { - printk(KERN_WARNING "PCI: fixing NCR 53C810 class code for %s\n", d->slot_name); - d->class = PCI_CLASS_STORAGE_SCSI << 8; - } -} - -static void __devinit pci_fixup_ide_bases(struct pci_dev *d) -{ - int i; - - /* - * PCI IDE controllers use non-standard I/O port decoding, respect it. - */ - if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) - return; - DBG("PCI: IDE base address fixup for %s\n", d->slot_name); - for(i=0; i<4; i++) { - struct resource *r = &d->resource[i]; - if ((r->start & ~0x80) == 0x374) { - r->start |= 2; - r->end = r->start; - } - } -} - -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810 }, - { 0 } -}; diff --git a/arch/x86_64/pci/irq.c b/arch/x86_64/pci/irq.c deleted file mode 100644 index 575ede9cb389..000000000000 --- a/arch/x86_64/pci/irq.c +++ /dev/null @@ -1,639 +0,0 @@ -/* - * Low-Level PCI Support for PC -- Routing of Interrupts - * - * (c) 1999--2000 Martin Mares <mj@ucw.cz> - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <asm/io.h> -#include <asm/smp.h> -#include <asm/io_apic.h> - -#include "pci.h" - -#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24)) -#define PIRQ_VERSION 0x0100 - -int broken_hp_bios_irq9; - -static struct irq_routing_table *pirq_table; - -/* - * Never use: 0, 1, 2 (timer, keyboard, and cascade) - * Avoid using: 13, 14 and 15 (FP error and IDE). - * Penalize: 3, 4, 6, 7, 12 (known ISA uses: serial, floppy, parallel and mouse) - */ -unsigned int pcibios_irq_mask = 0xfff8; - -static int pirq_penalty[16] = { - 1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000, - 0, 0, 0, 0, 1000, 100000, 100000, 100000 -}; - -struct irq_router { - char *name; - u16 vendor, device; - int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq); - int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new); -}; - -int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; - -/* - * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table. - */ - -static struct irq_routing_table * __init pirq_find_routing_table(void) -{ - u8 *addr; - struct irq_routing_table *rt; - int i; - u8 sum; - - for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) { - rt = (struct irq_routing_table *) addr; - if (rt->signature != PIRQ_SIGNATURE || - rt->version != PIRQ_VERSION || - rt->size % 16 || - rt->size < sizeof(struct irq_routing_table)) - continue; - sum = 0; - for(i=0; i<rt->size; i++) - sum += addr[i]; - if (!sum) { - DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt); - return rt; - } - } - return NULL; -} - -/* - * If we have a IRQ routing table, use it to search for peer host - * bridges. It's a gross hack, but since there are no other known - * ways how to get a list of buses, we have to go this way. - */ - -static void __init pirq_peer_trick(void) -{ - struct irq_routing_table *rt = pirq_table; - u8 busmap[256]; - int i; - struct irq_info *e; - - memset(busmap, 0, sizeof(busmap)); - for(i=0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) { - e = &rt->slots[i]; -#ifdef DEBUG - { - int j; - DBG("%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot); - for(j=0; j<4; j++) - DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap); - DBG("\n"); - } -#endif - busmap[e->bus] = 1; - } - for(i=1; i<256; i++) - /* - * It might be a secondary bus, but in this case its parent is already - * known (ascending bus order) and therefore pci_scan_bus returns immediately. - */ - if (busmap[i] && pci_scan_bus(i, pci_root_bus->ops, NULL)) - printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i); - //pcibios_last_bus = -1; -} - -/* - * Code for querying and setting of IRQ routes on various interrupt routers. - */ - -void eisa_set_level_irq(unsigned int irq) -{ - unsigned char mask = 1 << (irq & 7); - unsigned int port = 0x4d0 + (irq >> 3); - unsigned char val = inb(port); - - if (!(val & mask)) { - DBG(" -> edge"); - outb(val | mask, port); - } -} - -/* - * Common IRQ routing practice: nybbles in config space, - * offset by some magic constant. - */ -static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr) -{ - u8 x; - unsigned reg = offset + (nr >> 1); - - pci_read_config_byte(router, reg, &x); - return (nr & 1) ? (x >> 4) : (x & 0xf); -} - -static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr, unsigned int val) -{ - u8 x; - unsigned reg = offset + (nr >> 1); - - pci_read_config_byte(router, reg, &x); - x = (nr & 1) ? ((x & 0x0f) | (val << 4)) : ((x & 0xf0) | val); - pci_write_config_byte(router, reg, x); -} - -#if 0 /* enable when pci ids ae known */ -/* - * The VIA pirq rules are nibble-based, like ALI, - * but without the ugly irq number munging. - */ -static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq) -{ - return read_config_nybble(router, 0x55, pirq); -} - -static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) -{ - write_config_nybble(router, 0x55, pirq, irq); - return 1; -} - -/* - * PIRQ routing for SiS 85C503 router used in several SiS chipsets - * According to the SiS 5595 datasheet (preliminary V1.0, 12/24/1997) - * the related registers work as follows: - * - * general: one byte per re-routable IRQ, - * bit 7 IRQ mapping enabled (0) or disabled (1) - * bits [6:4] reserved - * bits [3:0] IRQ to map to - * allowed: 3-7, 9-12, 14-15 - * reserved: 0, 1, 2, 8, 13 - * - * individual registers in device config space: - * - * 0x41/0x42/0x43/0x44: PCI INT A/B/C/D - bits as in general case - * - * 0x61: IDEIRQ: bits as in general case - but: - * bits [6:5] must be written 01 - * bit 4 channel-select primary (0), secondary (1) - * - * 0x62: USBIRQ: bits as in general case - but: - * bit 4 OHCI function disabled (0), enabled (1) - * - * 0x6a: ACPI/SCI IRQ - bits as in general case - * - * 0x7e: Data Acq. Module IRQ - bits as in general case - * - * Apparently there are systems implementing PCI routing table using both - * link values 0x01-0x04 and 0x41-0x44 for PCI INTA..D, but register offsets - * like 0x62 as link values for USBIRQ e.g. So there is no simple - * "register = offset + pirq" relation. - * Currently we support PCI INTA..D and USBIRQ and try our best to handle - * both link mappings. - * IDE/ACPI/DAQ mapping is currently unsupported (left untouched as set by BIOS). - */ - -static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq) -{ - u8 x; - int reg = pirq; - - switch(pirq) { - case 0x01: - case 0x02: - case 0x03: - case 0x04: - reg += 0x40; - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x62: - pci_read_config_byte(router, reg, &x); - if (reg != 0x62) - break; - if (!(x & 0x40)) - return 0; - break; - case 0x61: - case 0x6a: - case 0x7e: - printk(KERN_INFO "SiS pirq: advanced IDE/ACPI/DAQ mapping not yet implemented\n"); - return 0; - default: - printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq); - return 0; - } - return (x & 0x80) ? 0 : (x & 0x0f); -} - -static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) -{ - u8 x; - int reg = pirq; - - switch(pirq) { - case 0x01: - case 0x02: - case 0x03: - case 0x04: - reg += 0x40; - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x62: - x = (irq&0x0f) ? (irq&0x0f) : 0x80; - if (reg != 0x62) - break; - /* always mark OHCI enabled, as nothing else knows about this */ - x |= 0x40; - break; - case 0x61: - case 0x6a: - case 0x7e: - printk(KERN_INFO "advanced SiS pirq mapping not yet implemented\n"); - return 0; - default: - printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq); - return 0; - } - pci_write_config_byte(router, reg, x); - - return 1; -} - -#endif - -/* Support for AMD756 PCI IRQ Routing - * Jhon H. Caicedo <jhcaiced@osso.org.co> - * Jun/21/2001 0.2.0 Release, fixed to use "nybble" functions... (jhcaiced) - * Jun/19/2001 Alpha Release 0.1.0 (jhcaiced) - * The AMD756 pirq rules are nibble-based - * offset 0x56 0-3 PIRQA 4-7 PIRQB - * offset 0x57 0-3 PIRQC 4-7 PIRQD - */ -static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq) -{ - u8 irq; - irq = 0; - if (pirq <= 4) - { - irq = read_config_nybble(router, 0x56, pirq - 1); - } - printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n", - dev->vendor, dev->device, pirq, irq); - return irq; -} - -static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) -{ - printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", - dev->vendor, dev->device, pirq, irq); - if (pirq <= 4) - { - write_config_nybble(router, 0x56, pirq - 1, irq); - } - return 1; -} - -static struct irq_router pirq_routers[] = { -#if 0 /* all these do not exist on Hammer currently, but keep one example - for each. All these vendors have announced K8 chipsets, so we'll - eventually need a router for them. Luckily they tend to use the - same ones, so with luck just enabling the existing ones will work - when you know the final PCI ids. */ - - { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set }, - - { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set }, - - { "SIS", PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, pirq_sis_get, pirq_sis_set }, - -#endif - - { "AMD756 VIPER", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B, - pirq_amd756_get, pirq_amd756_set }, - - { "default", 0, 0, NULL, NULL } -}; - -static struct irq_router *pirq_router; -static struct pci_dev *pirq_router_dev; - -static void __init pirq_find_router(void) -{ - struct irq_routing_table *rt = pirq_table; - struct irq_router *r; - - DBG("PCI: Attempting to find IRQ router for %04x:%04x\n", - rt->rtr_vendor, rt->rtr_device); - - /* fall back to default router if nothing else found */ - pirq_router = &pirq_routers[ARRAY_SIZE(pirq_routers) - 1]; - - pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn); - if (!pirq_router_dev) { - DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn); - return; - } - - for(r=pirq_routers; r->vendor; r++) { - /* Exact match against router table entry? Use it! */ - if (r->vendor == rt->rtr_vendor && r->device == rt->rtr_device) { - pirq_router = r; - break; - } - /* Match against router device entry? Use it as a fallback */ - if (r->vendor == pirq_router_dev->vendor && r->device == pirq_router_dev->device) { - pirq_router = r; - } - } - printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n", - pirq_router->name, - pirq_router_dev->vendor, - pirq_router_dev->device, - pirq_router_dev->slot_name); -} - -static struct irq_info *pirq_get_info(struct pci_dev *dev) -{ - struct irq_routing_table *rt = pirq_table; - int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); - struct irq_info *info; - - for (info = rt->slots; entries--; info++) - if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn)) - return info; - return NULL; -} - -static irqreturn_t pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs) -{ - return IRQ_NONE; -} - -static int pcibios_lookup_irq(struct pci_dev *dev, int assign) -{ - u8 pin; - struct irq_info *info; - int i, pirq, newirq; - int irq = 0; - u32 mask; - struct irq_router *r = pirq_router; - struct pci_dev *dev2 = NULL; - char *msg = NULL; - - /* Find IRQ pin */ - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - if (!pin) { - DBG(" -> no interrupt pin\n"); - return 0; - } - pin = pin - 1; - - /* Find IRQ routing entry */ - - if (!pirq_table) - return 0; - - DBG("IRQ for %s:%d", dev->slot_name, pin); - info = pirq_get_info(dev); - if (!info) { - DBG(" -> not found in routing table\n"); - return 0; - } - pirq = info->irq[pin].link; - mask = info->irq[pin].bitmap; - if (!pirq) { - DBG(" -> not routed\n"); - return 0; - } - DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs); - mask &= pcibios_irq_mask; - - /* Work around broken HP Pavilion Notebooks which assign USB to - IRQ 9 even though it is actually wired to IRQ 11 */ - - if (broken_hp_bios_irq9 && pirq == 0x59 && dev->irq == 9) { - dev->irq = 11; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); - r->set(pirq_router_dev, dev, pirq, 11); - } - - /* - * Find the best IRQ to assign: use the one - * reported by the device if possible. - */ - newirq = dev->irq; - if (!((1 << newirq) & mask)) { - if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0; - else printk(KERN_WARNING "PCI: IRQ %i for device %s doesn't match PIRQ mask - try pci=usepirqmask\n", newirq, dev->slot_name); - } - if (!newirq && assign) { - for (i = 0; i < 16; i++) { - if (!(mask & (1 << i))) - continue; - if (pirq_penalty[i] < pirq_penalty[newirq] && - !request_irq(i, pcibios_test_irq_handler, SA_SHIRQ, "pci-test", dev)) { - free_irq(i, dev); - newirq = i; - } - } - } - DBG(" -> newirq=%d", newirq); - - /* Check if it is hardcoded */ - if ((pirq & 0xf0) == 0xf0) { - irq = pirq & 0xf; - DBG(" -> hardcoded IRQ %d\n", irq); - msg = "Hardcoded"; - } else if ( r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \ - ((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) { - DBG(" -> got IRQ %d\n", irq); - msg = "Found"; - } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) { - DBG(" -> assigning IRQ %d", newirq); - if (r->set(pirq_router_dev, dev, pirq, newirq)) { - eisa_set_level_irq(newirq); - DBG(" ... OK\n"); - msg = "Assigned"; - irq = newirq; - } - } - - if (!irq) { - DBG(" ... failed\n"); - if (newirq && mask == (1 << newirq)) { - msg = "Guessed"; - irq = newirq; - } else - return 0; - } - printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, dev->slot_name); - - /* Update IRQ for all devices with the same pirq value */ - while ((dev2 = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) { - pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin); - if (!pin) - continue; - pin--; - info = pirq_get_info(dev2); - if (!info) - continue; - if (info->irq[pin].link == pirq) { - /* We refuse to override the dev->irq information. Give a warning! */ - if ( dev2->irq && dev2->irq != irq && \ - (!(pci_probe & PCI_USE_PIRQ_MASK) || \ - ((1 << dev2->irq) & mask)) ) { - printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n", - dev2->slot_name, dev2->irq, irq); - continue; - } - dev2->irq = irq; - pirq_penalty[irq]++; - if (dev != dev2) - printk(KERN_INFO "PCI: Sharing IRQ %d with %s\n", irq, dev2->slot_name); - } - } - return 1; -} - -void __init pcibios_fixup_irqs(void) -{ - struct pci_dev *dev = NULL; - u8 pin; - - DBG("PCI: IRQ fixup\n"); - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - /* - * If the BIOS has set an out of range IRQ number, just ignore it. - * Also keep track of which IRQ's are already in use. - */ - if (dev->irq >= 16) { - DBG("%s: ignoring bogus IRQ %d\n", dev->slot_name, dev->irq); - dev->irq = 0; - } - /* If the IRQ is already assigned to a PCI device, ignore its ISA use penalty */ - if (pirq_penalty[dev->irq] >= 100 && pirq_penalty[dev->irq] < 100000) - pirq_penalty[dev->irq] = 0; - pirq_penalty[dev->irq]++; - } - - dev = NULL; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); -#ifdef CONFIG_X86_IO_APIC - /* - * Recalculate IRQ numbers if we use the I/O APIC. - */ - if (io_apic_assign_pci_irqs) - { - int irq; - - if (pin) { - pin--; /* interrupt pins are numbered starting from 1 */ - irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin); - /* - * Busses behind bridges are typically not listed in the MP-table. - * In this case we have to look up the IRQ based on the parent bus, - * parent slot, and pin number. The SMP code detects such bridged - * busses itself so we should get into this branch reliably. - */ - if (irq < 0 && dev->bus->parent) { /* go back to the bridge */ - struct pci_dev * bridge = dev->bus->self; - - pin = (pin + PCI_SLOT(dev->devfn)) % 4; - irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, - PCI_SLOT(bridge->devfn), pin); - if (irq >= 0) - printk(KERN_WARNING "PCI: using PPB(B%d,I%d,P%d) to get irq %d\n", - bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq); - } - if (irq >= 0) { - printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n", - dev->bus->number, PCI_SLOT(dev->devfn), pin, irq); - dev->irq = irq; - } - } - } -#endif - /* - * Still no IRQ? Try to lookup one... - */ - if (pin && !dev->irq) - pcibios_lookup_irq(dev, 0); - } -} - -static int __init pcibios_irq_init(void) -{ - DBG("PCI: IRQ init\n"); - - if (pcibios_enable_irq) - return 0; - - pirq_table = pirq_find_routing_table(); - - if (pirq_table) { - pirq_peer_trick(); - pirq_find_router(); - if (pirq_table->exclusive_irqs) { - int i; - for (i=0; i<16; i++) - if (!(pirq_table->exclusive_irqs & (1 << i))) - pirq_penalty[i] += 100; - } - /* If we're using the I/O APIC, avoid using the PCI IRQ routing table */ - if (io_apic_assign_pci_irqs) - pirq_table = NULL; - } - - pcibios_enable_irq = pirq_enable_irq; - - pcibios_fixup_irqs(); - return 0; -} - -subsys_initcall(pcibios_irq_init); - - -void pcibios_penalize_isa_irq(int irq) -{ - /* - * If any ISAPnP device reports an IRQ in its list of possible - * IRQ's, we try to avoid assigning it to PCI devices. - */ - pirq_penalty[irq] += 100; -} - -int pirq_enable_irq(struct pci_dev *dev) -{ - u8 pin; - extern int interrupt_line_quirk; - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { - /* With IDE legacy devices the IRQ lookup failure is not a problem.. */ - if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5)) - return 0; - - printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.\n", - 'A' + pin - 1, dev->slot_name); - } - /* VIA bridges use interrupt line for apic/pci steering across - the V-Link */ - else if (interrupt_line_quirk) - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - - return 0; -} diff --git a/arch/x86_64/pci/legacy.c b/arch/x86_64/pci/legacy.c deleted file mode 100644 index e43d70fdee5c..000000000000 --- a/arch/x86_64/pci/legacy.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * legacy.c - traditional, old school PCI bus probing - */ -#include <linux/init.h> -#include <linux/pci.h> -#include "pci.h" - -/* - * Discover remaining PCI buses in case there are peer host bridges. - * We use the number of last PCI bus provided by the PCI BIOS. - */ -void __devinit pcibios_fixup_peer_bridges(void) -{ - int n; - struct pci_bus *bus; - struct pci_dev *dev; - u16 l; - - if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) - return; - DBG("PCI: Peer bridge fixup\n"); - - bus = kmalloc(sizeof(*bus), GFP_ATOMIC); - dev = kmalloc(sizeof(*dev), GFP_ATOMIC); - if (!bus || !dev) { - printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__); - goto exit; - } - - for (n=0; n <= pcibios_last_bus; n++) { - if (pci_bus_exists(&pci_root_buses, n)) - continue; - bus->number = n; - bus->ops = pci_root_ops; - dev->bus = bus; - for (dev->devfn=0; dev->devfn<256; dev->devfn += 8) - if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) && - l != 0x0000 && l != 0xffff) { - DBG("Found device at %02x:%02x [%04x]\n", n, dev->devfn, l); - printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n); - pci_scan_bus(n, pci_root_ops, NULL); - break; - } - } -exit: - kfree(dev); - kfree(bus); -} - -static int __init pci_legacy_init(void) -{ - if (!pci_root_ops) { - printk("PCI: System does not support PCI\n"); - return 0; - } - - if (pcibios_scanned++) - return 0; - - printk("PCI: Probing PCI hardware\n"); - pci_root_bus = pcibios_scan_root(0); - - pcibios_fixup_peer_bridges(); - - return 0; -} - -subsys_initcall(pci_legacy_init); diff --git a/arch/x86_64/pci/pci.h b/arch/x86_64/pci/pci.h deleted file mode 100644 index c89003343f9c..000000000000 --- a/arch/x86_64/pci/pci.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Low-Level PCI Access for x86-64 machines. - * - * (c) 1999 Martin Mares <mj@ucw.cz> - */ - -#undef DEBUG - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -#define PCI_PROBE_BIOS 0x0001 -#define PCI_PROBE_CONF1 0x0002 -#define PCI_PROBE_CONF2 0x0004 -#define PCI_NO_SORT 0x0100 -#define PCI_BIOS_SORT 0x0200 -#define PCI_NO_CHECKS 0x0400 -#define PCI_USE_PIRQ_MASK 0x0800 -#define PCI_ASSIGN_ROMS 0x1000 -#define PCI_BIOS_IRQ_SCAN 0x2000 -#define PCI_ASSIGN_ALL_BUSSES 0x4000 -#define PCI_NO_ACPI_ROUTING 0x8000 - -extern unsigned int pci_probe; - -extern unsigned int pcibios_max_latency; - -void pcibios_resource_survey(void); -int pcibios_enable_resources(struct pci_dev *, int); - -/* pci-pc.c */ - -extern int pcibios_last_bus; -extern struct pci_bus *pci_root_bus; -extern struct pci_ops *pci_root_ops; - -/* pci-irq.c */ - -struct irq_info { - u8 bus, devfn; /* Bus, device and function */ - struct { - u8 link; /* IRQ line ID, chipset dependent, 0=not routed */ - u16 bitmap; /* Available IRQs */ - } __attribute__((packed)) irq[4]; - u8 slot; /* Slot number, 0=onboard */ - u8 rfu; -} __attribute__((packed)); - -struct irq_routing_table { - u32 signature; /* PIRQ_SIGNATURE should be here */ - u16 version; /* PIRQ_VERSION */ - u16 size; /* Table size in bytes */ - u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */ - u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */ - u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */ - u32 miniport_data; /* Crap */ - u8 rfu[11]; - u8 checksum; /* Modulo 256 checksum must give zero */ - struct irq_info slots[0]; -} __attribute__((packed)); - -extern unsigned int pcibios_irq_mask; - -extern int pcibios_scanned; -extern spinlock_t pci_config_lock; - -int pirq_enable_irq(struct pci_dev *dev); - -extern int (*pcibios_enable_irq)(struct pci_dev *dev); - -/* legacy.c */ -extern void pcibios_fixup_peer_bridges(void); diff --git a/arch/x86_64/pci/x86-64.c b/arch/x86_64/pci/x86-64.c deleted file mode 100644 index 15a41b747f07..000000000000 --- a/arch/x86_64/pci/x86-64.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Low-Level PCI Access for x86-64 machines - * - * Copyright 1993, 1994 Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * Drew@Colorado.EDU - * +1 (303) 786-7975 - * - * Drew's work was sponsored by: - * iX Multiuser Multitasking Magazine - * Hannover, Germany - * hm@ix.de - * - * Copyright 1997--2000 Martin Mares <mj@ucw.cz> - * - * For more information, please consult the following manuals (look at - * http://www.pcisig.com/ for how to get them): - * - * PCI BIOS Specification - * PCI Local Bus Specification - * PCI to PCI Bridge Specification - * PCI System Design Guide - * - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/ioport.h> -#include <linux/errno.h> - -#include "pci.h" - -/* - * We need to avoid collisions with `mirrored' VGA ports - * and other strange ISA hardware, so we always want the - * addresses to be allocated in the 0x000-0x0ff region - * modulo 0x400. - * - * Why? Because some silly external IO cards only decode - * the low 10 bits of the IO address. The 0x00-0xff region - * is reserved for motherboard devices that decode all 16 - * bits, so it's ok to allocate at, say, 0x2800-0x28ff, - * but we want to try to avoid allocating at 0x2900-0x2bff - * which might have be mirrored at 0x0100-0x03ff.. - */ -void -pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ - if (res->flags & IORESOURCE_IO) { - unsigned long start = res->start; - - if (start & 0x300) { - start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } -} - - -/* - * Handle resources of PCI devices. If the world were perfect, we could - * just allocate all the resource regions and do nothing more. It isn't. - * On the other hand, we cannot just re-allocate all devices, as it would - * require us to know lots of host bridge internals. So we attempt to - * keep as much of the original configuration as possible, but tweak it - * when it's found to be wrong. - * - * Known BIOS problems we have to work around: - * - I/O or memory regions not configured - * - regions configured, but not enabled in the command register - * - bogus I/O addresses above 64K used - * - expansion ROMs left enabled (this may sound harmless, but given - * the fact the PCI specs explicitly allow address decoders to be - * shared between expansion ROMs and other resource regions, it's - * at least dangerous) - * - * Our solution: - * (1) Allocate resources for all buses behind PCI-to-PCI bridges. - * This gives us fixed barriers on where we can allocate. - * (2) Allocate resources for all enabled devices. If there is - * a collision, just mark the resource as unallocated. Also - * disable expansion ROMs during this step. - * (3) Try to allocate resources for disabled devices. If the - * resources were assigned correctly, everything goes well, - * if they weren't, they won't disturb allocation of other - * resources. - * (4) Assign new addresses to resources which were either - * not configured at all or misconfigured. If explicitly - * requested by the user, configure expansion ROM address - * as well. - */ - -static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) -{ - struct list_head *ln; - struct pci_bus *bus; - struct pci_dev *dev; - int idx; - struct resource *r, *pr; - - /* Depth-First Search on bus tree */ - for (ln=bus_list->next; ln != bus_list; ln=ln->next) { - bus = pci_bus_b(ln); - if ((dev = bus->self)) { - for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { - r = &dev->resource[idx]; - if (!r->start) - continue; - pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) - printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name); - } - } - pcibios_allocate_bus_resources(&bus->children); - } -} - -static void __init pcibios_allocate_resources(int pass) -{ - struct pci_dev *dev = NULL; - int idx, disabled; - u16 command; - struct resource *r, *pr; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - pci_read_config_word(dev, PCI_COMMAND, &command); - for(idx = 0; idx < 6; idx++) { - r = &dev->resource[idx]; - if (r->parent) /* Already allocated */ - continue; - if (!r->start) /* Address not assigned at all */ - continue; - if (r->flags & IORESOURCE_IO) - disabled = !(command & PCI_COMMAND_IO); - else - disabled = !(command & PCI_COMMAND_MEMORY); - if (pass == disabled) { - DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n", - r->start, r->end, r->flags, disabled, pass); - pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) { - printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, dev->slot_name); - /* We'll assign a new address later */ - r->end -= r->start; - r->start = 0; - } - } - } - if (!pass) { - r = &dev->resource[PCI_ROM_RESOURCE]; - if (r->flags & PCI_ROM_ADDRESS_ENABLE) { - /* Turn the ROM off, leave the resource region, but keep it unregistered. */ - u32 reg; - DBG("PCI: Switching off ROM of %s\n", dev->slot_name); - r->flags &= ~PCI_ROM_ADDRESS_ENABLE; - pci_read_config_dword(dev, dev->rom_base_reg, ®); - pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE); - } - } - } -} - -static void __init pcibios_assign_resources(void) -{ - struct pci_dev *dev = NULL; - int idx; - struct resource *r; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - int class = dev->class >> 8; - - /* Don't touch classless devices and host bridges */ - if (!class || class == PCI_CLASS_BRIDGE_HOST) - continue; - - for(idx=0; idx<6; idx++) { - r = &dev->resource[idx]; - - /* - * Don't touch IDE controllers and I/O ports of video cards! - */ - if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) || - (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO))) - continue; - - /* - * We shall assign a new address to this resource, either because - * the BIOS forgot to do so or because we have decided the old - * address was unusable for some reason. - */ - if (!r->start && r->end) - pci_assign_resource(dev, idx); - } - - if (pci_probe & PCI_ASSIGN_ROMS) { - r = &dev->resource[PCI_ROM_RESOURCE]; - r->end -= r->start; - r->start = 0; - if (r->end) - pci_assign_resource(dev, PCI_ROM_RESOURCE); - } - } -} - -void __init pcibios_resource_survey(void) -{ - DBG("PCI: Allocating resources\n"); - pcibios_allocate_bus_resources(&pci_root_buses); - pcibios_allocate_resources(0); - pcibios_allocate_resources(1); - pcibios_assign_resources(); -} - -int pcibios_enable_resources(struct pci_dev *dev, int mask) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for(idx=0; idx<6; idx++) { - if (!(mask & (1<<idx))) - continue; - - r = &dev->resource[idx]; - if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (dev->resource[PCI_ROM_RESOURCE].start) - cmd |= PCI_COMMAND_MEMORY; - if (cmd != old_cmd) { - printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -/* - * If we set up a device for bus mastering, we need to check the latency - * timer as certain crappy BIOSes forget to set it properly. - */ -unsigned int pcibios_max_latency = 255; - -void pcibios_set_master(struct pci_dev *dev) -{ - u8 lat; - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - if (lat < 16) - lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; - else if (lat > pcibios_max_latency) - lat = pcibios_max_latency; - else - return; - printk("PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); -} - -int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine) -{ - unsigned long prot; - - /* I/O space cannot be accessed via normal processor loads and - * stores on this platform. - */ - if (mmap_state == pci_mmap_io) - return -EINVAL; - - /* 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); - - prot = pgprot_val(vma->vm_page_prot); - if (boot_cpu_data.x86 > 3) - prot |= _PAGE_PCD | _PAGE_PWT; - vma->vm_page_prot = __pgprot(prot); - - /* Write-combine setting is ignored, it is changed via the mtrr - * interfaces on this platform. - */ - if (remap_page_range(vma, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot)) - return -EAGAIN; - - return 0; -} diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h index a03fc84b2b62..cf8b16cbe8db 100644 --- a/include/asm-x86_64/fixmap.h +++ b/include/asm-x86_64/fixmap.h @@ -16,6 +16,7 @@ #include <asm/apicdef.h> #include <asm/page.h> #include <asm/vsyscall.h> +#include <asm/vsyscall32.h> /* * Here we define all the compile-time 'special' virtual @@ -62,6 +63,10 @@ extern void __set_fixmap (enum fixed_addresses idx, #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) +/* Only covers 32bit vsyscalls currently. Need another set for 64bit. */ +#define FIXADDR_USER_START ((unsigned long)VSYSCALL32_VSYSCALL) +#define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE) + #define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) extern void __this_fixmap_does_not_exist(void); diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h index 7d80bcbc798e..b2cc4f1a241a 100644 --- a/include/asm-x86_64/io.h +++ b/include/asm-x86_64/io.h @@ -105,7 +105,7 @@ __OUTS(l) #define IO_SPACE_LIMIT 0xffff -#ifdef __KERNEL__ +#if defined(__KERNEL__) && __x86_64__ #include <linux/vmalloc.h> diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h index 9db87d94b771..c1a69000c8d7 100644 --- a/include/asm-x86_64/mmzone.h +++ b/include/asm-x86_64/mmzone.h @@ -23,7 +23,6 @@ extern int maxnode; extern struct pglist_data *node_data[]; -/* kern_addr_valid below hardcodes the same algorithm*/ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr) { int nid; @@ -46,19 +45,6 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr) #define local_mapnr(kvaddr) \ ( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) ) -#define kern_addr_valid(kvaddr) ({ \ - int ok = 0; \ - unsigned long index = __pa(kvaddr) >> memnode_shift; \ - if (index <= NODEMAPSIZE) { \ - unsigned nodeid = memnodemap[index]; \ - unsigned long pfn = __pa(kvaddr) >> PAGE_SHIFT; \ - unsigned long start_pfn = node_start_pfn(nodeid); \ - ok = (nodeid != 0xff) && \ - (pfn >= start_pfn) && \ - (pfn < start_pfn + node_size(nodeid)); \ - } \ - ok; \ -}) /* AK: this currently doesn't deal with invalid addresses. We'll see if the 2.5 kernel doesn't pass them diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h index e4198d618b26..47ef9dfd93dd 100644 --- a/include/asm-x86_64/page.h +++ b/include/asm-x86_64/page.h @@ -76,6 +76,8 @@ extern unsigned long vm_force_exec32; #define __PAGE_OFFSET 0x0000010000000000 /* 1 << 40 */ #define __PHYSICAL_MASK_SHIFT 40 #define __PHYSICAL_MASK ((1UL << __PHYSICAL_MASK_SHIFT) - 1) +#define __VIRTUAL_MASK_SHIFT 48 +#define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1) #define KERNEL_TEXT_SIZE (40UL*1024*1024) #define KERNEL_TEXT_START 0xffffffff80000000UL diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h index dac7f737e270..10763ac9ed18 100644 --- a/include/asm-x86_64/pci.h +++ b/include/asm-x86_64/pci.h @@ -45,7 +45,6 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq); struct pci_dev; extern int iommu_setup(char *opt); -extern void pci_iommu_init(void); /* Allocate and map kernel buffer using consistent mode DMA for a device. * hwdev should be valid struct pci_dev pointer for PCI devices, diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index 83a902a5550b..893dc0858734 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h @@ -339,7 +339,7 @@ static inline pgd_t *current_pgd_offset_k(unsigned long address) #define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) #define pmd_bad(x) ((pmd_val(x) & (~PTE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE ) #define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot))) - +#define pmd_pfn(x) ((pmd_val(x) >> PAGE_SHIFT) & __PHYSICAL_MASK) #define pte_to_pgoff(pte) ((pte_val(pte) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT) #define pgoff_to_pte(off) ((pte_t) { ((off) << PAGE_SHIFT) | _PAGE_FILE }) @@ -392,9 +392,7 @@ typedef pte_t *pte_addr_t; #endif /* !__ASSEMBLY__ */ -#ifndef CONFIG_DISCONTIGMEM -#define kern_addr_valid(addr) (1) -#endif +extern int kern_addr_valid(unsigned long addr); #define io_remap_page_range remap_page_range @@ -403,4 +401,9 @@ typedef pte_t *pte_addr_t; #define pgtable_cache_init() do { } while (0) #define check_pgt_cache() do { } while (0) +/* fs/proc/kcore.c */ +#define kc_vaddr_to_offset(v) ((v) & __VIRTUAL_MASK) +#define kc_offset_to_vaddr(o) \ + (((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o)) + #endif /* _X86_64_PGTABLE_H */ diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h index 78f6a491449d..c2402015727b 100644 --- a/include/asm-x86_64/proto.h +++ b/include/asm-x86_64/proto.h @@ -16,7 +16,12 @@ extern void mcheck_init(struct cpuinfo_x86 *c); extern void init_memory_mapping(void); extern void system_call(void); +extern int kernel_syscall(void); +extern void syscall_init(void); + +extern void ia32_syscall(void); extern void ia32_cstar_target(void); + extern void calibrate_delay(void); extern void cpu_idle(void); extern void sys_ni_syscall(void); @@ -24,6 +29,8 @@ extern void config_acpi_tables(void); extern void ia32_syscall(void); extern void iommu_hole_init(void); +extern void time_init_smp(void); + extern void do_softirq_thunk(void); extern int numa_setup(char *opt); @@ -39,8 +46,12 @@ extern unsigned long numa_free_all_bootmem(void); extern void reserve_bootmem_generic(unsigned long phys, unsigned len); extern void free_bootmem_generic(unsigned long phys, unsigned len); +extern void load_gs_index(unsigned gs); + extern unsigned long end_pfn_map; +extern unsigned long cpu_initialized; + extern void show_stack(unsigned long * rsp); extern void show_trace(unsigned long * rsp); extern void show_registers(struct pt_regs *regs); @@ -66,9 +77,16 @@ extern unsigned long max_mapnr; extern unsigned long end_pfn; extern unsigned long table_start, table_end; -extern void syscall_init(void); +extern int exception_trace; +extern int no_iommu, force_mmu; +extern int using_apic_timer; +extern int disable_apic; +extern unsigned cpu_khz; -struct pt_regs; +extern int fallback_aper_order; +extern int fallback_aper_force; + +extern void smp_local_timer_interrupt(struct pt_regs * regs); long do_arch_prctl(struct task_struct *task, int code, unsigned long addr); -- 2.30.9