diff --git a/[refs] b/[refs] index d10f817b2b94..b41003e5cc1b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0238cb4e7583c521bb3538060f98a73e65f61324 +refs/heads/master: 9c782e3b2083c33b5a14c9955cf15f32ea88116b diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index b4a1ea762698..9474501dd6cc 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -123,15 +123,6 @@ Who: Christoph Hellwig --------------------------- -What: CONFIG_FORCED_INLINING -When: June 2006 -Why: Config option is there to see if gcc is good enough. (in january - 2006). If it is, the behavior should just be the default. If it's not, - the option should just go away entirely. -Who: Arjan van de Ven - ---------------------------- - What: START_ARRAY ioctl for md When: July 2006 Files: drivers/md/md.c diff --git a/trunk/Documentation/filesystems/tmpfs.txt b/trunk/Documentation/filesystems/tmpfs.txt index dbe4d87d2615..0d783c504ead 100644 --- a/trunk/Documentation/filesystems/tmpfs.txt +++ b/trunk/Documentation/filesystems/tmpfs.txt @@ -78,18 +78,6 @@ use up all the memory on the machine; but enhances the scalability of that instance in a system with many cpus making intensive use of it. -tmpfs has a mount option to set the NUMA memory allocation policy for -all files in that instance: -mpol=interleave prefers to allocate memory from each node in turn -mpol=default prefers to allocate memory from the local node -mpol=bind prefers to allocate from mpol_nodelist -mpol=preferred prefers to allocate from first node in mpol_nodelist - -The following mount option is used in conjunction with mpol=interleave, -mpol=bind or mpol=preferred: -mpol_nodelist: nodelist suitable for parsing with nodelist_parse. - - To specify the initial root directory you can use the following mount options: diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 1cbcf65b764b..fe11fccf7e41 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -471,7 +471,7 @@ running once the system is up. arch/i386/kernel/cpu/cpufreq/elanfreq.c. elevator= [IOSCHED] - Format: {"anticipatory" | "cfq" | "deadline" | "noop"} + Format: {"as" | "cfq" | "deadline" | "noop"} See Documentation/block/as-iosched.txt and Documentation/block/deadline-iosched.txt for details. @@ -712,17 +712,9 @@ running once the system is up. load_ramdisk= [RAM] List of ramdisks to load from floppy See Documentation/ramdisk.txt. - lockd.nlm_grace_period=P [NFS] Assign grace period. - Format: - - lockd.nlm_tcpport=N [NFS] Assign TCP port. - Format: + lockd.udpport= [NFS] - lockd.nlm_timeout=T [NFS] Assign timeout value. - Format: - - lockd.nlm_udpport=M [NFS] Assign UDP port. - Format: + lockd.tcpport= [NFS] logibm.irq= [HW,MOUSE] Logitech Bus Mouse Driver Format: diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index ce3c8f52c919..71693c5c3137 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1300,12 +1300,6 @@ M: ttb@tentacle.dhs.org and rml@novell.com L: linux-kernel@vger.kernel.org S: Maintained -INTEL FRAMEBUFFER DRIVER (excluding 810 and 815) -P: Sylvain Meyer -M: sylvain.meyer@worldonline.fr -L: linux-fbdev-devel@lists.sourceforge.net -S: Maintained - INTEL 810/815 FRAMEBUFFER DRIVER P: Antonino Daplas M: adaplas@pol.net @@ -1895,11 +1889,11 @@ W: http://linux-ntfs.sf.net/ T: git kernel.org:/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git S: Maintained -NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER -P: Antonino Daplas -M: adaplas@pol.net -L: linux-fbdev-devel@lists.sourceforge.net -S: Maintained +NVIDIA (RIVA) FRAMEBUFFER DRIVER +P: Ani Joshi +M: ajoshi@shell.unixbox.com +L: linux-nvidia@lists.surfsouth.com +S: Maintained ORACLE CLUSTER FILESYSTEM 2 (OCFS2) P: Mark Fasheh @@ -2194,12 +2188,6 @@ L: rtl@rtlinux.org W: www.rtlinux.org S: Maintained -S3 SAVAGE FRAMEBUFFER DRIVER -P: Antonino Daplas -M: adaplas@pol.net -L: linux-fbdev-devel@lists.sourceforge.net -S: Maintained - S390 P: Martin Schwidefsky M: schwidefsky@de.ibm.com @@ -2965,12 +2953,6 @@ M: dm@sangoma.com W: http://www.sangoma.com S: Supported -WATCHDOG DEVICE DRIVERS -P: Wim Van Sebroeck -M: wim@iguana.be -T: git kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog.git -S: Maintained - WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS P: Jean Tourrilhes M: jt@hpl.hp.com diff --git a/trunk/Makefile b/trunk/Makefile index 673148e07603..deedaf79cdca 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -151,7 +151,7 @@ export srctree objtree VPATH TOPDIR SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ -e s/arm.*/arm/ -e s/sa110/arm/ \ -e s/s390x/s390/ -e s/parisc64/parisc/ \ - -e s/ppc.*/powerpc/ ) + -e s/ppc64/powerpc/ ) # Cross compiling and selecting different set of gcc/bin-utils # --------------------------------------------------------------------------- diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index 5959e36c3b4c..3cfd82a05b20 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -180,7 +180,6 @@ config ARCH_OMAP config ARCH_VERSATILE bool "Versatile" select ARM_AMBA - select ARM_VIC select ICST307 help This enables support for ARM Ltd Versatile board. @@ -401,38 +400,6 @@ config NO_IDLE_HZ Currently at least OMAP, PXA2xx and SA11x0 platforms are known to have accurate timekeeping with dynamic tick. -config AEABI - bool "Use the ARM EABI to compile the kernel" - help - This option allows for the kernel to be compiled using the latest - ARM ABI (aka EABI). This is only useful if you are using a user - space environment that is also compiled with EABI. - - Since there are major incompatibilities between the legacy ABI and - EABI, especially with regard to structure member alignment, this - option also changes the kernel syscall calling convention to - disambiguate both ABIs and allow for backward compatibility support - (selected with CONFIG_OABI_COMPAT). - - To use this you need GCC version 4.0.0 or later. - -config OABI_COMPAT - bool "Allow old ABI binaries to run with this kernel" - depends on AEABI - default y - help - This option preserves the old syscall interface along with the - new (ARM EABI) one. It also provides a compatibility layer to - intercept syscalls that have structure arguments which layout - in memory differs between the legacy ABI and the new ARM EABI - (only for non "thumb" binaries). This option adds a tiny - overhead to all syscalls and produces a slightly larger kernel. - If you know you'll be using only pure EABI user space then you - can say N here. If this option is not selected and you attempt - to execute a legacy ABI binary then the result will be - UNPREDICTABLE (in fact it can be predicted that it won't work - at all). If in doubt say Y. - config ARCH_DISCONTIGMEM_ENABLE bool default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) @@ -619,7 +586,6 @@ comment "At least one emulation must be selected" config FPE_NWFPE bool "NWFPE math emulation" - depends on !AEABI || OABI_COMPAT ---help--- Say Y to include the NWFPE floating point emulator in the kernel. This is necessary to run most binaries. Linux does not currently @@ -643,7 +609,7 @@ config FPE_NWFPE_XP config FPE_FASTFPE bool "FastFPE math emulation (EXPERIMENTAL)" - depends on (!AEABI || OABI_COMPAT) && !CPU_32v3 && EXPERIMENTAL + depends on !CPU_32v3 && EXPERIMENTAL ---help--- Say Y here to include the FAST floating point emulator in the kernel. This is an experimental much faster emulator which now also has full @@ -675,7 +641,6 @@ source "fs/Kconfig.binfmt" config ARTHUR tristate "RISC OS personality" - depends on !AEABI help Say Y here to include the kernel code necessary if you want to run Acorn RISC OS/Arthur binaries under Linux. This code is still very diff --git a/trunk/arch/arm/Makefile b/trunk/arch/arm/Makefile index fbfc14a56b96..1fa2a1011584 100644 --- a/trunk/arch/arm/Makefile +++ b/trunk/arch/arm/Makefile @@ -56,13 +56,8 @@ tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) -ifeq ($(CONFIG_AEABI),y) -CFLAGS_ABI :=-mabi=aapcs -mno-thumb-interwork -else -CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,) -endif - # Need -Uarm for gcc < 3.x +CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,) CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float diff --git a/trunk/arch/arm/common/Kconfig b/trunk/arch/arm/common/Kconfig index 5e34ca6d38b6..d7509c7a3c5e 100644 --- a/trunk/arch/arm/common/Kconfig +++ b/trunk/arch/arm/common/Kconfig @@ -1,10 +1,7 @@ -config ARM_GIC - bool - -config ARM_VIC +config ICST525 bool -config ICST525 +config ARM_GIC bool config ICST307 diff --git a/trunk/arch/arm/common/Makefile b/trunk/arch/arm/common/Makefile index c81a2ff6b5be..ec8d17c96906 100644 --- a/trunk/arch/arm/common/Makefile +++ b/trunk/arch/arm/common/Makefile @@ -4,7 +4,6 @@ obj-y += rtctime.o obj-$(CONFIG_ARM_GIC) += gic.o -obj-$(CONFIG_ARM_VIC) += vic.o obj-$(CONFIG_ICST525) += icst525.o obj-$(CONFIG_ICST307) += icst307.o obj-$(CONFIG_SA1111) += sa1111.o diff --git a/trunk/arch/arm/common/vic.c b/trunk/arch/arm/common/vic.c deleted file mode 100644 index a45ed1687a59..000000000000 --- a/trunk/arch/arm/common/vic.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * linux/arch/arm/common/vic.c - * - * Copyright (C) 1999 - 2003 ARM Limited - * Copyright (C) 2000 Deep Blue Solutions Ltd - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include - -#include -#include -#include -#include - -static void __iomem *vic_base; - -static void vic_mask_irq(unsigned int irq) -{ - irq -= IRQ_VIC_START; - writel(1 << irq, vic_base + VIC_INT_ENABLE_CLEAR); -} - -static void vic_unmask_irq(unsigned int irq) -{ - irq -= IRQ_VIC_START; - writel(1 << irq, vic_base + VIC_INT_ENABLE); -} - -static struct irqchip vic_chip = { - .ack = vic_mask_irq, - .mask = vic_mask_irq, - .unmask = vic_unmask_irq, -}; - -void __init vic_init(void __iomem *base, u32 vic_sources) -{ - unsigned int i; - - vic_base = base; - - /* Disable all interrupts initially. */ - - writel(0, vic_base + VIC_INT_SELECT); - writel(0, vic_base + VIC_INT_ENABLE); - writel(~0, vic_base + VIC_INT_ENABLE_CLEAR); - writel(0, vic_base + VIC_IRQ_STATUS); - writel(0, vic_base + VIC_ITCR); - writel(~0, vic_base + VIC_INT_SOFT_CLEAR); - - /* - * Make sure we clear all existing interrupts - */ - writel(0, vic_base + VIC_VECT_ADDR); - for (i = 0; i < 19; i++) { - unsigned int value; - - value = readl(vic_base + VIC_VECT_ADDR); - writel(value, vic_base + VIC_VECT_ADDR); - } - - for (i = 0; i < 16; i++) { - void __iomem *reg = vic_base + VIC_VECT_CNTL0 + (i * 4); - writel(VIC_VECT_CNTL_ENABLE | i, reg); - } - - writel(32, vic_base + VIC_DEF_VECT_ADDR); - - for (i = 0; i < 32; i++) { - unsigned int irq = IRQ_VIC_START + i; - - set_irq_chip(irq, &vic_chip); - - if (vic_sources & (1 << i)) { - set_irq_handler(irq, do_level_IRQ); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - } - } -} diff --git a/trunk/arch/arm/kernel/Makefile b/trunk/arch/arm/kernel/Makefile index 2ce0e3a27a45..de94b0f3ee2a 100644 --- a/trunk/arch/arm/kernel/Makefile +++ b/trunk/arch/arm/kernel/Makefile @@ -20,7 +20,6 @@ obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_PCI) += bios32.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_IWMMXT) += iwmmxt.o AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt diff --git a/trunk/arch/arm/kernel/armksyms.c b/trunk/arch/arm/kernel/armksyms.c index 1574941ebfe1..9997098009a9 100644 --- a/trunk/arch/arm/kernel/armksyms.c +++ b/trunk/arch/arm/kernel/armksyms.c @@ -35,16 +35,6 @@ extern void __udivsi3(void); extern void __umodsi3(void); extern void __do_div64(void); -extern void __aeabi_idiv(void); -extern void __aeabi_idivmod(void); -extern void __aeabi_lasr(void); -extern void __aeabi_llsl(void); -extern void __aeabi_llsr(void); -extern void __aeabi_lmul(void); -extern void __aeabi_uidiv(void); -extern void __aeabi_uidivmod(void); -extern void __aeabi_ulcmp(void); - extern void fpundefinstr(void); extern void fp_enter(void); @@ -151,18 +141,6 @@ EXPORT_SYMBOL(__udivsi3); EXPORT_SYMBOL(__umodsi3); EXPORT_SYMBOL(__do_div64); -#ifdef CONFIG_AEABI -EXPORT_SYMBOL(__aeabi_idiv); -EXPORT_SYMBOL(__aeabi_idivmod); -EXPORT_SYMBOL(__aeabi_lasr); -EXPORT_SYMBOL(__aeabi_llsl); -EXPORT_SYMBOL(__aeabi_llsr); -EXPORT_SYMBOL(__aeabi_lmul); -EXPORT_SYMBOL(__aeabi_uidiv); -EXPORT_SYMBOL(__aeabi_uidivmod); -EXPORT_SYMBOL(__aeabi_ulcmp); -#endif - /* bitops */ EXPORT_SYMBOL(_set_bit_le); EXPORT_SYMBOL(_test_and_set_bit_le); diff --git a/trunk/arch/arm/kernel/calls.S b/trunk/arch/arm/kernel/calls.S index 75e6f9a94713..55076a75e5bf 100644 --- a/trunk/arch/arm/kernel/calls.S +++ b/trunk/arch/arm/kernel/calls.S @@ -13,7 +13,7 @@ #define NR_syscalls 328 #else -100: +__syscall_start: /* 0 */ .long sys_restart_syscall .long sys_exit .long sys_fork_wrapper @@ -27,7 +27,7 @@ /* 10 */ .long sys_unlink .long sys_execve_wrapper .long sys_chdir - .long OBSOLETE(sys_time) /* used by libc4 */ + .long sys_time /* used by libc4 */ .long sys_mknod /* 15 */ .long sys_chmod .long sys_lchown16 @@ -36,15 +36,15 @@ .long sys_lseek /* 20 */ .long sys_getpid .long sys_mount - .long OBSOLETE(sys_oldumount) /* used by libc4 */ + .long sys_oldumount /* used by libc4 */ .long sys_setuid16 .long sys_getuid16 -/* 25 */ .long OBSOLETE(sys_stime) +/* 25 */ .long sys_stime .long sys_ptrace - .long OBSOLETE(sys_alarm) /* used by libc4 */ + .long sys_alarm /* used by libc4 */ .long sys_ni_syscall /* was sys_fstat */ .long sys_pause -/* 30 */ .long OBSOLETE(sys_utime) /* used by libc4 */ +/* 30 */ .long sys_utime /* used by libc4 */ .long sys_ni_syscall /* was sys_stty */ .long sys_ni_syscall /* was sys_getty */ .long sys_access @@ -90,21 +90,21 @@ .long sys_sigpending .long sys_sethostname /* 75 */ .long sys_setrlimit - .long OBSOLETE(sys_old_getrlimit) /* used by libc4 */ + .long sys_old_getrlimit /* used by libc4 */ .long sys_getrusage .long sys_gettimeofday .long sys_settimeofday /* 80 */ .long sys_getgroups16 .long sys_setgroups16 - .long OBSOLETE(old_select) /* used by libc4 */ + .long old_select /* used by libc4 */ .long sys_symlink .long sys_ni_syscall /* was sys_lstat */ /* 85 */ .long sys_readlink .long sys_uselib .long sys_swapon .long sys_reboot - .long OBSOLETE(old_readdir) /* used by libc4 */ -/* 90 */ .long OBSOLETE(old_mmap) /* used by libc4 */ + .long old_readdir /* used by libc4 */ +/* 90 */ .long old_mmap /* used by libc4 */ .long sys_munmap .long sys_truncate .long sys_ftruncate @@ -116,7 +116,7 @@ .long sys_statfs /* 100 */ .long sys_fstatfs .long sys_ni_syscall - .long OBSOLETE(sys_socketcall) + .long sys_socketcall .long sys_syslog .long sys_setitimer /* 105 */ .long sys_getitimer @@ -127,11 +127,11 @@ /* 110 */ .long sys_ni_syscall /* was sys_iopl */ .long sys_vhangup .long sys_ni_syscall - .long OBSOLETE(sys_syscall) /* call a syscall */ + .long sys_syscall /* call a syscall */ .long sys_wait4 /* 115 */ .long sys_swapoff .long sys_sysinfo - .long OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)) + .long sys_ipc .long sys_fsync .long sys_sigreturn_wrapper /* 120 */ .long sys_clone_wrapper @@ -194,8 +194,8 @@ .long sys_rt_sigtimedwait .long sys_rt_sigqueueinfo .long sys_rt_sigsuspend_wrapper -/* 180 */ .long ABI(sys_pread64, sys_oabi_pread64) - .long ABI(sys_pwrite64, sys_oabi_pwrite64) +/* 180 */ .long sys_pread64 + .long sys_pwrite64 .long sys_chown16 .long sys_getcwd .long sys_capget @@ -207,11 +207,11 @@ /* 190 */ .long sys_vfork_wrapper .long sys_getrlimit .long sys_mmap2 - .long ABI(sys_truncate64, sys_oabi_truncate64) - .long ABI(sys_ftruncate64, sys_oabi_ftruncate64) -/* 195 */ .long ABI(sys_stat64, sys_oabi_stat64) - .long ABI(sys_lstat64, sys_oabi_lstat64) - .long ABI(sys_fstat64, sys_oabi_fstat64) + .long sys_truncate64 + .long sys_ftruncate64 +/* 195 */ .long sys_stat64 + .long sys_lstat64 + .long sys_fstat64 .long sys_lchown .long sys_getuid /* 200 */ .long sys_getgid @@ -235,11 +235,11 @@ .long sys_pivot_root .long sys_mincore /* 220 */ .long sys_madvise - .long ABI(sys_fcntl64, sys_oabi_fcntl64) + .long sys_fcntl64 .long sys_ni_syscall /* TUX */ .long sys_ni_syscall .long sys_gettid -/* 225 */ .long ABI(sys_readahead, sys_oabi_readahead) +/* 225 */ .long sys_readahead .long sys_setxattr .long sys_lsetxattr .long sys_fsetxattr @@ -265,8 +265,8 @@ .long sys_exit_group .long sys_lookup_dcookie /* 250 */ .long sys_epoll_create - .long ABI(sys_epoll_ctl, sys_oabi_epoll_ctl) - .long ABI(sys_epoll_wait, sys_oabi_epoll_wait) + .long sys_epoll_ctl + .long sys_epoll_wait .long sys_remap_file_pages .long sys_ni_syscall /* sys_set_thread_area */ /* 255 */ .long sys_ni_syscall /* sys_get_thread_area */ @@ -280,8 +280,8 @@ .long sys_clock_gettime .long sys_clock_getres /* 265 */ .long sys_clock_nanosleep - .long sys_statfs64_wrapper - .long sys_fstatfs64_wrapper + .long sys_statfs64 + .long sys_fstatfs64 .long sys_tgkill .long sys_utimes /* 270 */ .long sys_arm_fadvise64_64 @@ -312,7 +312,7 @@ /* 295 */ .long sys_getsockopt .long sys_sendmsg .long sys_recvmsg - .long ABI(sys_semop, sys_oabi_semop) + .long sys_semop .long sys_semget /* 300 */ .long sys_semctl .long sys_msgsnd @@ -326,7 +326,7 @@ .long sys_add_key /* 310 */ .long sys_request_key .long sys_keyctl - .long ABI(sys_semtimedop, sys_oabi_semtimedop) + .long sys_semtimedop /* vserver */ .long sys_ni_syscall .long sys_ioprio_set /* 315 */ .long sys_ioprio_get @@ -336,8 +336,9 @@ .long sys_mbind /* 320 */ .long sys_get_mempolicy .long sys_set_mempolicy +__syscall_end: - .rept NR_syscalls - (. - 100b) / 4 + .rept NR_syscalls - (__syscall_end - __syscall_start) / 4 .long sys_ni_syscall .endr #endif diff --git a/trunk/arch/arm/kernel/entry-armv.S b/trunk/arch/arm/kernel/entry-armv.S index 874e6bb79405..a52baedf6262 100644 --- a/trunk/arch/arm/kernel/entry-armv.S +++ b/trunk/arch/arm/kernel/entry-armv.S @@ -3,7 +3,6 @@ * * Copyright (C) 1996,1997,1998 Russell King. * ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk) - * nommu support by Hyok S. Choi (hyok.choi@samsung.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -105,24 +104,14 @@ common_invalid: /* * SVC mode handlers */ - -#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) -#define SPFIX(code...) code -#else -#define SPFIX(code...) -#endif - .macro svc_entry sub sp, sp, #S_FRAME_SIZE - SPFIX( tst sp, #4 ) - SPFIX( bicne sp, sp, #4 ) stmib sp, {r1 - r12} ldmia r0, {r1 - r3} add r5, sp, #S_SP @ here for interlock avoidance mov r4, #-1 @ "" "" "" "" add r0, sp, #S_FRAME_SIZE @ "" "" "" "" - SPFIX( addne r0, r0, #4 ) str r1, [sp] @ save the "real" r0 copied @ from the exception stack @@ -313,14 +302,7 @@ __pabt_svc: /* * User mode handlers - * - * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE */ - -#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7) -#error "sizeof(struct pt_regs) must be a multiple of 8" -#endif - .macro usr_entry sub sp, sp, #S_FRAME_SIZE stmib sp, {r1 - r12} @@ -556,11 +538,7 @@ ENTRY(__switch_to) add ip, r1, #TI_CPU_SAVE ldr r3, [r2, #TI_TP_VALUE] stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack -#ifndef CONFIG_MMU - add r2, r2, #TI_CPU_DOMAIN -#else ldr r6, [r2, #TI_CPU_DOMAIN]! -#endif #if __LINUX_ARM_ARCH__ >= 6 #ifdef CONFIG_CPU_MPCORE clrex @@ -578,9 +556,7 @@ ENTRY(__switch_to) mov r4, #0xffff0fff str r3, [r4, #-15] @ TLS val at 0xffff0ff0 #endif -#ifdef CONFIG_MMU mcr p15, 0, r6, c3, c0, 0 @ Set domain register -#endif #ifdef CONFIG_VFP @ Always disable VFP so we can lazily save/restore the old @ state. This occurs in the context of the previous thread. diff --git a/trunk/arch/arm/kernel/entry-common.S b/trunk/arch/arm/kernel/entry-common.S index 2b92ce85f97f..e2b42997ad33 100644 --- a/trunk/arch/arm/kernel/entry-common.S +++ b/trunk/arch/arm/kernel/entry-common.S @@ -98,14 +98,20 @@ ENTRY(ret_from_fork) run on an ARM7 and we can save a couple of instructions. --pb */ #ifdef CONFIG_CPU_ARM710 -#define A710(code...) code -.Larm710bug: + .macro arm710_bug_check, instr, temp + and \temp, \instr, #0x0f000000 @ check for SWI + teq \temp, #0x0f000000 + bne .Larm700bug + .endm + +.Larm700bug: ldmia sp, {r0 - lr}^ @ Get calling r0 - lr mov r0, r0 add sp, sp, #S_FRAME_SIZE subs pc, lr, #4 #else -#define A710(code...) + .macro arm710_bug_check, instr, temp + .endm #endif .align 5 @@ -123,50 +129,14 @@ ENTRY(vector_swi) /* * Get the system call number. */ - -#if defined(CONFIG_OABI_COMPAT) - - /* - * If we have CONFIG_OABI_COMPAT then we need to look at the swi - * value to determine if it is an EABI or an old ABI call. - */ #ifdef CONFIG_ARM_THUMB - tst r8, #PSR_T_BIT - movne r10, #0 @ no thumb OABI emulation - ldreq r10, [lr, #-4] @ get SWI instruction -#else - ldr r10, [lr, #-4] @ get SWI instruction - A710( and ip, r10, #0x0f000000 @ check for SWI ) - A710( teq ip, #0x0f000000 ) - A710( bne .Larm710bug ) -#endif - -#elif defined(CONFIG_AEABI) - - /* - * Pure EABI user space always put syscall number into scno (r7). - */ - A710( ldr ip, [lr, #-4] @ get SWI instruction ) - A710( and ip, ip, #0x0f000000 @ check for SWI ) - A710( teq ip, #0x0f000000 ) - A710( bne .Larm710bug ) - -#elif defined(CONFIG_ARM_THUMB) - - /* Legacy ABI only, possibly thumb mode. */ tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in ldreq scno, [lr, #-4] - #else - - /* Legacy ABI only. */ ldr scno, [lr, #-4] @ get SWI instruction - A710( and ip, scno, #0x0f000000 @ check for SWI ) - A710( teq ip, #0x0f000000 ) - A710( bne .Larm710bug ) - #endif + arm710_bug_check scno, ip #ifdef CONFIG_ALIGNMENT_TRAP ldr ip, __cr_alignment @@ -175,31 +145,18 @@ ENTRY(vector_swi) #endif enable_irq + stmdb sp!, {r4, r5} @ push fifth and sixth args + get_thread_info tsk - adr tbl, sys_call_table @ load syscall table pointer ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing - -#if defined(CONFIG_OABI_COMPAT) - /* - * If the swi argument is zero, this is an EABI call and we do nothing. - * - * If this is an old ABI call, get the syscall number into scno and - * get the old ABI syscall table address. - */ - bics r10, r10, #0xff000000 - eorne scno, r10, #__NR_OABI_SYSCALL_BASE - ldrne tbl, =sys_oabi_call_table -#elif !defined(CONFIG_AEABI) bic scno, scno, #0xff000000 @ mask off SWI op-code eor scno, scno, #__NR_SYSCALL_BASE @ check OS number -#endif - - stmdb sp!, {r4, r5} @ push fifth and sixth args + adr tbl, sys_call_table @ load syscall table pointer tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? bne __sys_trace - cmp scno, #NR_syscalls @ check upper syscall limit adr lr, ret_fast_syscall @ return address + cmp scno, #NR_syscalls @ check upper syscall limit ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine add r1, sp, #S_OFF @@ -214,13 +171,11 @@ ENTRY(vector_swi) * context switches, and waiting for our parent to respond. */ __sys_trace: - mov r2, scno add r1, sp, #S_OFF mov r0, #0 @ trace entry [IP = 0] bl syscall_trace adr lr, __sys_trace_return @ return address - mov scno, r0 @ syscall number (possibly new) add r1, sp, #S_R0 + S_OFF @ pointer to regs cmp scno, #NR_syscalls @ check upper syscall limit ldmccia r1, {r0 - r3} @ have to reload r0 - r3 @@ -229,7 +184,6 @@ __sys_trace: __sys_trace_return: str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 - mov r2, scno mov r1, sp mov r0, #1 @ trace exit [IP = 1] bl syscall_trace @@ -240,25 +194,11 @@ __sys_trace_return: .type __cr_alignment, #object __cr_alignment: .word cr_alignment -#endif - .ltorg - -/* - * This is the syscall table declaration for native ABI syscalls. - * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall. - */ -#define ABI(native, compat) native -#ifdef CONFIG_AEABI -#define OBSOLETE(syscall) sys_ni_syscall -#else -#define OBSOLETE(syscall) syscall #endif .type sys_call_table, #object ENTRY(sys_call_table) #include "calls.S" -#undef ABI -#undef OBSOLETE /*============================================================================ * Special system call wrappers @@ -267,7 +207,7 @@ ENTRY(sys_call_table) @ r8 = syscall table .type sys_syscall, #function sys_syscall: - eor scno, r0, #__NR_OABI_SYSCALL_BASE + eor scno, r0, #__NR_SYSCALL_BASE cmp scno, #__NR_syscall - __NR_SYSCALL_BASE cmpne scno, #NR_syscalls @ check range stmloia sp, {r5, r6} @ shuffle args @@ -315,16 +255,6 @@ sys_sigaltstack_wrapper: ldr r2, [sp, #S_OFF + S_SP] b do_sigaltstack -sys_statfs64_wrapper: - teq r1, #88 - moveq r1, #84 - b sys_statfs64 - -sys_fstatfs64_wrapper: - teq r1, #88 - moveq r1, #84 - b sys_fstatfs64 - /* * Note: off_4k (r5) is always units of 4K. If we can't do the requested * offset, we return EINVAL. @@ -341,49 +271,3 @@ sys_mmap2: str r5, [sp, #4] b do_mmap2 #endif - -#ifdef CONFIG_OABI_COMPAT - -/* - * These are syscalls with argument register differences - */ - -sys_oabi_pread64: - stmia sp, {r3, r4} - b sys_pread64 - -sys_oabi_pwrite64: - stmia sp, {r3, r4} - b sys_pwrite64 - -sys_oabi_truncate64: - mov r3, r2 - mov r2, r1 - b sys_truncate64 - -sys_oabi_ftruncate64: - mov r3, r2 - mov r2, r1 - b sys_ftruncate64 - -sys_oabi_readahead: - str r3, [sp] - mov r3, r2 - mov r2, r1 - b sys_readahead - -/* - * Let's declare a second syscall table for old ABI binaries - * using the compatibility syscall entries. - */ -#define ABI(native, compat) compat -#define OBSOLETE(syscall) syscall - - .type sys_oabi_call_table, #object -ENTRY(sys_oabi_call_table) -#include "calls.S" -#undef ABI -#undef OBSOLETE - -#endif - diff --git a/trunk/arch/arm/kernel/entry-header.S b/trunk/arch/arm/kernel/entry-header.S index 55c99cdab7d6..648cfff93138 100644 --- a/trunk/arch/arm/kernel/entry-header.S +++ b/trunk/arch/arm/kernel/entry-header.S @@ -19,7 +19,6 @@ @ @ Most of the stack format comes from struct pt_regs, but with @ the addition of 8 bytes for storing syscall args 5 and 6. -@ This _must_ remain a multiple of 8 for EABI. @ #define S_OFF 8 diff --git a/trunk/arch/arm/kernel/head.S b/trunk/arch/arm/kernel/head.S index 1aca1775b28f..1e985f2cd70f 100644 --- a/trunk/arch/arm/kernel/head.S +++ b/trunk/arch/arm/kernel/head.S @@ -251,11 +251,12 @@ __turn_mmu_on: * r10 = procinfo * * Returns: - * r0, r3, r6, r7 corrupted + * r0, r3, r5, r6, r7 corrupted * r4 = physical page table address */ .type __create_page_tables, %function __create_page_tables: + ldr r5, [r8, #MACHINFO_PHYSRAM] @ physram pgtbl r4 @ page table address /* @@ -302,7 +303,7 @@ __create_page_tables: * Then map first 1MB of ram in case it contains our boot params. */ add r0, r4, #PAGE_OFFSET >> 18 - orr r6, r7, #PHYS_OFFSET + orr r6, r5, r7 str r6, [r0] #ifdef CONFIG_XIP_KERNEL @@ -310,7 +311,7 @@ __create_page_tables: * Map some ram to cover our .data and .bss areas. * Mapping 3MB should be plenty. */ - sub r3, r4, #PHYS_OFFSET + sub r3, r4, r5 mov r3, r3, lsr #20 add r0, r0, r3, lsl #2 add r6, r6, r3, lsl #20 diff --git a/trunk/arch/arm/kernel/ptrace.c b/trunk/arch/arm/kernel/ptrace.c index 7b6256bb590e..e591f72bcdeb 100644 --- a/trunk/arch/arm/kernel/ptrace.c +++ b/trunk/arch/arm/kernel/ptrace.c @@ -766,11 +766,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) (unsigned long __user *) data); break; - case PTRACE_SET_SYSCALL: - ret = 0; - child->ptrace_message = data; - break; - default: ret = ptrace_request(child, request, addr, data); break; @@ -779,14 +774,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) return ret; } -asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) +asmlinkage void syscall_trace(int why, struct pt_regs *regs) { unsigned long ip; if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return scno; + return; if (!(current->ptrace & PT_PTRACED)) - return scno; + return; /* * Save IP. IP is used to denote syscall entry/exit: @@ -795,8 +790,6 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) ip = regs->ARM_ip; regs->ARM_ip = why; - current->ptrace_message = scno; - /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) @@ -811,6 +804,4 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) current->exit_code = 0; } regs->ARM_ip = ip; - - return current->ptrace_message; } diff --git a/trunk/arch/arm/kernel/semaphore.c b/trunk/arch/arm/kernel/semaphore.c index 981fe5c6ccbe..4c31f2923055 100644 --- a/trunk/arch/arm/kernel/semaphore.c +++ b/trunk/arch/arm/kernel/semaphore.c @@ -177,42 +177,41 @@ int __down_trylock(struct semaphore * sem) * ip contains the semaphore pointer on entry. Save the C-clobbered * registers (r0 to r3 and lr), but not ip, as we use it as a return * value in some cases.. - * To remain AAPCS compliant (64-bit stack align) we save r4 as well. */ asm(" .section .sched.text,\"ax\",%progbits \n\ .align 5 \n\ .globl __down_failed \n\ __down_failed: \n\ - stmfd sp!, {r0 - r4, lr} \n\ + stmfd sp!, {r0 - r3, lr} \n\ mov r0, ip \n\ bl __down \n\ - ldmfd sp!, {r0 - r4, pc} \n\ + ldmfd sp!, {r0 - r3, pc} \n\ \n\ .align 5 \n\ .globl __down_interruptible_failed \n\ __down_interruptible_failed: \n\ - stmfd sp!, {r0 - r4, lr} \n\ + stmfd sp!, {r0 - r3, lr} \n\ mov r0, ip \n\ bl __down_interruptible \n\ mov ip, r0 \n\ - ldmfd sp!, {r0 - r4, pc} \n\ + ldmfd sp!, {r0 - r3, pc} \n\ \n\ .align 5 \n\ .globl __down_trylock_failed \n\ __down_trylock_failed: \n\ - stmfd sp!, {r0 - r4, lr} \n\ + stmfd sp!, {r0 - r3, lr} \n\ mov r0, ip \n\ bl __down_trylock \n\ mov ip, r0 \n\ - ldmfd sp!, {r0 - r4, pc} \n\ + ldmfd sp!, {r0 - r3, pc} \n\ \n\ .align 5 \n\ .globl __up_wakeup \n\ __up_wakeup: \n\ - stmfd sp!, {r0 - r4, lr} \n\ + stmfd sp!, {r0 - r3, lr} \n\ mov r0, ip \n\ bl __up \n\ - ldmfd sp!, {r0 - r4, pc} \n\ + ldmfd sp!, {r0 - r3, pc} \n\ "); EXPORT_SYMBOL(__down_failed); diff --git a/trunk/arch/arm/kernel/sys_arm.c b/trunk/arch/arm/kernel/sys_arm.c index a491de2d9024..ea569ba482b1 100644 --- a/trunk/arch/arm/kernel/sys_arm.c +++ b/trunk/arch/arm/kernel/sys_arm.c @@ -147,7 +147,6 @@ asmlinkage int old_select(struct sel_arg_struct __user *arg) return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); } -#if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. * @@ -227,7 +226,6 @@ asmlinkage int sys_ipc(uint call, int first, int second, int third, return -ENOSYS; } } -#endif /* Fork a new task - this creates a new program thread. * This is called indirectly via a small wrapper diff --git a/trunk/arch/arm/kernel/sys_oabi-compat.c b/trunk/arch/arm/kernel/sys_oabi-compat.c deleted file mode 100644 index eafa8e5284af..000000000000 --- a/trunk/arch/arm/kernel/sys_oabi-compat.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * arch/arm/kernel/sys_oabi-compat.c - * - * Compatibility wrappers for syscalls that are used from - * old ABI user space binaries with an EABI kernel. - * - * Author: Nicolas Pitre - * Created: Oct 7, 2005 - * Copyright: MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * The legacy ABI and the new ARM EABI have different rules making some - * syscalls incompatible especially with structure arguments. - * Most notably, Eabi says 64-bit members should be 64-bit aligned instead of - * simply word aligned. EABI also pads structures to the size of the largest - * member it contains instead of the invariant 32-bit. - * - * The following syscalls are affected: - * - * sys_stat64: - * sys_lstat64: - * sys_fstat64: - * - * struct stat64 has different sizes and some members are shifted - * Compatibility wrappers are needed for them and provided below. - * - * sys_fcntl64: - * - * struct flock64 has different sizes and some members are shifted - * A compatibility wrapper is needed and provided below. - * - * sys_statfs64: - * sys_fstatfs64: - * - * struct statfs64 has extra padding with EABI growing its size from - * 84 to 88. This struct is now __attribute__((packed,aligned(4))) - * with a small assembly wrapper to force the sz argument to 84 if it is 88 - * to avoid copying the extra padding over user space unexpecting it. - * - * sys_newuname: - * - * struct new_utsname has no padding with EABI. No problem there. - * - * sys_epoll_ctl: - * sys_epoll_wait: - * - * struct epoll_event has its second member shifted also affecting the - * structure size. Compatibility wrappers are needed and provided below. - * - * sys_ipc: - * sys_semop: - * sys_semtimedop: - * - * struct sembuf loses its padding with EABI. Since arrays of them are - * used they have to be copyed to remove the padding. Compatibility wrappers - * provided below. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -struct oldabi_stat64 { - unsigned long long st_dev; - unsigned int __pad1; - unsigned long __st_ino; - unsigned int st_mode; - unsigned int st_nlink; - - unsigned long st_uid; - unsigned long st_gid; - - unsigned long long st_rdev; - unsigned int __pad2; - - long long st_size; - unsigned long st_blksize; - unsigned long long st_blocks; - - unsigned long st_atime; - unsigned long st_atime_nsec; - - unsigned long st_mtime; - unsigned long st_mtime_nsec; - - unsigned long st_ctime; - unsigned long st_ctime_nsec; - - unsigned long long st_ino; -} __attribute__ ((packed,aligned(4))); - -static long cp_oldabi_stat64(struct kstat *stat, - struct oldabi_stat64 __user *statbuf) -{ - struct oldabi_stat64 tmp; - - tmp.st_dev = huge_encode_dev(stat->dev); - tmp.__pad1 = 0; - tmp.__st_ino = stat->ino; - tmp.st_mode = stat->mode; - tmp.st_nlink = stat->nlink; - tmp.st_uid = stat->uid; - tmp.st_gid = stat->gid; - tmp.st_rdev = huge_encode_dev(stat->rdev); - tmp.st_size = stat->size; - tmp.st_blocks = stat->blocks; - tmp.__pad2 = 0; - tmp.st_blksize = stat->blksize; - tmp.st_atime = stat->atime.tv_sec; - tmp.st_atime_nsec = stat->atime.tv_nsec; - tmp.st_mtime = stat->mtime.tv_sec; - tmp.st_mtime_nsec = stat->mtime.tv_nsec; - tmp.st_ctime = stat->ctime.tv_sec; - tmp.st_ctime_nsec = stat->ctime.tv_nsec; - tmp.st_ino = stat->ino; - return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; -} - -asmlinkage long sys_oabi_stat64(char __user * filename, - struct oldabi_stat64 __user * statbuf) -{ - struct kstat stat; - int error = vfs_stat(filename, &stat); - if (!error) - error = cp_oldabi_stat64(&stat, statbuf); - return error; -} - -asmlinkage long sys_oabi_lstat64(char __user * filename, - struct oldabi_stat64 __user * statbuf) -{ - struct kstat stat; - int error = vfs_lstat(filename, &stat); - if (!error) - error = cp_oldabi_stat64(&stat, statbuf); - return error; -} - -asmlinkage long sys_oabi_fstat64(unsigned long fd, - struct oldabi_stat64 __user * statbuf) -{ - struct kstat stat; - int error = vfs_fstat(fd, &stat); - if (!error) - error = cp_oldabi_stat64(&stat, statbuf); - return error; -} - -struct oabi_flock64 { - short l_type; - short l_whence; - loff_t l_start; - loff_t l_len; - pid_t l_pid; -} __attribute__ ((packed,aligned(4))); - -asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, - unsigned long arg) -{ - struct oabi_flock64 user; - struct flock64 kernel; - mm_segment_t fs = USER_DS; /* initialized to kill a warning */ - unsigned long local_arg = arg; - int ret; - - switch (cmd) { - case F_GETLK64: - case F_SETLK64: - case F_SETLKW64: - if (copy_from_user(&user, (struct oabi_flock64 __user *)arg, - sizeof(user))) - return -EFAULT; - kernel.l_type = user.l_type; - kernel.l_whence = user.l_whence; - kernel.l_start = user.l_start; - kernel.l_len = user.l_len; - kernel.l_pid = user.l_pid; - local_arg = (unsigned long)&kernel; - fs = get_fs(); - set_fs(KERNEL_DS); - } - - ret = sys_fcntl64(fd, cmd, local_arg); - - switch (cmd) { - case F_GETLK64: - if (!ret) { - user.l_type = kernel.l_type; - user.l_whence = kernel.l_whence; - user.l_start = kernel.l_start; - user.l_len = kernel.l_len; - user.l_pid = kernel.l_pid; - if (copy_to_user((struct oabi_flock64 __user *)arg, - &user, sizeof(user))) - ret = -EFAULT; - } - case F_SETLK64: - case F_SETLKW64: - set_fs(fs); - } - - return ret; -} - -struct oabi_epoll_event { - __u32 events; - __u64 data; -} __attribute__ ((packed,aligned(4))); - -asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd, - struct oabi_epoll_event __user *event) -{ - struct oabi_epoll_event user; - struct epoll_event kernel; - mm_segment_t fs; - long ret; - - if (op == EPOLL_CTL_DEL) - return sys_epoll_ctl(epfd, op, fd, NULL); - if (copy_from_user(&user, event, sizeof(user))) - return -EFAULT; - kernel.events = user.events; - kernel.data = user.data; - fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_epoll_ctl(epfd, op, fd, &kernel); - set_fs(fs); - return ret; -} - -asmlinkage long sys_oabi_epoll_wait(int epfd, - struct oabi_epoll_event __user *events, - int maxevents, int timeout) -{ - struct epoll_event *kbuf; - mm_segment_t fs; - long ret, err, i; - - if (maxevents <= 0 || maxevents > (INT_MAX/sizeof(struct epoll_event))) - return -EINVAL; - kbuf = kmalloc(sizeof(*kbuf) * maxevents, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; - fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_epoll_wait(epfd, kbuf, maxevents, timeout); - set_fs(fs); - err = 0; - for (i = 0; i < ret; i++) { - __put_user_error(kbuf[i].events, &events->events, err); - __put_user_error(kbuf[i].data, &events->data, err); - events++; - } - kfree(kbuf); - return err ? -EFAULT : ret; -} - -struct oabi_sembuf { - unsigned short sem_num; - short sem_op; - short sem_flg; - unsigned short __pad; -}; - -asmlinkage long sys_oabi_semtimedop(int semid, - struct oabi_sembuf __user *tsops, - unsigned nsops, - const struct timespec __user *timeout) -{ - struct sembuf *sops; - struct timespec local_timeout; - long err; - int i; - - if (nsops < 1) - return -EINVAL; - sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL); - if (!sops) - return -ENOMEM; - err = 0; - for (i = 0; i < nsops; i++) { - __get_user_error(sops[i].sem_num, &tsops->sem_num, err); - __get_user_error(sops[i].sem_op, &tsops->sem_op, err); - __get_user_error(sops[i].sem_flg, &tsops->sem_flg, err); - tsops++; - } - if (timeout) { - /* copy this as well before changing domain protection */ - err |= copy_from_user(&local_timeout, timeout, sizeof(*timeout)); - timeout = &local_timeout; - } - if (err) { - err = -EFAULT; - } else { - mm_segment_t fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_semtimedop(semid, sops, nsops, timeout); - set_fs(fs); - } - kfree(sops); - return err; -} - -asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user *tsops, - unsigned nsops) -{ - return sys_oabi_semtimedop(semid, tsops, nsops, NULL); -} - -extern asmlinkage int sys_ipc(uint call, int first, int second, int third, - void __user *ptr, long fifth); - -asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third, - void __user *ptr, long fifth) -{ - switch (call & 0xffff) { - case SEMOP: - return sys_oabi_semtimedop(first, - (struct oabi_sembuf __user *)ptr, - second, NULL); - case SEMTIMEDOP: - return sys_oabi_semtimedop(first, - (struct oabi_sembuf __user *)ptr, - second, - (const struct timespec __user *)fifth); - default: - return sys_ipc(call, first, second, third, ptr, fifth); - } -} diff --git a/trunk/arch/arm/kernel/traps.c b/trunk/arch/arm/kernel/traps.c index 10235b01582e..93cfd3ffcc72 100644 --- a/trunk/arch/arm/kernel/traps.c +++ b/trunk/arch/arm/kernel/traps.c @@ -404,7 +404,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) struct thread_info *thread = current_thread_info(); siginfo_t info; - if ((no >> 16) != (__ARM_NR_BASE>> 16)) + if ((no >> 16) != 0x9f) return bad_syscall(no, regs); switch (no & 0xffff) { diff --git a/trunk/arch/arm/lib/ashldi3.S b/trunk/arch/arm/lib/ashldi3.S index 55e57a1c2e6d..561e20717b30 100644 --- a/trunk/arch/arm/lib/ashldi3.S +++ b/trunk/arch/arm/lib/ashldi3.S @@ -37,7 +37,6 @@ Boston, MA 02110-1301, USA. */ #endif ENTRY(__ashldi3) -ENTRY(__aeabi_llsl) subs r3, r2, #32 rsb ip, r2, #32 diff --git a/trunk/arch/arm/lib/ashrdi3.S b/trunk/arch/arm/lib/ashrdi3.S index 0b31398f89b2..86fb2a90c301 100644 --- a/trunk/arch/arm/lib/ashrdi3.S +++ b/trunk/arch/arm/lib/ashrdi3.S @@ -37,7 +37,6 @@ Boston, MA 02110-1301, USA. */ #endif ENTRY(__ashrdi3) -ENTRY(__aeabi_lasr) subs r3, r2, #32 rsb ip, r2, #32 diff --git a/trunk/arch/arm/lib/lib1funcs.S b/trunk/arch/arm/lib/lib1funcs.S index 4e492f4b3f0e..59026029d017 100644 --- a/trunk/arch/arm/lib/lib1funcs.S +++ b/trunk/arch/arm/lib/lib1funcs.S @@ -206,7 +206,6 @@ Boston, MA 02111-1307, USA. */ ENTRY(__udivsi3) -ENTRY(__aeabi_uidiv) subs r2, r1, #1 moveq pc, lr @@ -247,7 +246,6 @@ ENTRY(__umodsi3) ENTRY(__divsi3) -ENTRY(__aeabi_idiv) cmp r1, #0 eor ip, r0, r1 @ save the sign of the result. @@ -305,33 +303,12 @@ ENTRY(__modsi3) rsbmi r0, r0, #0 mov pc, lr -#ifdef CONFIG_AEABI - -ENTRY(__aeabi_uidivmod) - - stmfd sp!, {r0, r1, ip, lr} - bl __aeabi_uidiv - ldmfd sp!, {r1, r2, ip, lr} - mul r3, r0, r2 - sub r1, r1, r3 - mov pc, lr - -ENTRY(__aeabi_idivmod) - - stmfd sp!, {r0, r1, ip, lr} - bl __aeabi_idiv - ldmfd sp!, {r1, r2, ip, lr} - mul r3, r0, r2 - sub r1, r1, r3 - mov pc, lr - -#endif Ldiv0: - str lr, [sp, #-8]! + str lr, [sp, #-4]! bl __div0 mov r0, #0 @ About as wrong as it could be. - ldr pc, [sp], #8 + ldr pc, [sp], #4 diff --git a/trunk/arch/arm/lib/lshrdi3.S b/trunk/arch/arm/lib/lshrdi3.S index a86dbdd59cc4..46c2ed19ec95 100644 --- a/trunk/arch/arm/lib/lshrdi3.S +++ b/trunk/arch/arm/lib/lshrdi3.S @@ -37,7 +37,6 @@ Boston, MA 02110-1301, USA. */ #endif ENTRY(__lshrdi3) -ENTRY(__aeabi_llsr) subs r3, r2, #32 rsb ip, r2, #32 diff --git a/trunk/arch/arm/lib/muldi3.S b/trunk/arch/arm/lib/muldi3.S index 72d594184b8a..c7fbdf005319 100644 --- a/trunk/arch/arm/lib/muldi3.S +++ b/trunk/arch/arm/lib/muldi3.S @@ -25,7 +25,6 @@ #endif ENTRY(__muldi3) -ENTRY(__aeabi_lmul) mul xh, yl, xh mla xh, xl, yh, xh diff --git a/trunk/arch/arm/lib/ucmpdi2.S b/trunk/arch/arm/lib/ucmpdi2.S index d847a62834cb..112630f93e5d 100644 --- a/trunk/arch/arm/lib/ucmpdi2.S +++ b/trunk/arch/arm/lib/ucmpdi2.S @@ -10,7 +10,6 @@ * published by the Free Software Foundation. */ -#include #include #ifdef __ARMEB__ @@ -34,16 +33,3 @@ ENTRY(__ucmpdi2) movhi r0, #2 mov pc, lr -#ifdef CONFIG_AEABI - -ENTRY(__aeabi_ulcmp) - - cmp xh, yh - cmpeq xl, yl - movlo r0, #-1 - moveq r0, #0 - movhi r0, #1 - mov pc, lr - -#endif - diff --git a/trunk/arch/arm/mach-aaec2000/aaed2000.c b/trunk/arch/arm/mach-aaec2000/aaed2000.c index dc5fa8e5ebef..f5ef69702296 100644 --- a/trunk/arch/arm/mach-aaec2000/aaed2000.c +++ b/trunk/arch/arm/mach-aaec2000/aaed2000.c @@ -90,6 +90,7 @@ static void __init aaed2000_map_io(void) MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform") /* Maintainer: Nicolas Bellido Y Ortega */ + .phys_ram = 0xf0000000, .phys_io = PIO_BASE, .io_pg_offst = ((VIO_BASE) >> 18) & 0xfffc, .map_io = aaed2000_map_io, diff --git a/trunk/arch/arm/mach-at91rm9200/board-csb337.c b/trunk/arch/arm/mach-at91rm9200/board-csb337.c index 54022e58d50d..4aec834ee47f 100644 --- a/trunk/arch/arm/mach-at91rm9200/board-csb337.c +++ b/trunk/arch/arm/mach-at91rm9200/board-csb337.c @@ -132,6 +132,7 @@ static void __init csb337_board_init(void) MACHINE_START(CSB337, "Cogent CSB337") /* Maintainer: Bill Gatliff */ + .phys_ram = AT91_SDRAM_BASE, .phys_io = AT91_BASE_SYS, .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, .boot_params = AT91_SDRAM_BASE + 0x100, diff --git a/trunk/arch/arm/mach-at91rm9200/board-csb637.c b/trunk/arch/arm/mach-at91rm9200/board-csb637.c index 8195f9d919ea..23e4cc21481a 100644 --- a/trunk/arch/arm/mach-at91rm9200/board-csb637.c +++ b/trunk/arch/arm/mach-at91rm9200/board-csb637.c @@ -105,6 +105,7 @@ static void __init csb637_board_init(void) MACHINE_START(CSB637, "Cogent CSB637") /* Maintainer: Bill Gatliff */ + .phys_ram = AT91_SDRAM_BASE, .phys_io = AT91_BASE_SYS, .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, .boot_params = AT91_SDRAM_BASE + 0x100, diff --git a/trunk/arch/arm/mach-at91rm9200/board-dk.c b/trunk/arch/arm/mach-at91rm9200/board-dk.c index 8a783368366e..8c747a31b95a 100644 --- a/trunk/arch/arm/mach-at91rm9200/board-dk.c +++ b/trunk/arch/arm/mach-at91rm9200/board-dk.c @@ -127,6 +127,7 @@ static void __init dk_board_init(void) MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK") /* Maintainer: SAN People/Atmel */ + .phys_ram = AT91_SDRAM_BASE, .phys_io = AT91_BASE_SYS, .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, .boot_params = AT91_SDRAM_BASE + 0x100, diff --git a/trunk/arch/arm/mach-at91rm9200/board-ek.c b/trunk/arch/arm/mach-at91rm9200/board-ek.c index fd0752eba897..d140645711be 100644 --- a/trunk/arch/arm/mach-at91rm9200/board-ek.c +++ b/trunk/arch/arm/mach-at91rm9200/board-ek.c @@ -120,6 +120,7 @@ static void __init ek_board_init(void) MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK") /* Maintainer: SAN People/Atmel */ + .phys_ram = AT91_SDRAM_BASE, .phys_io = AT91_BASE_SYS, .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, .boot_params = AT91_SDRAM_BASE + 0x100, diff --git a/trunk/arch/arm/mach-clps711x/autcpu12.c b/trunk/arch/arm/mach-clps711x/autcpu12.c index c13ca6c56baa..43b9423d1440 100644 --- a/trunk/arch/arm/mach-clps711x/autcpu12.c +++ b/trunk/arch/arm/mach-clps711x/autcpu12.c @@ -64,6 +64,7 @@ void __init autcpu12_map_io(void) MACHINE_START(AUTCPU12, "autronix autcpu12") /* Maintainer: Thomas Gleixner */ + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, .boot_params = 0xc0020000, diff --git a/trunk/arch/arm/mach-clps711x/cdb89712.c b/trunk/arch/arm/mach-clps711x/cdb89712.c index 831df007f6c7..cba7be5a06c3 100644 --- a/trunk/arch/arm/mach-clps711x/cdb89712.c +++ b/trunk/arch/arm/mach-clps711x/cdb89712.c @@ -55,6 +55,7 @@ static void __init cdb89712_map_io(void) MACHINE_START(CDB89712, "Cirrus-CDB89712") /* Maintainer: Ray Lehtiniemi */ + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-clps711x/ceiva.c b/trunk/arch/arm/mach-clps711x/ceiva.c index e2b2c5ac8a83..35d51a759b59 100644 --- a/trunk/arch/arm/mach-clps711x/ceiva.c +++ b/trunk/arch/arm/mach-clps711x/ceiva.c @@ -56,6 +56,7 @@ static void __init ceiva_map_io(void) MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame") /* Maintainer: Rob Scott */ + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-clps711x/clep7312.c b/trunk/arch/arm/mach-clps711x/clep7312.c index 09fb57e45213..c83f3fd68fcd 100644 --- a/trunk/arch/arm/mach-clps711x/clep7312.c +++ b/trunk/arch/arm/mach-clps711x/clep7312.c @@ -38,6 +38,7 @@ fixup_clep7312(struct machine_desc *desc, struct tag *tags, MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312") /* Maintainer: Nobody */ + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-clps711x/edb7211-arch.c b/trunk/arch/arm/mach-clps711x/edb7211-arch.c index dc81cc68595d..255c98b63e15 100644 --- a/trunk/arch/arm/mach-clps711x/edb7211-arch.c +++ b/trunk/arch/arm/mach-clps711x/edb7211-arch.c @@ -52,6 +52,7 @@ fixup_edb7211(struct machine_desc *desc, struct tag *tags, MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)") /* Maintainer: Jon McClintock */ + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, .boot_params = 0xc0020100, /* 0xc0000000 - 0xc001ffff can be video RAM */ diff --git a/trunk/arch/arm/mach-clps711x/fortunet.c b/trunk/arch/arm/mach-clps711x/fortunet.c index ff26a85aa4ba..3d88da0c287b 100644 --- a/trunk/arch/arm/mach-clps711x/fortunet.c +++ b/trunk/arch/arm/mach-clps711x/fortunet.c @@ -78,6 +78,7 @@ fortunet_fixup(struct machine_desc *desc, struct tag *tags, MACHINE_START(FORTUNET, "ARM-FortuNet") /* Maintainer: FortuNet Inc. */ + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc, .boot_params = 0x00000000, diff --git a/trunk/arch/arm/mach-clps711x/p720t.c b/trunk/arch/arm/mach-clps711x/p720t.c index 9ba45f4d5a7e..a1acb945fb51 100644 --- a/trunk/arch/arm/mach-clps711x/p720t.c +++ b/trunk/arch/arm/mach-clps711x/p720t.c @@ -90,6 +90,7 @@ static void __init p720t_map_io(void) MACHINE_START(P720T, "ARM-Prospector720T") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-clps7500/core.c b/trunk/arch/arm/mach-clps7500/core.c index 5b12cab0e691..d869af0023f8 100644 --- a/trunk/arch/arm/mach-clps7500/core.c +++ b/trunk/arch/arm/mach-clps7500/core.c @@ -384,6 +384,7 @@ static void __init clps7500_init(void) MACHINE_START(CLPS7500, "CL-PS7500") /* Maintainer: Philip Blundell */ + .phys_ram = 0x10000000, .phys_io = 0x03000000, .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, .map_io = clps7500_map_io, diff --git a/trunk/arch/arm/mach-ebsa110/core.c b/trunk/arch/arm/mach-ebsa110/core.c index 6d620d8268cc..ed4614983adb 100644 --- a/trunk/arch/arm/mach-ebsa110/core.c +++ b/trunk/arch/arm/mach-ebsa110/core.c @@ -284,6 +284,7 @@ arch_initcall(ebsa110_init); MACHINE_START(EBSA110, "EBSA110") /* Maintainer: Russell King */ + .phys_ram = 0x00000000, .phys_io = 0xe0000000, .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, .boot_params = 0x00000400, diff --git a/trunk/arch/arm/mach-footbridge/cats-hw.c b/trunk/arch/arm/mach-footbridge/cats-hw.c index 5b64d5c5b967..49b898af0032 100644 --- a/trunk/arch/arm/mach-footbridge/cats-hw.c +++ b/trunk/arch/arm/mach-footbridge/cats-hw.c @@ -85,6 +85,7 @@ fixup_cats(struct machine_desc *desc, struct tag *tags, MACHINE_START(CATS, "Chalice-CATS") /* Maintainer: Philip Blundell */ + .phys_ram = 0x00000000, .phys_io = DC21285_ARMCSR_BASE, .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-footbridge/co285.c b/trunk/arch/arm/mach-footbridge/co285.c index 4545576ad8d9..548a79081688 100644 --- a/trunk/arch/arm/mach-footbridge/co285.c +++ b/trunk/arch/arm/mach-footbridge/co285.c @@ -29,6 +29,7 @@ fixup_coebsa285(struct machine_desc *desc, struct tag *tags, MACHINE_START(CO285, "co-EBSA285") /* Maintainer: Mark van Doesburg */ + .phys_ram = 0x00000000, .phys_io = DC21285_ARMCSR_BASE, .io_pg_offst = ((0x7cf00000) >> 18) & 0xfffc, .fixup = fixup_coebsa285, diff --git a/trunk/arch/arm/mach-footbridge/ebsa285.c b/trunk/arch/arm/mach-footbridge/ebsa285.c index b1d3bf20a41e..1c37605268d5 100644 --- a/trunk/arch/arm/mach-footbridge/ebsa285.c +++ b/trunk/arch/arm/mach-footbridge/ebsa285.c @@ -14,6 +14,7 @@ MACHINE_START(EBSA285, "EBSA285") /* Maintainer: Russell King */ + .phys_ram = 0x00000000, .phys_io = DC21285_ARMCSR_BASE, .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-footbridge/netwinder-hw.c b/trunk/arch/arm/mach-footbridge/netwinder-hw.c index 229bf0585e40..9e563de465b5 100644 --- a/trunk/arch/arm/mach-footbridge/netwinder-hw.c +++ b/trunk/arch/arm/mach-footbridge/netwinder-hw.c @@ -649,6 +649,7 @@ fixup_netwinder(struct machine_desc *desc, struct tag *tags, MACHINE_START(NETWINDER, "Rebel-NetWinder") /* Maintainer: Russell King/Rebel.com */ + .phys_ram = 0x00000000, .phys_io = DC21285_ARMCSR_BASE, .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-footbridge/personal.c b/trunk/arch/arm/mach-footbridge/personal.c index c4f843fc099d..0146b8bb59da 100644 --- a/trunk/arch/arm/mach-footbridge/personal.c +++ b/trunk/arch/arm/mach-footbridge/personal.c @@ -14,6 +14,7 @@ MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer") /* Maintainer: Jamey Hicks / George France */ + .phys_ram = 0x00000000, .phys_io = DC21285_ARMCSR_BASE, .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-h720x/h7201-eval.c b/trunk/arch/arm/mach-h720x/h7201-eval.c index 193f968edac3..fa59e9e2a5c8 100644 --- a/trunk/arch/arm/mach-h720x/h7201-eval.c +++ b/trunk/arch/arm/mach-h720x/h7201-eval.c @@ -31,6 +31,7 @@ MACHINE_START(H7201, "Hynix GMS30C7201") /* Maintainer: Robert Schwebel, Pengutronix */ + .phys_ram = 0x40000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc, .boot_params = 0xc0001000, diff --git a/trunk/arch/arm/mach-h720x/h7202-eval.c b/trunk/arch/arm/mach-h720x/h7202-eval.c index 36266896979c..d75c8221d2a5 100644 --- a/trunk/arch/arm/mach-h720x/h7202-eval.c +++ b/trunk/arch/arm/mach-h720x/h7202-eval.c @@ -72,6 +72,7 @@ static void __init init_eval_h7202(void) MACHINE_START(H7202, "Hynix HMS30C7202") /* Maintainer: Robert Schwebel, Pengutronix */ + .phys_ram = 0x40000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc, .boot_params = 0x40000100, diff --git a/trunk/arch/arm/mach-imx/mx1ads.c b/trunk/arch/arm/mach-imx/mx1ads.c index dc31e3fd6c57..c9e0cd8ed016 100644 --- a/trunk/arch/arm/mach-imx/mx1ads.c +++ b/trunk/arch/arm/mach-imx/mx1ads.c @@ -69,6 +69,7 @@ mx1ads_map_io(void) MACHINE_START(MX1ADS, "Motorola MX1ADS") /* Maintainer: Sascha Hauer, Pengutronix */ + .phys_ram = 0x08000000, .phys_io = 0x00200000, .io_pg_offst = ((0xe0200000) >> 18) & 0xfffc, .boot_params = 0x08000100, diff --git a/trunk/arch/arm/mach-integrator/integrator_ap.c b/trunk/arch/arm/mach-integrator/integrator_ap.c index d8d3c2a5a97e..3afedeb56a6e 100644 --- a/trunk/arch/arm/mach-integrator/integrator_ap.c +++ b/trunk/arch/arm/mach-integrator/integrator_ap.c @@ -347,6 +347,7 @@ static struct sys_timer ap_timer = { MACHINE_START(INTEGRATOR, "ARM-Integrator") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ + .phys_ram = 0x00000000, .phys_io = 0x16000000, .io_pg_offst = ((0xf1600000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-integrator/integrator_cp.c b/trunk/arch/arm/mach-integrator/integrator_cp.c index 31820170f306..16cf2482a3e9 100644 --- a/trunk/arch/arm/mach-integrator/integrator_cp.c +++ b/trunk/arch/arm/mach-integrator/integrator_cp.c @@ -578,6 +578,7 @@ static struct sys_timer cp_timer = { MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ + .phys_ram = 0x00000000, .phys_io = 0x16000000, .io_pg_offst = ((0xf1600000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-iop3xx/iop321-setup.c b/trunk/arch/arm/mach-iop3xx/iop321-setup.c index e4f4c52d93d4..80770233b8d4 100644 --- a/trunk/arch/arm/mach-iop3xx/iop321-setup.c +++ b/trunk/arch/arm/mach-iop3xx/iop321-setup.c @@ -151,6 +151,7 @@ extern void iop321_init_time(void); #if defined(CONFIG_ARCH_IQ80321) MACHINE_START(IQ80321, "Intel IQ80321") /* Maintainer: Intel Corporation */ + .phys_ram = PHYS_OFFSET, .phys_io = IQ80321_UART, .io_pg_offst = ((IQ80321_UART) >> 18) & 0xfffc, .map_io = iq80321_map_io, @@ -162,6 +163,7 @@ MACHINE_END #elif defined(CONFIG_ARCH_IQ31244) MACHINE_START(IQ31244, "Intel IQ31244") /* Maintainer: Intel Corp. */ + .phys_ram = PHYS_OFFSET, .phys_io = IQ31244_UART, .io_pg_offst = ((IQ31244_UART) >> 18) & 0xfffc, .map_io = iq31244_map_io, diff --git a/trunk/arch/arm/mach-iop3xx/iop331-setup.c b/trunk/arch/arm/mach-iop3xx/iop331-setup.c index 63585485123e..e6ea1cba6a17 100644 --- a/trunk/arch/arm/mach-iop3xx/iop331-setup.c +++ b/trunk/arch/arm/mach-iop3xx/iop331-setup.c @@ -195,6 +195,7 @@ extern void iq80332_map_io(void); #if defined(CONFIG_ARCH_IQ80331) MACHINE_START(IQ80331, "Intel IQ80331") /* Maintainer: Intel Corp. */ + .phys_ram = PHYS_OFFSET, .phys_io = 0xfefff000, .io_pg_offst = ((0xfffff000) >> 18) & 0xfffc, // virtual, physical .map_io = iq80331_map_io, @@ -207,6 +208,7 @@ MACHINE_END #elif defined(CONFIG_MACH_IQ80332) MACHINE_START(IQ80332, "Intel IQ80332") /* Maintainer: Intel Corp. */ + .phys_ram = PHYS_OFFSET, .phys_io = 0xfefff000, .io_pg_offst = ((0xfffff000) >> 18) & 0xfffc, // virtual, physical .map_io = iq80332_map_io, diff --git a/trunk/arch/arm/mach-ixp2000/core.c b/trunk/arch/arm/mach-ixp2000/core.c index cfd5bef3190b..6851abaf5524 100644 --- a/trunk/arch/arm/mach-ixp2000/core.c +++ b/trunk/arch/arm/mach-ixp2000/core.c @@ -105,16 +105,6 @@ static struct map_desc ixp2000_io_desc[] __initdata = { .pfn = __phys_to_pfn(IXP2000_MSF_PHYS_BASE), .length = IXP2000_MSF_SIZE, .type = MT_IXP2000_DEVICE, - }, { - .virtual = IXP2000_SCRATCH_RING_VIRT_BASE, - .pfn = __phys_to_pfn(IXP2000_SCRATCH_RING_PHYS_BASE), - .length = IXP2000_SCRATCH_RING_SIZE, - .type = MT_IXP2000_DEVICE, - }, { - .virtual = IXP2000_SRAM0_VIRT_BASE, - .pfn = __phys_to_pfn(IXP2000_SRAM0_PHYS_BASE), - .length = IXP2000_SRAM0_SIZE, - .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_PCI_IO_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_PCI_IO_PHYS_BASE), diff --git a/trunk/arch/arm/mach-ixp2000/enp2611.c b/trunk/arch/arm/mach-ixp2000/enp2611.c index 9e5a13bb39d0..61f6006241bd 100644 --- a/trunk/arch/arm/mach-ixp2000/enp2611.c +++ b/trunk/arch/arm/mach-ixp2000/enp2611.c @@ -254,6 +254,7 @@ static void __init enp2611_init_machine(void) MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board") /* Maintainer: Lennert Buytenhek */ + .phys_ram = 0x00000000, .phys_io = IXP2000_UART_PHYS_BASE, .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-ixp2000/ixdp2400.c b/trunk/arch/arm/mach-ixp2000/ixdp2400.c index 7c782403042a..fd280a93637e 100644 --- a/trunk/arch/arm/mach-ixp2000/ixdp2400.c +++ b/trunk/arch/arm/mach-ixp2000/ixdp2400.c @@ -169,6 +169,7 @@ void ixdp2400_init_irq(void) MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform") /* Maintainer: MontaVista Software, Inc. */ + .phys_ram = 0x00000000, .phys_io = IXP2000_UART_PHYS_BASE, .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-ixp2000/ixdp2800.c b/trunk/arch/arm/mach-ixp2000/ixdp2800.c index 076e3f8acc96..f9073aa28615 100644 --- a/trunk/arch/arm/mach-ixp2000/ixdp2800.c +++ b/trunk/arch/arm/mach-ixp2000/ixdp2800.c @@ -285,6 +285,7 @@ void ixdp2800_init_irq(void) MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform") /* Maintainer: MontaVista Software, Inc. */ + .phys_ram = 0x00000000, .phys_io = IXP2000_UART_PHYS_BASE, .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-ixp2000/ixdp2x01.c b/trunk/arch/arm/mach-ixp2000/ixdp2x01.c index 10f06606d460..e6a882f35da2 100644 --- a/trunk/arch/arm/mach-ixp2000/ixdp2x01.c +++ b/trunk/arch/arm/mach-ixp2000/ixdp2x01.c @@ -376,6 +376,7 @@ static void __init ixdp2x01_init_machine(void) #ifdef CONFIG_ARCH_IXDP2401 MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform") /* Maintainer: MontaVista Software, Inc. */ + .phys_ram = 0x00000000, .phys_io = IXP2000_UART_PHYS_BASE, .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, .boot_params = 0x00000100, @@ -389,6 +390,7 @@ MACHINE_END #ifdef CONFIG_ARCH_IXDP2801 MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform") /* Maintainer: MontaVista Software, Inc. */ + .phys_ram = 0x00000000, .phys_io = IXP2000_UART_PHYS_BASE, .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-ixp4xx/coyote-setup.c b/trunk/arch/arm/mach-ixp4xx/coyote-setup.c index 13f8a7ac3ba9..679594a73981 100644 --- a/trunk/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/coyote-setup.c @@ -101,6 +101,7 @@ static void __init coyote_init(void) #ifdef CONFIG_ARCH_ADI_COYOTE MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote") /* Maintainer: MontaVista Software, Inc. */ + .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, @@ -118,6 +119,7 @@ MACHINE_END #ifdef CONFIG_MACH_IXDPG425 MACHINE_START(IXDPG425, "Intel IXDPG425") /* Maintainer: MontaVista Software, Inc. */ + .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, diff --git a/trunk/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/trunk/arch/arm/mach-ixp4xx/gtwx5715-setup.c index 654e2eed81fb..038670489970 100644 --- a/trunk/arch/arm/mach-ixp4xx/gtwx5715-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/gtwx5715-setup.c @@ -142,6 +142,7 @@ static void __init gtwx5715_init(void) MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)") /* Maintainer: George Joseph */ + .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_UART2_BASE_PHYS, .io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, diff --git a/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c b/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c index da72383ee301..c2e105c89c95 100644 --- a/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -121,6 +121,7 @@ static void __init ixdp425_init(void) #ifdef CONFIG_ARCH_IXDP425 MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") /* Maintainer: MontaVista Software, Inc. */ + .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, @@ -134,6 +135,7 @@ MACHINE_END #ifdef CONFIG_MACH_IXDP465 MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") /* Maintainer: MontaVista Software, Inc. */ + .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, @@ -147,6 +149,7 @@ MACHINE_END #ifdef CONFIG_ARCH_PRPMC1100 MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") /* Maintainer: MontaVista Software, Inc. */ + .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, @@ -166,6 +169,7 @@ MACHINE_END #ifdef CONFIG_ARCH_AVILA MACHINE_START(AVILA, "Gateworks Avila Network Platform") /* Maintainer: Deepak Saxena */ + .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, diff --git a/trunk/arch/arm/mach-ixp4xx/nas100d-setup.c b/trunk/arch/arm/mach-ixp4xx/nas100d-setup.c index 856d56f3b2ae..49998a8bd4e8 100644 --- a/trunk/arch/arm/mach-ixp4xx/nas100d-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/nas100d-setup.c @@ -124,6 +124,7 @@ static void __init nas100d_init(void) MACHINE_START(NAS100D, "Iomega NAS 100d") /* Maintainer: www.nslu2-linux.org */ + .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-ixp4xx/nslu2-setup.c b/trunk/arch/arm/mach-ixp4xx/nslu2-setup.c index da9340a53434..289e94cb65c2 100644 --- a/trunk/arch/arm/mach-ixp4xx/nslu2-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/nslu2-setup.c @@ -123,6 +123,7 @@ static void __init nslu2_init(void) MACHINE_START(NSLU2, "Linksys NSLU2") /* Maintainer: www.nslu2-linux.org */ + .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-l7200/core.c b/trunk/arch/arm/mach-l7200/core.c index ac626436e96f..03ed742ae2be 100644 --- a/trunk/arch/arm/mach-l7200/core.c +++ b/trunk/arch/arm/mach-l7200/core.c @@ -91,6 +91,7 @@ static void __init l7200_map_io(void) MACHINE_START(L7200, "LinkUp Systems L7200") /* Maintainer: Steve Hill / Scott McConnell */ + .phys_ram = 0xf0000000, .phys_io = 0x80040000, .io_pg_offst = ((0xd0000000) >> 18) & 0xfffc, .map_io = l7200_map_io, diff --git a/trunk/arch/arm/mach-lh7a40x/arch-kev7a400.c b/trunk/arch/arm/mach-lh7a40x/arch-kev7a400.c index 2cccc27c62e4..19f2fa2244c4 100644 --- a/trunk/arch/arm/mach-lh7a40x/arch-kev7a400.c +++ b/trunk/arch/arm/mach-lh7a40x/arch-kev7a400.c @@ -112,6 +112,7 @@ void __init lh7a40x_init_board_irq (void) MACHINE_START (KEV7A400, "Sharp KEV7a400") /* Maintainer: Marc Singer */ + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/trunk/arch/arm/mach-lh7a40x/arch-lpd7a40x.c index 12e23277c5ea..4eb962fdb3a8 100644 --- a/trunk/arch/arm/mach-lh7a40x/arch-lpd7a40x.c +++ b/trunk/arch/arm/mach-lh7a40x/arch-lpd7a40x.c @@ -317,6 +317,7 @@ lpd7a400_map_io(void) MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10") /* Maintainer: Marc Singer */ + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc, .boot_params = 0xc0000100, @@ -332,6 +333,7 @@ MACHINE_END MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10") /* Maintainer: Marc Singer */ + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-omap1/board-generic.c b/trunk/arch/arm/mach-omap1/board-generic.c index bdc20b51b076..4b292e93fbe2 100644 --- a/trunk/arch/arm/mach-omap1/board-generic.c +++ b/trunk/arch/arm/mach-omap1/board-generic.c @@ -109,6 +109,7 @@ static void __init omap_generic_map_io(void) MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710") /* Maintainer: Tony Lindgren */ + .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/trunk/arch/arm/mach-omap1/board-h2.c b/trunk/arch/arm/mach-omap1/board-h2.c index 9533c36a92df..a07e2c9307fa 100644 --- a/trunk/arch/arm/mach-omap1/board-h2.c +++ b/trunk/arch/arm/mach-omap1/board-h2.c @@ -199,6 +199,7 @@ static void __init h2_map_io(void) MACHINE_START(OMAP_H2, "TI-H2") /* Maintainer: Imre Deak */ + .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/trunk/arch/arm/mach-omap1/board-h3.c b/trunk/arch/arm/mach-omap1/board-h3.c index d665efc1c344..668e278433c2 100644 --- a/trunk/arch/arm/mach-omap1/board-h3.c +++ b/trunk/arch/arm/mach-omap1/board-h3.c @@ -215,6 +215,7 @@ static void __init h3_map_io(void) MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board") /* Maintainer: Texas Instruments, Inc. */ + .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/trunk/arch/arm/mach-omap1/board-innovator.c b/trunk/arch/arm/mach-omap1/board-innovator.c index 652f37c7f906..95f1ff36cdcb 100644 --- a/trunk/arch/arm/mach-omap1/board-innovator.c +++ b/trunk/arch/arm/mach-omap1/board-innovator.c @@ -303,6 +303,7 @@ static void __init innovator_map_io(void) MACHINE_START(OMAP_INNOVATOR, "TI-Innovator") /* Maintainer: MontaVista Software, Inc. */ + .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/trunk/arch/arm/mach-omap1/board-netstar.c b/trunk/arch/arm/mach-omap1/board-netstar.c index 58f783930d45..0448fa7de8a4 100644 --- a/trunk/arch/arm/mach-omap1/board-netstar.c +++ b/trunk/arch/arm/mach-omap1/board-netstar.c @@ -149,6 +149,7 @@ postcore_initcall(netstar_late_init); MACHINE_START(NETSTAR, "NetStar OMAP5910") /* Maintainer: Ladislav Michl */ + .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/trunk/arch/arm/mach-omap1/board-osk.c b/trunk/arch/arm/mach-omap1/board-osk.c index e5d126e8f276..e990e1bc1669 100644 --- a/trunk/arch/arm/mach-omap1/board-osk.c +++ b/trunk/arch/arm/mach-omap1/board-osk.c @@ -274,6 +274,7 @@ static void __init osk_map_io(void) MACHINE_START(OMAP_OSK, "TI-OSK") /* Maintainer: Dirk Behme */ + .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/trunk/arch/arm/mach-omap1/board-palmte.c b/trunk/arch/arm/mach-omap1/board-palmte.c index 67fada207622..5c975eb5c34b 100644 --- a/trunk/arch/arm/mach-omap1/board-palmte.c +++ b/trunk/arch/arm/mach-omap1/board-palmte.c @@ -76,6 +76,7 @@ static void __init omap_generic_map_io(void) } MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E") + .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/trunk/arch/arm/mach-omap1/board-perseus2.c b/trunk/arch/arm/mach-omap1/board-perseus2.c index 88708a0c52a2..92ff5dc07351 100644 --- a/trunk/arch/arm/mach-omap1/board-perseus2.c +++ b/trunk/arch/arm/mach-omap1/board-perseus2.c @@ -199,6 +199,7 @@ static void __init omap_perseus2_map_io(void) MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2") /* Maintainer: Kevin Hilman */ + .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/trunk/arch/arm/mach-omap1/board-voiceblue.c b/trunk/arch/arm/mach-omap1/board-voiceblue.c index 959b4b847c87..6f9a6220e78a 100644 --- a/trunk/arch/arm/mach-omap1/board-voiceblue.c +++ b/trunk/arch/arm/mach-omap1/board-voiceblue.c @@ -281,6 +281,7 @@ EXPORT_SYMBOL(voiceblue_wdt_ping); MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910") /* Maintainer: Ladislav Michl */ + .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/trunk/arch/arm/mach-omap2/board-generic.c b/trunk/arch/arm/mach-omap2/board-generic.c index b937123e5c65..c602e7a3d93e 100644 --- a/trunk/arch/arm/mach-omap2/board-generic.c +++ b/trunk/arch/arm/mach-omap2/board-generic.c @@ -69,6 +69,7 @@ static void __init omap_generic_map_io(void) MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx") /* Maintainer: Paul Mundt */ + .phys_ram = 0x80000000, .phys_io = 0x48000000, .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, .boot_params = 0x80000100, diff --git a/trunk/arch/arm/mach-omap2/board-h4.c b/trunk/arch/arm/mach-omap2/board-h4.c index c3c35d40378a..f2554469a76a 100644 --- a/trunk/arch/arm/mach-omap2/board-h4.c +++ b/trunk/arch/arm/mach-omap2/board-h4.c @@ -186,6 +186,7 @@ static void __init omap_h4_map_io(void) MACHINE_START(OMAP_H4, "OMAP2420 H4 board") /* Maintainer: Paul Mundt */ + .phys_ram = 0x80000000, .phys_io = 0x48000000, .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, .boot_params = 0x80000100, diff --git a/trunk/arch/arm/mach-pxa/corgi.c b/trunk/arch/arm/mach-pxa/corgi.c index 7ffd2de8f2f3..5a7b873f29b3 100644 --- a/trunk/arch/arm/mach-pxa/corgi.c +++ b/trunk/arch/arm/mach-pxa/corgi.c @@ -342,6 +342,7 @@ static void __init fixup_corgi(struct machine_desc *desc, #ifdef CONFIG_MACH_CORGI MACHINE_START(CORGI, "SHARP Corgi") + .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, @@ -354,6 +355,7 @@ MACHINE_END #ifdef CONFIG_MACH_SHEPHERD MACHINE_START(SHEPHERD, "SHARP Shepherd") + .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, @@ -366,6 +368,7 @@ MACHINE_END #ifdef CONFIG_MACH_HUSKY MACHINE_START(HUSKY, "SHARP Husky") + .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, diff --git a/trunk/arch/arm/mach-pxa/idp.c b/trunk/arch/arm/mach-pxa/idp.c index 347b9dea24c6..7de159e2ab42 100644 --- a/trunk/arch/arm/mach-pxa/idp.c +++ b/trunk/arch/arm/mach-pxa/idp.c @@ -183,6 +183,7 @@ static void __init idp_map_io(void) MACHINE_START(PXA_IDP, "Vibren PXA255 IDP") /* Maintainer: Vibren Technologies */ + .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = idp_map_io, diff --git a/trunk/arch/arm/mach-pxa/lubbock.c b/trunk/arch/arm/mach-pxa/lubbock.c index 3e26d7ce5bb2..b464bc88ff93 100644 --- a/trunk/arch/arm/mach-pxa/lubbock.c +++ b/trunk/arch/arm/mach-pxa/lubbock.c @@ -437,6 +437,7 @@ static void __init lubbock_map_io(void) MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)") /* Maintainer: MontaVista Software Inc. */ + .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = lubbock_map_io, diff --git a/trunk/arch/arm/mach-pxa/mainstone.c b/trunk/arch/arm/mach-pxa/mainstone.c index d5bda60209ec..8da9d3efe9a0 100644 --- a/trunk/arch/arm/mach-pxa/mainstone.c +++ b/trunk/arch/arm/mach-pxa/mainstone.c @@ -489,6 +489,7 @@ static void __init mainstone_map_io(void) MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)") /* Maintainer: MontaVista Software Inc. */ + .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = mainstone_map_io, diff --git a/trunk/arch/arm/mach-pxa/poodle.c b/trunk/arch/arm/mach-pxa/poodle.c index 911e6ff5a9bd..663c95005985 100644 --- a/trunk/arch/arm/mach-pxa/poodle.c +++ b/trunk/arch/arm/mach-pxa/poodle.c @@ -311,6 +311,7 @@ static void __init fixup_poodle(struct machine_desc *desc, } MACHINE_START(POODLE, "SHARP Poodle") + .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_poodle, diff --git a/trunk/arch/arm/mach-pxa/spitz.c b/trunk/arch/arm/mach-pxa/spitz.c index c094d99ebf56..a9eacc06555f 100644 --- a/trunk/arch/arm/mach-pxa/spitz.c +++ b/trunk/arch/arm/mach-pxa/spitz.c @@ -497,6 +497,7 @@ static void __init fixup_spitz(struct machine_desc *desc, #ifdef CONFIG_MACH_SPITZ MACHINE_START(SPITZ, "SHARP Spitz") + .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_spitz, @@ -509,6 +510,7 @@ MACHINE_END #ifdef CONFIG_MACH_BORZOI MACHINE_START(BORZOI, "SHARP Borzoi") + .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_spitz, @@ -521,6 +523,7 @@ MACHINE_END #ifdef CONFIG_MACH_AKITA MACHINE_START(AKITA, "SHARP Akita") + .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_spitz, diff --git a/trunk/arch/arm/mach-pxa/tosa.c b/trunk/arch/arm/mach-pxa/tosa.c index d168286ed470..e4f92efc616e 100644 --- a/trunk/arch/arm/mach-pxa/tosa.c +++ b/trunk/arch/arm/mach-pxa/tosa.c @@ -295,6 +295,7 @@ static void __init fixup_tosa(struct machine_desc *desc, } MACHINE_START(TOSA, "SHARP Tosa") + .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_tosa, diff --git a/trunk/arch/arm/mach-realview/Kconfig b/trunk/arch/arm/mach-realview/Kconfig index 17f5f4439fe7..129976866d47 100644 --- a/trunk/arch/arm/mach-realview/Kconfig +++ b/trunk/arch/arm/mach-realview/Kconfig @@ -3,6 +3,7 @@ menu "RealView platform type" config MACH_REALVIEW_EB bool "Support RealView/EB platform" + default n select ARM_GIC help Include support for the ARM(R) RealView Emulation Baseboard platform. diff --git a/trunk/arch/arm/mach-realview/realview_eb.c b/trunk/arch/arm/mach-realview/realview_eb.c index d4a586e38d5b..112f7592aca9 100644 --- a/trunk/arch/arm/mach-realview/realview_eb.c +++ b/trunk/arch/arm/mach-realview/realview_eb.c @@ -166,6 +166,7 @@ static void __init realview_eb_init(void) MACHINE_START(REALVIEW_EB, "ARM-RealView EB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ + .phys_ram = 0x00000000, .phys_io = REALVIEW_UART0_BASE, .io_pg_offst = (IO_ADDRESS(REALVIEW_UART0_BASE) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-rpc/riscpc.c b/trunk/arch/arm/mach-rpc/riscpc.c index 208a2b5dba1b..5c4ac1c008a6 100644 --- a/trunk/arch/arm/mach-rpc/riscpc.c +++ b/trunk/arch/arm/mach-rpc/riscpc.c @@ -177,6 +177,7 @@ extern struct sys_timer ioc_timer; MACHINE_START(RISCPC, "Acorn-RiscPC") /* Maintainer: Russell King */ + .phys_ram = 0x10000000, .phys_io = 0x03000000, .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/trunk/arch/arm/mach-s3c2410/mach-anubis.c b/trunk/arch/arm/mach-s3c2410/mach-anubis.c index 3e327b8e46be..0f81fc0c2f7f 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-anubis.c +++ b/trunk/arch/arm/mach-s3c2410/mach-anubis.c @@ -294,6 +294,7 @@ static void __init anubis_map_io(void) MACHINE_START(ANUBIS, "Simtec-Anubis") /* Maintainer: Ben Dooks */ + .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/trunk/arch/arm/mach-s3c2410/mach-bast.c b/trunk/arch/arm/mach-s3c2410/mach-bast.c index 995bb8add331..4d962717fdf7 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-bast.c +++ b/trunk/arch/arm/mach-s3c2410/mach-bast.c @@ -527,6 +527,7 @@ static void __init bast_init(void) MACHINE_START(BAST, "Simtec-BAST") /* Maintainer: Ben Dooks */ + .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/trunk/arch/arm/mach-s3c2410/mach-h1940.c b/trunk/arch/arm/mach-s3c2410/mach-h1940.c index 1c316f14ed94..0aa8760598f7 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-h1940.c +++ b/trunk/arch/arm/mach-s3c2410/mach-h1940.c @@ -171,6 +171,7 @@ static void __init h1940_init(void) MACHINE_START(H1940, "IPAQ-H1940") /* Maintainer: Ben Dooks */ + .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/trunk/arch/arm/mach-s3c2410/mach-n30.c b/trunk/arch/arm/mach-s3c2410/mach-n30.c index 116ac3169966..378d640ab00b 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-n30.c +++ b/trunk/arch/arm/mach-s3c2410/mach-n30.c @@ -128,6 +128,7 @@ MACHINE_START(N30, "Acer-N30") /* Maintainer: Christer Weinigel , Ben Dooks */ + .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/trunk/arch/arm/mach-s3c2410/mach-nexcoder.c b/trunk/arch/arm/mach-s3c2410/mach-nexcoder.c index 07d09509a626..42b0eeff2e0f 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-nexcoder.c +++ b/trunk/arch/arm/mach-s3c2410/mach-nexcoder.c @@ -148,6 +148,7 @@ static void __init nexcoder_map_io(void) MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440") /* Maintainer: Guillaume GOURAT */ + .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/trunk/arch/arm/mach-s3c2410/mach-otom.c b/trunk/arch/arm/mach-s3c2410/mach-otom.c index b39daedf93ca..a2eb9ed48fcd 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-otom.c +++ b/trunk/arch/arm/mach-s3c2410/mach-otom.c @@ -116,6 +116,7 @@ static void __init otom11_map_io(void) MACHINE_START(OTOM, "Nex Vision - Otom 1.1") /* Maintainer: Guillaume GOURAT */ + .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/trunk/arch/arm/mach-s3c2410/mach-rx3715.c b/trunk/arch/arm/mach-s3c2410/mach-rx3715.c index 0260ed5ab946..f8d86d1e16b6 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-rx3715.c +++ b/trunk/arch/arm/mach-s3c2410/mach-rx3715.c @@ -205,6 +205,7 @@ static void __init rx3715_init_machine(void) MACHINE_START(RX3715, "IPAQ-RX3715") /* Maintainer: Ben Dooks */ + .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/trunk/arch/arm/mach-s3c2410/mach-smdk2410.c b/trunk/arch/arm/mach-s3c2410/mach-smdk2410.c index 1e76e1fdfcea..2c91965ee1c8 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-smdk2410.c +++ b/trunk/arch/arm/mach-s3c2410/mach-smdk2410.c @@ -115,6 +115,7 @@ static void __init smdk2410_init_irq(void) MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch * to SMDK2410 */ /* Maintainer: Jonas Dietsche */ + .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/trunk/arch/arm/mach-s3c2410/mach-smdk2440.c b/trunk/arch/arm/mach-s3c2410/mach-smdk2440.c index f4315721c3b8..4e31118533e6 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-smdk2440.c +++ b/trunk/arch/arm/mach-s3c2410/mach-smdk2440.c @@ -216,6 +216,7 @@ static void __init smdk2440_machine_init(void) MACHINE_START(S3C2440, "SMDK2440") /* Maintainer: Ben Dooks */ + .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/trunk/arch/arm/mach-s3c2410/mach-vr1000.c b/trunk/arch/arm/mach-s3c2410/mach-vr1000.c index 785fc9cdcf7c..ae7e099bf6c8 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/trunk/arch/arm/mach-s3c2410/mach-vr1000.c @@ -395,6 +395,7 @@ static void __init vr1000_map_io(void) MACHINE_START(VR1000, "Thorcom-VR1000") /* Maintainer: Ben Dooks */ + .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/trunk/arch/arm/mach-sa1100/assabet.c b/trunk/arch/arm/mach-sa1100/assabet.c index a599bb0d4ab8..a66ac61233a2 100644 --- a/trunk/arch/arm/mach-sa1100/assabet.c +++ b/trunk/arch/arm/mach-sa1100/assabet.c @@ -447,6 +447,7 @@ static void __init assabet_map_io(void) MACHINE_START(ASSABET, "Intel-Assabet") + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-sa1100/badge4.c b/trunk/arch/arm/mach-sa1100/badge4.c index f60b7a66dfa0..edccd5eb06be 100644 --- a/trunk/arch/arm/mach-sa1100/badge4.c +++ b/trunk/arch/arm/mach-sa1100/badge4.c @@ -297,6 +297,7 @@ static void __init badge4_map_io(void) } MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4") + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-sa1100/cerf.c b/trunk/arch/arm/mach-sa1100/cerf.c index 8269a9ef9afe..508593722bc7 100644 --- a/trunk/arch/arm/mach-sa1100/cerf.c +++ b/trunk/arch/arm/mach-sa1100/cerf.c @@ -135,6 +135,7 @@ static void __init cerf_init(void) MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube") /* Maintainer: support@intrinsyc.com */ + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .map_io = cerf_map_io, diff --git a/trunk/arch/arm/mach-sa1100/collie.c b/trunk/arch/arm/mach-sa1100/collie.c index 6888816a1935..522abc036d3a 100644 --- a/trunk/arch/arm/mach-sa1100/collie.c +++ b/trunk/arch/arm/mach-sa1100/collie.c @@ -191,6 +191,7 @@ static void __init collie_map_io(void) } MACHINE_START(COLLIE, "Sharp-Collie") + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .map_io = collie_map_io, diff --git a/trunk/arch/arm/mach-sa1100/h3600.c b/trunk/arch/arm/mach-sa1100/h3600.c index b04d92271020..e8352b7f74b0 100644 --- a/trunk/arch/arm/mach-sa1100/h3600.c +++ b/trunk/arch/arm/mach-sa1100/h3600.c @@ -392,6 +392,7 @@ static void __init h3100_map_io(void) } MACHINE_START(H3100, "Compaq iPAQ H3100") + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, @@ -509,6 +510,7 @@ static void __init h3600_map_io(void) } MACHINE_START(H3600, "Compaq iPAQ H3600") + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, @@ -895,6 +897,7 @@ static void __init h3800_map_io(void) } MACHINE_START(H3800, "Compaq iPAQ H3800") + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-sa1100/hackkit.c b/trunk/arch/arm/mach-sa1100/hackkit.c index 046b213efd5b..c922e043c424 100644 --- a/trunk/arch/arm/mach-sa1100/hackkit.c +++ b/trunk/arch/arm/mach-sa1100/hackkit.c @@ -195,6 +195,7 @@ static void __init hackkit_init(void) */ MACHINE_START(HACKKIT, "HackKit Cpu Board") + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-sa1100/jornada720.c b/trunk/arch/arm/mach-sa1100/jornada720.c index 17f5a43acdb7..2f671cc3cb99 100644 --- a/trunk/arch/arm/mach-sa1100/jornada720.c +++ b/trunk/arch/arm/mach-sa1100/jornada720.c @@ -173,6 +173,7 @@ static void __init jornada720_mach_init(void) MACHINE_START(JORNADA720, "HP Jornada 720") /* Maintainer: Michael Gernoth */ + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-sa1100/lart.c b/trunk/arch/arm/mach-sa1100/lart.c index 07d3a696ae7f..8c9e3dd52942 100644 --- a/trunk/arch/arm/mach-sa1100/lart.c +++ b/trunk/arch/arm/mach-sa1100/lart.c @@ -60,6 +60,7 @@ static void __init lart_map_io(void) } MACHINE_START(LART, "LART") + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-sa1100/pleb.c b/trunk/arch/arm/mach-sa1100/pleb.c index 0709ebab531c..58c18f9e9b7b 100644 --- a/trunk/arch/arm/mach-sa1100/pleb.c +++ b/trunk/arch/arm/mach-sa1100/pleb.c @@ -146,6 +146,7 @@ static void __init pleb_map_io(void) } MACHINE_START(PLEB, "PLEB") + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .map_io = pleb_map_io, diff --git a/trunk/arch/arm/mach-sa1100/shannon.c b/trunk/arch/arm/mach-sa1100/shannon.c index 5aafe0b56992..7482288278d9 100644 --- a/trunk/arch/arm/mach-sa1100/shannon.c +++ b/trunk/arch/arm/mach-sa1100/shannon.c @@ -83,6 +83,7 @@ static void __init shannon_map_io(void) } MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)") + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-sa1100/simpad.c b/trunk/arch/arm/mach-sa1100/simpad.c index d2c23b2c34d1..439ddc9b06d6 100644 --- a/trunk/arch/arm/mach-sa1100/simpad.c +++ b/trunk/arch/arm/mach-sa1100/simpad.c @@ -229,6 +229,7 @@ arch_initcall(simpad_init); MACHINE_START(SIMPAD, "Simpad") /* Maintainer: Holger Freyther */ + .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/trunk/arch/arm/mach-shark/core.c b/trunk/arch/arm/mach-shark/core.c index 877600e212dd..2d428b6dbb58 100644 --- a/trunk/arch/arm/mach-shark/core.c +++ b/trunk/arch/arm/mach-shark/core.c @@ -111,6 +111,7 @@ static struct sys_timer shark_timer = { MACHINE_START(SHARK, "Shark") /* Maintainer: Alexander Schulz */ + .phys_ram = 0x08000000, .phys_io = 0x40000000, .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, .boot_params = 0x08003000, diff --git a/trunk/arch/arm/mach-versatile/Kconfig b/trunk/arch/arm/mach-versatile/Kconfig index 95096afd5271..8d787f4c78e6 100644 --- a/trunk/arch/arm/mach-versatile/Kconfig +++ b/trunk/arch/arm/mach-versatile/Kconfig @@ -9,6 +9,7 @@ config ARCH_VERSATILE_PB config MACH_VERSATILE_AB bool "Support Versatile/AB platform" + default n help Include support for the ARM(R) Versatile/AP platform. diff --git a/trunk/arch/arm/mach-versatile/core.c b/trunk/arch/arm/mach-versatile/core.c index 9ebbe808b41d..90023745b23a 100644 --- a/trunk/arch/arm/mach-versatile/core.c +++ b/trunk/arch/arm/mach-versatile/core.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -57,6 +56,24 @@ #define VA_VIC_BASE __io_address(VERSATILE_VIC_BASE) #define VA_SIC_BASE __io_address(VERSATILE_SIC_BASE) +static void vic_mask_irq(unsigned int irq) +{ + irq -= IRQ_VIC_START; + writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR); +} + +static void vic_unmask_irq(unsigned int irq) +{ + irq -= IRQ_VIC_START; + writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE); +} + +static struct irqchip vic_chip = { + .ack = vic_mask_irq, + .mask = vic_mask_irq, + .unmask = vic_unmask_irq, +}; + static void sic_mask_irq(unsigned int irq) { irq -= IRQ_SIC_START; @@ -110,12 +127,43 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) void __init versatile_init_irq(void) { - unsigned int i; + unsigned int i, value; + + /* Disable all interrupts initially. */ - vic_init(VA_VIC_BASE, ~(1 << 31)); + writel(0, VA_VIC_BASE + VIC_INT_SELECT); + writel(0, VA_VIC_BASE + VIC_IRQ_ENABLE); + writel(~0, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR); + writel(0, VA_VIC_BASE + VIC_IRQ_STATUS); + writel(0, VA_VIC_BASE + VIC_ITCR); + writel(~0, VA_VIC_BASE + VIC_IRQ_SOFT_CLEAR); + + /* + * Make sure we clear all existing interrupts + */ + writel(0, VA_VIC_BASE + VIC_VECT_ADDR); + for (i = 0; i < 19; i++) { + value = readl(VA_VIC_BASE + VIC_VECT_ADDR); + writel(value, VA_VIC_BASE + VIC_VECT_ADDR); + } + + for (i = 0; i < 16; i++) { + value = readl(VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4)); + writel(value | VICVectCntl_Enable | i, VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4)); + } + + writel(32, VA_VIC_BASE + VIC_DEF_VECT_ADDR); + + for (i = IRQ_VIC_START; i <= IRQ_VIC_END; i++) { + if (i != IRQ_VICSOURCE31) { + set_irq_chip(i, &vic_chip); + set_irq_handler(i, do_level_IRQ); + set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + } + } set_irq_handler(IRQ_VICSOURCE31, sic_handle_irq); - enable_irq(IRQ_VICSOURCE31); + vic_unmask_irq(IRQ_VICSOURCE31); /* Do second interrupt controller */ writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); @@ -829,7 +877,7 @@ static unsigned long versatile_gettimeoffset(void) ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; do { ticks1 = ticks2; - status = __raw_readl(VA_IC_BASE + VIC_RAW_STATUS); + status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS); ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; } while (ticks2 > ticks1); diff --git a/trunk/arch/arm/mach-versatile/versatile_ab.c b/trunk/arch/arm/mach-versatile/versatile_ab.c index 1eb596782078..e74c8a2fbb95 100644 --- a/trunk/arch/arm/mach-versatile/versatile_ab.c +++ b/trunk/arch/arm/mach-versatile/versatile_ab.c @@ -36,6 +36,7 @@ MACHINE_START(VERSATILE_AB, "ARM-Versatile AB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ + .phys_ram = 0x00000000, .phys_io = 0x101f1000, .io_pg_offst = ((0xf11f1000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/mach-versatile/versatile_pb.c b/trunk/arch/arm/mach-versatile/versatile_pb.c index f17ab4fb548a..22d5ca07f75d 100644 --- a/trunk/arch/arm/mach-versatile/versatile_pb.c +++ b/trunk/arch/arm/mach-versatile/versatile_pb.c @@ -100,6 +100,7 @@ arch_initcall(versatile_pb_init); MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ + .phys_ram = 0x00000000, .phys_io = 0x101f1000, .io_pg_offst = ((0xf11f1000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/trunk/arch/arm/nwfpe/fpa11.h b/trunk/arch/arm/nwfpe/fpa11.h index 28cd79a451d3..da4c616b6c49 100644 --- a/trunk/arch/arm/nwfpe/fpa11.h +++ b/trunk/arch/arm/nwfpe/fpa11.h @@ -62,7 +62,7 @@ typedef union tagFPREG { #else u32 padding[3]; #endif -} __attribute__ ((packed,aligned(4))) FPREG; +} FPREG; /* * FPA11 device model. @@ -89,7 +89,7 @@ typedef struct tagFPA11 { so we can use it to detect whether this instance of the emulator needs to be initialised. */ -} __attribute__ ((packed,aligned(4))) FPA11; +} FPA11; extern int8 SetRoundingMode(const unsigned int); extern int8 SetRoundingPrecision(const unsigned int); diff --git a/trunk/arch/arm/plat-omap/Kconfig b/trunk/arch/arm/plat-omap/Kconfig index 0887bb2a2551..9693e9b4ffd1 100644 --- a/trunk/arch/arm/plat-omap/Kconfig +++ b/trunk/arch/arm/plat-omap/Kconfig @@ -22,6 +22,7 @@ comment "OMAP Feature Selections" config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" depends on ARCH_OMAP + default n help Say Y if you want to reset unused clocks during boot. This option saves power, but assumes all drivers are @@ -43,6 +44,7 @@ config OMAP_MUX config OMAP_MUX_DEBUG bool "Multiplexing debug output" depends on OMAP_MUX + default n help Makes the multiplexing functions print out a lot of debug info. This is useful if you want to find out the correct values of the @@ -91,6 +93,7 @@ config OMAP_32K_TIMER_HZ config OMAP_DM_TIMER bool "Use dual-mode timer" + default n depends on ARCH_OMAP16XX help Select this option if you want to use OMAP Dual-Mode timers. diff --git a/trunk/arch/i386/Kconfig b/trunk/arch/i386/Kconfig index cbde675bc95c..d5d0df7f04fc 100644 --- a/trunk/arch/i386/Kconfig +++ b/trunk/arch/i386/Kconfig @@ -702,15 +702,6 @@ config PHYSICAL_START Don't change this unless you know what you are doing. -config HOTPLUG_CPU - bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" - depends on SMP && HOTPLUG && EXPERIMENTAL - ---help--- - Say Y here to experiment with turning CPUs off and on. CPUs - can be controlled through /sys/devices/system/cpu. - - Say N. - endmenu @@ -997,6 +988,15 @@ config SCx200 This support is also available as a module. If compiled as a module, it will be called scx200. +config HOTPLUG_CPU + bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" + depends on SMP && HOTPLUG && EXPERIMENTAL + ---help--- + Say Y here to experiment with turning CPUs off and on. CPUs + can be controlled through /sys/devices/system/cpu. + + Say N. + source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" diff --git a/trunk/arch/i386/Makefile b/trunk/arch/i386/Makefile index bd2d53a9dd2b..d3c0409d201c 100644 --- a/trunk/arch/i386/Makefile +++ b/trunk/arch/i386/Makefile @@ -42,9 +42,9 @@ include $(srctree)/arch/i386/Makefile.cpu cflags-$(CONFIG_REGPARM) += $(shell if [ $(call cc-version) -ge 0300 ] ; then \ echo "-mregparm=3"; fi ;) -# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use -# a lot more stack due to the lack of sharing of stacklots: -CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;) +# Disable unit-at-a-time mode, it makes gcc use a lot more stack +# due to the lack of sharing of stacklots. +CFLAGS += $(call cc-option,-fno-unit-at-a-time) CFLAGS += $(cflags-y) diff --git a/trunk/arch/i386/kernel/traps.c b/trunk/arch/i386/kernel/traps.c index 0aaebf3e1cfa..b9f0030a2ebb 100644 --- a/trunk/arch/i386/kernel/traps.c +++ b/trunk/arch/i386/kernel/traps.c @@ -112,38 +112,33 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) p < (void *)tinfo + THREAD_SIZE - 3; } -static void print_addr_and_symbol(unsigned long addr, char *log_lvl) -{ - printk(log_lvl); - printk(" [<%08lx>] ", addr); - print_symbol("%s", addr); - printk("\n"); -} - static inline unsigned long print_context_stack(struct thread_info *tinfo, - unsigned long *stack, unsigned long ebp, - char *log_lvl) + unsigned long *stack, unsigned long ebp) { unsigned long addr; #ifdef CONFIG_FRAME_POINTER while (valid_stack_ptr(tinfo, (void *)ebp)) { addr = *(unsigned long *)(ebp + 4); - print_addr_and_symbol(addr, log_lvl); + printk(KERN_EMERG " [<%08lx>] ", addr); + print_symbol("%s", addr); + printk("\n"); ebp = *(unsigned long *)ebp; } #else while (valid_stack_ptr(tinfo, stack)) { addr = *stack++; - if (__kernel_text_address(addr)) - print_addr_and_symbol(addr, log_lvl); + if (__kernel_text_address(addr)) { + printk(KERN_EMERG " [<%08lx>]", addr); + print_symbol(" %s", addr); + printk("\n"); + } } #endif return ebp; } -static void show_trace_log_lvl(struct task_struct *task, - unsigned long *stack, char *log_lvl) +void show_trace(struct task_struct *task, unsigned long * stack) { unsigned long ebp; @@ -162,7 +157,7 @@ static void show_trace_log_lvl(struct task_struct *task, struct thread_info *context; context = (struct thread_info *) ((unsigned long)stack & (~(THREAD_SIZE - 1))); - ebp = print_context_stack(context, stack, ebp, log_lvl); + ebp = print_context_stack(context, stack, ebp); stack = (unsigned long*)context->previous_esp; if (!stack) break; @@ -170,13 +165,7 @@ static void show_trace_log_lvl(struct task_struct *task, } } -void show_trace(struct task_struct *task, unsigned long * stack) -{ - show_trace_log_lvl(task, stack, ""); -} - -static void show_stack_log_lvl(struct task_struct *task, unsigned long *esp, - char *log_lvl) +void show_stack(struct task_struct *task, unsigned long *esp) { unsigned long *stack; int i; @@ -189,26 +178,16 @@ static void show_stack_log_lvl(struct task_struct *task, unsigned long *esp, } stack = esp; - printk(log_lvl); + printk(KERN_EMERG); for(i = 0; i < kstack_depth_to_print; i++) { if (kstack_end(stack)) break; - if (i && ((i % 8) == 0)) { - printk("\n"); - printk(log_lvl); - printk(" "); - } + if (i && ((i % 8) == 0)) + printk("\n" KERN_EMERG " "); printk("%08lx ", *stack++); } - printk("\n"); - printk(log_lvl); - printk("Call Trace:\n"); - show_trace_log_lvl(task, esp, log_lvl); -} - -void show_stack(struct task_struct *task, unsigned long *esp) -{ - show_stack_log_lvl(task, esp, ""); + printk("\n" KERN_EMERG "Call Trace:\n"); + show_trace(task, esp); } /* @@ -259,7 +238,7 @@ void show_registers(struct pt_regs *regs) u8 __user *eip; printk("\n" KERN_EMERG "Stack: "); - show_stack_log_lvl(NULL, (unsigned long *)esp, KERN_EMERG); + show_stack(NULL, (unsigned long*)esp); printk(KERN_EMERG "Code: "); diff --git a/trunk/arch/i386/pci/fixup.c b/trunk/arch/i386/pci/fixup.c index 83c3645ccc43..65f67070db64 100644 --- a/trunk/arch/i386/pci/fixup.c +++ b/trunk/arch/i386/pci/fixup.c @@ -449,19 +449,3 @@ static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev) } DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032, pci_post_fixup_toshiba_ohci1394); - - -/* - * Prevent the BIOS trapping accesses to the Cyrix CS5530A video device - * configuration space. - */ -static void __devinit pci_early_fixup_cyrix_5530(struct pci_dev *dev) -{ - u8 r; - /* clear 'F4 Video Configuration Trap' bit */ - pci_read_config_byte(dev, 0x42, &r); - r &= 0xfd; - pci_write_config_byte(dev, 0x42, r); -} -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, - pci_early_fixup_cyrix_5530); diff --git a/trunk/arch/ia64/configs/gensparse_defconfig b/trunk/arch/ia64/configs/gensparse_defconfig index 1d07d8072ec2..80f8663bc6d9 100644 --- a/trunk/arch/ia64/configs/gensparse_defconfig +++ b/trunk/arch/ia64/configs/gensparse_defconfig @@ -701,7 +701,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_SGI_L1_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_SERIAL_SGI_IOC4=y -CONFIG_SERIAL_SGI_IOC3=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -1047,7 +1046,6 @@ CONFIG_INFINIBAND_IPOIB=m # SN Devices # CONFIG_SGI_IOC4=y -CONFIG_SGI_IOC3=y # # File systems diff --git a/trunk/arch/ia64/configs/sn2_defconfig b/trunk/arch/ia64/configs/sn2_defconfig index 3cb503b659e6..ff8bb3770c9d 100644 --- a/trunk/arch/ia64/configs/sn2_defconfig +++ b/trunk/arch/ia64/configs/sn2_defconfig @@ -659,7 +659,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_SGI_L1_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_SERIAL_SGI_IOC4=y -CONFIG_SERIAL_SGI_IOC3=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -900,7 +899,6 @@ CONFIG_INFINIBAND_SRP=m # SN Devices # CONFIG_SGI_IOC4=y -CONFIG_SGI_IOC3=y # # File systems diff --git a/trunk/arch/powerpc/Kconfig b/trunk/arch/powerpc/Kconfig index df338c5cc910..01feed0e2a15 100644 --- a/trunk/arch/powerpc/Kconfig +++ b/trunk/arch/powerpc/Kconfig @@ -78,6 +78,17 @@ config PPC_UDBG_16550 bool default n +config CRASH_DUMP + bool "kernel crash dumps (EXPERIMENTAL)" + depends on PPC_MULTIPLATFORM + depends on EXPERIMENTAL + help + Build a kernel suitable for use as a kdump capture kernel. + The kernel will be linked at a different address than normal, and + so can only be used for Kdump. + + Don't change this unless you know what you are doing. + config GENERIC_TBSYNC bool default y if PPC32 && SMP @@ -573,16 +584,6 @@ config KEXEC support. As of this writing the exact hardware interface is strongly in flux, so no good recommendation can be made. -config CRASH_DUMP - bool "kernel crash dumps (EXPERIMENTAL)" - depends on PPC_MULTIPLATFORM && PPC64 && EXPERIMENTAL - help - Build a kernel suitable for use as a kdump capture kernel. - The kernel will be linked at a different address than normal, and - so can only be used for Kdump. - - Don't change this unless you know what you are doing. - config EMBEDDEDBOOT bool depends on 8xx || 8260 diff --git a/trunk/arch/powerpc/boot/Makefile b/trunk/arch/powerpc/boot/Makefile index 840ae595a617..788dec4c7ef3 100644 --- a/trunk/arch/powerpc/boot/Makefile +++ b/trunk/arch/powerpc/boot/Makefile @@ -27,7 +27,6 @@ BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \ BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc OBJCOPYFLAGS := contents,alloc,load,readonly,data OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 -OBJCOPY_MIB_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h @@ -91,11 +90,11 @@ gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) hostprogs-y := addnote addRamDisk hack-coff targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ - zImage.coff zImage.initrd.coff miboot.image miboot.initrd.image \ + zImage.coff zImage.initrd.coff \ $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ - vmlinux.initrd dummy.o + vmlinux.initrd extra-y := initrd.o quiet_cmd_ramdisk = RAMDISK $@ @@ -117,10 +116,6 @@ quiet_cmd_addsection = ADDSEC $@ quiet_cmd_addnote = ADDNOTE $@ cmd_addnote = $(obj)/addnote $@ -quiet_cmd_gen-miboot = GEN $@ - cmd_gen-miboot = $(OBJCOPY) $(OBJCOPY_MIB_ARGS) \ - --add-section=$1=$(word 2, $^) $< $@ - quiet_cmd_gencoff = COFF $@ cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $@ && \ $(obj)/hack-coff $@ @@ -146,25 +141,19 @@ $(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds $(call cmd,bootld,$(obj-boot),zImage.lds) -# For 32-bit powermacs, build the COFF and miboot images -# as well as the ELF images. +# For 32-bit powermacs, build the COFF images as well as the ELF images. coffimage-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.coff coffrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.initrd.coff -mibootimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/miboot.image -mibrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/miboot.initrd.image -$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y) \ - $(mibootimg-y-y) +$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y) @cp -f $< $@ $(call if_changed,addnote) -$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote \ - $(coffrdimg-y-y) $(mibrdimg-y-y) +$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote $(coffrdimg-y-y) @cp -f $< $@ $(call if_changed,addnote) -$(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) \ - $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff +$(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff $(call cmd,bootld,$(obj-boot),zImage.coff.lds) $(call cmd,gencoff) @@ -173,12 +162,6 @@ $(obj)/zImage.initrd.coff: $(call obj-sec, $(required) $(initrd)) $(obj-boot) \ $(call cmd,bootld,$(obj-boot),zImage.coff.lds) $(call cmd,gencoff) -$(obj)/miboot.image: $(obj)/dummy.o $(obj)/vmlinux.gz - $(call cmd,gen-miboot,image) - -$(obj)/miboot.initrd.image: $(obj)/miboot.image $(images)/ramdisk.image.gz - $(call cmd,gen-miboot,initrd) - #----------------------------------------------------------- # build u-boot images #----------------------------------------------------------- diff --git a/trunk/arch/powerpc/boot/dummy.c b/trunk/arch/powerpc/boot/dummy.c deleted file mode 100644 index 31dbf45bf99c..000000000000 --- a/trunk/arch/powerpc/boot/dummy.c +++ /dev/null @@ -1,4 +0,0 @@ -int main(void) -{ - return 0; -} diff --git a/trunk/arch/powerpc/configs/pmac32_defconfig b/trunk/arch/powerpc/configs/pmac32_defconfig index 2ace57d1e333..398203bd98eb 100644 --- a/trunk/arch/powerpc/configs/pmac32_defconfig +++ b/trunk/arch/powerpc/configs/pmac32_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15 -# Sat Jan 14 16:26:08 2006 +# Linux kernel version: 2.6.15-rc5 +# Tue Dec 13 17:24:05 2005 # # CONFIG_PPC64 is not set CONFIG_PPC32=y @@ -15,15 +15,11 @@ CONFIG_EARLY_PRINTK=y CONFIG_GENERIC_NVRAM=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y -CONFIG_PPC_OF=y -# CONFIG_PPC_UDBG_16550 is not set -# CONFIG_CRASH_DUMP is not set -# CONFIG_GENERIC_TBSYNC is not set # # Processor support # -CONFIG_CLASSIC32=y +CONFIG_6xx=y # CONFIG_PPC_52xx is not set # CONFIG_PPC_82xx is not set # CONFIG_PPC_83xx is not set @@ -32,7 +28,6 @@ CONFIG_CLASSIC32=y # CONFIG_8xx is not set # CONFIG_E200 is not set # CONFIG_E500 is not set -CONFIG_6xx=y CONFIG_PPC_FPU=y CONFIG_ALTIVEC=y CONFIG_PPC_STD_MMU=y @@ -58,18 +53,17 @@ CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_INITRAMFS_SOURCE="" -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y -CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -78,10 +72,8 @@ CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 -CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set # # Loadable module support @@ -121,10 +113,13 @@ CONFIG_PPC_MULTIPLATFORM=y # CONFIG_APUS is not set # CONFIG_PPC_CHRP is not set CONFIG_PPC_PMAC=y +CONFIG_PPC_OF=y CONFIG_MPIC=y # CONFIG_PPC_RTAS is not set # CONFIG_MMIO_NVRAM is not set +# CONFIG_CRASH_DUMP is not set CONFIG_PPC_MPC106=y +# CONFIG_GENERIC_TBSYNC is not set CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_TABLE=y # CONFIG_CPU_FREQ_DEBUG is not set @@ -200,11 +195,6 @@ CONFIG_CARDBUS=y # PC-card bridges # CONFIG_YENTA=m -CONFIG_YENTA_O2=y -CONFIG_YENTA_RICOH=y -CONFIG_YENTA_TI=y -CONFIG_YENTA_ENE_TUNE=y -CONFIG_YENTA_TOSHIBA=y # CONFIG_PD6729 is not set # CONFIG_I82092 is not set CONFIG_PCCARD_NONSTATIC=m @@ -474,7 +464,7 @@ CONFIG_IEEE80211_CRYPT_TKIP=m # # CONFIG_STANDALONE is not set CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y +CONFIG_FW_LOADER=m # CONFIG_DEBUG_DRIVER is not set # @@ -501,7 +491,7 @@ CONFIG_PROC_EVENTS=y # Block devices # # CONFIG_BLK_DEV_FD is not set -CONFIG_MAC_FLOPPY=m +CONFIG_MAC_FLOPPY=y # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -613,7 +603,7 @@ CONFIG_SCSI_CONSTANTS=y # SCSI Transport Attributes # CONFIG_SCSI_SPI_ATTRS=y -CONFIG_SCSI_FC_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_ATTRS is not set @@ -655,7 +645,12 @@ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA24XX is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -663,7 +658,7 @@ CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_DEBUG is not set CONFIG_SCSI_MESH=y CONFIG_SCSI_MESH_SYNC_RATE=5 -CONFIG_SCSI_MESH_RESET_DELAY_MS=4000 +CONFIG_SCSI_MESH_RESET_DELAY_MS=1000 CONFIG_SCSI_MAC53C94=y # @@ -732,6 +727,7 @@ CONFIG_IEEE1394_SBP2=m CONFIG_IEEE1394_ETH1394=m CONFIG_IEEE1394_DV1394=m CONFIG_IEEE1394_RAWIO=m +# CONFIG_IEEE1394_CMP is not set # # I2O device support @@ -744,7 +740,7 @@ CONFIG_IEEE1394_RAWIO=m CONFIG_ADB=y CONFIG_ADB_CUDA=y CONFIG_ADB_PMU=y -CONFIG_PMAC_APM_EMU=m +CONFIG_PMAC_APM_EMU=y CONFIG_PMAC_MEDIABAY=y CONFIG_PMAC_BACKLIGHT=y CONFIG_INPUT_ADBHID=y @@ -823,7 +819,6 @@ CONFIG_PCNET32=y # CONFIG_R8169 is not set # CONFIG_SIS190 is not set # CONFIG_SKGE is not set -# CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set @@ -983,14 +978,14 @@ CONFIG_HW_CONSOLE=y CONFIG_SERIAL_8250=m # CONFIG_SERIAL_8250_CS is not set CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=m -CONFIG_SERIAL_PMACZILOG=m +# CONFIG_SERIAL_PMACZILOG is not set +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -1063,7 +1058,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set -CONFIG_I2C_POWERMAC=y +CONFIG_I2C_KEYWEST=m # CONFIG_I2C_MPC is not set # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set @@ -1165,6 +1160,7 @@ CONFIG_FB_ATY128=y CONFIG_FB_ATY=y CONFIG_FB_ATY_CT=y # CONFIG_FB_ATY_GENERIC_LCD is not set +# CONFIG_FB_ATY_XL_INIT is not set CONFIG_FB_ATY_GX=y # CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set @@ -1173,6 +1169,7 @@ CONFIG_FB_ATY_GX=y CONFIG_FB_3DFX=y # CONFIG_FB_3DFX_ACCEL is not set # CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_CYBLA is not set # CONFIG_FB_TRIDENT is not set # CONFIG_FB_VIRTUAL is not set @@ -1217,10 +1214,9 @@ CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=m CONFIG_SND_PCM_OSS=m CONFIG_SND_SEQUENCER_OSS=y -# CONFIG_SND_DYNAMIC_MINORS is not set -CONFIG_SND_SUPPORT_OLD_API=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set +CONFIG_SND_GENERIC_DRIVER=y # # Generic devices @@ -1234,8 +1230,6 @@ CONFIG_SND_DUMMY=m # # PCI devices # -# CONFIG_SND_AD1889 is not set -# CONFIG_SND_ALS4000 is not set # CONFIG_SND_ALI5451 is not set # CONFIG_SND_ATIIXP is not set # CONFIG_SND_ATIIXP_MODEM is not set @@ -1244,44 +1238,45 @@ CONFIG_SND_DUMMY=m # CONFIG_SND_AU8830 is not set # CONFIG_SND_AZT3328 is not set # CONFIG_SND_BT87X is not set -# CONFIG_SND_CA0106 is not set -# CONFIG_SND_CMIPCI is not set -# CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set +# CONFIG_SND_CS4281 is not set # CONFIG_SND_EMU10K1 is not set # CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_YMFPCI is not set +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS4000 is not set +# CONFIG_SND_CMIPCI is not set # CONFIG_SND_ENS1370 is not set # CONFIG_SND_ENS1371 is not set # CONFIG_SND_ES1938 is not set # CONFIG_SND_ES1968 is not set +# CONFIG_SND_MAESTRO3 is not set # CONFIG_SND_FM801 is not set -# CONFIG_SND_HDA_INTEL is not set -# CONFIG_SND_HDSP is not set -# CONFIG_SND_HDSPM is not set # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set # CONFIG_SND_INTEL8X0M is not set -# CONFIG_SND_KORG1212 is not set -# CONFIG_SND_MAESTRO3 is not set -# CONFIG_SND_MIXART is not set -# CONFIG_SND_NM256 is not set -# CONFIG_SND_PCXHR is not set -# CONFIG_SND_RME32 is not set -# CONFIG_SND_RME96 is not set -# CONFIG_SND_RME9652 is not set # CONFIG_SND_SONICVIBES is not set -# CONFIG_SND_TRIDENT is not set # CONFIG_SND_VIA82XX is not set # CONFIG_SND_VIA82XX_MODEM is not set # CONFIG_SND_VX222 is not set -# CONFIG_SND_YMFPCI is not set +# CONFIG_SND_HDA_INTEL is not set # # ALSA PowerMac devices # CONFIG_SND_POWERMAC=m -CONFIG_SND_POWERMAC_AUTO_DRC=y +# CONFIG_SND_POWERMAC_AUTO_DRC is not set # # USB devices @@ -1341,7 +1336,6 @@ CONFIG_USB_PRINTER=m # may also be needed; see USB_STORAGE Help for more information # # CONFIG_USB_STORAGE is not set -# CONFIG_USB_LIBUSUAL is not set # # USB Input Devices @@ -1361,7 +1355,6 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set -# CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_KEYSPAN_REMOTE is not set CONFIG_USB_APPLETOUCH=y @@ -1508,7 +1501,6 @@ CONFIG_FS_MBCACHE=y # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set -# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y @@ -1548,7 +1540,6 @@ CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y CONFIG_RELAYFS_FS=m -# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -1679,13 +1670,12 @@ CONFIG_OPROFILE=y # Kernel hacking # # CONFIG_PRINTK_TIME is not set -# CONFIG_MAGIC_SYSRQ is not set CONFIG_DEBUG_KERNEL=y +# CONFIG_MAGIC_SYSRQ is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set @@ -1698,11 +1688,6 @@ CONFIG_XMON=y CONFIG_XMON_DEFAULT=y # CONFIG_BDI_SWITCH is not set CONFIG_BOOTX_TEXT=y -# CONFIG_PPC_EARLY_DEBUG_LPAR is not set -# CONFIG_PPC_EARLY_DEBUG_G5 is not set -# CONFIG_PPC_EARLY_DEBUG_RTAS is not set -# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set -# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set # # Security options diff --git a/trunk/arch/powerpc/kernel/Makefile b/trunk/arch/powerpc/kernel/Makefile index c287980b7e65..a94699d8dc52 100644 --- a/trunk/arch/powerpc/kernel/Makefile +++ b/trunk/arch/powerpc/kernel/Makefile @@ -60,8 +60,7 @@ obj-$(CONFIG_MODULES) += $(module-y) pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ pci_direct_iommu.o iomap.o -pci32-$(CONFIG_PPC32) := pci_32.o -obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) +obj-$(CONFIG_PCI) += $(pci64-y) kexec-$(CONFIG_PPC64) := machine_kexec_64.o crash.o kexec-$(CONFIG_PPC32) := machine_kexec_32.o obj-$(CONFIG_KEXEC) += machine_kexec.o $(kexec-y) diff --git a/trunk/arch/powerpc/kernel/crash.c b/trunk/arch/powerpc/kernel/crash.c index 8c21d378f5d2..5f248e3fdf82 100644 --- a/trunk/arch/powerpc/kernel/crash.c +++ b/trunk/arch/powerpc/kernel/crash.c @@ -84,10 +84,7 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu) * squirrelled away. ELF notes happen to provide * all of that that no need to invent something new. */ - buf = (u32*)per_cpu_ptr(crash_notes, cpu); - if (!buf) - return; - + buf = &crash_notes[cpu][0]; memset(&prstatus, 0, sizeof(prstatus)); prstatus.pr_pid = current->pid; elf_core_copy_regs(&prstatus.pr_reg, regs); @@ -96,6 +93,76 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu) final_note(buf); } +/* FIXME Merge this with xmon_save_regs ?? */ +static inline void crash_get_current_regs(struct pt_regs *regs) +{ + unsigned long tmp1, tmp2; + + __asm__ __volatile__ ( + "std 0,0(%2)\n" + "std 1,8(%2)\n" + "std 2,16(%2)\n" + "std 3,24(%2)\n" + "std 4,32(%2)\n" + "std 5,40(%2)\n" + "std 6,48(%2)\n" + "std 7,56(%2)\n" + "std 8,64(%2)\n" + "std 9,72(%2)\n" + "std 10,80(%2)\n" + "std 11,88(%2)\n" + "std 12,96(%2)\n" + "std 13,104(%2)\n" + "std 14,112(%2)\n" + "std 15,120(%2)\n" + "std 16,128(%2)\n" + "std 17,136(%2)\n" + "std 18,144(%2)\n" + "std 19,152(%2)\n" + "std 20,160(%2)\n" + "std 21,168(%2)\n" + "std 22,176(%2)\n" + "std 23,184(%2)\n" + "std 24,192(%2)\n" + "std 25,200(%2)\n" + "std 26,208(%2)\n" + "std 27,216(%2)\n" + "std 28,224(%2)\n" + "std 29,232(%2)\n" + "std 30,240(%2)\n" + "std 31,248(%2)\n" + "mfmsr %0\n" + "std %0, 264(%2)\n" + "mfctr %0\n" + "std %0, 280(%2)\n" + "mflr %0\n" + "std %0, 288(%2)\n" + "bl 1f\n" + "1: mflr %1\n" + "std %1, 256(%2)\n" + "mtlr %0\n" + "mfxer %0\n" + "std %0, 296(%2)\n" + : "=&r" (tmp1), "=&r" (tmp2) + : "b" (regs)); +} + +/* We may have saved_regs from where the error came from + * or it is NULL if via a direct panic(). + */ +static void crash_save_self(struct pt_regs *saved_regs) +{ + struct pt_regs regs; + int cpu; + + cpu = smp_processor_id(); + if (saved_regs) + memcpy(®s, saved_regs, sizeof(regs)); + else + crash_get_current_regs(®s); + crash_save_this_cpu(®s, cpu); +} + #ifdef CONFIG_SMP static atomic_t waiting_for_crash_ipi; @@ -193,5 +260,5 @@ void default_machine_crash_shutdown(struct pt_regs *regs) */ crashing_cpu = smp_processor_id(); crash_kexec_prepare_cpus(); - crash_save_this_cpu(regs, crashing_cpu); + crash_save_self(regs); } diff --git a/trunk/arch/powerpc/kernel/pci_32.c b/trunk/arch/powerpc/kernel/pci_32.c deleted file mode 100644 index 704c846b2b0f..000000000000 --- a/trunk/arch/powerpc/kernel/pci_32.c +++ /dev/null @@ -1,1897 +0,0 @@ -/* - * Common pmac/prep/chrp pci routines. -- Cort - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef DEBUG - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -unsigned long isa_io_base = 0; -unsigned long isa_mem_base = 0; -unsigned long pci_dram_offset = 0; -int pcibios_assign_bus_offset = 1; - -void pcibios_make_OF_bus_map(void); - -static int pci_relocate_bridge_resource(struct pci_bus *bus, int i); -static int probe_resource(struct pci_bus *parent, struct resource *pr, - struct resource *res, struct resource **conflict); -static void update_bridge_base(struct pci_bus *bus, int i); -static void pcibios_fixup_resources(struct pci_dev* dev); -static void fixup_broken_pcnet32(struct pci_dev* dev); -static int reparent_resources(struct resource *parent, struct resource *res); -static void fixup_cpc710_pci64(struct pci_dev* dev); -#ifdef CONFIG_PPC_OF -static u8* pci_to_OF_bus_map; -#endif - -/* By default, we don't re-assign bus numbers. We do this only on - * some pmacs - */ -int pci_assign_all_buses; - -struct pci_controller* hose_head; -struct pci_controller** hose_tail = &hose_head; - -static int pci_bus_count; - -static void -fixup_broken_pcnet32(struct pci_dev* dev) -{ - if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { - dev->vendor = PCI_VENDOR_ID_AMD; - pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD); - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32); - -static void -fixup_cpc710_pci64(struct pci_dev* dev) -{ - /* Hide the PCI64 BARs from the kernel as their content doesn't - * fit well in the resource management - */ - dev->resource[0].start = dev->resource[0].end = 0; - dev->resource[0].flags = 0; - dev->resource[1].start = dev->resource[1].end = 0; - dev->resource[1].flags = 0; -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64); - -static void -pcibios_fixup_resources(struct pci_dev *dev) -{ - struct pci_controller* hose = (struct pci_controller *)dev->sysdata; - int i; - unsigned long offset; - - if (!hose) { - printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev)); - return; - } - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - struct resource *res = dev->resource + i; - if (!res->flags) - continue; - if (res->end == 0xffffffff) { - DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n", - pci_name(dev), i, res->start, res->end); - res->end -= res->start; - res->start = 0; - res->flags |= IORESOURCE_UNSET; - continue; - } - offset = 0; - if (res->flags & IORESOURCE_MEM) { - offset = hose->pci_mem_offset; - } else if (res->flags & IORESOURCE_IO) { - offset = (unsigned long) hose->io_base_virt - - isa_io_base; - } - if (offset != 0) { - res->start += offset; - res->end += offset; -#ifdef DEBUG - printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n", - i, res->flags, pci_name(dev), - res->start - offset, res->start); -#endif - } - } - - /* Call machine specific resource fixup */ - if (ppc_md.pcibios_fixup_resources) - ppc_md.pcibios_fixup_resources(dev); -} -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources); - -void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, - struct resource *res) -{ - unsigned long offset = 0; - struct pci_controller *hose = dev->sysdata; - - if (hose && res->flags & IORESOURCE_IO) - offset = (unsigned long)hose->io_base_virt - isa_io_base; - else if (hose && res->flags & IORESOURCE_MEM) - offset = hose->pci_mem_offset; - region->start = res->start - offset; - region->end = res->end - offset; -} -EXPORT_SYMBOL(pcibios_resource_to_bus); - -void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, - struct pci_bus_region *region) -{ - unsigned long offset = 0; - struct pci_controller *hose = dev->sysdata; - - if (hose && res->flags & IORESOURCE_IO) - offset = (unsigned long)hose->io_base_virt - isa_io_base; - else if (hose && res->flags & IORESOURCE_MEM) - offset = hose->pci_mem_offset; - res->start = region->start + offset; - res->end = region->end + offset; -} -EXPORT_SYMBOL(pcibios_bus_to_resource); - -/* - * 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) -{ - struct pci_dev *dev = data; - - if (res->flags & IORESOURCE_IO) { - unsigned long start = res->start; - - if (size > 0x100) { - printk(KERN_ERR "PCI: I/O Region %s/%d too large" - " (%ld bytes)\n", pci_name(dev), - dev->resource - res, size); - } - - if (start & 0x300) { - start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } -} -EXPORT_SYMBOL(pcibios_align_resource); - -/* - * 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 pci_bus *bus; - int i; - struct resource *res, *pr; - - /* Depth-First Search on bus tree */ - list_for_each_entry(bus, bus_list, node) { - for (i = 0; i < 4; ++i) { - if ((res = bus->resource[i]) == NULL || !res->flags - || res->start > res->end) - continue; - if (bus->parent == NULL) - pr = (res->flags & IORESOURCE_IO)? - &ioport_resource: &iomem_resource; - else { - pr = pci_find_parent_resource(bus->self, res); - if (pr == res) { - /* this happens when the generic PCI - * code (wrongly) decides that this - * bridge is transparent -- paulus - */ - continue; - } - } - - DBG("PCI: bridge rsrc %lx..%lx (%lx), parent %p\n", - res->start, res->end, res->flags, pr); - if (pr) { - if (request_resource(pr, res) == 0) - continue; - /* - * Must be a conflict with an existing entry. - * Move that entry (or entries) under the - * bridge resource and try again. - */ - if (reparent_resources(pr, res) == 0) - continue; - } - printk(KERN_ERR "PCI: Cannot allocate resource region " - "%d of PCI bridge %d\n", i, bus->number); - if (pci_relocate_bridge_resource(bus, i)) - bus->resource[i] = NULL; - } - pcibios_allocate_bus_resources(&bus->children); - } -} - -/* - * Reparent resource children of pr that conflict with res - * under res, and make res replace those children. - */ -static int __init -reparent_resources(struct resource *parent, struct resource *res) -{ - struct resource *p, **pp; - struct resource **firstpp = NULL; - - for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) { - if (p->end < res->start) - continue; - if (res->end < p->start) - break; - if (p->start < res->start || p->end > res->end) - return -1; /* not completely contained */ - if (firstpp == NULL) - firstpp = pp; - } - if (firstpp == NULL) - return -1; /* didn't find any conflicting entries? */ - res->parent = parent; - res->child = *firstpp; - res->sibling = *pp; - *firstpp = res; - *pp = NULL; - for (p = res->child; p != NULL; p = p->sibling) { - p->parent = res; - DBG(KERN_INFO "PCI: reparented %s [%lx..%lx] under %s\n", - p->name, p->start, p->end, res->name); - } - return 0; -} - -/* - * A bridge has been allocated a range which is outside the range - * of its parent bridge, so it needs to be moved. - */ -static int __init -pci_relocate_bridge_resource(struct pci_bus *bus, int i) -{ - struct resource *res, *pr, *conflict; - unsigned long try, size; - int j; - struct pci_bus *parent = bus->parent; - - if (parent == NULL) { - /* shouldn't ever happen */ - printk(KERN_ERR "PCI: can't move host bridge resource\n"); - return -1; - } - res = bus->resource[i]; - if (res == NULL) - return -1; - pr = NULL; - for (j = 0; j < 4; j++) { - struct resource *r = parent->resource[j]; - if (!r) - continue; - if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM)) - continue; - if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) { - pr = r; - break; - } - if (res->flags & IORESOURCE_PREFETCH) - pr = r; - } - if (pr == NULL) - return -1; - size = res->end - res->start; - if (pr->start > pr->end || size > pr->end - pr->start) - return -1; - try = pr->end; - for (;;) { - res->start = try - size; - res->end = try; - if (probe_resource(bus->parent, pr, res, &conflict) == 0) - break; - if (conflict->start <= pr->start + size) - return -1; - try = conflict->start - 1; - } - if (request_resource(pr, res)) { - DBG(KERN_ERR "PCI: huh? couldn't move to %lx..%lx\n", - res->start, res->end); - return -1; /* "can't happen" */ - } - update_bridge_base(bus, i); - printk(KERN_INFO "PCI: bridge %d resource %d moved to %lx..%lx\n", - bus->number, i, res->start, res->end); - return 0; -} - -static int __init -probe_resource(struct pci_bus *parent, struct resource *pr, - struct resource *res, struct resource **conflict) -{ - struct pci_bus *bus; - struct pci_dev *dev; - struct resource *r; - int i; - - for (r = pr->child; r != NULL; r = r->sibling) { - if (r->end >= res->start && res->end >= r->start) { - *conflict = r; - return 1; - } - } - list_for_each_entry(bus, &parent->children, node) { - for (i = 0; i < 4; ++i) { - if ((r = bus->resource[i]) == NULL) - continue; - if (!r->flags || r->start > r->end || r == res) - continue; - if (pci_find_parent_resource(bus->self, r) != pr) - continue; - if (r->end >= res->start && res->end >= r->start) { - *conflict = r; - return 1; - } - } - } - list_for_each_entry(dev, &parent->devices, bus_list) { - for (i = 0; i < 6; ++i) { - r = &dev->resource[i]; - if (!r->flags || (r->flags & IORESOURCE_UNSET)) - continue; - if (pci_find_parent_resource(dev, r) != pr) - continue; - if (r->end >= res->start && res->end >= r->start) { - *conflict = r; - return 1; - } - } - } - return 0; -} - -static void __init -update_bridge_base(struct pci_bus *bus, int i) -{ - struct resource *res = bus->resource[i]; - u8 io_base_lo, io_limit_lo; - u16 mem_base, mem_limit; - u16 cmd; - unsigned long start, end, off; - struct pci_dev *dev = bus->self; - struct pci_controller *hose = dev->sysdata; - - if (!hose) { - printk("update_bridge_base: no hose?\n"); - return; - } - pci_read_config_word(dev, PCI_COMMAND, &cmd); - pci_write_config_word(dev, PCI_COMMAND, - cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)); - if (res->flags & IORESOURCE_IO) { - off = (unsigned long) hose->io_base_virt - isa_io_base; - start = res->start - off; - end = res->end - off; - io_base_lo = (start >> 8) & PCI_IO_RANGE_MASK; - io_limit_lo = (end >> 8) & PCI_IO_RANGE_MASK; - if (end > 0xffff) { - pci_write_config_word(dev, PCI_IO_BASE_UPPER16, - start >> 16); - pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16, - end >> 16); - io_base_lo |= PCI_IO_RANGE_TYPE_32; - } else - io_base_lo |= PCI_IO_RANGE_TYPE_16; - pci_write_config_byte(dev, PCI_IO_BASE, io_base_lo); - pci_write_config_byte(dev, PCI_IO_LIMIT, io_limit_lo); - - } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH)) - == IORESOURCE_MEM) { - off = hose->pci_mem_offset; - mem_base = ((res->start - off) >> 16) & PCI_MEMORY_RANGE_MASK; - mem_limit = ((res->end - off) >> 16) & PCI_MEMORY_RANGE_MASK; - pci_write_config_word(dev, PCI_MEMORY_BASE, mem_base); - pci_write_config_word(dev, PCI_MEMORY_LIMIT, mem_limit); - - } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH)) - == (IORESOURCE_MEM | IORESOURCE_PREFETCH)) { - off = hose->pci_mem_offset; - mem_base = ((res->start - off) >> 16) & PCI_PREF_RANGE_MASK; - mem_limit = ((res->end - off) >> 16) & PCI_PREF_RANGE_MASK; - pci_write_config_word(dev, PCI_PREF_MEMORY_BASE, mem_base); - pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, mem_limit); - - } else { - DBG(KERN_ERR "PCI: ugh, bridge %s res %d has flags=%lx\n", - pci_name(dev), i, res->flags); - } - pci_write_config_word(dev, PCI_COMMAND, cmd); -} - -static inline void alloc_resource(struct pci_dev *dev, int idx) -{ - struct resource *pr, *r = &dev->resource[idx]; - - DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx)\n", - pci_name(dev), idx, r->start, r->end, r->flags); - 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, pci_name(dev)); - if (pr) - DBG("PCI: parent is %p: %08lx-%08lx (f=%lx)\n", - pr, pr->start, pr->end, pr->flags); - /* We'll assign a new address later */ - r->flags |= IORESOURCE_UNSET; - r->end -= r->start; - r->start = 0; - } -} - -static void __init -pcibios_allocate_resources(int pass) -{ - struct pci_dev *dev = NULL; - int idx, disabled; - u16 command; - struct resource *r; - - for_each_pci_dev(dev) { - 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->flags || (r->flags & IORESOURCE_UNSET)) - continue; /* Not assigned at all */ - if (r->flags & IORESOURCE_IO) - disabled = !(command & PCI_COMMAND_IO); - else - disabled = !(command & PCI_COMMAND_MEMORY); - if (pass == disabled) - alloc_resource(dev, idx); - } - if (pass) - continue; - r = &dev->resource[PCI_ROM_RESOURCE]; - if (r->flags & IORESOURCE_ROM_ENABLE) { - /* Turn the ROM off, leave the resource region, but keep it unregistered. */ - u32 reg; - DBG("PCI: Switching off ROM of %s\n", pci_name(dev)); - r->flags &= ~IORESOURCE_ROM_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; - - for_each_pci_dev(dev) { - 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]; - - /* - * We shall assign a new address to this resource, - * either because the BIOS (sic) forgot to do so - * or because we have decided the old address was - * unusable for some reason. - */ - if ((r->flags & IORESOURCE_UNSET) && r->end && - (!ppc_md.pcibios_enable_device_hook || - !ppc_md.pcibios_enable_device_hook(dev, 1))) { - r->flags &= ~IORESOURCE_UNSET; - pci_assign_resource(dev, idx); - } - } - -#if 0 /* don't 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); -#endif - } -} - - -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++) { - /* Only set up the requested stuff */ - if (!(mask & (1<resource[idx]; - if (r->flags & IORESOURCE_UNSET) { - printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); - 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", pci_name(dev), old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -static int next_controller_index; - -struct pci_controller * __init -pcibios_alloc_controller(void) -{ - struct pci_controller *hose; - - hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose)); - memset(hose, 0, sizeof(struct pci_controller)); - - *hose_tail = hose; - hose_tail = &hose->next; - - hose->index = next_controller_index++; - - return hose; -} - -#ifdef CONFIG_PPC_OF -/* - * Functions below are used on OpenFirmware machines. - */ -static void -make_one_node_map(struct device_node* node, u8 pci_bus) -{ - int *bus_range; - int len; - - if (pci_bus >= pci_bus_count) - return; - bus_range = (int *) get_property(node, "bus-range", &len); - if (bus_range == NULL || len < 2 * sizeof(int)) { - printk(KERN_WARNING "Can't get bus-range for %s, " - "assuming it starts at 0\n", node->full_name); - pci_to_OF_bus_map[pci_bus] = 0; - } else - pci_to_OF_bus_map[pci_bus] = bus_range[0]; - - for (node=node->child; node != 0;node = node->sibling) { - struct pci_dev* dev; - unsigned int *class_code, *reg; - - class_code = (unsigned int *) get_property(node, "class-code", NULL); - if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && - (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) - continue; - reg = (unsigned int *)get_property(node, "reg", NULL); - if (!reg) - continue; - dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff)); - if (!dev || !dev->subordinate) - continue; - make_one_node_map(node, dev->subordinate->number); - } -} - -void -pcibios_make_OF_bus_map(void) -{ - int i; - struct pci_controller* hose; - u8* of_prop_map; - - pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL); - if (!pci_to_OF_bus_map) { - printk(KERN_ERR "Can't allocate OF bus map !\n"); - return; - } - - /* We fill the bus map with invalid values, that helps - * debugging. - */ - for (i=0; inext) { - struct device_node* node; - node = (struct device_node *)hose->arch_data; - if (!node) - continue; - make_one_node_map(node, hose->first_busno); - } - of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", NULL); - if (of_prop_map) - memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count); -#ifdef DEBUG - printk("PCI->OF bus map:\n"); - for (i=0; i %d\n", i, pci_to_OF_bus_map[i]); - } -#endif -} - -typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data); - -static struct device_node* -scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data) -{ - struct device_node* sub_node; - - for (; node != 0;node = node->sibling) { - unsigned int *class_code; - - if (filter(node, data)) - return node; - - /* For PCI<->PCI bridges or CardBus bridges, we go down - * Note: some OFs create a parent node "multifunc-device" as - * a fake root for all functions of a multi-function device, - * we go down them as well. - */ - class_code = (unsigned int *) get_property(node, "class-code", NULL); - if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && - (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) && - strcmp(node->name, "multifunc-device")) - continue; - sub_node = scan_OF_pci_childs(node->child, filter, data); - if (sub_node) - return sub_node; - } - return NULL; -} - -static int -scan_OF_pci_childs_iterator(struct device_node* node, void* data) -{ - unsigned int *reg; - u8* fdata = (u8*)data; - - reg = (unsigned int *) get_property(node, "reg", NULL); - if (reg && ((reg[0] >> 8) & 0xff) == fdata[1] - && ((reg[0] >> 16) & 0xff) == fdata[0]) - return 1; - return 0; -} - -static struct device_node* -scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn) -{ - u8 filter_data[2] = {bus, dev_fn}; - - return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data); -} - -/* - * Scans the OF tree for a device node matching a PCI device - */ -struct device_node * -pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) -{ - struct pci_controller *hose; - struct device_node *node; - int busnr; - - if (!have_of) - return NULL; - - /* Lookup the hose */ - busnr = bus->number; - hose = pci_bus_to_hose(busnr); - if (!hose) - return NULL; - - /* Check it has an OF node associated */ - node = (struct device_node *) hose->arch_data; - if (!node) - return NULL; - - /* Fixup bus number according to what OF think it is. */ -#ifdef CONFIG_PPC_PMAC - /* The G5 need a special case here. Basically, we don't remap all - * busses on it so we don't create the pci-OF-map. However, we do - * remap the AGP bus and so have to deal with it. A future better - * fix has to be done by making the remapping per-host and always - * filling the pci_to_OF map. --BenH - */ - if (_machine == _MACH_Pmac && busnr >= 0xf0) - busnr -= 0xf0; - else -#endif - if (pci_to_OF_bus_map) - busnr = pci_to_OF_bus_map[busnr]; - if (busnr == 0xff) - return NULL; - - /* Now, lookup childs of the hose */ - return scan_OF_childs_for_device(node->child, busnr, devfn); -} -EXPORT_SYMBOL(pci_busdev_to_OF_node); - -struct device_node* -pci_device_to_OF_node(struct pci_dev *dev) -{ - return pci_busdev_to_OF_node(dev->bus, dev->devfn); -} -EXPORT_SYMBOL(pci_device_to_OF_node); - -/* This routine is meant to be used early during boot, when the - * PCI bus numbers have not yet been assigned, and you need to - * issue PCI config cycles to an OF device. - * It could also be used to "fix" RTAS config cycles if you want - * to set pci_assign_all_buses to 1 and still use RTAS for PCI - * config cycles. - */ -struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) -{ - if (!have_of) - return NULL; - while(node) { - struct pci_controller* hose; - for (hose=hose_head;hose;hose=hose->next) - if (hose->arch_data == node) - return hose; - node=node->parent; - } - return NULL; -} - -static int -find_OF_pci_device_filter(struct device_node* node, void* data) -{ - return ((void *)node == data); -} - -/* - * Returns the PCI device matching a given OF node - */ -int -pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn) -{ - unsigned int *reg; - struct pci_controller* hose; - struct pci_dev* dev = NULL; - - if (!have_of) - return -ENODEV; - /* Make sure it's really a PCI device */ - hose = pci_find_hose_for_OF_device(node); - if (!hose || !hose->arch_data) - return -ENODEV; - if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child, - find_OF_pci_device_filter, (void *)node)) - return -ENODEV; - reg = (unsigned int *) get_property(node, "reg", NULL); - if (!reg) - return -ENODEV; - *bus = (reg[0] >> 16) & 0xff; - *devfn = ((reg[0] >> 8) & 0xff); - - /* Ok, here we need some tweak. If we have already renumbered - * all busses, we can't rely on the OF bus number any more. - * the pci_to_OF_bus_map is not enough as several PCI busses - * may match the same OF bus number. - */ - if (!pci_to_OF_bus_map) - return 0; - - for_each_pci_dev(dev) - if (pci_to_OF_bus_map[dev->bus->number] == *bus && - dev->devfn == *devfn) { - *bus = dev->bus->number; - pci_dev_put(dev); - return 0; - } - - return -ENODEV; -} -EXPORT_SYMBOL(pci_device_from_OF_node); - -void __init -pci_process_bridge_OF_ranges(struct pci_controller *hose, - struct device_node *dev, int primary) -{ - static unsigned int static_lc_ranges[256] __initdata; - unsigned int *dt_ranges, *lc_ranges, *ranges, *prev; - unsigned int size; - int rlen = 0, orig_rlen; - int memno = 0; - struct resource *res; - int np, na = prom_n_addr_cells(dev); - np = na + 5; - - /* First we try to merge ranges to fix a problem with some pmacs - * that can have more than 3 ranges, fortunately using contiguous - * addresses -- BenH - */ - dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen); - if (!dt_ranges) - return; - /* Sanity check, though hopefully that never happens */ - if (rlen > sizeof(static_lc_ranges)) { - printk(KERN_WARNING "OF ranges property too large !\n"); - rlen = sizeof(static_lc_ranges); - } - lc_ranges = static_lc_ranges; - memcpy(lc_ranges, dt_ranges, rlen); - orig_rlen = rlen; - - /* Let's work on a copy of the "ranges" property instead of damaging - * the device-tree image in memory - */ - ranges = lc_ranges; - prev = NULL; - while ((rlen -= np * sizeof(unsigned int)) >= 0) { - if (prev) { - if (prev[0] == ranges[0] && prev[1] == ranges[1] && - (prev[2] + prev[na+4]) == ranges[2] && - (prev[na+2] + prev[na+4]) == ranges[na+2]) { - prev[na+4] += ranges[na+4]; - ranges[0] = 0; - ranges += np; - continue; - } - } - prev = ranges; - ranges += np; - } - - /* - * The ranges property is laid out as an array of elements, - * each of which comprises: - * cells 0 - 2: a PCI address - * cells 3 or 3+4: a CPU physical address - * (size depending on dev->n_addr_cells) - * cells 4+5 or 5+6: the size of the range - */ - ranges = lc_ranges; - rlen = orig_rlen; - while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) { - res = NULL; - size = ranges[na+4]; - switch ((ranges[0] >> 24) & 0x3) { - case 1: /* I/O space */ - if (ranges[2] != 0) - break; - hose->io_base_phys = ranges[na+2]; - /* limit I/O space to 16MB */ - if (size > 0x01000000) - size = 0x01000000; - hose->io_base_virt = ioremap(ranges[na+2], size); - if (primary) - isa_io_base = (unsigned long) hose->io_base_virt; - res = &hose->io_resource; - res->flags = IORESOURCE_IO; - res->start = ranges[2]; - DBG("PCI: IO 0x%lx -> 0x%lx\n", - res->start, res->start + size - 1); - break; - case 2: /* memory space */ - memno = 0; - if (ranges[1] == 0 && ranges[2] == 0 - && ranges[na+4] <= (16 << 20)) { - /* 1st 16MB, i.e. ISA memory area */ - if (primary) - isa_mem_base = ranges[na+2]; - memno = 1; - } - while (memno < 3 && hose->mem_resources[memno].flags) - ++memno; - if (memno == 0) - hose->pci_mem_offset = ranges[na+2] - ranges[2]; - if (memno < 3) { - res = &hose->mem_resources[memno]; - res->flags = IORESOURCE_MEM; - if(ranges[0] & 0x40000000) - res->flags |= IORESOURCE_PREFETCH; - res->start = ranges[na+2]; - DBG("PCI: MEM[%d] 0x%lx -> 0x%lx\n", memno, - res->start, res->start + size - 1); - } - break; - } - if (res != NULL) { - res->name = dev->full_name; - res->end = res->start + size - 1; - res->parent = NULL; - res->sibling = NULL; - res->child = NULL; - } - ranges += np; - } -} - -/* We create the "pci-OF-bus-map" property now so it appears in the - * /proc device tree - */ -void __init -pci_create_OF_bus_map(void) -{ - struct property* of_prop; - - of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256); - if (of_prop && find_path_device("/")) { - memset(of_prop, -1, sizeof(struct property) + 256); - of_prop->name = "pci-OF-bus-map"; - of_prop->length = 256; - of_prop->value = (unsigned char *)&of_prop[1]; - prom_add_property(find_path_device("/"), of_prop); - } -} - -static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct pci_dev *pdev; - struct device_node *np; - - pdev = to_pci_dev (dev); - np = pci_device_to_OF_node(pdev); - if (np == NULL || np->full_name == NULL) - return 0; - return sprintf(buf, "%s", np->full_name); -} -static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); - -#else /* CONFIG_PPC_OF */ -void pcibios_make_OF_bus_map(void) -{ -} -#endif /* CONFIG_PPC_OF */ - -/* Add sysfs properties */ -void pcibios_add_platform_entries(struct pci_dev *pdev) -{ -#ifdef CONFIG_PPC_OF - device_create_file(&pdev->dev, &dev_attr_devspec); -#endif /* CONFIG_PPC_OF */ -} - - -#ifdef CONFIG_PPC_PMAC -/* - * This set of routines checks for PCI<->PCI bridges that have closed - * IO resources and have child devices. It tries to re-open an IO - * window on them. - * - * This is a _temporary_ fix to workaround a problem with Apple's OF - * closing IO windows on P2P bridges when the OF drivers of cards - * below this bridge don't claim any IO range (typically ATI or - * Adaptec). - * - * A more complete fix would be to use drivers/pci/setup-bus.c, which - * involves a working pcibios_fixup_pbus_ranges(), some more care about - * ordering when creating the host bus resources, and maybe a few more - * minor tweaks - */ - -/* Initialize bridges with base/limit values we have collected */ -static void __init -do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga) -{ - struct pci_dev *bridge = bus->self; - struct pci_controller* hose = (struct pci_controller *)bridge->sysdata; - u32 l; - u16 w; - struct resource res; - - if (bus->resource[0] == NULL) - return; - res = *(bus->resource[0]); - - DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge)); - res.start -= ((unsigned long) hose->io_base_virt - isa_io_base); - res.end -= ((unsigned long) hose->io_base_virt - isa_io_base); - DBG(" IO window: %08lx-%08lx\n", res.start, res.end); - - /* Set up the top and bottom of the PCI I/O segment for this bus. */ - pci_read_config_dword(bridge, PCI_IO_BASE, &l); - l &= 0xffff000f; - l |= (res.start >> 8) & 0x00f0; - l |= res.end & 0xf000; - pci_write_config_dword(bridge, PCI_IO_BASE, l); - - if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { - l = (res.start >> 16) | (res.end & 0xffff0000); - pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l); - } - - pci_read_config_word(bridge, PCI_COMMAND, &w); - w |= PCI_COMMAND_IO; - pci_write_config_word(bridge, PCI_COMMAND, w); - -#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */ - if (enable_vga) { - pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w); - w |= PCI_BRIDGE_CTL_VGA; - pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w); - } -#endif -} - -/* This function is pretty basic and actually quite broken for the - * general case, it's enough for us right now though. It's supposed - * to tell us if we need to open an IO range at all or not and what - * size. - */ -static int __init -check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga) -{ - struct pci_dev *dev; - int i; - int rc = 0; - -#define push_end(res, size) do { unsigned long __sz = (size) ; \ - res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \ - } while (0) - - list_for_each_entry(dev, &bus->devices, bus_list) { - u16 class = dev->class >> 8; - - if (class == PCI_CLASS_DISPLAY_VGA || - class == PCI_CLASS_NOT_DEFINED_VGA) - *found_vga = 1; - if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate) - rc |= check_for_io_childs(dev->subordinate, res, found_vga); - if (class == PCI_CLASS_BRIDGE_CARDBUS) - push_end(res, 0xfff); - - for (i=0; iclass >> 8 == PCI_CLASS_BRIDGE_PCI - && i >= PCI_BRIDGE_RESOURCES) - continue; - r = &dev->resource[i]; - r_size = r->end - r->start; - if (r_size < 0xfff) - r_size = 0xfff; - if (r->flags & IORESOURCE_IO && (r_size) != 0) { - rc = 1; - push_end(res, r_size); - } - } - } - - return rc; -} - -/* Here we scan all P2P bridges of a given level that have a closed - * IO window. Note that the test for the presence of a VGA card should - * be improved to take into account already configured P2P bridges, - * currently, we don't see them and might end up configuring 2 bridges - * with VGA pass through enabled - */ -static void __init -do_fixup_p2p_level(struct pci_bus *bus) -{ - struct pci_bus *b; - int i, parent_io; - int has_vga = 0; - - for (parent_io=0; parent_io<4; parent_io++) - if (bus->resource[parent_io] - && bus->resource[parent_io]->flags & IORESOURCE_IO) - break; - if (parent_io >= 4) - return; - - list_for_each_entry(b, &bus->children, node) { - struct pci_dev *d = b->self; - struct pci_controller* hose = (struct pci_controller *)d->sysdata; - struct resource *res = b->resource[0]; - struct resource tmp_res; - unsigned long max; - int found_vga = 0; - - memset(&tmp_res, 0, sizeof(tmp_res)); - tmp_res.start = bus->resource[parent_io]->start; - - /* We don't let low addresses go through that closed P2P bridge, well, - * that may not be necessary but I feel safer that way - */ - if (tmp_res.start == 0) - tmp_res.start = 0x1000; - - if (!list_empty(&b->devices) && res && res->flags == 0 && - res != bus->resource[parent_io] && - (d->class >> 8) == PCI_CLASS_BRIDGE_PCI && - check_for_io_childs(b, &tmp_res, &found_vga)) { - u8 io_base_lo; - - printk(KERN_INFO "Fixing up IO bus %s\n", b->name); - - if (found_vga) { - if (has_vga) { - printk(KERN_WARNING "Skipping VGA, already active" - " on bus segment\n"); - found_vga = 0; - } else - has_vga = 1; - } - pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo); - - if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) - max = ((unsigned long) hose->io_base_virt - - isa_io_base) + 0xffffffff; - else - max = ((unsigned long) hose->io_base_virt - - isa_io_base) + 0xffff; - - *res = tmp_res; - res->flags = IORESOURCE_IO; - res->name = b->name; - - /* Find a resource in the parent where we can allocate */ - for (i = 0 ; i < 4; i++) { - struct resource *r = bus->resource[i]; - if (!r) - continue; - if ((r->flags & IORESOURCE_IO) == 0) - continue; - DBG("Trying to allocate from %08lx, size %08lx from parent" - " res %d: %08lx -> %08lx\n", - res->start, res->end, i, r->start, r->end); - - if (allocate_resource(r, res, res->end + 1, res->start, max, - res->end + 1, NULL, NULL) < 0) { - DBG("Failed !\n"); - continue; - } - do_update_p2p_io_resource(b, found_vga); - break; - } - } - do_fixup_p2p_level(b); - } -} - -static void -pcibios_fixup_p2p_bridges(void) -{ - struct pci_bus *b; - - list_for_each_entry(b, &pci_root_buses, node) - do_fixup_p2p_level(b); -} - -#endif /* CONFIG_PPC_PMAC */ - -static int __init -pcibios_init(void) -{ - struct pci_controller *hose; - struct pci_bus *bus; - int next_busno; - - printk(KERN_INFO "PCI: Probing PCI hardware\n"); - - /* Scan all of the recorded PCI controllers. */ - for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { - if (pci_assign_all_buses) - hose->first_busno = next_busno; - hose->last_busno = 0xff; - bus = pci_scan_bus(hose->first_busno, hose->ops, hose); - hose->last_busno = bus->subordinate; - if (pci_assign_all_buses || next_busno <= hose->last_busno) - next_busno = hose->last_busno + pcibios_assign_bus_offset; - } - pci_bus_count = next_busno; - - /* OpenFirmware based machines need a map of OF bus - * numbers vs. kernel bus numbers since we may have to - * remap them. - */ - if (pci_assign_all_buses && have_of) - pcibios_make_OF_bus_map(); - - /* Do machine dependent PCI interrupt routing */ - if (ppc_md.pci_swizzle && ppc_md.pci_map_irq) - pci_fixup_irqs(ppc_md.pci_swizzle, ppc_md.pci_map_irq); - - /* Call machine dependent fixup */ - if (ppc_md.pcibios_fixup) - ppc_md.pcibios_fixup(); - - /* Allocate and assign resources */ - pcibios_allocate_bus_resources(&pci_root_buses); - pcibios_allocate_resources(0); - pcibios_allocate_resources(1); -#ifdef CONFIG_PPC_PMAC - pcibios_fixup_p2p_bridges(); -#endif /* CONFIG_PPC_PMAC */ - pcibios_assign_resources(); - - /* Call machine dependent post-init code */ - if (ppc_md.pcibios_after_init) - ppc_md.pcibios_after_init(); - - return 0; -} - -subsys_initcall(pcibios_init); - -unsigned char __init -common_swizzle(struct pci_dev *dev, unsigned char *pinp) -{ - struct pci_controller *hose = dev->sysdata; - - if (dev->bus->number != hose->first_busno) { - u8 pin = *pinp; - do { - pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); - /* Move up the chain of bridges. */ - dev = dev->bus->self; - } while (dev->bus->self); - *pinp = pin; - - /* The slot is the idsel of the last bridge. */ - } - return PCI_SLOT(dev->devfn); -} - -unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, - unsigned long start, unsigned long size) -{ - return start; -} - -void __init pcibios_fixup_bus(struct pci_bus *bus) -{ - struct pci_controller *hose = (struct pci_controller *) bus->sysdata; - unsigned long io_offset; - struct resource *res; - int i; - - io_offset = (unsigned long)hose->io_base_virt - isa_io_base; - if (bus->parent == NULL) { - /* This is a host bridge - fill in its resources */ - hose->bus = bus; - - bus->resource[0] = res = &hose->io_resource; - if (!res->flags) { - if (io_offset) - printk(KERN_ERR "I/O resource not set for host" - " bridge %d\n", hose->index); - res->start = 0; - res->end = IO_SPACE_LIMIT; - res->flags = IORESOURCE_IO; - } - res->start += io_offset; - res->end += io_offset; - - for (i = 0; i < 3; ++i) { - res = &hose->mem_resources[i]; - if (!res->flags) { - if (i > 0) - continue; - printk(KERN_ERR "Memory resource not set for " - "host bridge %d\n", hose->index); - res->start = hose->pci_mem_offset; - res->end = ~0U; - res->flags = IORESOURCE_MEM; - } - bus->resource[i+1] = res; - } - } else { - /* This is a subordinate bridge */ - pci_read_bridge_bases(bus); - - for (i = 0; i < 4; ++i) { - if ((res = bus->resource[i]) == NULL) - continue; - if (!res->flags) - continue; - if (io_offset && (res->flags & IORESOURCE_IO)) { - res->start += io_offset; - res->end += io_offset; - } else if (hose->pci_mem_offset - && (res->flags & IORESOURCE_MEM)) { - res->start += hose->pci_mem_offset; - res->end += hose->pci_mem_offset; - } - } - } - - if (ppc_md.pcibios_fixup_bus) - ppc_md.pcibios_fixup_bus(bus); -} - -char __init *pcibios_setup(char *str) -{ - return str; -} - -/* the next one is stolen from the alpha port... */ -void __init -pcibios_update_irq(struct pci_dev *dev, int irq) -{ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); - /* XXX FIXME - update OF device tree node interrupt property */ -} - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - if (ppc_md.pcibios_enable_device_hook) - if (ppc_md.pcibios_enable_device_hook(dev, 0)) - return -EINVAL; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for (idx=0; idx<6; idx++) { - r = &dev->resource[idx]; - if (r->flags & IORESOURCE_UNSET) { - printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (cmd != old_cmd) { - printk("PCI: Enabling device %s (%04x -> %04x)\n", - pci_name(dev), old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -struct pci_controller* -pci_bus_to_hose(int bus) -{ - struct pci_controller* hose = hose_head; - - for (; hose; hose = hose->next) - if (bus >= hose->first_busno && bus <= hose->last_busno) - return hose; - return NULL; -} - -void __iomem * -pci_bus_io_base(unsigned int bus) -{ - struct pci_controller *hose; - - hose = pci_bus_to_hose(bus); - if (!hose) - return NULL; - return hose->io_base_virt; -} - -unsigned long -pci_bus_io_base_phys(unsigned int bus) -{ - struct pci_controller *hose; - - hose = pci_bus_to_hose(bus); - if (!hose) - return 0; - return hose->io_base_phys; -} - -unsigned long -pci_bus_mem_base_phys(unsigned int bus) -{ - struct pci_controller *hose; - - hose = pci_bus_to_hose(bus); - if (!hose) - return 0; - return hose->pci_mem_offset; -} - -unsigned long -pci_resource_to_bus(struct pci_dev *pdev, struct resource *res) -{ - /* Hack alert again ! See comments in chrp_pci.c - */ - struct pci_controller* hose = - (struct pci_controller *)pdev->sysdata; - if (hose && res->flags & IORESOURCE_MEM) - return res->start - hose->pci_mem_offset; - /* We may want to do something with IOs here... */ - return res->start; -} - - -static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, - unsigned long *offset, - enum pci_mmap_state mmap_state) -{ - struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); - unsigned long io_offset = 0; - int i, res_bit; - - if (hose == 0) - return NULL; /* should never happen */ - - /* If memory, add on the PCI bridge address offset */ - if (mmap_state == pci_mmap_mem) { - *offset += hose->pci_mem_offset; - res_bit = IORESOURCE_MEM; - } else { - io_offset = hose->io_base_virt - ___IO_BASE; - *offset += io_offset; - res_bit = IORESOURCE_IO; - } - - /* - * Check that the offset requested corresponds to one of the - * resources of the device. - */ - for (i = 0; i <= PCI_ROM_RESOURCE; i++) { - struct resource *rp = &dev->resource[i]; - int flags = rp->flags; - - /* treat ROM as memory (should be already) */ - if (i == PCI_ROM_RESOURCE) - flags |= IORESOURCE_MEM; - - /* Active and same type? */ - if ((flags & res_bit) == 0) - continue; - - /* In the range of this resource? */ - if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) - continue; - - /* found it! construct the final physical address */ - if (mmap_state == pci_mmap_io) - *offset += hose->io_base_phys - io_offset; - return rp; - } - - return NULL; -} - -/* - * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci - * device mapping. - */ -static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, - pgprot_t protection, - enum pci_mmap_state mmap_state, - int write_combine) -{ - unsigned long prot = pgprot_val(protection); - - /* Write combine is always 0 on non-memory space mappings. On - * memory space, if the user didn't pass 1, we check for a - * "prefetchable" resource. This is a bit hackish, but we use - * this to workaround the inability of /sysfs to provide a write - * combine bit - */ - if (mmap_state != pci_mmap_mem) - write_combine = 0; - else if (write_combine == 0) { - if (rp->flags & IORESOURCE_PREFETCH) - write_combine = 1; - } - - /* XXX would be nice to have a way to ask for write-through */ - prot |= _PAGE_NO_CACHE; - if (write_combine) - prot &= ~_PAGE_GUARDED; - else - prot |= _PAGE_GUARDED; - - printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start, - prot); - - return __pgprot(prot); -} - -/* - * This one is used by /dev/mem and fbdev who have no clue about the - * PCI device, it tries to find the PCI device first and calls the - * above routine - */ -pgprot_t pci_phys_mem_access_prot(struct file *file, - unsigned long pfn, - unsigned long size, - pgprot_t protection) -{ - struct pci_dev *pdev = NULL; - struct resource *found = NULL; - unsigned long prot = pgprot_val(protection); - unsigned long offset = pfn << PAGE_SHIFT; - int i; - - if (page_is_ram(pfn)) - return prot; - - prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; - - for_each_pci_dev(pdev) { - for (i = 0; i <= PCI_ROM_RESOURCE; i++) { - struct resource *rp = &pdev->resource[i]; - int flags = rp->flags; - - /* Active and same type? */ - if ((flags & IORESOURCE_MEM) == 0) - continue; - /* In the range of this resource? */ - if (offset < (rp->start & PAGE_MASK) || - offset > rp->end) - continue; - found = rp; - break; - } - if (found) - break; - } - if (found) { - if (found->flags & IORESOURCE_PREFETCH) - prot &= ~_PAGE_GUARDED; - pci_dev_put(pdev); - } - - DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); - - return __pgprot(prot); -} - - -/* - * Perform the actual remap of the pages for a PCI device mapping, as - * appropriate for this architecture. The region in the process to map - * is described by vm_start and vm_end members of VMA, the base physical - * address is found in vm_pgoff. - * The pci device structure is provided so that architectures may make mapping - * decisions on a per-device or per-bus basis. - * - * Returns a negative error code on failure, zero on success. - */ -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 offset = vma->vm_pgoff << PAGE_SHIFT; - struct resource *rp; - int ret; - - rp = __pci_mmap_make_offset(dev, &offset, mmap_state); - if (rp == NULL) - return -EINVAL; - - vma->vm_pgoff = offset >> PAGE_SHIFT; - vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO; - vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, - vma->vm_page_prot, - mmap_state, write_combine); - - ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - vma->vm_end - vma->vm_start, vma->vm_page_prot); - - return ret; -} - -/* Obsolete functions. Should be removed once the symbios driver - * is fixed - */ -unsigned long -phys_to_bus(unsigned long pa) -{ - struct pci_controller *hose; - int i; - - for (hose = hose_head; hose; hose = hose->next) { - for (i = 0; i < 3; ++i) { - if (pa >= hose->mem_resources[i].start - && pa <= hose->mem_resources[i].end) { - /* - * XXX the hose->pci_mem_offset really - * only applies to mem_resources[0]. - * We need a way to store an offset for - * the others. -- paulus - */ - if (i == 0) - pa -= hose->pci_mem_offset; - return pa; - } - } - } - /* hmmm, didn't find it */ - return 0; -} - -unsigned long -pci_phys_to_bus(unsigned long pa, int busnr) -{ - struct pci_controller* hose = pci_bus_to_hose(busnr); - if (!hose) - return pa; - return pa - hose->pci_mem_offset; -} - -unsigned long -pci_bus_to_phys(unsigned int ba, int busnr) -{ - struct pci_controller* hose = pci_bus_to_hose(busnr); - if (!hose) - return ba; - return ba + hose->pci_mem_offset; -} - -/* Provide information on locations of various I/O regions in physical - * memory. Do this on a per-card basis so that we choose the right - * root bridge. - * Note that the returned IO or memory base is a physical address - */ - -long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) -{ - struct pci_controller* hose; - long result = -EOPNOTSUPP; - - /* Argh ! Please forgive me for that hack, but that's the - * simplest way to get existing XFree to not lockup on some - * G5 machines... So when something asks for bus 0 io base - * (bus 0 is HT root), we return the AGP one instead. - */ -#ifdef CONFIG_PPC_PMAC - if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4")) - if (bus == 0) - bus = 0xf0; -#endif /* CONFIG_PPC_PMAC */ - - hose = pci_bus_to_hose(bus); - if (!hose) - return -ENODEV; - - switch (which) { - case IOBASE_BRIDGE_NUMBER: - return (long)hose->first_busno; - case IOBASE_MEMORY: - return (long)hose->pci_mem_offset; - case IOBASE_IO: - return (long)hose->io_base_phys; - case IOBASE_ISA_IO: - return (long)isa_io_base; - case IOBASE_ISA_MEM: - return (long)isa_mem_base; - } - - return result; -} - -void pci_resource_to_user(const struct pci_dev *dev, int bar, - const struct resource *rsrc, - u64 *start, u64 *end) -{ - struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); - unsigned long offset = 0; - - if (hose == NULL) - return; - - if (rsrc->flags & IORESOURCE_IO) - offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys; - - *start = rsrc->start + offset; - *end = rsrc->end + offset; -} - -void __init -pci_init_resource(struct resource *res, unsigned long start, unsigned long end, - int flags, char *name) -{ - res->start = start; - res->end = end; - res->flags = flags; - res->name = name; - res->parent = NULL; - res->sibling = NULL; - res->child = NULL; -} - -void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max) -{ - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); - unsigned long flags = pci_resource_flags(dev, bar); - - if (!len) - return NULL; - if (max && len > max) - len = max; - if (flags & IORESOURCE_IO) - return ioport_map(start, len); - if (flags & IORESOURCE_MEM) - /* Not checking IORESOURCE_CACHEABLE because PPC does - * not currently distinguish between ioremap and - * ioremap_nocache. - */ - return ioremap(start, len); - /* What? */ - return NULL; -} - -void pci_iounmap(struct pci_dev *dev, void __iomem *addr) -{ - /* Nothing to do */ -} -EXPORT_SYMBOL(pci_iomap); -EXPORT_SYMBOL(pci_iounmap); - -unsigned long pci_address_to_pio(phys_addr_t address) -{ - struct pci_controller* hose = hose_head; - - for (; hose; hose = hose->next) { - unsigned int size = hose->io_resource.end - - hose->io_resource.start + 1; - if (address >= hose->io_base_phys && - address < (hose->io_base_phys + size)) { - unsigned long base = - (unsigned long)hose->io_base_virt - _IO_BASE; - return base + (address - hose->io_base_phys); - } - } - return (unsigned int)-1; -} -EXPORT_SYMBOL(pci_address_to_pio); - -/* - * Null PCI config access functions, for the case when we can't - * find a hose. - */ -#define NULL_PCI_OP(rw, size, type) \ -static int \ -null_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \ -{ \ - return PCIBIOS_DEVICE_NOT_FOUND; \ -} - -static int -null_read_config(struct pci_bus *bus, unsigned int devfn, int offset, - int len, u32 *val) -{ - return PCIBIOS_DEVICE_NOT_FOUND; -} - -static int -null_write_config(struct pci_bus *bus, unsigned int devfn, int offset, - int len, u32 val) -{ - return PCIBIOS_DEVICE_NOT_FOUND; -} - -static struct pci_ops null_pci_ops = -{ - null_read_config, - null_write_config -}; - -/* - * These functions are used early on before PCI scanning is done - * and all of the pci_dev and pci_bus structures have been created. - */ -static struct pci_bus * -fake_pci_bus(struct pci_controller *hose, int busnr) -{ - static struct pci_bus bus; - - if (hose == 0) { - hose = pci_bus_to_hose(busnr); - if (hose == 0) - printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr); - } - bus.number = busnr; - bus.sysdata = hose; - bus.ops = hose? hose->ops: &null_pci_ops; - return &bus; -} - -#define EARLY_PCI_OP(rw, size, type) \ -int early_##rw##_config_##size(struct pci_controller *hose, int bus, \ - int devfn, int offset, type value) \ -{ \ - return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus), \ - devfn, offset, value); \ -} - -EARLY_PCI_OP(read, byte, u8 *) -EARLY_PCI_OP(read, word, u16 *) -EARLY_PCI_OP(read, dword, u32 *) -EARLY_PCI_OP(write, byte, u8) -EARLY_PCI_OP(write, word, u16) -EARLY_PCI_OP(write, dword, u32) diff --git a/trunk/arch/powerpc/kernel/prom_init.c b/trunk/arch/powerpc/kernel/prom_init.c index 7881ec96ef11..d963a12ec640 100644 --- a/trunk/arch/powerpc/kernel/prom_init.c +++ b/trunk/arch/powerpc/kernel/prom_init.c @@ -605,8 +605,7 @@ static void __init early_cmdline_parse(void) opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel=")); if (opt) { opt += 12; - RELOC(prom_crashk_size) = - prom_memparse(opt, (const char **)&opt); + RELOC(prom_crashk_size) = prom_memparse(opt, &opt); if (ALIGN(RELOC(prom_crashk_size), 0x1000000) != RELOC(prom_crashk_size)) { diff --git a/trunk/arch/powerpc/platforms/maple/pci.c b/trunk/arch/powerpc/platforms/maple/pci.c index 7d4099a34f92..f40451da037c 100644 --- a/trunk/arch/powerpc/platforms/maple/pci.c +++ b/trunk/arch/powerpc/platforms/maple/pci.c @@ -316,6 +316,7 @@ static int __init add_bridge(struct device_node *dev) char* disp_name; int *bus_range; int primary = 1; + struct property *of_prop; DBG("Adding PCI host bridge %s\n", dev->full_name); diff --git a/trunk/arch/powerpc/platforms/maple/setup.c b/trunk/arch/powerpc/platforms/maple/setup.c index ec5c1e10c407..a1cb4d236720 100644 --- a/trunk/arch/powerpc/platforms/maple/setup.c +++ b/trunk/arch/powerpc/platforms/maple/setup.c @@ -71,60 +71,38 @@ #define DBG(fmt...) #endif -static unsigned long maple_find_nvram_base(void) -{ - struct device_node *rtcs; - unsigned long result = 0; - - /* find NVRAM device */ - rtcs = of_find_compatible_node(NULL, "nvram", "AMD8111"); - if (rtcs) { - struct resource r; - if (of_address_to_resource(rtcs, 0, &r)) { - printk(KERN_EMERG "Maple: Unable to translate NVRAM" - " address\n"); - goto bail; - } - if (!(r.flags & IORESOURCE_IO)) { - printk(KERN_EMERG "Maple: NVRAM address isn't PIO!\n"); - goto bail; - } - result = r.start; - } else - printk(KERN_EMERG "Maple: Unable to find NVRAM\n"); - bail: - of_node_put(rtcs); - return result; -} - static void maple_restart(char *cmd) { unsigned int maple_nvram_base; unsigned int maple_nvram_offset; unsigned int maple_nvram_command; - struct device_node *sp; + struct device_node *rtcs; - maple_nvram_base = maple_find_nvram_base(); - if (maple_nvram_base == 0) - goto fail; + /* find NVRAM device */ + rtcs = find_compatible_devices("nvram", "AMD8111"); + if (rtcs && rtcs->addrs) { + maple_nvram_base = rtcs->addrs[0].address; + } else { + printk(KERN_EMERG "Maple: Unable to find NVRAM\n"); + printk(KERN_EMERG "Maple: Manual Restart Required\n"); + return; + } /* find service processor device */ - sp = of_find_node_by_name(NULL, "service-processor"); - if (!sp) { + rtcs = find_devices("service-processor"); + if (!rtcs) { printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); - goto fail; + printk(KERN_EMERG "Maple: Manual Restart Required\n"); + return; } - maple_nvram_offset = *(unsigned int*) get_property(sp, + maple_nvram_offset = *(unsigned int*) get_property(rtcs, "restart-addr", NULL); - maple_nvram_command = *(unsigned int*) get_property(sp, + maple_nvram_command = *(unsigned int*) get_property(rtcs, "restart-value", NULL); - of_node_put(sp); /* send command */ outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset); for (;;) ; - fail: - printk(KERN_EMERG "Maple: Manual Restart Required\n"); } static void maple_power_off(void) @@ -132,29 +110,33 @@ static void maple_power_off(void) unsigned int maple_nvram_base; unsigned int maple_nvram_offset; unsigned int maple_nvram_command; - struct device_node *sp; + struct device_node *rtcs; - maple_nvram_base = maple_find_nvram_base(); - if (maple_nvram_base == 0) - goto fail; + /* find NVRAM device */ + rtcs = find_compatible_devices("nvram", "AMD8111"); + if (rtcs && rtcs->addrs) { + maple_nvram_base = rtcs->addrs[0].address; + } else { + printk(KERN_EMERG "Maple: Unable to find NVRAM\n"); + printk(KERN_EMERG "Maple: Manual Power-Down Required\n"); + return; + } /* find service processor device */ - sp = of_find_node_by_name(NULL, "service-processor"); - if (!sp) { + rtcs = find_devices("service-processor"); + if (!rtcs) { printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); - goto fail; + printk(KERN_EMERG "Maple: Manual Power-Down Required\n"); + return; } - maple_nvram_offset = *(unsigned int*) get_property(sp, + maple_nvram_offset = *(unsigned int*) get_property(rtcs, "power-off-addr", NULL); - maple_nvram_command = *(unsigned int*) get_property(sp, + maple_nvram_command = *(unsigned int*) get_property(rtcs, "power-off-value", NULL); - of_node_put(sp); /* send command */ outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset); for (;;) ; - fail: - printk(KERN_EMERG "Maple: Manual Power-Down Required\n"); } static void maple_halt(void) @@ -197,6 +179,9 @@ void __init maple_setup_arch(void) */ static void __init maple_init_early(void) { + unsigned int default_speed; + u64 physport; + DBG(" -> maple_init_early\n"); /* Initialize hash table, from now on, we can take hash faults diff --git a/trunk/arch/powerpc/platforms/maple/time.c b/trunk/arch/powerpc/platforms/maple/time.c index 50bc4eb85353..15846cc938ac 100644 --- a/trunk/arch/powerpc/platforms/maple/time.c +++ b/trunk/arch/powerpc/platforms/maple/time.c @@ -168,24 +168,11 @@ unsigned long __init maple_get_boot_time(void) struct rtc_time tm; struct device_node *rtcs; - rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00"); - if (rtcs) { - struct resource r; - if (of_address_to_resource(rtcs, 0, &r)) { - printk(KERN_EMERG "Maple: Unable to translate RTC" - " address\n"); - goto bail; - } - if (!(r.flags & IORESOURCE_IO)) { - printk(KERN_EMERG "Maple: RTC address isn't PIO!\n"); - goto bail; - } - maple_rtc_addr = r.start; - printk(KERN_INFO "Maple: Found RTC at IO 0x%x\n", - maple_rtc_addr); - } - bail: - if (maple_rtc_addr == 0) { + rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); + if (rtcs && rtcs->addrs) { + maple_rtc_addr = rtcs->addrs[0].address; + printk(KERN_INFO "Maple: Found RTC at 0x%x\n", maple_rtc_addr); + } else { maple_rtc_addr = RTC_PORT(0); /* legacy address */ printk(KERN_INFO "Maple: No device node for RTC, assuming " "legacy address (0x%x)\n", maple_rtc_addr); diff --git a/trunk/arch/ppc/Kconfig b/trunk/arch/ppc/Kconfig index 11899f06bf06..d65810108bc3 100644 --- a/trunk/arch/ppc/Kconfig +++ b/trunk/arch/ppc/Kconfig @@ -58,11 +58,11 @@ config 6xx help There are four types of PowerPC chips supported. The more common types (601, 603, 604, 740, 750, 7400), the Motorola embedded - versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM - embedded versions (403 and 405) and the POWER3 processor. - (For support for more recent 64-bit processors, set ARCH=powerpc.) + versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM embedded + versions (403 and 405) and the high end 64 bit Power processors + (POWER 3, POWER4, and IBM 970 also known as G5) Unless you are building a kernel for one of the embedded processor - systems or a POWER3-based IBM RS/6000, choose 6xx. + systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx. Note that the kernel runs in 32-bit mode even on 64-bit chips. Also note that because the 52xx, 82xx, & 83xx family has a 603e core, specific support for that chipset is asked later on. @@ -77,6 +77,10 @@ config POWER3 select PPC_FPU bool "POWER3" +config POWER4 + select PPC_FPU + bool "POWER4 and 970 (G5)" + config 8xx bool "8xx" @@ -119,7 +123,7 @@ config PHYS_64BIT config ALTIVEC bool "AltiVec Support" - depends on 6xx + depends on 6xx || POWER4 depends on !8260 && !83xx ---help--- This option enables kernel support for the Altivec extensions to the @@ -231,9 +235,18 @@ config KEXEC source "drivers/cpufreq/Kconfig" +config CPU_FREQ_PMAC + bool "Support for Apple PowerBooks" + depends on CPU_FREQ && ADB_PMU + select CPU_FREQ_TABLE + help + This adds support for frequency switching on Apple PowerBooks, + this currently includes some models of iBook & Titanium + PowerBook. + config PPC601_SYNC_FIX bool "Workarounds for PPC601 bugs" - depends on 6xx && PPC_PREP + depends on 6xx && (PPC_PREP || PPC_PMAC) help Some versions of the PPC601 (the first PowerPC chip) have bugs which mean that extra synchronization instructions are required near @@ -245,17 +258,26 @@ config PPC601_SYNC_FIX If in doubt, say Y here. +config HOTPLUG_CPU + bool "Support for enabling/disabling CPUs" + depends on SMP && HOTPLUG && EXPERIMENTAL && PPC_PMAC + ---help--- + Say Y here to be able to disable and re-enable individual + CPUs at runtime on SMP machines. + + Say N if you are unsure. + source arch/ppc/platforms/4xx/Kconfig source arch/ppc/platforms/85xx/Kconfig config PPC64BRIDGE bool - depends on POWER3 + depends on POWER3 || POWER4 default y config PPC_STD_MMU bool - depends on 6xx || POWER3 + depends on 6xx || POWER3 || POWER4 default y config NOT_COHERENT_CACHE @@ -483,7 +505,7 @@ endchoice choice prompt "Machine Type" - depends on 6xx || POWER3 + depends on 6xx || POWER3 || POWER4 default PPC_MULTIPLATFORM ---help--- Linux currently supports several different kinds of PowerPC-based @@ -494,15 +516,11 @@ choice Platform) machines (including all of the recent IBM RS/6000 and pSeries machines), and several embedded PowerPC systems containing 4xx, 6xx, 7xx, 8xx, 74xx, and 82xx processors. Currently, the - default option is to build a kernel which works on PReP and CHRP. + default option is to build a kernel which works on the first three. - Note that support for Apple machines is now only available with - ARCH=powerpc, and has been removed from this menu. If you wish - to build a kernel for an Apple machine, exit this configuration - process and re-run it with ARCH=powerpc. - - Select CHRP/PReP if configuring for an IBM RS/6000 or - pSeries machine, or a PReP machine. + Select CHRP/PowerMac/PReP if configuring for an IBM RS/6000 or + pSeries machine, a Power Macintosh (including iMacs, iBooks and + Powerbooks), or a PReP machine. Select Gemini if configuring for a Synergy Microsystems' Gemini series Single Board Computer. More information is available at: @@ -512,7 +530,7 @@ choice available at: . config PPC_MULTIPLATFORM - bool "CHRP/PReP" + bool "CHRP/PowerMac/PReP" config APUS bool "Amiga-APUS" @@ -750,14 +768,25 @@ config CPM2 on it (826x, 827x, 8560). config PPC_CHRP - bool "Support for CHRP (Common Hardware Reference Platform) machines" + bool depends on PPC_MULTIPLATFORM select PPC_I8259 select PPC_INDIRECT_PCI default y +config PPC_PMAC + bool + depends on PPC_MULTIPLATFORM + select PPC_INDIRECT_PCI + default y + +config PPC_PMAC64 + bool + depends on PPC_PMAC && POWER4 + default y + config PPC_PREP - bool "Support for PReP (PowerPC Reference Platform) machines" + bool depends on PPC_MULTIPLATFORM select PPC_I8259 select PPC_INDIRECT_PCI @@ -765,7 +794,7 @@ config PPC_PREP config PPC_OF bool - depends on PPC_CHRP + depends on PPC_PMAC || PPC_CHRP default y config PPC_GEN550 @@ -1137,7 +1166,7 @@ config ISA config GENERIC_ISA_DMA bool - depends on POWER3 || 6xx && !CPM2 + depends on POWER3 || POWER4 || 6xx && !CPM2 default y config PPC_I8259 diff --git a/trunk/arch/ppc/boot/Makefile b/trunk/arch/ppc/boot/Makefile index efd8ce515d5f..995f89bb049c 100644 --- a/trunk/arch/ppc/boot/Makefile +++ b/trunk/arch/ppc/boot/Makefile @@ -18,7 +18,7 @@ BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd bootdir-y := simple bootdir-$(CONFIG_PPC_OF) += openfirmware subdir-y := lib common images -subdir-$(CONFIG_PPC_MULTIPLATFORM) += of1275 +subdir-$(CONFIG_PPC_OF) += of1275 # for cleaning subdir- += simple openfirmware diff --git a/trunk/arch/ppc/boot/openfirmware/Makefile b/trunk/arch/ppc/boot/openfirmware/Makefile index 2a411ec2e650..83a6433459ce 100644 --- a/trunk/arch/ppc/boot/openfirmware/Makefile +++ b/trunk/arch/ppc/boot/openfirmware/Makefile @@ -21,16 +21,26 @@ bootlib := $(boot)/lib of1275 := $(boot)/of1275 images := $(boot)/images +OBJCOPY_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment +COFF_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00500000 \ + -Bstatic CHRP_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00800000 +NEWWORLD_LD_ARGS:= -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x01000000 COMMONOBJS := start.o misc.o common.o +COFFOBJS := coffcrt0.o $(COMMONOBJS) coffmain.o CHRPOBJS := crt0.o $(COMMONOBJS) chrpmain.o +NEWWORLDOBJS := crt0.o $(COMMONOBJS) newworldmain.o -targets := $(CHRPOBJS) dummy.o +targets := $(COFFOBJS) $(CHRPOBJS) $(NEWWORLDOBJS) dummy.o +COFFOBJS := $(addprefix $(obj)/, $(COFFOBJS)) CHRPOBJS := $(addprefix $(obj)/, $(CHRPOBJS)) +NEWWORLDOBJS := $(addprefix $(obj)/, $(NEWWORLDOBJS)) LIBS := lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a +HACKCOFF := $(utils)/hack-coff + ifdef CONFIG_SMP END := .smp endif @@ -62,11 +72,56 @@ targets += image.initrd.o $(obj)/image.initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz FORCE $(call if_changed,genimage-initrd) +# Create the note section for New-World PowerMacs. +quiet_cmd_mknote = MKNOTE $@ + cmd_mknote = $(utils)/mknote > $@ +targets += note +$(obj)/note: $(utils)/mknote FORCE + $(call if_changed,mknote) + -targets += crt0.o -$(obj)/crt0.o: $(common)/crt0.S FORCE +$(obj)/coffcrt0.o: EXTRA_AFLAGS := -DXCOFF +targets += coffcrt0.o crt0.o +$(obj)/coffcrt0.o $(obj)/crt0.o: $(common)/crt0.S FORCE $(call if_changed_dep,as_o_S) +quiet_cmd_gencoffb = COFF $@ + cmd_gencoffb = $(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) $< $(LIBS) && \ + $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec) +targets += coffboot +$(obj)/coffboot: $(obj)/image.o $(COFFOBJS) $(LIBS) $(srctree)/$(boot)/ld.script FORCE + $(call if_changed,gencoffb) +targets += coffboot.initrd +$(obj)/coffboot.initrd: $(obj)/image.initrd.o $(COFFOBJS) $(LIBS) \ + $(srctree)/$(boot)/ld.script FORCE + $(call if_changed,gencoffb) + + +quiet_cmd_gen-coff = COFF $@ + cmd_gen-coff = $(OBJCOPY) $(OBJCOPY_ARGS) $< $@ && \ + $(HACKCOFF) $@ && \ + ln -sf $(notdir $@) $(images)/zImage$(initrd).pmac + +$(images)/vmlinux.coff: $(obj)/coffboot + $(call cmd,gen-coff) + +$(images)/vmlinux.initrd.coff: $(obj)/coffboot.initrd + $(call cmd,gen-coff) + +quiet_cmd_gen-elf-pmac = ELF $@ + cmd_gen-elf-pmac = $(LD) $(NEWWORLD_LD_ARGS) -o $@ \ + $(NEWWORLDOBJS) $(LIBS) $< && \ + $(OBJCOPY) $@ $@ --add-section=.note=$(obj)/note \ + -R .comment $(del-ramdisk-sec) + +$(images)/vmlinux.elf-pmac: $(obj)/image.o $(NEWWORLDOBJS) $(LIBS) \ + $(obj)/note $(srctree)/$(boot)/ld.script + $(call cmd,gen-elf-pmac) +$(images)/vmlinux.initrd.elf-pmac: $(obj)/image.initrd.o $(NEWWORLDOBJS) \ + $(LIBS) $(obj)/note \ + $(srctree)/$(boot)/ld.script + $(call cmd,gen-elf-pmac) + quiet_cmd_gen-chrp = CHRP $@ cmd_gen-chrp = $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) $< $(LIBS) && \ $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec) @@ -84,23 +139,46 @@ $(images)/zImage.chrp-rs6k $(images)/zImage.initrd.chrp-rs6k: \ %-rs6k: % $(call cmd,addnote) +quiet_cmd_gen-miboot = GEN $@ + cmd_gen-miboot = $(OBJCOPY) $(OBJCOPY_ARGS) \ + --add-section=$1=$(word 2, $^) $< $@ +$(images)/miboot.image: $(obj)/dummy.o $(images)/vmlinux.gz + $(call cmd,gen-miboot,image) + +$(images)/miboot.initrd.image: $(images)/miboot.image $(images)/ramdisk.image.gz + $(call cmd,gen-miboot,initrd) + # The targets used on the make command-line .PHONY: zImage zImage.initrd -zImage: $(images)/zImage.chrp \ - $(images)/zImage.chrp-rs6k +zImage: $(images)/vmlinux.coff \ + $(images)/vmlinux.elf-pmac \ + $(images)/zImage.chrp \ + $(images)/zImage.chrp-rs6k \ + $(images)/miboot.image @echo ' kernel: $@ is ready ($<)' -zImage.initrd: $(images)/zImage.initrd.chrp \ - $(images)/zImage.initrd.chrp-rs6k +zImage.initrd: $(images)/vmlinux.initrd.coff \ + $(images)/vmlinux.initrd.elf-pmac \ + $(images)/zImage.initrd.chrp \ + $(images)/zImage.initrd.chrp-rs6k \ + $(images)/miboot.initrd.image @echo ' kernel: $@ is ready ($<)' TFTPIMAGE := /tftpboot/zImage .PHONY: znetboot znetboot.initrd -znetboot: $(images)/zImage.chrp +znetboot: $(images)/vmlinux.coff \ + $(images)/vmlinux.elf-pmac \ + $(images)/zImage.chrp + cp $(images)/vmlinux.coff $(TFTPIMAGE).pmac$(END) + cp $(images)/vmlinux.elf-pmac $(TFTPIMAGE).pmac$(END).elf cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END) @echo ' kernel: $@ is ready ($<)' -znetboot.initrd:$(images)/zImage.initrd.chrp +znetboot.initrd:$(images)/vmlinux.initrd.coff \ + $(images)/vmlinux.initrd.elf-pmac \ + $(images)/zImage.initrd.chrp + cp $(images)/vmlinux.initrd.coff $(TFTPIMAGE).pmac$(END) + cp $(images)/vmlinux.initrd.elf-pmac $(TFTPIMAGE).pmac$(END).elf cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END) @echo ' kernel: $@ is ready ($<)' diff --git a/trunk/arch/ppc/boot/openfirmware/coffmain.c b/trunk/arch/ppc/boot/openfirmware/coffmain.c new file mode 100644 index 000000000000..2da8855e2be0 --- /dev/null +++ b/trunk/arch/ppc/boot/openfirmware/coffmain.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) Paul Mackerras 1997. + * + * 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; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include + +#include "nonstdio.h" +#include "of1275.h" + +/* Passed from the linker */ +extern char __image_begin, __image_end; +extern char __ramdisk_begin[], __ramdisk_end; +extern char _start, _end; + +extern char image_data[], initrd_data[]; +extern int initrd_len, image_len; +extern unsigned int heap_max; +extern void flush_cache(void *start, unsigned int len); +extern void gunzip(void *, int, unsigned char *, int *); +extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, + unsigned int progend); +extern void setup_bats(unsigned long start); + +char *avail_ram; +char *begin_avail, *end_avail; +char *avail_high; + +#define SCRATCH_SIZE (128 << 10) + +static char heap[SCRATCH_SIZE]; + +static unsigned long ram_start = 0; +static unsigned long ram_end = 0x1000000; + +static unsigned long prog_start = 0x800000; +static unsigned long prog_size = 0x700000; + +typedef void (*kernel_start_t)(int, int, void *); + +void boot(int a1, int a2, void *prom) +{ + unsigned sa, len; + void *dst; + unsigned char *im; + unsigned initrd_start, initrd_size; + + printf("coffboot starting: loaded at 0x%p\n", &_start); + setup_bats(ram_start); + + initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin); + if (initrd_size) { + initrd_start = (ram_end - initrd_size) & ~0xFFF; + a1 = initrd_start; + a2 = initrd_size; + claim(initrd_start, ram_end - initrd_start, 0); + printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r", + initrd_start, (char *)(&__ramdisk_begin), initrd_size); + memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size); + prog_size = initrd_start - prog_start; + } else + a2 = 0xdeadbeef; + + im = (char *)(&__image_begin); + len = (char *)(&__image_end) - (char *)(&__image_begin); + /* claim 4MB starting at PROG_START */ + claim(prog_start, prog_size, 0); + map(prog_start, prog_start, prog_size); + dst = (void *) prog_start; + if (im[0] == 0x1f && im[1] == 0x8b) { + /* set up scratch space */ + begin_avail = avail_high = avail_ram = heap; + end_avail = heap + sizeof(heap); + printf("heap at 0x%p\n", avail_ram); + printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); + gunzip(dst, prog_size, im, &len); + printf("done %u bytes\n", len); + printf("%u bytes of heap consumed, max in use %u\n", + avail_high - begin_avail, heap_max); + } else { + memmove(dst, im, len); + } + + flush_cache(dst, len); + make_bi_recs(((unsigned long) dst + len), "coffboot", _MACH_Pmac, + (prog_start + prog_size)); + + sa = (unsigned long)prog_start; + printf("start address = 0x%x\n", sa); + + (*(kernel_start_t)sa)(a1, a2, prom); + + printf("returned?\n"); + + pause(); +} diff --git a/trunk/arch/ppc/boot/openfirmware/newworldmain.c b/trunk/arch/ppc/boot/openfirmware/newworldmain.c new file mode 100644 index 000000000000..fa8a8f9313f9 --- /dev/null +++ b/trunk/arch/ppc/boot/openfirmware/newworldmain.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) Paul Mackerras 1997. + * + * 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; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include "nonstdio.h" +#include "of1275.h" +#include +#include + +/* Passed from the linker */ +extern char __image_begin, __image_end; +extern char __ramdisk_begin[], __ramdisk_end; +extern char _start, _end; + +extern unsigned int heap_max; +extern void flush_cache(void *start, unsigned int len); +extern void gunzip(void *, int, unsigned char *, int *); +extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, + unsigned int progend); + +char *avail_ram; +char *begin_avail, *end_avail; +char *avail_high; + + +#define RAM_END (16 << 20) + +#define PROG_START 0x00010000 +#define PROG_SIZE 0x007f0000 + +#define SCRATCH_SIZE (128 << 10) + +typedef void (*kernel_start_t)(int, int, void *); + +void boot(int a1, int a2, void *prom) +{ + unsigned sa, len; + void *dst; + unsigned char *im; + unsigned initrd_start, initrd_size; + + printf("chrpboot starting: loaded at 0x%p\n", &_start); + + initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin); + if (initrd_size) { + initrd_start = (RAM_END - initrd_size) & ~0xFFF; + a1 = initrd_start; + a2 = initrd_size; + claim(initrd_start, RAM_END - initrd_start, 0); + printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r", + initrd_start, (char *)(&__ramdisk_begin), initrd_size); + memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size); + } else + a2 = 0xdeadbeef; + + im = (char *)(&__image_begin); + len = (char *)(&__image_end) - (char *)(&__image_begin); + /* claim 3MB starting at PROG_START */ + claim(PROG_START, PROG_SIZE, 0); + dst = (void *) PROG_START; + if (im[0] == 0x1f && im[1] == 0x8b) { + /* claim some memory for scratch space */ + avail_ram = (char *) claim(0, SCRATCH_SIZE, 0x10); + begin_avail = avail_high = avail_ram; + end_avail = avail_ram + SCRATCH_SIZE; + printf("heap at 0x%p\n", avail_ram); + printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); + gunzip(dst, PROG_SIZE, im, &len); + printf("done %u bytes\n", len); + printf("%u bytes of heap consumed, max in use %u\n", + avail_high - begin_avail, heap_max); + release(begin_avail, SCRATCH_SIZE); + } else { + memmove(dst, im, len); + } + + flush_cache(dst, len); + make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_Pmac, + (PROG_START + PROG_SIZE)); + + sa = (unsigned long)PROG_START; + printf("start address = 0x%x\n", sa); + + (*(kernel_start_t)sa)(a1, a2, prom); + + printf("returned?\n"); + + pause(); +} diff --git a/trunk/arch/ppc/kernel/Makefile b/trunk/arch/ppc/kernel/Makefile index e399bbb969a4..ca0201300868 100644 --- a/trunk/arch/ppc/kernel/Makefile +++ b/trunk/arch/ppc/kernel/Makefile @@ -9,6 +9,7 @@ extra-$(CONFIG_44x) := head_44x.o extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o extra-$(CONFIG_8xx) := head_8xx.o extra-$(CONFIG_6xx) += idle_6xx.o +extra-$(CONFIG_POWER4) += idle_power4.o extra-y += vmlinux.lds obj-y := entry.o traps.o idle.o time.o misc.o \ @@ -16,6 +17,7 @@ obj-y := entry.o traps.o idle.o time.o misc.o \ ppc_htab.o obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o +obj-$(CONFIG_POWER4) += cpu_setup_power4.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o obj-$(CONFIG_PCI) += pci.o @@ -40,6 +42,7 @@ obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o +obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_KGDB) += ppc-stub.o obj-$(CONFIG_TAU) += temp.o ifndef CONFIG_E200 diff --git a/trunk/arch/ppc/kernel/misc.S b/trunk/arch/ppc/kernel/misc.S index c3427eed8345..fb5658bba285 100644 --- a/trunk/arch/ppc/kernel/misc.S +++ b/trunk/arch/ppc/kernel/misc.S @@ -204,6 +204,78 @@ _GLOBAL(call_setup_cpu) mtctr r5 bctr +#if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx) + +/* This gets called by via-pmu.c to switch the PLL selection + * on 750fx CPU. This function should really be moved to some + * other place (as most of the cpufreq code in via-pmu + */ +_GLOBAL(low_choose_750fx_pll) + /* Clear MSR:EE */ + mfmsr r7 + rlwinm r0,r7,0,17,15 + mtmsr r0 + + /* If switching to PLL1, disable HID0:BTIC */ + cmplwi cr0,r3,0 + beq 1f + mfspr r5,SPRN_HID0 + rlwinm r5,r5,0,27,25 + sync + mtspr SPRN_HID0,r5 + isync + sync + +1: + /* Calc new HID1 value */ + mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */ + rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */ + rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */ + or r4,r4,r5 + mtspr SPRN_HID1,r4 + + /* Store new HID1 image */ + rlwinm r6,r1,0,0,18 + lwz r6,TI_CPU(r6) + slwi r6,r6,2 + addis r6,r6,nap_save_hid1@ha + stw r4,nap_save_hid1@l(r6) + + /* If switching to PLL0, enable HID0:BTIC */ + cmplwi cr0,r3,0 + bne 1f + mfspr r5,SPRN_HID0 + ori r5,r5,HID0_BTIC + sync + mtspr SPRN_HID0,r5 + isync + sync + +1: + /* Return */ + mtmsr r7 + blr + +_GLOBAL(low_choose_7447a_dfs) + /* Clear MSR:EE */ + mfmsr r7 + rlwinm r0,r7,0,17,15 + mtmsr r0 + + /* Calc new HID1 value */ + mfspr r4,SPRN_HID1 + insrwi r4,r3,1,9 /* insert parameter into bit 9 */ + sync + mtspr SPRN_HID1,r4 + sync + isync + + /* Return */ + mtmsr r7 + blr + +#endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */ + /* * complement mask on the msr then "or" some values on. * _nmask_and_or_msr(nmask, value_to_or) diff --git a/trunk/arch/ppc/kernel/pci.c b/trunk/arch/ppc/kernel/pci.c index 04d04c5bfdd0..704c846b2b0f 100644 --- a/trunk/arch/ppc/kernel/pci.c +++ b/trunk/arch/ppc/kernel/pci.c @@ -1,5 +1,5 @@ /* - * Common prep/chrp pci routines. -- Cort + * Common pmac/prep/chrp pci routines. -- Cort */ #include @@ -50,7 +50,8 @@ static void fixup_cpc710_pci64(struct pci_dev* dev); static u8* pci_to_OF_bus_map; #endif -/* By default, we don't re-assign bus numbers. +/* By default, we don't re-assign bus numbers. We do this only on + * some pmacs */ int pci_assign_all_buses; @@ -779,6 +780,17 @@ pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) return NULL; /* Fixup bus number according to what OF think it is. */ +#ifdef CONFIG_PPC_PMAC + /* The G5 need a special case here. Basically, we don't remap all + * busses on it so we don't create the pci-OF-map. However, we do + * remap the AGP bus and so have to deal with it. A future better + * fix has to be done by making the remapping per-host and always + * filling the pci_to_OF map. --BenH + */ + if (_machine == _MACH_Pmac && busnr >= 0xf0) + busnr -= 0xf0; + else +#endif if (pci_to_OF_bus_map) busnr = pci_to_OF_bus_map[busnr]; if (busnr == 0xff) @@ -1028,6 +1040,216 @@ void pcibios_add_platform_entries(struct pci_dev *pdev) } +#ifdef CONFIG_PPC_PMAC +/* + * This set of routines checks for PCI<->PCI bridges that have closed + * IO resources and have child devices. It tries to re-open an IO + * window on them. + * + * This is a _temporary_ fix to workaround a problem with Apple's OF + * closing IO windows on P2P bridges when the OF drivers of cards + * below this bridge don't claim any IO range (typically ATI or + * Adaptec). + * + * A more complete fix would be to use drivers/pci/setup-bus.c, which + * involves a working pcibios_fixup_pbus_ranges(), some more care about + * ordering when creating the host bus resources, and maybe a few more + * minor tweaks + */ + +/* Initialize bridges with base/limit values we have collected */ +static void __init +do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga) +{ + struct pci_dev *bridge = bus->self; + struct pci_controller* hose = (struct pci_controller *)bridge->sysdata; + u32 l; + u16 w; + struct resource res; + + if (bus->resource[0] == NULL) + return; + res = *(bus->resource[0]); + + DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge)); + res.start -= ((unsigned long) hose->io_base_virt - isa_io_base); + res.end -= ((unsigned long) hose->io_base_virt - isa_io_base); + DBG(" IO window: %08lx-%08lx\n", res.start, res.end); + + /* Set up the top and bottom of the PCI I/O segment for this bus. */ + pci_read_config_dword(bridge, PCI_IO_BASE, &l); + l &= 0xffff000f; + l |= (res.start >> 8) & 0x00f0; + l |= res.end & 0xf000; + pci_write_config_dword(bridge, PCI_IO_BASE, l); + + if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { + l = (res.start >> 16) | (res.end & 0xffff0000); + pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l); + } + + pci_read_config_word(bridge, PCI_COMMAND, &w); + w |= PCI_COMMAND_IO; + pci_write_config_word(bridge, PCI_COMMAND, w); + +#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */ + if (enable_vga) { + pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w); + w |= PCI_BRIDGE_CTL_VGA; + pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w); + } +#endif +} + +/* This function is pretty basic and actually quite broken for the + * general case, it's enough for us right now though. It's supposed + * to tell us if we need to open an IO range at all or not and what + * size. + */ +static int __init +check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga) +{ + struct pci_dev *dev; + int i; + int rc = 0; + +#define push_end(res, size) do { unsigned long __sz = (size) ; \ + res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \ + } while (0) + + list_for_each_entry(dev, &bus->devices, bus_list) { + u16 class = dev->class >> 8; + + if (class == PCI_CLASS_DISPLAY_VGA || + class == PCI_CLASS_NOT_DEFINED_VGA) + *found_vga = 1; + if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate) + rc |= check_for_io_childs(dev->subordinate, res, found_vga); + if (class == PCI_CLASS_BRIDGE_CARDBUS) + push_end(res, 0xfff); + + for (i=0; iclass >> 8 == PCI_CLASS_BRIDGE_PCI + && i >= PCI_BRIDGE_RESOURCES) + continue; + r = &dev->resource[i]; + r_size = r->end - r->start; + if (r_size < 0xfff) + r_size = 0xfff; + if (r->flags & IORESOURCE_IO && (r_size) != 0) { + rc = 1; + push_end(res, r_size); + } + } + } + + return rc; +} + +/* Here we scan all P2P bridges of a given level that have a closed + * IO window. Note that the test for the presence of a VGA card should + * be improved to take into account already configured P2P bridges, + * currently, we don't see them and might end up configuring 2 bridges + * with VGA pass through enabled + */ +static void __init +do_fixup_p2p_level(struct pci_bus *bus) +{ + struct pci_bus *b; + int i, parent_io; + int has_vga = 0; + + for (parent_io=0; parent_io<4; parent_io++) + if (bus->resource[parent_io] + && bus->resource[parent_io]->flags & IORESOURCE_IO) + break; + if (parent_io >= 4) + return; + + list_for_each_entry(b, &bus->children, node) { + struct pci_dev *d = b->self; + struct pci_controller* hose = (struct pci_controller *)d->sysdata; + struct resource *res = b->resource[0]; + struct resource tmp_res; + unsigned long max; + int found_vga = 0; + + memset(&tmp_res, 0, sizeof(tmp_res)); + tmp_res.start = bus->resource[parent_io]->start; + + /* We don't let low addresses go through that closed P2P bridge, well, + * that may not be necessary but I feel safer that way + */ + if (tmp_res.start == 0) + tmp_res.start = 0x1000; + + if (!list_empty(&b->devices) && res && res->flags == 0 && + res != bus->resource[parent_io] && + (d->class >> 8) == PCI_CLASS_BRIDGE_PCI && + check_for_io_childs(b, &tmp_res, &found_vga)) { + u8 io_base_lo; + + printk(KERN_INFO "Fixing up IO bus %s\n", b->name); + + if (found_vga) { + if (has_vga) { + printk(KERN_WARNING "Skipping VGA, already active" + " on bus segment\n"); + found_vga = 0; + } else + has_vga = 1; + } + pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo); + + if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) + max = ((unsigned long) hose->io_base_virt + - isa_io_base) + 0xffffffff; + else + max = ((unsigned long) hose->io_base_virt + - isa_io_base) + 0xffff; + + *res = tmp_res; + res->flags = IORESOURCE_IO; + res->name = b->name; + + /* Find a resource in the parent where we can allocate */ + for (i = 0 ; i < 4; i++) { + struct resource *r = bus->resource[i]; + if (!r) + continue; + if ((r->flags & IORESOURCE_IO) == 0) + continue; + DBG("Trying to allocate from %08lx, size %08lx from parent" + " res %d: %08lx -> %08lx\n", + res->start, res->end, i, r->start, r->end); + + if (allocate_resource(r, res, res->end + 1, res->start, max, + res->end + 1, NULL, NULL) < 0) { + DBG("Failed !\n"); + continue; + } + do_update_p2p_io_resource(b, found_vga); + break; + } + } + do_fixup_p2p_level(b); + } +} + +static void +pcibios_fixup_p2p_bridges(void) +{ + struct pci_bus *b; + + list_for_each_entry(b, &pci_root_buses, node) + do_fixup_p2p_level(b); +} + +#endif /* CONFIG_PPC_PMAC */ + static int __init pcibios_init(void) { @@ -1068,6 +1290,9 @@ pcibios_init(void) pcibios_allocate_bus_resources(&pci_root_buses); pcibios_allocate_resources(0); pcibios_allocate_resources(1); +#ifdef CONFIG_PPC_PMAC + pcibios_fixup_p2p_bridges(); +#endif /* CONFIG_PPC_PMAC */ pcibios_assign_resources(); /* Call machine dependent post-init code */ @@ -1497,6 +1722,17 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) struct pci_controller* hose; long result = -EOPNOTSUPP; + /* Argh ! Please forgive me for that hack, but that's the + * simplest way to get existing XFree to not lockup on some + * G5 machines... So when something asks for bus 0 io base + * (bus 0 is HT root), we return the AGP one instead. + */ +#ifdef CONFIG_PPC_PMAC + if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4")) + if (bus == 0) + bus = 0xf0; +#endif /* CONFIG_PPC_PMAC */ + hose = pci_bus_to_hose(bus); if (!hose) return -ENODEV; diff --git a/trunk/arch/ppc/kernel/ppc_ksyms.c b/trunk/arch/ppc/kernel/ppc_ksyms.c index 3a6e4bcb3c53..fb0da7c209db 100644 --- a/trunk/arch/ppc/kernel/ppc_ksyms.c +++ b/trunk/arch/ppc/kernel/ppc_ksyms.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,7 @@ extern void machine_check_exception(struct pt_regs *regs); extern void alignment_exception(struct pt_regs *regs); extern void program_check_exception(struct pt_regs *regs); extern void single_step_exception(struct pt_regs *regs); +extern int pmac_newworld; extern int sys_sigreturn(struct pt_regs *regs); long long __ashrdi3(long long, int); @@ -211,6 +213,10 @@ EXPORT_SYMBOL(adb_try_handler_change); EXPORT_SYMBOL(cuda_request); EXPORT_SYMBOL(cuda_poll); #endif /* CONFIG_ADB_CUDA */ +#ifdef CONFIG_PPC_PMAC +EXPORT_SYMBOL(sys_ctrler); +EXPORT_SYMBOL(pmac_newworld); +#endif #ifdef CONFIG_PPC_OF EXPORT_SYMBOL(find_devices); EXPORT_SYMBOL(find_type_devices); @@ -235,6 +241,9 @@ EXPORT_SYMBOL(of_node_put); #if defined(CONFIG_BOOTX_TEXT) EXPORT_SYMBOL(btext_update_display); #endif +#if defined(CONFIG_SCSI) && defined(CONFIG_PPC_PMAC) +EXPORT_SYMBOL(note_scsi_host); +#endif #ifdef CONFIG_VT EXPORT_SYMBOL(kd_mksound); #endif diff --git a/trunk/arch/ppc/kernel/setup.c b/trunk/arch/ppc/kernel/setup.c index c08ab432e958..e707c6f6e61b 100644 --- a/trunk/arch/ppc/kernel/setup.c +++ b/trunk/arch/ppc/kernel/setup.c @@ -1,5 +1,5 @@ /* - * Common prep/chrp boot and setup code. + * Common prep/pmac/chrp boot and setup code. */ #include @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,7 @@ extern void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); +extern void bootx_init(unsigned long r4, unsigned long phys); extern void identify_cpu(unsigned long offset, unsigned long cpu); extern void do_cpu_ftr_fixups(unsigned long offset); extern void reloc_got2(unsigned long offset); @@ -78,6 +80,8 @@ EXPORT_SYMBOL(_machine); extern void prep_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); +extern void pmac_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7); extern void chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); @@ -320,15 +324,20 @@ early_init(int r3, int r4, int r5) identify_cpu(offset, 0); do_cpu_ftr_fixups(offset); -#if defined(CONFIG_PPC_OF) +#if defined(CONFIG_PPC_MULTIPLATFORM) reloc_got2(offset); + /* If we came here from BootX, clear the screen, + * set up some pointers and return. */ + if ((r3 == 0x426f6f58) && (r5 == 0)) + bootx_init(r4, phys); + /* * don't do anything on prep * for now, don't use bootinfo because it breaks yaboot 0.5 * and assume that if we didn't find a magic number, we have OF */ - if (*(unsigned long *)(0) != 0xdeadc0de) + else if (*(unsigned long *)(0) != 0xdeadc0de) phys = prom_init(r3, r4, (prom_entry)r5); reloc_got2(-offset); @@ -415,7 +424,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, } #endif -#ifdef CONFIG_PPC_OF have_of = 1; /* prom_init has already been called from __start */ @@ -487,17 +495,19 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, #endif /* CONFIG_ADB */ switch (_machine) { +#ifdef CONFIG_PPC_PMAC + case _MACH_Pmac: + pmac_init(r3, r4, r5, r6, r7); + break; +#endif #ifdef CONFIG_PPC_CHRP case _MACH_chrp: chrp_init(r3, r4, r5, r6, r7); break; #endif } -#endif /* CONFIG_PPC_OF */ } -#endif /* CONFIG_PPC_MULTIPLATFORM */ -#ifdef CONFIG_PPC_OF #ifdef CONFIG_SERIAL_CORE_CONSOLE extern char *of_stdout_device; @@ -554,7 +564,7 @@ static int __init set_preferred_console(void) } console_initcall(set_preferred_console); #endif /* CONFIG_SERIAL_CORE_CONSOLE */ -#endif /* CONFIG_PPC_OF */ +#endif /* CONFIG_PPC_MULTIPLATFORM */ struct bi_record *find_bootinfo(void) { @@ -737,6 +747,14 @@ void __init setup_arch(char **cmdline_p) if (ppc_md.init_early) ppc_md.init_early(); +#ifdef CONFIG_PPC_MULTIPLATFORM + /* This could be called "early setup arch", it must be done + * now because xmon need it + */ + if (_machine == _MACH_Pmac) + pmac_feature_init(); /* New cool way */ +#endif + #ifdef CONFIG_XMON xmon_init(1); if (strstr(cmd_line, "xmon")) diff --git a/trunk/arch/ppc/kernel/traps.c b/trunk/arch/ppc/kernel/traps.c index 6d0a1838d94c..9dbc4d28fa28 100644 --- a/trunk/arch/ppc/kernel/traps.c +++ b/trunk/arch/ppc/kernel/traps.c @@ -38,6 +38,9 @@ #include #include #include +#ifdef CONFIG_PMAC_BACKLIGHT +#include +#endif #include #ifdef CONFIG_XMON @@ -82,6 +85,12 @@ int die(const char * str, struct pt_regs * fp, long err) int nl = 0; console_verbose(); spin_lock_irq(&die_lock); +#ifdef CONFIG_PMAC_BACKLIGHT + if (_machine == _MACH_Pmac) { + set_backlight_enable(1); + set_backlight_level(BACKLIGHT_MAX); + } +#endif printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); #ifdef CONFIG_PREEMPT printk("PREEMPT "); @@ -150,7 +159,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) */ static inline int check_io_access(struct pt_regs *regs) { -#if defined CONFIG_8xx +#if defined CONFIG_PPC_PMAC || defined CONFIG_8xx unsigned long msr = regs->msr; const struct exception_table_entry *entry; unsigned int *nip = (unsigned int *)regs->nip; @@ -187,7 +196,7 @@ static inline int check_io_access(struct pt_regs *regs) return 1; } } -#endif /* CONFIG_8xx */ +#endif /* CONFIG_PPC_PMAC */ return 0; } diff --git a/trunk/arch/ppc/mm/init.c b/trunk/arch/ppc/mm/init.c index 134db5c04203..45f0782059f1 100644 --- a/trunk/arch/ppc/mm/init.c +++ b/trunk/arch/ppc/mm/init.c @@ -67,6 +67,10 @@ unsigned long ppc_memoffset = PAGE_OFFSET; int mem_init_done; int init_bootmem_done; int boot_mapsize; +#ifdef CONFIG_PPC_PMAC +unsigned long agp_special_page; +EXPORT_SYMBOL(agp_special_page); +#endif extern char _end[]; extern char etext[], _stext[]; @@ -419,6 +423,10 @@ void __init mem_init(void) addr < PAGE_ALIGN((ulong)__va(rtas_data)+rtas_size) ; addr += PAGE_SIZE) SetPageReserved(virt_to_page(addr)); +#endif +#ifdef CONFIG_PPC_PMAC + if (agp_special_page) + SetPageReserved(virt_to_page(agp_special_page)); #endif for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory; addr += PAGE_SIZE) { @@ -455,6 +463,11 @@ void __init mem_init(void) initpages<< (PAGE_SHIFT-10), (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); +#ifdef CONFIG_PPC_PMAC + if (agp_special_page) + printk(KERN_INFO "AGP special page: 0x%08lx\n", agp_special_page); +#endif + mem_init_done = 1; } @@ -499,6 +512,22 @@ set_phys_avail(unsigned long total_memory) if (rtas_data) mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1); #endif +#ifdef CONFIG_PPC_PMAC + /* Because of some uninorth weirdness, we need a page of + * memory as high as possible (it must be outside of the + * bus address seen as the AGP aperture). It will be used + * by the r128 DRM driver + * + * FIXME: We need to make sure that page doesn't overlap any of the\ + * above. This could be done by improving mem_pieces_find to be able + * to do a backward search from the end of the list. + */ + if (_machine == _MACH_Pmac && find_devices("uni-north-agp")) { + agp_special_page = (total_memory - PAGE_SIZE); + mem_pieces_remove(&phys_avail, agp_special_page, PAGE_SIZE, 0); + agp_special_page = (unsigned long)__va(agp_special_page); + } +#endif /* CONFIG_PPC_PMAC */ } /* Mark some memory as reserved by removing it from phys_avail. */ diff --git a/trunk/arch/ppc/platforms/Makefile b/trunk/arch/ppc/platforms/Makefile index 51430e294b32..7c5cdabf6f3c 100644 --- a/trunk/arch/ppc/platforms/Makefile +++ b/trunk/arch/ppc/platforms/Makefile @@ -3,18 +3,26 @@ # # Extra CFLAGS so we don't have to do relative includes -CFLAGS_chrp_setup.o += -Iarch/$(ARCH)/mm +CFLAGS_pmac_setup.o += -Iarch/$(ARCH)/mm obj-$(CONFIG_APUS) += apus_setup.o ifeq ($(CONFIG_APUS),y) obj-$(CONFIG_PCI) += apus_pci.o endif +obj-$(CONFIG_PPC_PMAC) += pmac_pic.o pmac_setup.o pmac_time.o \ + pmac_feature.o pmac_pci.o pmac_sleep.o \ + pmac_low_i2c.o pmac_cache.o obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o \ chrp_pegasos_eth.o ifeq ($(CONFIG_PPC_CHRP),y) obj-$(CONFIG_NVRAM) += chrp_nvram.o endif obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o +ifeq ($(CONFIG_PPC_PMAC),y) +obj-$(CONFIG_NVRAM) += pmac_nvram.o +obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o +endif +obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o obj-$(CONFIG_PREP_RESIDUAL) += residual.o obj-$(CONFIG_PQ2ADS) += pq2ads.o obj-$(CONFIG_TQM8260) += tqm8260_setup.o @@ -39,5 +47,6 @@ obj-$(CONFIG_LITE5200) += lite5200.o obj-$(CONFIG_EV64360) += ev64360.o ifeq ($(CONFIG_SMP),y) +obj-$(CONFIG_PPC_PMAC) += pmac_smp.o obj-$(CONFIG_PPC_CHRP) += chrp_smp.o endif diff --git a/trunk/arch/ppc/platforms/chrp_pci.c b/trunk/arch/ppc/platforms/chrp_pci.c index c7fe6182bb77..bd047aac01b1 100644 --- a/trunk/arch/ppc/platforms/chrp_pci.c +++ b/trunk/arch/ppc/platforms/chrp_pci.c @@ -275,7 +275,7 @@ chrp_find_bridges(void) setup_python(hose, dev); } else if (is_mot || strncmp(model, "Motorola, Grackle", 17) == 0) { - setup_indirect_pci(hose, 0xfec00000, 0xfee00000); + setup_grackle(hose); } else if (is_longtrail) { void __iomem *p = ioremap(GG2_PCI_CONFIG_BASE, 0x80000); hose->ops = &gg2_pci_ops; diff --git a/trunk/arch/ppc/platforms/chrp_setup.c b/trunk/arch/ppc/platforms/chrp_setup.c index 48996b787378..056ac2a7b5c1 100644 --- a/trunk/arch/ppc/platforms/chrp_setup.c +++ b/trunk/arch/ppc/platforms/chrp_setup.c @@ -53,7 +53,6 @@ #include #include #include -#include "mem_pieces.h" unsigned long chrp_get_rtc_time(void); int chrp_set_rtc_time(unsigned long nowtime); @@ -66,6 +65,7 @@ void rtas_display_progress(char *, unsigned short); void rtas_indicator_progress(char *, unsigned short); void btext_progress(char *, unsigned short); +extern unsigned long pmac_find_end_of_memory(void); extern int of_show_percpuinfo(struct seq_file *, int); int _chrp_type; @@ -467,75 +467,6 @@ chrp_init2(void) ppc_md.progress(" Have fun! ", 0x7777); } -static struct device_node *memory_node; - -static int __init get_mem_prop(char *name, struct mem_pieces *mp) -{ - struct reg_property *rp; - int i, s; - unsigned int *ip; - int nac = prom_n_addr_cells(memory_node); - int nsc = prom_n_size_cells(memory_node); - - ip = (unsigned int *) get_property(memory_node, name, &s); - if (ip == NULL) { - printk(KERN_ERR "error: couldn't get %s property on /memory\n", - name); - return 0; - } - s /= (nsc + nac) * 4; - rp = mp->regions; - for (i = 0; i < s; ++i, ip += nac+nsc) { - if (nac >= 2 && ip[nac-2] != 0) - continue; - rp->address = ip[nac-1]; - if (nsc >= 2 && ip[nac+nsc-2] != 0) - rp->size = ~0U; - else - rp->size = ip[nac+nsc-1]; - ++rp; - } - mp->n_regions = rp - mp->regions; - - /* Make sure the pieces are sorted. */ - mem_pieces_sort(mp); - mem_pieces_coalesce(mp); - return 1; -} - -static unsigned long __init chrp_find_end_of_memory(void) -{ - unsigned long a, total; - struct mem_pieces phys_mem; - - /* - * Find out where physical memory is, and check that it - * starts at 0 and is contiguous. It seems that RAM is - * always physically contiguous on Power Macintoshes. - * - * Supporting discontiguous physical memory isn't hard, - * it just makes the virtual <-> physical mapping functions - * more complicated (or else you end up wasting space - * in mem_map). - */ - memory_node = find_devices("memory"); - if (memory_node == NULL || !get_mem_prop("reg", &phys_mem) - || phys_mem.n_regions == 0) - panic("No RAM??"); - a = phys_mem.regions[0].address; - if (a != 0) - panic("RAM doesn't start at physical address 0"); - total = phys_mem.regions[0].size; - - if (phys_mem.n_regions > 1) { - printk("RAM starting at 0x%x is not contiguous\n", - phys_mem.regions[1].address); - printk("Using RAM from 0 to 0x%lx\n", total-1); - } - - return total; -} - void __init chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) @@ -594,7 +525,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, ppc_md.get_rtc_time = chrp_get_rtc_time; ppc_md.calibrate_decr = chrp_calibrate_decr; - ppc_md.find_end_of_memory = chrp_find_end_of_memory; + ppc_md.find_end_of_memory = pmac_find_end_of_memory; if (rtas_data) { struct device_node *rtas; diff --git a/trunk/arch/ppc/platforms/chrp_time.c b/trunk/arch/ppc/platforms/chrp_time.c index 57753a55b580..29d074c305f0 100644 --- a/trunk/arch/ppc/platforms/chrp_time.c +++ b/trunk/arch/ppc/platforms/chrp_time.c @@ -163,75 +163,13 @@ unsigned long chrp_get_rtc_time(void) return mktime(year, mon, day, hour, min, sec); } -/* - * Calibrate the decrementer frequency with the VIA timer 1. - */ -#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */ - -/* VIA registers */ -#define RS 0x200 /* skip between registers */ -#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ -#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ -#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ -#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ -#define ACR (11*RS) /* Auxiliary control register */ -#define IFR (13*RS) /* Interrupt flag register */ - -/* Bits in ACR */ -#define T1MODE 0xc0 /* Timer 1 mode */ -#define T1MODE_CONT 0x40 /* continuous interrupts */ - -/* Bits in IFR and IER */ -#define T1_INT 0x40 /* Timer 1 interrupt */ - -static int __init chrp_via_calibrate_decr(void) -{ - struct device_node *vias; - volatile unsigned char __iomem *via; - int count = VIA_TIMER_FREQ_6 / 100; - unsigned int dstart, dend; - - vias = find_devices("via-cuda"); - if (vias == 0) - vias = find_devices("via"); - if (vias == 0 || vias->n_addrs == 0) - return 0; - via = ioremap(vias->addrs[0].address, vias->addrs[0].size); - - /* set timer 1 for continuous interrupts */ - out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT); - /* set the counter to a small value */ - out_8(&via[T1CH], 2); - /* set the latch to `count' */ - out_8(&via[T1LL], count); - out_8(&via[T1LH], count >> 8); - /* wait until it hits 0 */ - while ((in_8(&via[IFR]) & T1_INT) == 0) - ; - dstart = get_dec(); - /* clear the interrupt & wait until it hits 0 again */ - in_8(&via[T1CL]); - while ((in_8(&via[IFR]) & T1_INT) == 0) - ; - dend = get_dec(); - - tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100); - tb_to_us = mulhwu_scale_factor(dstart - dend, 60000); - - printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n", - tb_ticks_per_jiffy, dstart - dend); - - iounmap(via); - - return 1; -} void __init chrp_calibrate_decr(void) { struct device_node *cpu; unsigned int freq, *fp; - if (chrp_via_calibrate_decr()) + if (via_calibrate_decr()) return; /* diff --git a/trunk/arch/ppc/platforms/pmac_backlight.c b/trunk/arch/ppc/platforms/pmac_backlight.c new file mode 100644 index 000000000000..8be2f7d071f0 --- /dev/null +++ b/trunk/arch/ppc/platforms/pmac_backlight.c @@ -0,0 +1,202 @@ +/* + * Miscellaneous procedures for dealing with the PowerMac hardware. + * Contains support for the backlight. + * + * Copyright (C) 2000 Benjamin Herrenschmidt + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static struct backlight_controller *backlighter; +static void* backlighter_data; +static int backlight_autosave; +static int backlight_level = BACKLIGHT_MAX; +static int backlight_enabled = 1; +static int backlight_req_level = -1; +static int backlight_req_enable = -1; + +static void backlight_callback(void *); +static DECLARE_WORK(backlight_work, backlight_callback, NULL); + +void register_backlight_controller(struct backlight_controller *ctrler, + void *data, char *type) +{ + struct device_node* bk_node; + char *prop; + int valid = 0; + + /* There's already a matching controller, bail out */ + if (backlighter != NULL) + return; + + bk_node = find_devices("backlight"); + +#ifdef CONFIG_ADB_PMU + /* Special case for the old PowerBook since I can't test on it */ + backlight_autosave = machine_is_compatible("AAPL,3400/2400") + || machine_is_compatible("AAPL,3500"); + if ((backlight_autosave + || machine_is_compatible("AAPL,PowerBook1998") + || machine_is_compatible("PowerBook1,1")) + && !strcmp(type, "pmu")) + valid = 1; +#endif + if (bk_node) { + prop = get_property(bk_node, "backlight-control", NULL); + if (prop && !strncmp(prop, type, strlen(type))) + valid = 1; + } + if (!valid) + return; + backlighter = ctrler; + backlighter_data = data; + + if (bk_node && !backlight_autosave) + prop = get_property(bk_node, "bklt", NULL); + else + prop = NULL; + if (prop) { + backlight_level = ((*prop)+1) >> 1; + if (backlight_level > BACKLIGHT_MAX) + backlight_level = BACKLIGHT_MAX; + } + +#ifdef CONFIG_ADB_PMU + if (backlight_autosave) { + struct adb_request req; + pmu_request(&req, NULL, 2, 0xd9, 0); + while (!req.complete) + pmu_poll(); + backlight_level = req.reply[0] >> 4; + } +#endif + acquire_console_sem(); + if (!backlighter->set_enable(1, backlight_level, data)) + backlight_enabled = 1; + release_console_sem(); + + printk(KERN_INFO "Registered \"%s\" backlight controller," + "level: %d/15\n", type, backlight_level); +} +EXPORT_SYMBOL(register_backlight_controller); + +void unregister_backlight_controller(struct backlight_controller + *ctrler, void *data) +{ + /* We keep the current backlight level (for now) */ + if (ctrler == backlighter && data == backlighter_data) + backlighter = NULL; +} +EXPORT_SYMBOL(unregister_backlight_controller); + +static int __set_backlight_enable(int enable) +{ + int rc; + + if (!backlighter) + return -ENODEV; + acquire_console_sem(); + rc = backlighter->set_enable(enable, backlight_level, + backlighter_data); + if (!rc) + backlight_enabled = enable; + release_console_sem(); + return rc; +} +int set_backlight_enable(int enable) +{ + if (!backlighter) + return -ENODEV; + backlight_req_enable = enable; + schedule_work(&backlight_work); + return 0; +} + +EXPORT_SYMBOL(set_backlight_enable); + +int get_backlight_enable(void) +{ + if (!backlighter) + return -ENODEV; + return backlight_enabled; +} +EXPORT_SYMBOL(get_backlight_enable); + +static int __set_backlight_level(int level) +{ + int rc = 0; + + if (!backlighter) + return -ENODEV; + if (level < BACKLIGHT_MIN) + level = BACKLIGHT_OFF; + if (level > BACKLIGHT_MAX) + level = BACKLIGHT_MAX; + acquire_console_sem(); + if (backlight_enabled) + rc = backlighter->set_level(level, backlighter_data); + if (!rc) + backlight_level = level; + release_console_sem(); + if (!rc && !backlight_autosave) { + level <<=1; + if (level & 0x10) + level |= 0x01; + // -- todo: save to property "bklt" + } + return rc; +} +int set_backlight_level(int level) +{ + if (!backlighter) + return -ENODEV; + backlight_req_level = level; + schedule_work(&backlight_work); + return 0; +} + +EXPORT_SYMBOL(set_backlight_level); + +int get_backlight_level(void) +{ + if (!backlighter) + return -ENODEV; + return backlight_level; +} +EXPORT_SYMBOL(get_backlight_level); + +static void backlight_callback(void *dummy) +{ + int level, enable; + + do { + level = backlight_req_level; + enable = backlight_req_enable; + mb(); + + if (level >= 0) + __set_backlight_level(level); + if (enable >= 0) + __set_backlight_enable(enable); + } while(cmpxchg(&backlight_req_level, level, -1) != level || + cmpxchg(&backlight_req_enable, enable, -1) != enable); +} diff --git a/trunk/arch/ppc/platforms/pmac_cache.S b/trunk/arch/ppc/platforms/pmac_cache.S new file mode 100644 index 000000000000..fb977de6b704 --- /dev/null +++ b/trunk/arch/ppc/platforms/pmac_cache.S @@ -0,0 +1,359 @@ +/* + * This file contains low-level cache management functions + * used for sleep and CPU speed changes on Apple machines. + * (In fact the only thing that is Apple-specific is that we assume + * that we can read from ROM at physical address 0xfff00000.) + * + * Copyright (C) 2004 Paul Mackerras (paulus@samba.org) and + * Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * 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; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include + +/* + * Flush and disable all data caches (dL1, L2, L3). This is used + * when going to sleep, when doing a PMU based cpufreq transition, + * or when "offlining" a CPU on SMP machines. This code is over + * paranoid, but I've had enough issues with various CPU revs and + * bugs that I decided it was worth beeing over cautious + */ + +_GLOBAL(flush_disable_caches) +#ifndef CONFIG_6xx + blr +#else +BEGIN_FTR_SECTION + b flush_disable_745x +END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) +BEGIN_FTR_SECTION + b flush_disable_75x +END_FTR_SECTION_IFSET(CPU_FTR_L2CR) + b __flush_disable_L1 + +/* This is the code for G3 and 74[01]0 */ +flush_disable_75x: + mflr r10 + + /* Turn off EE and DR in MSR */ + mfmsr r11 + rlwinm r0,r11,0,~MSR_EE + rlwinm r0,r0,0,~MSR_DR + sync + mtmsr r0 + isync + + /* Stop DST streams */ +BEGIN_FTR_SECTION + DSSALL + sync +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) + + /* Stop DPM */ + mfspr r8,SPRN_HID0 /* Save SPRN_HID0 in r8 */ + rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */ + sync + mtspr SPRN_HID0,r4 /* Disable DPM */ + sync + + /* Disp-flush L1. We have a weird problem here that I never + * totally figured out. On 750FX, using the ROM for the flush + * results in a non-working flush. We use that workaround for + * now until I finally understand what's going on. --BenH + */ + + /* ROM base by default */ + lis r4,0xfff0 + mfpvr r3 + srwi r3,r3,16 + cmplwi cr0,r3,0x7000 + bne+ 1f + /* RAM base on 750FX */ + li r4,0 +1: li r4,0x4000 + mtctr r4 +1: lwz r0,0(r4) + addi r4,r4,32 + bdnz 1b + sync + isync + + /* Disable / invalidate / enable L1 data */ + mfspr r3,SPRN_HID0 + rlwinm r3,r3,0,~(HID0_DCE | HID0_ICE) + mtspr SPRN_HID0,r3 + sync + isync + ori r3,r3,(HID0_DCE|HID0_DCI|HID0_ICE|HID0_ICFI) + sync + isync + mtspr SPRN_HID0,r3 + xori r3,r3,(HID0_DCI|HID0_ICFI) + mtspr SPRN_HID0,r3 + sync + + /* Get the current enable bit of the L2CR into r4 */ + mfspr r5,SPRN_L2CR + /* Set to data-only (pre-745x bit) */ + oris r3,r5,L2CR_L2DO@h + b 2f + /* When disabling L2, code must be in L1 */ + .balign 32 +1: mtspr SPRN_L2CR,r3 +3: sync + isync + b 1f +2: b 3f +3: sync + isync + b 1b +1: /* disp-flush L2. The interesting thing here is that the L2 can be + * up to 2Mb ... so using the ROM, we'll end up wrapping back to memory + * but that is probbaly fine. We disp-flush over 4Mb to be safe + */ + lis r4,2 + mtctr r4 + lis r4,0xfff0 +1: lwz r0,0(r4) + addi r4,r4,32 + bdnz 1b + sync + isync + lis r4,2 + mtctr r4 + lis r4,0xfff0 +1: dcbf 0,r4 + addi r4,r4,32 + bdnz 1b + sync + isync + + /* now disable L2 */ + rlwinm r5,r5,0,~L2CR_L2E + b 2f + /* When disabling L2, code must be in L1 */ + .balign 32 +1: mtspr SPRN_L2CR,r5 +3: sync + isync + b 1f +2: b 3f +3: sync + isync + b 1b +1: sync + isync + /* Invalidate L2. This is pre-745x, we clear the L2I bit ourselves */ + oris r4,r5,L2CR_L2I@h + mtspr SPRN_L2CR,r4 + sync + isync + + /* Wait for the invalidation to complete */ +1: mfspr r3,SPRN_L2CR + rlwinm. r0,r3,0,31,31 + bne 1b + + /* Clear L2I */ + xoris r4,r4,L2CR_L2I@h + sync + mtspr SPRN_L2CR,r4 + sync + + /* now disable the L1 data cache */ + mfspr r0,SPRN_HID0 + rlwinm r0,r0,0,~(HID0_DCE|HID0_ICE) + mtspr SPRN_HID0,r0 + sync + isync + + /* Restore HID0[DPM] to whatever it was before */ + sync + mfspr r0,SPRN_HID0 + rlwimi r0,r8,0,11,11 /* Turn back HID0[DPM] */ + mtspr SPRN_HID0,r0 + sync + + /* restore DR and EE */ + sync + mtmsr r11 + isync + + mtlr r10 + blr + +/* This code is for 745x processors */ +flush_disable_745x: + /* Turn off EE and DR in MSR */ + mfmsr r11 + rlwinm r0,r11,0,~MSR_EE + rlwinm r0,r0,0,~MSR_DR + sync + mtmsr r0 + isync + + /* Stop prefetch streams */ + DSSALL + sync + + /* Disable L2 prefetching */ + mfspr r0,SPRN_MSSCR0 + rlwinm r0,r0,0,0,29 + mtspr SPRN_MSSCR0,r0 + sync + isync + lis r4,0 + dcbf 0,r4 + dcbf 0,r4 + dcbf 0,r4 + dcbf 0,r4 + dcbf 0,r4 + dcbf 0,r4 + dcbf 0,r4 + dcbf 0,r4 + + /* Due to a bug with the HW flush on some CPU revs, we occasionally + * experience data corruption. I'm adding a displacement flush along + * with a dcbf loop over a few Mb to "help". The problem isn't totally + * fixed by this in theory, but at least, in practice, I couldn't reproduce + * it even with a big hammer... + */ + + lis r4,0x0002 + mtctr r4 + li r4,0 +1: + lwz r0,0(r4) + addi r4,r4,32 /* Go to start of next cache line */ + bdnz 1b + isync + + /* Now, flush the first 4MB of memory */ + lis r4,0x0002 + mtctr r4 + li r4,0 + sync +1: + dcbf 0,r4 + addi r4,r4,32 /* Go to start of next cache line */ + bdnz 1b + + /* Flush and disable the L1 data cache */ + mfspr r6,SPRN_LDSTCR + lis r3,0xfff0 /* read from ROM for displacement flush */ + li r4,0xfe /* start with only way 0 unlocked */ + li r5,128 /* 128 lines in each way */ +1: mtctr r5 + rlwimi r6,r4,0,24,31 + mtspr SPRN_LDSTCR,r6 + sync + isync +2: lwz r0,0(r3) /* touch each cache line */ + addi r3,r3,32 + bdnz 2b + rlwinm r4,r4,1,24,30 /* move on to the next way */ + ori r4,r4,1 + cmpwi r4,0xff /* all done? */ + bne 1b + /* now unlock the L1 data cache */ + li r4,0 + rlwimi r6,r4,0,24,31 + sync + mtspr SPRN_LDSTCR,r6 + sync + isync + + /* Flush the L2 cache using the hardware assist */ + mfspr r3,SPRN_L2CR + cmpwi r3,0 /* check if it is enabled first */ + bge 4f + oris r0,r3,(L2CR_L2IO_745x|L2CR_L2DO_745x)@h + b 2f + /* When disabling/locking L2, code must be in L1 */ + .balign 32 +1: mtspr SPRN_L2CR,r0 /* lock the L2 cache */ +3: sync + isync + b 1f +2: b 3f +3: sync + isync + b 1b +1: sync + isync + ori r0,r3,L2CR_L2HWF_745x + sync + mtspr SPRN_L2CR,r0 /* set the hardware flush bit */ +3: mfspr r0,SPRN_L2CR /* wait for it to go to 0 */ + andi. r0,r0,L2CR_L2HWF_745x + bne 3b + sync + rlwinm r3,r3,0,~L2CR_L2E + b 2f + /* When disabling L2, code must be in L1 */ + .balign 32 +1: mtspr SPRN_L2CR,r3 /* disable the L2 cache */ +3: sync + isync + b 1f +2: b 3f +3: sync + isync + b 1b +1: sync + isync + oris r4,r3,L2CR_L2I@h + mtspr SPRN_L2CR,r4 + sync + isync +1: mfspr r4,SPRN_L2CR + andis. r0,r4,L2CR_L2I@h + bne 1b + sync + +BEGIN_FTR_SECTION + /* Flush the L3 cache using the hardware assist */ +4: mfspr r3,SPRN_L3CR + cmpwi r3,0 /* check if it is enabled */ + bge 6f + oris r0,r3,L3CR_L3IO@h + ori r0,r0,L3CR_L3DO + sync + mtspr SPRN_L3CR,r0 /* lock the L3 cache */ + sync + isync + ori r0,r0,L3CR_L3HWF + sync + mtspr SPRN_L3CR,r0 /* set the hardware flush bit */ +5: mfspr r0,SPRN_L3CR /* wait for it to go to zero */ + andi. r0,r0,L3CR_L3HWF + bne 5b + rlwinm r3,r3,0,~L3CR_L3E + sync + mtspr SPRN_L3CR,r3 /* disable the L3 cache */ + sync + ori r4,r3,L3CR_L3I + mtspr SPRN_L3CR,r4 +1: mfspr r4,SPRN_L3CR + andi. r0,r4,L3CR_L3I + bne 1b + sync +END_FTR_SECTION_IFSET(CPU_FTR_L3CR) + +6: mfspr r0,SPRN_HID0 /* now disable the L1 data cache */ + rlwinm r0,r0,0,~HID0_DCE + mtspr SPRN_HID0,r0 + sync + isync + mtmsr r11 /* restore DR and EE */ + isync + blr +#endif /* CONFIG_6xx */ diff --git a/trunk/arch/ppc/platforms/pmac_cpufreq.c b/trunk/arch/ppc/platforms/pmac_cpufreq.c new file mode 100644 index 000000000000..fba7e4d7c0bf --- /dev/null +++ b/trunk/arch/ppc/platforms/pmac_cpufreq.c @@ -0,0 +1,735 @@ +/* + * arch/ppc/platforms/pmac_cpufreq.c + * + * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt + * Copyright (C) 2004 John Steele Scott + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * TODO: Need a big cleanup here. Basically, we need to have different + * cpufreq_driver structures for the different type of HW instead of the + * current mess. We also need to better deal with the detection of the + * type of machine. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* WARNING !!! This will cause calibrate_delay() to be called, + * but this is an __init function ! So you MUST go edit + * init/main.c to make it non-init before enabling DEBUG_FREQ + */ +#undef DEBUG_FREQ + +/* + * There is a problem with the core cpufreq code on SMP kernels, + * it won't recalculate the Bogomips properly + */ +#ifdef CONFIG_SMP +#warning "WARNING, CPUFREQ not recommended on SMP kernels" +#endif + +extern void low_choose_7447a_dfs(int dfs); +extern void low_choose_750fx_pll(int pll); +extern void low_sleep_handler(void); + +/* + * Currently, PowerMac cpufreq supports only high & low frequencies + * that are set by the firmware + */ +static unsigned int low_freq; +static unsigned int hi_freq; +static unsigned int cur_freq; +static unsigned int sleep_freq; + +/* + * Different models uses different mecanisms to switch the frequency + */ +static int (*set_speed_proc)(int low_speed); +static unsigned int (*get_speed_proc)(void); + +/* + * Some definitions used by the various speedprocs + */ +static u32 voltage_gpio; +static u32 frequency_gpio; +static u32 slew_done_gpio; +static int no_schedule; +static int has_cpu_l2lve; +static int is_pmu_based; + +/* There are only two frequency states for each processor. Values + * are in kHz for the time being. + */ +#define CPUFREQ_HIGH 0 +#define CPUFREQ_LOW 1 + +static struct cpufreq_frequency_table pmac_cpu_freqs[] = { + {CPUFREQ_HIGH, 0}, + {CPUFREQ_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +static struct freq_attr* pmac_cpu_freqs_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +static inline void local_delay(unsigned long ms) +{ + if (no_schedule) + mdelay(ms); + else + msleep(ms); +} + +static inline void wakeup_decrementer(void) +{ + set_dec(tb_ticks_per_jiffy); + /* No currently-supported powerbook has a 601, + * so use get_tbl, not native + */ + last_jiffy_stamp(0) = tb_last_stamp = get_tbl(); +} + +#ifdef DEBUG_FREQ +static inline void debug_calc_bogomips(void) +{ + /* This will cause a recalc of bogomips and display the + * result. We backup/restore the value to avoid affecting the + * core cpufreq framework's own calculation. + */ + extern void calibrate_delay(void); + + unsigned long save_lpj = loops_per_jiffy; + calibrate_delay(); + loops_per_jiffy = save_lpj; +} +#endif /* DEBUG_FREQ */ + +/* Switch CPU speed under 750FX CPU control + */ +static int cpu_750fx_cpu_speed(int low_speed) +{ + u32 hid2; + + if (low_speed == 0) { + /* ramping up, set voltage first */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); + /* Make sure we sleep for at least 1ms */ + local_delay(10); + + /* tweak L2 for high voltage */ + if (has_cpu_l2lve) { + hid2 = mfspr(SPRN_HID2); + hid2 &= ~0x2000; + mtspr(SPRN_HID2, hid2); + } + } +#ifdef CONFIG_6xx + low_choose_750fx_pll(low_speed); +#endif + if (low_speed == 1) { + /* tweak L2 for low voltage */ + if (has_cpu_l2lve) { + hid2 = mfspr(SPRN_HID2); + hid2 |= 0x2000; + mtspr(SPRN_HID2, hid2); + } + + /* ramping down, set voltage last */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); + local_delay(10); + } + + return 0; +} + +static unsigned int cpu_750fx_get_cpu_speed(void) +{ + if (mfspr(SPRN_HID1) & HID1_PS) + return low_freq; + else + return hi_freq; +} + +/* Switch CPU speed using DFS */ +static int dfs_set_cpu_speed(int low_speed) +{ + if (low_speed == 0) { + /* ramping up, set voltage first */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); + /* Make sure we sleep for at least 1ms */ + local_delay(1); + } + + /* set frequency */ +#ifdef CONFIG_6xx + low_choose_7447a_dfs(low_speed); +#endif + udelay(100); + + if (low_speed == 1) { + /* ramping down, set voltage last */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); + local_delay(1); + } + + return 0; +} + +static unsigned int dfs_get_cpu_speed(void) +{ + if (mfspr(SPRN_HID1) & HID1_DFS) + return low_freq; + else + return hi_freq; +} + + +/* Switch CPU speed using slewing GPIOs + */ +static int gpios_set_cpu_speed(int low_speed) +{ + int gpio, timeout = 0; + + /* If ramping up, set voltage first */ + if (low_speed == 0) { + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); + /* Delay is way too big but it's ok, we schedule */ + local_delay(10); + } + + /* Set frequency */ + gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); + if (low_speed == ((gpio & 0x01) == 0)) + goto skip; + + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio, + low_speed ? 0x04 : 0x05); + udelay(200); + do { + if (++timeout > 100) + break; + local_delay(1); + gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0); + } while((gpio & 0x02) == 0); + skip: + /* If ramping down, set voltage last */ + if (low_speed == 1) { + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); + /* Delay is way too big but it's ok, we schedule */ + local_delay(10); + } + +#ifdef DEBUG_FREQ + debug_calc_bogomips(); +#endif + + return 0; +} + +/* Switch CPU speed under PMU control + */ +static int pmu_set_cpu_speed(int low_speed) +{ + struct adb_request req; + unsigned long save_l2cr; + unsigned long save_l3cr; + unsigned int pic_prio; + unsigned long flags; + + preempt_disable(); + +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); +#endif + pmu_suspend(); + + /* Disable all interrupt sources on openpic */ + pic_prio = openpic_get_priority(); + openpic_set_priority(0xf); + + /* Make sure the decrementer won't interrupt us */ + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + /* Make sure any pending DEC interrupt occuring while we did + * the above didn't re-enable the DEC */ + mb(); + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + + /* We can now disable MSR_EE */ + local_irq_save(flags); + + /* Giveup the FPU & vec */ + enable_kernel_fp(); + +#ifdef CONFIG_ALTIVEC + if (cpu_has_feature(CPU_FTR_ALTIVEC)) + enable_kernel_altivec(); +#endif /* CONFIG_ALTIVEC */ + + /* Save & disable L2 and L3 caches */ + save_l3cr = _get_L3CR(); /* (returns -1 if not available) */ + save_l2cr = _get_L2CR(); /* (returns -1 if not available) */ + + /* Send the new speed command. My assumption is that this command + * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep + */ + pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed); + while (!req.complete) + pmu_poll(); + + /* Prepare the northbridge for the speed transition */ + pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1); + + /* Call low level code to backup CPU state and recover from + * hardware reset + */ + low_sleep_handler(); + + /* Restore the northbridge */ + pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0); + + /* Restore L2 cache */ + if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) + _set_L2CR(save_l2cr); + /* Restore L3 cache */ + if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) + _set_L3CR(save_l3cr); + + /* Restore userland MMU context */ + set_context(current->active_mm->context, current->active_mm->pgd); + +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); +#endif + + /* Restore low level PMU operations */ + pmu_unlock(); + + /* Restore decrementer */ + wakeup_decrementer(); + + /* Restore interrupts */ + openpic_set_priority(pic_prio); + + /* Let interrupts flow again ... */ + local_irq_restore(flags); + +#ifdef DEBUG_FREQ + debug_calc_bogomips(); +#endif + + pmu_resume(); + + preempt_enable(); + + return 0; +} + +static int do_set_cpu_speed(int speed_mode, int notify) +{ + struct cpufreq_freqs freqs; + unsigned long l3cr; + static unsigned long prev_l3cr; + + freqs.old = cur_freq; + freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; + freqs.cpu = smp_processor_id(); + + if (freqs.old == freqs.new) + return 0; + + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + if (speed_mode == CPUFREQ_LOW && + cpu_has_feature(CPU_FTR_L3CR)) { + l3cr = _get_L3CR(); + if (l3cr & L3CR_L3E) { + prev_l3cr = l3cr; + _set_L3CR(0); + } + } + set_speed_proc(speed_mode == CPUFREQ_LOW); + if (speed_mode == CPUFREQ_HIGH && + cpu_has_feature(CPU_FTR_L3CR)) { + l3cr = _get_L3CR(); + if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr) + _set_L3CR(prev_l3cr); + } + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; + + return 0; +} + +static unsigned int pmac_cpufreq_get_speed(unsigned int cpu) +{ + return cur_freq; +} + +static int pmac_cpufreq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs); +} + +static int pmac_cpufreq_target( struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int newstate = 0; + + if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs, + target_freq, relation, &newstate)) + return -EINVAL; + + return do_set_cpu_speed(newstate, 1); +} + +unsigned int pmac_get_one_cpufreq(int i) +{ + /* Supports only one CPU for now */ + return (i == 0) ? cur_freq : 0; +} + +static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -ENODEV; + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = cur_freq; + + cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu); + return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs); +} + +static u32 read_gpio(struct device_node *np) +{ + u32 *reg = (u32 *)get_property(np, "reg", NULL); + u32 offset; + + if (reg == NULL) + return 0; + /* That works for all keylargos but shall be fixed properly + * some day... The problem is that it seems we can't rely + * on the "reg" property of the GPIO nodes, they are either + * relative to the base of KeyLargo or to the base of the + * GPIO space, and the device-tree doesn't help. + */ + offset = *reg; + if (offset < KEYLARGO_GPIO_LEVELS0) + offset += KEYLARGO_GPIO_LEVELS0; + return offset; +} + +static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg) +{ + /* Ok, this could be made a bit smarter, but let's be robust for now. We + * always force a speed change to high speed before sleep, to make sure + * we have appropriate voltage and/or bus speed for the wakeup process, + * and to make sure our loops_per_jiffies are "good enough", that is will + * not cause too short delays if we sleep in low speed and wake in high + * speed.. + */ + no_schedule = 1; + sleep_freq = cur_freq; + if (cur_freq == low_freq && !is_pmu_based) + do_set_cpu_speed(CPUFREQ_HIGH, 0); + return 0; +} + +static int pmac_cpufreq_resume(struct cpufreq_policy *policy) +{ + /* If we resume, first check if we have a get() function */ + if (get_speed_proc) + cur_freq = get_speed_proc(); + else + cur_freq = 0; + + /* We don't, hrm... we don't really know our speed here, best + * is that we force a switch to whatever it was, which is + * probably high speed due to our suspend() routine + */ + do_set_cpu_speed(sleep_freq == low_freq ? + CPUFREQ_LOW : CPUFREQ_HIGH, 0); + + no_schedule = 0; + return 0; +} + +static struct cpufreq_driver pmac_cpufreq_driver = { + .verify = pmac_cpufreq_verify, + .target = pmac_cpufreq_target, + .get = pmac_cpufreq_get_speed, + .init = pmac_cpufreq_cpu_init, + .suspend = pmac_cpufreq_suspend, + .resume = pmac_cpufreq_resume, + .flags = CPUFREQ_PM_NO_WARN, + .attr = pmac_cpu_freqs_attr, + .name = "powermac", + .owner = THIS_MODULE, +}; + + +static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) +{ + struct device_node *volt_gpio_np = of_find_node_by_name(NULL, + "voltage-gpio"); + struct device_node *freq_gpio_np = of_find_node_by_name(NULL, + "frequency-gpio"); + struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL, + "slewing-done"); + u32 *value; + + /* + * Check to see if it's GPIO driven or PMU only + * + * The way we extract the GPIO address is slightly hackish, but it + * works well enough for now. We need to abstract the whole GPIO + * stuff sooner or later anyway + */ + + if (volt_gpio_np) + voltage_gpio = read_gpio(volt_gpio_np); + if (freq_gpio_np) + frequency_gpio = read_gpio(freq_gpio_np); + if (slew_done_gpio_np) + slew_done_gpio = read_gpio(slew_done_gpio_np); + + /* If we use the frequency GPIOs, calculate the min/max speeds based + * on the bus frequencies + */ + if (frequency_gpio && slew_done_gpio) { + int lenp, rc; + u32 *freqs, *ratio; + + freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp); + lenp /= sizeof(u32); + if (freqs == NULL || lenp != 2) { + printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); + return 1; + } + ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL); + if (ratio == NULL) { + printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); + return 1; + } + + /* Get the min/max bus frequencies */ + low_freq = min(freqs[0], freqs[1]); + hi_freq = max(freqs[0], freqs[1]); + + /* Grrrr.. It _seems_ that the device-tree is lying on the low bus + * frequency, it claims it to be around 84Mhz on some models while + * it appears to be approx. 101Mhz on all. Let's hack around here... + * fortunately, we don't need to be too precise + */ + if (low_freq < 98000000) + low_freq = 101000000; + + /* Convert those to CPU core clocks */ + low_freq = (low_freq * (*ratio)) / 2000; + hi_freq = (hi_freq * (*ratio)) / 2000; + + /* Now we get the frequencies, we read the GPIO to see what is out current + * speed + */ + rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); + cur_freq = (rc & 0x01) ? hi_freq : low_freq; + + set_speed_proc = gpios_set_cpu_speed; + return 1; + } + + /* If we use the PMU, look for the min & max frequencies in the + * device-tree + */ + value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL); + if (!value) + return 1; + low_freq = (*value) / 1000; + /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree + * here */ + if (low_freq < 100000) + low_freq *= 10; + + value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL); + if (!value) + return 1; + hi_freq = (*value) / 1000; + set_speed_proc = pmu_set_cpu_speed; + is_pmu_based = 1; + + return 0; +} + +static int pmac_cpufreq_init_7447A(struct device_node *cpunode) +{ + struct device_node *volt_gpio_np; + + if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) + return 1; + + volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); + if (volt_gpio_np) + voltage_gpio = read_gpio(volt_gpio_np); + if (!voltage_gpio){ + printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n"); + return 1; + } + + /* OF only reports the high frequency */ + hi_freq = cur_freq; + low_freq = cur_freq/2; + + /* Read actual frequency from CPU */ + cur_freq = dfs_get_cpu_speed(); + set_speed_proc = dfs_set_cpu_speed; + get_speed_proc = dfs_get_cpu_speed; + + return 0; +} + +static int pmac_cpufreq_init_750FX(struct device_node *cpunode) +{ + struct device_node *volt_gpio_np; + u32 pvr, *value; + + if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) + return 1; + + hi_freq = cur_freq; + value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL); + if (!value) + return 1; + low_freq = (*value) / 1000; + + volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); + if (volt_gpio_np) + voltage_gpio = read_gpio(volt_gpio_np); + + pvr = mfspr(SPRN_PVR); + has_cpu_l2lve = !((pvr & 0xf00) == 0x100); + + set_speed_proc = cpu_750fx_cpu_speed; + get_speed_proc = cpu_750fx_get_cpu_speed; + cur_freq = cpu_750fx_get_cpu_speed(); + + return 0; +} + +/* Currently, we support the following machines: + * + * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz) + * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz) + * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz) + * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz) + * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz) + * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage) + * - Recent MacRISC3 laptops + * - All new machines with 7447A CPUs + */ +static int __init pmac_cpufreq_setup(void) +{ + struct device_node *cpunode; + u32 *value; + + if (strstr(cmd_line, "nocpufreq")) + return 0; + + /* Assume only one CPU */ + cpunode = find_type_devices("cpu"); + if (!cpunode) + goto out; + + /* Get current cpu clock freq */ + value = (u32 *)get_property(cpunode, "clock-frequency", NULL); + if (!value) + goto out; + cur_freq = (*value) / 1000; + + /* Check for 7447A based MacRISC3 */ + if (machine_is_compatible("MacRISC3") && + get_property(cpunode, "dynamic-power-step", NULL) && + PVR_VER(mfspr(SPRN_PVR)) == 0x8003) { + pmac_cpufreq_init_7447A(cpunode); + /* Check for other MacRISC3 machines */ + } else if (machine_is_compatible("PowerBook3,4") || + machine_is_compatible("PowerBook3,5") || + machine_is_compatible("MacRISC3")) { + pmac_cpufreq_init_MacRISC3(cpunode); + /* Else check for iBook2 500/600 */ + } else if (machine_is_compatible("PowerBook4,1")) { + hi_freq = cur_freq; + low_freq = 400000; + set_speed_proc = pmu_set_cpu_speed; + is_pmu_based = 1; + } + /* Else check for TiPb 550 */ + else if (machine_is_compatible("PowerBook3,3") && cur_freq == 550000) { + hi_freq = cur_freq; + low_freq = 500000; + set_speed_proc = pmu_set_cpu_speed; + is_pmu_based = 1; + } + /* Else check for TiPb 400 & 500 */ + else if (machine_is_compatible("PowerBook3,2")) { + /* We only know about the 400 MHz and the 500Mhz model + * they both have 300 MHz as low frequency + */ + if (cur_freq < 350000 || cur_freq > 550000) + goto out; + hi_freq = cur_freq; + low_freq = 300000; + set_speed_proc = pmu_set_cpu_speed; + is_pmu_based = 1; + } + /* Else check for 750FX */ + else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) + pmac_cpufreq_init_750FX(cpunode); +out: + if (set_speed_proc == NULL) + return -ENODEV; + + pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq; + pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq; + + printk(KERN_INFO "Registering PowerMac CPU frequency driver\n"); + printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n", + low_freq/1000, hi_freq/1000, cur_freq/1000); + + return cpufreq_register_driver(&pmac_cpufreq_driver); +} + +module_init(pmac_cpufreq_setup); + diff --git a/trunk/arch/ppc/platforms/pmac_feature.c b/trunk/arch/ppc/platforms/pmac_feature.c new file mode 100644 index 000000000000..6b7b3a150631 --- /dev/null +++ b/trunk/arch/ppc/platforms/pmac_feature.c @@ -0,0 +1,3023 @@ +/* + * arch/ppc/platforms/pmac_feature.c + * + * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au) + * Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * 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; either version + * 2 of the License, or (at your option) any later version. + * + * TODO: + * + * - Replace mdelay with some schedule loop if possible + * - Shorten some obfuscated delays on some routines (like modem + * power) + * - Refcount some clocks (see darwin) + * - Split split split... + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG_FEATURE + +#ifdef DEBUG_FEATURE +#define DBG(fmt,...) printk(KERN_DEBUG fmt) +#else +#define DBG(fmt,...) +#endif + +#ifdef CONFIG_6xx +extern int powersave_lowspeed; +#endif + +extern int powersave_nap; +extern struct device_node *k2_skiplist[2]; + + +/* + * We use a single global lock to protect accesses. Each driver has + * to take care of its own locking + */ +static DEFINE_SPINLOCK(feature_lock); + +#define LOCK(flags) spin_lock_irqsave(&feature_lock, flags); +#define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags); + + +/* + * Instance of some macio stuffs + */ +struct macio_chip macio_chips[MAX_MACIO_CHIPS]; + +struct macio_chip* macio_find(struct device_node* child, int type) +{ + while(child) { + int i; + + for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++) + if (child == macio_chips[i].of_node && + (!type || macio_chips[i].type == type)) + return &macio_chips[i]; + child = child->parent; + } + return NULL; +} +EXPORT_SYMBOL_GPL(macio_find); + +static const char* macio_names[] = +{ + "Unknown", + "Grand Central", + "OHare", + "OHareII", + "Heathrow", + "Gatwick", + "Paddington", + "Keylargo", + "Pangea", + "Intrepid", + "K2" +}; + + + +/* + * Uninorth reg. access. Note that Uni-N regs are big endian + */ + +#define UN_REG(r) (uninorth_base + ((r) >> 2)) +#define UN_IN(r) (in_be32(UN_REG(r))) +#define UN_OUT(r,v) (out_be32(UN_REG(r), (v))) +#define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v))) +#define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v))) + +static struct device_node* uninorth_node; +static u32 __iomem * uninorth_base; +static u32 uninorth_rev; +static int uninorth_u3; +static void __iomem *u3_ht; + +/* + * For each motherboard family, we have a table of functions pointers + * that handle the various features. + */ + +typedef long (*feature_call)(struct device_node* node, long param, long value); + +struct feature_table_entry { + unsigned int selector; + feature_call function; +}; + +struct pmac_mb_def +{ + const char* model_string; + const char* model_name; + int model_id; + struct feature_table_entry* features; + unsigned long board_flags; +}; +static struct pmac_mb_def pmac_mb; + +/* + * Here are the chip specific feature functions + */ + +static inline int +simple_feature_tweak(struct device_node* node, int type, int reg, u32 mask, int value) +{ + struct macio_chip* macio; + unsigned long flags; + + macio = macio_find(node, type); + if (!macio) + return -ENODEV; + LOCK(flags); + if (value) + MACIO_BIS(reg, mask); + else + MACIO_BIC(reg, mask); + (void)MACIO_IN32(reg); + UNLOCK(flags); + + return 0; +} + +#ifndef CONFIG_POWER4 + +static long +ohare_htw_scc_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio; + unsigned long chan_mask; + unsigned long fcr; + unsigned long flags; + int htw, trans; + unsigned long rmask; + + macio = macio_find(node, 0); + if (!macio) + return -ENODEV; + if (!strcmp(node->name, "ch-a")) + chan_mask = MACIO_FLAG_SCCA_ON; + else if (!strcmp(node->name, "ch-b")) + chan_mask = MACIO_FLAG_SCCB_ON; + else + return -ENODEV; + + htw = (macio->type == macio_heathrow || macio->type == macio_paddington + || macio->type == macio_gatwick); + /* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */ + trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE && + pmac_mb.model_id != PMAC_TYPE_YIKES); + if (value) { +#ifdef CONFIG_ADB_PMU + if ((param & 0xfff) == PMAC_SCC_IRDA) + pmu_enable_irled(1); +#endif /* CONFIG_ADB_PMU */ + LOCK(flags); + fcr = MACIO_IN32(OHARE_FCR); + /* Check if scc cell need enabling */ + if (!(fcr & OH_SCC_ENABLE)) { + fcr |= OH_SCC_ENABLE; + if (htw) { + /* Side effect: this will also power up the + * modem, but it's too messy to figure out on which + * ports this controls the tranceiver and on which + * it controls the modem + */ + if (trans) + fcr &= ~HRW_SCC_TRANS_EN_N; + MACIO_OUT32(OHARE_FCR, fcr); + fcr |= (rmask = HRW_RESET_SCC); + MACIO_OUT32(OHARE_FCR, fcr); + } else { + fcr |= (rmask = OH_SCC_RESET); + MACIO_OUT32(OHARE_FCR, fcr); + } + UNLOCK(flags); + (void)MACIO_IN32(OHARE_FCR); + mdelay(15); + LOCK(flags); + fcr &= ~rmask; + MACIO_OUT32(OHARE_FCR, fcr); + } + if (chan_mask & MACIO_FLAG_SCCA_ON) + fcr |= OH_SCCA_IO; + if (chan_mask & MACIO_FLAG_SCCB_ON) + fcr |= OH_SCCB_IO; + MACIO_OUT32(OHARE_FCR, fcr); + macio->flags |= chan_mask; + UNLOCK(flags); + if (param & PMAC_SCC_FLAG_XMON) + macio->flags |= MACIO_FLAG_SCC_LOCKED; + } else { + if (macio->flags & MACIO_FLAG_SCC_LOCKED) + return -EPERM; + LOCK(flags); + fcr = MACIO_IN32(OHARE_FCR); + if (chan_mask & MACIO_FLAG_SCCA_ON) + fcr &= ~OH_SCCA_IO; + if (chan_mask & MACIO_FLAG_SCCB_ON) + fcr &= ~OH_SCCB_IO; + MACIO_OUT32(OHARE_FCR, fcr); + if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) { + fcr &= ~OH_SCC_ENABLE; + if (htw && trans) + fcr |= HRW_SCC_TRANS_EN_N; + MACIO_OUT32(OHARE_FCR, fcr); + } + macio->flags &= ~(chan_mask); + UNLOCK(flags); + mdelay(10); +#ifdef CONFIG_ADB_PMU + if ((param & 0xfff) == PMAC_SCC_IRDA) + pmu_enable_irled(0); +#endif /* CONFIG_ADB_PMU */ + } + return 0; +} + +static long +ohare_floppy_enable(struct device_node* node, long param, long value) +{ + return simple_feature_tweak(node, macio_ohare, + OHARE_FCR, OH_FLOPPY_ENABLE, value); +} + +static long +ohare_mesh_enable(struct device_node* node, long param, long value) +{ + return simple_feature_tweak(node, macio_ohare, + OHARE_FCR, OH_MESH_ENABLE, value); +} + +static long +ohare_ide_enable(struct device_node* node, long param, long value) +{ + switch(param) { + case 0: + /* For some reason, setting the bit in set_initial_features() + * doesn't stick. I'm still investigating... --BenH. + */ + if (value) + simple_feature_tweak(node, macio_ohare, + OHARE_FCR, OH_IOBUS_ENABLE, 1); + return simple_feature_tweak(node, macio_ohare, + OHARE_FCR, OH_IDE0_ENABLE, value); + case 1: + return simple_feature_tweak(node, macio_ohare, + OHARE_FCR, OH_BAY_IDE_ENABLE, value); + default: + return -ENODEV; + } +} + +static long +ohare_ide_reset(struct device_node* node, long param, long value) +{ + switch(param) { + case 0: + return simple_feature_tweak(node, macio_ohare, + OHARE_FCR, OH_IDE0_RESET_N, !value); + case 1: + return simple_feature_tweak(node, macio_ohare, + OHARE_FCR, OH_IDE1_RESET_N, !value); + default: + return -ENODEV; + } +} + +static long +ohare_sleep_state(struct device_node* node, long param, long value) +{ + struct macio_chip* macio = &macio_chips[0]; + + if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) + return -EPERM; + if (value == 1) { + MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE); + } else if (value == 0) { + MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); + } + + return 0; +} + +static long +heathrow_modem_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio; + u8 gpio; + unsigned long flags; + + macio = macio_find(node, macio_unknown); + if (!macio) + return -ENODEV; + gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1; + if (!value) { + LOCK(flags); + MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio); + UNLOCK(flags); + (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); + mdelay(250); + } + if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE && + pmac_mb.model_id != PMAC_TYPE_YIKES) { + LOCK(flags); + if (value) + MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); + else + MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); + UNLOCK(flags); + (void)MACIO_IN32(HEATHROW_FCR); + mdelay(250); + } + if (value) { + LOCK(flags); + MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); + (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); + UNLOCK(flags); mdelay(250); LOCK(flags); + MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio); + (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); + UNLOCK(flags); mdelay(250); LOCK(flags); + MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); + (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); + UNLOCK(flags); mdelay(250); + } + return 0; +} + +static long +heathrow_floppy_enable(struct device_node* node, long param, long value) +{ + return simple_feature_tweak(node, macio_unknown, + HEATHROW_FCR, + HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE, + value); +} + +static long +heathrow_mesh_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio; + unsigned long flags; + + macio = macio_find(node, macio_unknown); + if (!macio) + return -ENODEV; + LOCK(flags); + /* Set clear mesh cell enable */ + if (value) + MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE); + else + MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE); + (void)MACIO_IN32(HEATHROW_FCR); + udelay(10); + /* Set/Clear termination power */ + if (value) + MACIO_BIC(HEATHROW_MBCR, 0x04000000); + else + MACIO_BIS(HEATHROW_MBCR, 0x04000000); + (void)MACIO_IN32(HEATHROW_MBCR); + udelay(10); + UNLOCK(flags); + + return 0; +} + +static long +heathrow_ide_enable(struct device_node* node, long param, long value) +{ + switch(param) { + case 0: + return simple_feature_tweak(node, macio_unknown, + HEATHROW_FCR, HRW_IDE0_ENABLE, value); + case 1: + return simple_feature_tweak(node, macio_unknown, + HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value); + default: + return -ENODEV; + } +} + +static long +heathrow_ide_reset(struct device_node* node, long param, long value) +{ + switch(param) { + case 0: + return simple_feature_tweak(node, macio_unknown, + HEATHROW_FCR, HRW_IDE0_RESET_N, !value); + case 1: + return simple_feature_tweak(node, macio_unknown, + HEATHROW_FCR, HRW_IDE1_RESET_N, !value); + default: + return -ENODEV; + } +} + +static long +heathrow_bmac_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio; + unsigned long flags; + + macio = macio_find(node, 0); + if (!macio) + return -ENODEV; + if (value) { + LOCK(flags); + MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE); + MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET); + UNLOCK(flags); + (void)MACIO_IN32(HEATHROW_FCR); + mdelay(10); + LOCK(flags); + MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET); + UNLOCK(flags); + (void)MACIO_IN32(HEATHROW_FCR); + mdelay(10); + } else { + LOCK(flags); + MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE); + UNLOCK(flags); + } + return 0; +} + +static long +heathrow_sound_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio; + unsigned long flags; + + /* B&W G3 and Yikes don't support that properly (the + * sound appear to never come back after beeing shut down). + */ + if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE || + pmac_mb.model_id == PMAC_TYPE_YIKES) + return 0; + + macio = macio_find(node, 0); + if (!macio) + return -ENODEV; + if (value) { + LOCK(flags); + MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); + MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); + UNLOCK(flags); + (void)MACIO_IN32(HEATHROW_FCR); + } else { + LOCK(flags); + MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N); + MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); + UNLOCK(flags); + } + return 0; +} + +static u32 save_fcr[6]; +static u32 save_mbcr; +static u32 save_gpio_levels[2]; +static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT]; +static u8 save_gpio_normal[KEYLARGO_GPIO_CNT]; +static u32 save_unin_clock_ctl; +static struct dbdma_regs save_dbdma[13]; +static struct dbdma_regs save_alt_dbdma[13]; + +static void +dbdma_save(struct macio_chip* macio, struct dbdma_regs* save) +{ + int i; + + /* Save state & config of DBDMA channels */ + for (i=0; i<13; i++) { + volatile struct dbdma_regs __iomem * chan = (void __iomem *) + (macio->base + ((0x8000+i*0x100)>>2)); + save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi); + save[i].cmdptr = in_le32(&chan->cmdptr); + save[i].intr_sel = in_le32(&chan->intr_sel); + save[i].br_sel = in_le32(&chan->br_sel); + save[i].wait_sel = in_le32(&chan->wait_sel); + } +} + +static void +dbdma_restore(struct macio_chip* macio, struct dbdma_regs* save) +{ + int i; + + /* Save state & config of DBDMA channels */ + for (i=0; i<13; i++) { + volatile struct dbdma_regs __iomem * chan = (void __iomem *) + (macio->base + ((0x8000+i*0x100)>>2)); + out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16); + while (in_le32(&chan->status) & ACTIVE) + mb(); + out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi); + out_le32(&chan->cmdptr, save[i].cmdptr); + out_le32(&chan->intr_sel, save[i].intr_sel); + out_le32(&chan->br_sel, save[i].br_sel); + out_le32(&chan->wait_sel, save[i].wait_sel); + } +} + +static void +heathrow_sleep(struct macio_chip* macio, int secondary) +{ + if (secondary) { + dbdma_save(macio, save_alt_dbdma); + save_fcr[2] = MACIO_IN32(0x38); + save_fcr[3] = MACIO_IN32(0x3c); + } else { + dbdma_save(macio, save_dbdma); + save_fcr[0] = MACIO_IN32(0x38); + save_fcr[1] = MACIO_IN32(0x3c); + save_mbcr = MACIO_IN32(0x34); + /* Make sure sound is shut down */ + MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N); + MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); + /* This seems to be necessary as well or the fan + * keeps coming up and battery drains fast */ + MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE); + MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N); + /* Make sure eth is down even if module or sleep + * won't work properly */ + MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET); + } + /* Make sure modem is shut down */ + MACIO_OUT8(HRW_GPIO_MODEM_RESET, + MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1); + MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); + MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE); + + /* Let things settle */ + (void)MACIO_IN32(HEATHROW_FCR); +} + +static void +heathrow_wakeup(struct macio_chip* macio, int secondary) +{ + if (secondary) { + MACIO_OUT32(0x38, save_fcr[2]); + (void)MACIO_IN32(0x38); + mdelay(1); + MACIO_OUT32(0x3c, save_fcr[3]); + (void)MACIO_IN32(0x38); + mdelay(10); + dbdma_restore(macio, save_alt_dbdma); + } else { + MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE); + (void)MACIO_IN32(0x38); + mdelay(1); + MACIO_OUT32(0x3c, save_fcr[1]); + (void)MACIO_IN32(0x38); + mdelay(1); + MACIO_OUT32(0x34, save_mbcr); + (void)MACIO_IN32(0x38); + mdelay(10); + dbdma_restore(macio, save_dbdma); + } +} + +static long +heathrow_sleep_state(struct device_node* node, long param, long value) +{ + if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) + return -EPERM; + if (value == 1) { + if (macio_chips[1].type == macio_gatwick) + heathrow_sleep(&macio_chips[0], 1); + heathrow_sleep(&macio_chips[0], 0); + } else if (value == 0) { + heathrow_wakeup(&macio_chips[0], 0); + if (macio_chips[1].type == macio_gatwick) + heathrow_wakeup(&macio_chips[0], 1); + } + return 0; +} + +static long +core99_scc_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio; + unsigned long flags; + unsigned long chan_mask; + u32 fcr; + + macio = macio_find(node, 0); + if (!macio) + return -ENODEV; + if (!strcmp(node->name, "ch-a")) + chan_mask = MACIO_FLAG_SCCA_ON; + else if (!strcmp(node->name, "ch-b")) + chan_mask = MACIO_FLAG_SCCB_ON; + else + return -ENODEV; + + if (value) { + int need_reset_scc = 0; + int need_reset_irda = 0; + + LOCK(flags); + fcr = MACIO_IN32(KEYLARGO_FCR0); + /* Check if scc cell need enabling */ + if (!(fcr & KL0_SCC_CELL_ENABLE)) { + fcr |= KL0_SCC_CELL_ENABLE; + need_reset_scc = 1; + } + if (chan_mask & MACIO_FLAG_SCCA_ON) { + fcr |= KL0_SCCA_ENABLE; + /* Don't enable line drivers for I2S modem */ + if ((param & 0xfff) == PMAC_SCC_I2S1) + fcr &= ~KL0_SCC_A_INTF_ENABLE; + else + fcr |= KL0_SCC_A_INTF_ENABLE; + } + if (chan_mask & MACIO_FLAG_SCCB_ON) { + fcr |= KL0_SCCB_ENABLE; + /* Perform irda specific inits */ + if ((param & 0xfff) == PMAC_SCC_IRDA) { + fcr &= ~KL0_SCC_B_INTF_ENABLE; + fcr |= KL0_IRDA_ENABLE; + fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE; + fcr |= KL0_IRDA_SOURCE1_SEL; + fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); + fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); + need_reset_irda = 1; + } else + fcr |= KL0_SCC_B_INTF_ENABLE; + } + MACIO_OUT32(KEYLARGO_FCR0, fcr); + macio->flags |= chan_mask; + if (need_reset_scc) { + MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET); + (void)MACIO_IN32(KEYLARGO_FCR0); + UNLOCK(flags); + mdelay(15); + LOCK(flags); + MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET); + } + if (need_reset_irda) { + MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET); + (void)MACIO_IN32(KEYLARGO_FCR0); + UNLOCK(flags); + mdelay(15); + LOCK(flags); + MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET); + } + UNLOCK(flags); + if (param & PMAC_SCC_FLAG_XMON) + macio->flags |= MACIO_FLAG_SCC_LOCKED; + } else { + if (macio->flags & MACIO_FLAG_SCC_LOCKED) + return -EPERM; + LOCK(flags); + fcr = MACIO_IN32(KEYLARGO_FCR0); + if (chan_mask & MACIO_FLAG_SCCA_ON) + fcr &= ~KL0_SCCA_ENABLE; + if (chan_mask & MACIO_FLAG_SCCB_ON) { + fcr &= ~KL0_SCCB_ENABLE; + /* Perform irda specific clears */ + if ((param & 0xfff) == PMAC_SCC_IRDA) { + fcr &= ~KL0_IRDA_ENABLE; + fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE); + fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); + fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); + } + } + MACIO_OUT32(KEYLARGO_FCR0, fcr); + if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) { + fcr &= ~KL0_SCC_CELL_ENABLE; + MACIO_OUT32(KEYLARGO_FCR0, fcr); + } + macio->flags &= ~(chan_mask); + UNLOCK(flags); + mdelay(10); + } + return 0; +} + +static long +core99_modem_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio; + u8 gpio; + unsigned long flags; + + /* Hack for internal USB modem */ + if (node == NULL) { + if (macio_chips[0].type != macio_keylargo) + return -ENODEV; + node = macio_chips[0].of_node; + } + macio = macio_find(node, 0); + if (!macio) + return -ENODEV; + gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); + gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; + gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; + + if (!value) { + LOCK(flags); + MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); + UNLOCK(flags); + (void)MACIO_IN8(KL_GPIO_MODEM_RESET); + mdelay(250); + } + LOCK(flags); + if (value) { + MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); + UNLOCK(flags); + (void)MACIO_IN32(KEYLARGO_FCR2); + mdelay(250); + } else { + MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); + UNLOCK(flags); + } + if (value) { + LOCK(flags); + MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); + (void)MACIO_IN8(KL_GPIO_MODEM_RESET); + UNLOCK(flags); mdelay(250); LOCK(flags); + MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); + (void)MACIO_IN8(KL_GPIO_MODEM_RESET); + UNLOCK(flags); mdelay(250); LOCK(flags); + MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); + (void)MACIO_IN8(KL_GPIO_MODEM_RESET); + UNLOCK(flags); mdelay(250); + } + return 0; +} + +static long +pangea_modem_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio; + u8 gpio; + unsigned long flags; + + /* Hack for internal USB modem */ + if (node == NULL) { + if (macio_chips[0].type != macio_pangea && + macio_chips[0].type != macio_intrepid) + return -ENODEV; + node = macio_chips[0].of_node; + } + macio = macio_find(node, 0); + if (!macio) + return -ENODEV; + gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); + gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; + gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; + + if (!value) { + LOCK(flags); + MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); + UNLOCK(flags); + (void)MACIO_IN8(KL_GPIO_MODEM_RESET); + mdelay(250); + } + LOCK(flags); + if (value) { + MACIO_OUT8(KL_GPIO_MODEM_POWER, + KEYLARGO_GPIO_OUTPUT_ENABLE); + UNLOCK(flags); + (void)MACIO_IN32(KEYLARGO_FCR2); + mdelay(250); + } else { + MACIO_OUT8(KL_GPIO_MODEM_POWER, + KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); + UNLOCK(flags); + } + if (value) { + LOCK(flags); + MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); + (void)MACIO_IN8(KL_GPIO_MODEM_RESET); + UNLOCK(flags); mdelay(250); LOCK(flags); + MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); + (void)MACIO_IN8(KL_GPIO_MODEM_RESET); + UNLOCK(flags); mdelay(250); LOCK(flags); + MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); + (void)MACIO_IN8(KL_GPIO_MODEM_RESET); + UNLOCK(flags); mdelay(250); + } + return 0; +} + +static long +core99_ata100_enable(struct device_node* node, long value) +{ + unsigned long flags; + struct pci_dev *pdev = NULL; + u8 pbus, pid; + + if (uninorth_rev < 0x24) + return -ENODEV; + + LOCK(flags); + if (value) + UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); + else + UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); + (void)UN_IN(UNI_N_CLOCK_CNTL); + UNLOCK(flags); + udelay(20); + + if (value) { + if (pci_device_from_OF_node(node, &pbus, &pid) == 0) + pdev = pci_find_slot(pbus, pid); + if (pdev == NULL) + return 0; + pci_enable_device(pdev); + pci_set_master(pdev); + } + return 0; +} + +static long +core99_ide_enable(struct device_node* node, long param, long value) +{ + /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2 + * based ata-100 + */ + switch(param) { + case 0: + return simple_feature_tweak(node, macio_unknown, + KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value); + case 1: + return simple_feature_tweak(node, macio_unknown, + KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value); + case 2: + return simple_feature_tweak(node, macio_unknown, + KEYLARGO_FCR1, KL1_UIDE_ENABLE, value); + case 3: + return core99_ata100_enable(node, value); + default: + return -ENODEV; + } +} + +static long +core99_ide_reset(struct device_node* node, long param, long value) +{ + switch(param) { + case 0: + return simple_feature_tweak(node, macio_unknown, + KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value); + case 1: + return simple_feature_tweak(node, macio_unknown, + KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value); + case 2: + return simple_feature_tweak(node, macio_unknown, + KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value); + default: + return -ENODEV; + } +} + +static long +core99_gmac_enable(struct device_node* node, long param, long value) +{ + unsigned long flags; + + LOCK(flags); + if (value) + UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); + else + UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); + (void)UN_IN(UNI_N_CLOCK_CNTL); + UNLOCK(flags); + udelay(20); + + return 0; +} + +static long +core99_gmac_phy_reset(struct device_node* node, long param, long value) +{ + unsigned long flags; + struct macio_chip* macio; + + macio = &macio_chips[0]; + if (macio->type != macio_keylargo && macio->type != macio_pangea && + macio->type != macio_intrepid) + return -ENODEV; + + LOCK(flags); + MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET); + UNLOCK(flags); + mdelay(10); + LOCK(flags); + MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */ + KEYLARGO_GPIO_OUTOUT_DATA); + UNLOCK(flags); + mdelay(10); + + return 0; +} + +static long +core99_sound_chip_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio; + unsigned long flags; + + macio = macio_find(node, 0); + if (!macio) + return -ENODEV; + + /* Do a better probe code, screamer G4 desktops & + * iMacs can do that too, add a recalibrate in + * the driver as well + */ + if (pmac_mb.model_id == PMAC_TYPE_PISMO || + pmac_mb.model_id == PMAC_TYPE_TITANIUM) { + LOCK(flags); + if (value) + MACIO_OUT8(KL_GPIO_SOUND_POWER, + KEYLARGO_GPIO_OUTPUT_ENABLE | + KEYLARGO_GPIO_OUTOUT_DATA); + else + MACIO_OUT8(KL_GPIO_SOUND_POWER, + KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)MACIO_IN8(KL_GPIO_SOUND_POWER); + UNLOCK(flags); + } + return 0; +} + +static long +core99_airport_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio; + unsigned long flags; + int state; + + macio = macio_find(node, 0); + if (!macio) + return -ENODEV; + + /* Hint: we allow passing of macio itself for the sake of the + * sleep code + */ + if (node != macio->of_node && + (!node->parent || node->parent != macio->of_node)) + return -ENODEV; + state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0; + if (value == state) + return 0; + if (value) { + /* This code is a reproduction of OF enable-cardslot + * and init-wireless methods, slightly hacked until + * I got it working. + */ + LOCK(flags); + MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5); + (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf); + UNLOCK(flags); + mdelay(10); + LOCK(flags); + MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4); + (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf); + UNLOCK(flags); + + mdelay(10); + + LOCK(flags); + MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16); + (void)MACIO_IN32(KEYLARGO_FCR2); + udelay(10); + MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0); + (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb); + udelay(10); + MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28); + (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa); + udelay(10); + MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28); + (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd); + udelay(10); + MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28); + (void)MACIO_IN8(KEYLARGO_GPIO_0+0xd); + udelay(10); + MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28); + (void)MACIO_IN8(KEYLARGO_GPIO_0+0xe); + UNLOCK(flags); + udelay(10); + MACIO_OUT32(0x1c000, 0); + mdelay(1); + MACIO_OUT8(0x1a3e0, 0x41); + (void)MACIO_IN8(0x1a3e0); + udelay(10); + LOCK(flags); + MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16); + (void)MACIO_IN32(KEYLARGO_FCR2); + UNLOCK(flags); + mdelay(100); + + macio->flags |= MACIO_FLAG_AIRPORT_ON; + } else { + LOCK(flags); + MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16); + (void)MACIO_IN32(KEYLARGO_FCR2); + MACIO_OUT8(KL_GPIO_AIRPORT_0, 0); + MACIO_OUT8(KL_GPIO_AIRPORT_1, 0); + MACIO_OUT8(KL_GPIO_AIRPORT_2, 0); + MACIO_OUT8(KL_GPIO_AIRPORT_3, 0); + MACIO_OUT8(KL_GPIO_AIRPORT_4, 0); + (void)MACIO_IN8(KL_GPIO_AIRPORT_4); + UNLOCK(flags); + + macio->flags &= ~MACIO_FLAG_AIRPORT_ON; + } + return 0; +} + +#ifdef CONFIG_SMP +static long +core99_reset_cpu(struct device_node* node, long param, long value) +{ + unsigned int reset_io = 0; + unsigned long flags; + struct macio_chip* macio; + struct device_node* np; + const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0, + KL_GPIO_RESET_CPU1, + KL_GPIO_RESET_CPU2, + KL_GPIO_RESET_CPU3 }; + + macio = &macio_chips[0]; + if (macio->type != macio_keylargo) + return -ENODEV; + + np = find_path_device("/cpus"); + if (np == NULL) + return -ENODEV; + for (np = np->child; np != NULL; np = np->sibling) { + u32* num = (u32 *)get_property(np, "reg", NULL); + u32* rst = (u32 *)get_property(np, "soft-reset", NULL); + if (num == NULL || rst == NULL) + continue; + if (param == *num) { + reset_io = *rst; + break; + } + } + if (np == NULL || reset_io == 0) + reset_io = dflt_reset_lines[param]; + + LOCK(flags); + MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)MACIO_IN8(reset_io); + udelay(1); + MACIO_OUT8(reset_io, 0); + (void)MACIO_IN8(reset_io); + UNLOCK(flags); + + return 0; +} +#endif /* CONFIG_SMP */ + +static long +core99_usb_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio; + unsigned long flags; + char* prop; + int number; + u32 reg; + + macio = &macio_chips[0]; + if (macio->type != macio_keylargo && macio->type != macio_pangea && + macio->type != macio_intrepid) + return -ENODEV; + + prop = (char *)get_property(node, "AAPL,clock-id", NULL); + if (!prop) + return -ENODEV; + if (strncmp(prop, "usb0u048", 8) == 0) + number = 0; + else if (strncmp(prop, "usb1u148", 8) == 0) + number = 2; + else if (strncmp(prop, "usb2u248", 8) == 0) + number = 4; + else + return -ENODEV; + + /* Sorry for the brute-force locking, but this is only used during + * sleep and the timing seem to be critical + */ + LOCK(flags); + if (value) { + /* Turn ON */ + if (number == 0) { + MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); + (void)MACIO_IN32(KEYLARGO_FCR0); + UNLOCK(flags); + mdelay(1); + LOCK(flags); + MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); + } else if (number == 2) { + MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); + UNLOCK(flags); + (void)MACIO_IN32(KEYLARGO_FCR0); + mdelay(1); + LOCK(flags); + MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); + } else if (number == 4) { + MACIO_BIC(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); + UNLOCK(flags); + (void)MACIO_IN32(KEYLARGO_FCR1); + mdelay(1); + LOCK(flags); + MACIO_BIS(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE); + } + if (number < 4) { + reg = MACIO_IN32(KEYLARGO_FCR4); + reg &= ~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | + KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number)); + reg &= ~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | + KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1)); + MACIO_OUT32(KEYLARGO_FCR4, reg); + (void)MACIO_IN32(KEYLARGO_FCR4); + udelay(10); + } else { + reg = MACIO_IN32(KEYLARGO_FCR3); + reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | + KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0)); + reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | + KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1)); + MACIO_OUT32(KEYLARGO_FCR3, reg); + (void)MACIO_IN32(KEYLARGO_FCR3); + udelay(10); + } + if (macio->type == macio_intrepid) { + /* wait for clock stopped bits to clear */ + u32 test0 = 0, test1 = 0; + u32 status0, status1; + int timeout = 1000; + + UNLOCK(flags); + switch (number) { + case 0: + test0 = UNI_N_CLOCK_STOPPED_USB0; + test1 = UNI_N_CLOCK_STOPPED_USB0PCI; + break; + case 2: + test0 = UNI_N_CLOCK_STOPPED_USB1; + test1 = UNI_N_CLOCK_STOPPED_USB1PCI; + break; + case 4: + test0 = UNI_N_CLOCK_STOPPED_USB2; + test1 = UNI_N_CLOCK_STOPPED_USB2PCI; + break; + } + do { + if (--timeout <= 0) { + printk(KERN_ERR "core99_usb_enable: " + "Timeout waiting for clocks\n"); + break; + } + mdelay(1); + status0 = UN_IN(UNI_N_CLOCK_STOP_STATUS0); + status1 = UN_IN(UNI_N_CLOCK_STOP_STATUS1); + } while ((status0 & test0) | (status1 & test1)); + LOCK(flags); + } + } else { + /* Turn OFF */ + if (number < 4) { + reg = MACIO_IN32(KEYLARGO_FCR4); + reg |= KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | + KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number); + reg |= KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | + KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1); + MACIO_OUT32(KEYLARGO_FCR4, reg); + (void)MACIO_IN32(KEYLARGO_FCR4); + udelay(1); + } else { + reg = MACIO_IN32(KEYLARGO_FCR3); + reg |= KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | + KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0); + reg |= KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | + KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1); + MACIO_OUT32(KEYLARGO_FCR3, reg); + (void)MACIO_IN32(KEYLARGO_FCR3); + udelay(1); + } + if (number == 0) { + if (macio->type != macio_intrepid) + MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); + (void)MACIO_IN32(KEYLARGO_FCR0); + udelay(1); + MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); + (void)MACIO_IN32(KEYLARGO_FCR0); + } else if (number == 2) { + if (macio->type != macio_intrepid) + MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); + (void)MACIO_IN32(KEYLARGO_FCR0); + udelay(1); + MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); + (void)MACIO_IN32(KEYLARGO_FCR0); + } else if (number == 4) { + udelay(1); + MACIO_BIS(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); + (void)MACIO_IN32(KEYLARGO_FCR1); + } + udelay(1); + } + UNLOCK(flags); + + return 0; +} + +static long +core99_firewire_enable(struct device_node* node, long param, long value) +{ + unsigned long flags; + struct macio_chip* macio; + + macio = &macio_chips[0]; + if (macio->type != macio_keylargo && macio->type != macio_pangea && + macio->type != macio_intrepid) + return -ENODEV; + if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) + return -ENODEV; + + LOCK(flags); + if (value) { + UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); + (void)UN_IN(UNI_N_CLOCK_CNTL); + } else { + UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); + (void)UN_IN(UNI_N_CLOCK_CNTL); + } + UNLOCK(flags); + mdelay(1); + + return 0; +} + +static long +core99_firewire_cable_power(struct device_node* node, long param, long value) +{ + unsigned long flags; + struct macio_chip* macio; + + /* Trick: we allow NULL node */ + if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0) + return -ENODEV; + macio = &macio_chips[0]; + if (macio->type != macio_keylargo && macio->type != macio_pangea && + macio->type != macio_intrepid) + return -ENODEV; + if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) + return -ENODEV; + + LOCK(flags); + if (value) { + MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0); + MACIO_IN8(KL_GPIO_FW_CABLE_POWER); + udelay(10); + } else { + MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4); + MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10); + } + UNLOCK(flags); + mdelay(1); + + return 0; +} + +static long +intrepid_aack_delay_enable(struct device_node* node, long param, long value) +{ + unsigned long flags; + + if (uninorth_rev < 0xd2) + return -ENODEV; + + LOCK(flags); + if (param) + UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); + else + UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); + UNLOCK(flags); + + return 0; +} + + +#endif /* CONFIG_POWER4 */ + +static long +core99_read_gpio(struct device_node* node, long param, long value) +{ + struct macio_chip* macio = &macio_chips[0]; + + return MACIO_IN8(param); +} + + +static long +core99_write_gpio(struct device_node* node, long param, long value) +{ + struct macio_chip* macio = &macio_chips[0]; + + MACIO_OUT8(param, (u8)(value & 0xff)); + return 0; +} + +#ifdef CONFIG_POWER4 + +static long +g5_gmac_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio = &macio_chips[0]; + unsigned long flags; + u8 pbus, pid; + + LOCK(flags); + if (value) { + MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); + mb(); + k2_skiplist[0] = NULL; + } else { + k2_skiplist[0] = node; + mb(); + MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); + } + + UNLOCK(flags); + mdelay(1); + + return 0; +} + +static long +g5_fw_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio = &macio_chips[0]; + unsigned long flags; + + LOCK(flags); + if (value) { + MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); + mb(); + k2_skiplist[1] = NULL; + } else { + k2_skiplist[1] = node; + mb(); + MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); + } + + UNLOCK(flags); + mdelay(1); + + return 0; +} + +static long +g5_mpic_enable(struct device_node* node, long param, long value) +{ + unsigned long flags; + + if (node->parent == NULL || strcmp(node->parent->name, "u3")) + return 0; + + LOCK(flags); + UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE); + UNLOCK(flags); + + return 0; +} + +#ifdef CONFIG_SMP +static long +g5_reset_cpu(struct device_node* node, long param, long value) +{ + unsigned int reset_io = 0; + unsigned long flags; + struct macio_chip* macio; + struct device_node* np; + + macio = &macio_chips[0]; + if (macio->type != macio_keylargo2) + return -ENODEV; + + np = find_path_device("/cpus"); + if (np == NULL) + return -ENODEV; + for (np = np->child; np != NULL; np = np->sibling) { + u32* num = (u32 *)get_property(np, "reg", NULL); + u32* rst = (u32 *)get_property(np, "soft-reset", NULL); + if (num == NULL || rst == NULL) + continue; + if (param == *num) { + reset_io = *rst; + break; + } + } + if (np == NULL || reset_io == 0) + return -ENODEV; + + LOCK(flags); + MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)MACIO_IN8(reset_io); + udelay(1); + MACIO_OUT8(reset_io, 0); + (void)MACIO_IN8(reset_io); + UNLOCK(flags); + + return 0; +} +#endif /* CONFIG_SMP */ + +/* + * This can be called from pmac_smp so isn't static + * + * This takes the second CPU off the bus on dual CPU machines + * running UP + */ +void g5_phy_disable_cpu1(void) +{ + UN_OUT(U3_API_PHY_CONFIG_1, 0); +} + +#endif /* CONFIG_POWER4 */ + +#ifndef CONFIG_POWER4 + +static void +keylargo_shutdown(struct macio_chip* macio, int sleep_mode) +{ + u32 temp; + + if (sleep_mode) { + mdelay(1); + MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND); + (void)MACIO_IN32(KEYLARGO_FCR0); + mdelay(1); + } + + MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | + KL0_SCC_CELL_ENABLE | + KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE | + KL0_IRDA_CLK19_ENABLE); + + MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK); + MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE); + + MACIO_BIC(KEYLARGO_FCR1, + KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | + KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE | + KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | + KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | + KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | + KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N | + KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N | + KL1_UIDE_ENABLE); + + MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); + MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE); + + temp = MACIO_IN32(KEYLARGO_FCR3); + if (macio->rev >= 2) { + temp |= KL3_SHUTDOWN_PLL2X; + if (sleep_mode) + temp |= KL3_SHUTDOWN_PLL_TOTAL; + } + + temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | + KL3_SHUTDOWN_PLLKW35; + if (sleep_mode) + temp |= KL3_SHUTDOWN_PLLKW12; + temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE + | KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); + if (sleep_mode) + temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE); + MACIO_OUT32(KEYLARGO_FCR3, temp); + + /* Flush posted writes & wait a bit */ + (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); +} + +static void +pangea_shutdown(struct macio_chip* macio, int sleep_mode) +{ + u32 temp; + + MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | + KL0_SCC_CELL_ENABLE | + KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE); + + MACIO_BIC(KEYLARGO_FCR1, + KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | + KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE | + KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | + KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | + KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | + KL1_UIDE_ENABLE); + if (pmac_mb.board_flags & PMAC_MB_MOBILE) + MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); + + MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); + + temp = MACIO_IN32(KEYLARGO_FCR3); + temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | + KL3_SHUTDOWN_PLLKW35; + temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE + | KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE); + if (sleep_mode) + temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE); + MACIO_OUT32(KEYLARGO_FCR3, temp); + + /* Flush posted writes & wait a bit */ + (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); +} + +static void +intrepid_shutdown(struct macio_chip* macio, int sleep_mode) +{ + u32 temp; + + MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | + KL0_SCC_CELL_ENABLE); + + MACIO_BIC(KEYLARGO_FCR1, + /*KL1_USB2_CELL_ENABLE |*/ + KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | + KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | + KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE); + if (pmac_mb.board_flags & PMAC_MB_MOBILE) + MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); + + temp = MACIO_IN32(KEYLARGO_FCR3); + temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | + KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); + if (sleep_mode) + temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE); + MACIO_OUT32(KEYLARGO_FCR3, temp); + + /* Flush posted writes & wait a bit */ + (void)MACIO_IN32(KEYLARGO_FCR0); + mdelay(10); +} + + +void pmac_tweak_clock_spreading(int enable) +{ + struct macio_chip* macio = &macio_chips[0]; + + /* Hack for doing clock spreading on some machines PowerBooks and + * iBooks. This implements the "platform-do-clockspreading" OF + * property as decoded manually on various models. For safety, we also + * check the product ID in the device-tree in cases we'll whack the i2c + * chip to make reasonably sure we won't set wrong values in there + * + * Of course, ultimately, we have to implement a real parser for + * the platform-do-* stuff... + */ + + if (macio->type == macio_intrepid) { + struct device_node *clock = + of_find_node_by_path("/uni-n@f8000000/hw-clock"); + if (clock && get_property(clock, "platform-do-clockspreading", + NULL)) { + printk(KERN_INFO "%sabling clock spreading on Intrepid" + " ASIC\n", enable ? "En" : "Dis"); + if (enable) + UN_OUT(UNI_N_CLOCK_SPREADING, 2); + else + UN_OUT(UNI_N_CLOCK_SPREADING, 0); + mdelay(40); + } + of_node_put(clock); + } + + while (machine_is_compatible("PowerBook5,2") || + machine_is_compatible("PowerBook5,3") || + machine_is_compatible("PowerBook6,2") || + machine_is_compatible("PowerBook6,3")) { + struct device_node *ui2c = of_find_node_by_type(NULL, "i2c"); + struct device_node *dt = of_find_node_by_name(NULL, "device-tree"); + u8 buffer[9]; + u32 *productID; + int i, rc, changed = 0; + + if (dt == NULL) + break; + productID = (u32 *)get_property(dt, "pid#", NULL); + if (productID == NULL) + break; + while(ui2c) { + struct device_node *p = of_get_parent(ui2c); + if (p && !strcmp(p->name, "uni-n")) + break; + ui2c = of_find_node_by_type(ui2c, "i2c"); + } + if (ui2c == NULL) + break; + DBG("Trying to bump clock speed for PID: %08x...\n", *productID); + rc = pmac_low_i2c_open(ui2c, 1); + if (rc != 0) + break; + pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); + rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); + DBG("read result: %d,", rc); + if (rc != 0) { + pmac_low_i2c_close(ui2c); + break; + } + for (i=0; i<9; i++) + DBG(" %02x", buffer[i]); + DBG("\n"); + + switch(*productID) { + case 0x1182: /* AlBook 12" rev 2 */ + case 0x1183: /* iBook G4 12" */ + buffer[0] = (buffer[0] & 0x8f) | 0x70; + buffer[2] = (buffer[2] & 0x7f) | 0x00; + buffer[5] = (buffer[5] & 0x80) | 0x31; + buffer[6] = (buffer[6] & 0x40) | 0xb0; + buffer[7] = (buffer[7] & 0x00) | (enable ? 0xc0 : 0xba); + buffer[8] = (buffer[8] & 0x00) | 0x30; + changed = 1; + break; + case 0x3142: /* AlBook 15" (ATI M10) */ + case 0x3143: /* AlBook 17" (ATI M10) */ + buffer[0] = (buffer[0] & 0xaf) | 0x50; + buffer[2] = (buffer[2] & 0x7f) | 0x00; + buffer[5] = (buffer[5] & 0x80) | 0x31; + buffer[6] = (buffer[6] & 0x40) | 0xb0; + buffer[7] = (buffer[7] & 0x00) | (enable ? 0xd0 : 0xc0); + buffer[8] = (buffer[8] & 0x00) | 0x30; + changed = 1; + break; + default: + DBG("i2c-hwclock: Machine model not handled\n"); + break; + } + if (!changed) { + pmac_low_i2c_close(ui2c); + break; + } + printk(KERN_INFO "%sabling clock spreading on i2c clock chip\n", + enable ? "En" : "Dis"); + pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub); + rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9); + DBG("write result: %d,", rc); + pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); + rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); + DBG("read result: %d,", rc); + if (rc != 0) { + pmac_low_i2c_close(ui2c); + break; + } + for (i=0; i<9; i++) + DBG(" %02x", buffer[i]); + pmac_low_i2c_close(ui2c); + break; + } +} + + +static int +core99_sleep(void) +{ + struct macio_chip* macio; + int i; + + macio = &macio_chips[0]; + if (macio->type != macio_keylargo && macio->type != macio_pangea && + macio->type != macio_intrepid) + return -ENODEV; + + /* We power off the wireless slot in case it was not done + * by the driver. We don't power it on automatically however + */ + if (macio->flags & MACIO_FLAG_AIRPORT_ON) + core99_airport_enable(macio->of_node, 0, 0); + + /* We power off the FW cable. Should be done by the driver... */ + if (macio->flags & MACIO_FLAG_FW_SUPPORTED) { + core99_firewire_enable(NULL, 0, 0); + core99_firewire_cable_power(NULL, 0, 0); + } + + /* We make sure int. modem is off (in case driver lost it) */ + if (macio->type == macio_keylargo) + core99_modem_enable(macio->of_node, 0, 0); + else + pangea_modem_enable(macio->of_node, 0, 0); + + /* We make sure the sound is off as well */ + core99_sound_chip_enable(macio->of_node, 0, 0); + + /* + * Save various bits of KeyLargo + */ + + /* Save the state of the various GPIOs */ + save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0); + save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1); + for (i=0; itype == macio_keylargo) + save_mbcr = MACIO_IN32(KEYLARGO_MBCR); + save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0); + save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1); + save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2); + save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3); + save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4); + if (macio->type == macio_pangea || macio->type == macio_intrepid) + save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5); + + /* Save state & config of DBDMA channels */ + dbdma_save(macio, save_dbdma); + + /* + * Turn off as much as we can + */ + if (macio->type == macio_pangea) + pangea_shutdown(macio, 1); + else if (macio->type == macio_intrepid) + intrepid_shutdown(macio, 1); + else if (macio->type == macio_keylargo) + keylargo_shutdown(macio, 1); + + /* + * Put the host bridge to sleep + */ + + save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL); + /* Note: do not switch GMAC off, driver does it when necessary, WOL must keep it + * enabled ! + */ + UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl & + ~(/*UNI_N_CLOCK_CNTL_GMAC|*/UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/)); + udelay(100); + UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING); + UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP); + mdelay(10); + + /* + * FIXME: A bit of black magic with OpenPIC (don't ask me why) + */ + if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) { + MACIO_BIS(0x506e0, 0x00400000); + MACIO_BIS(0x506e0, 0x80000000); + } + return 0; +} + +static int +core99_wake_up(void) +{ + struct macio_chip* macio; + int i; + + macio = &macio_chips[0]; + if (macio->type != macio_keylargo && macio->type != macio_pangea && + macio->type != macio_intrepid) + return -ENODEV; + + /* + * Wakeup the host bridge + */ + UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL); + udelay(10); + UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING); + udelay(10); + + /* + * Restore KeyLargo + */ + + if (macio->type == macio_keylargo) { + MACIO_OUT32(KEYLARGO_MBCR, save_mbcr); + (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10); + } + MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]); + (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10); + MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]); + (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10); + MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]); + (void)MACIO_IN32(KEYLARGO_FCR2); udelay(10); + MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]); + (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10); + MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]); + (void)MACIO_IN32(KEYLARGO_FCR4); udelay(10); + if (macio->type == macio_pangea || macio->type == macio_intrepid) { + MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]); + (void)MACIO_IN32(KEYLARGO_FCR5); udelay(10); + } + + dbdma_restore(macio, save_dbdma); + + MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]); + MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]); + for (i=0; itype) { +#ifndef CONFIG_POWER4 + case macio_grand_central: + pmac_mb.model_id = PMAC_TYPE_PSURGE; + pmac_mb.model_name = "Unknown PowerSurge"; + break; + case macio_ohare: + pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE; + pmac_mb.model_name = "Unknown OHare-based"; + break; + case macio_heathrow: + pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW; + pmac_mb.model_name = "Unknown Heathrow-based"; + pmac_mb.features = heathrow_desktop_features; + break; + case macio_paddington: + pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON; + pmac_mb.model_name = "Unknown Paddington-based"; + pmac_mb.features = paddington_features; + break; + case macio_keylargo: + pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99; + pmac_mb.model_name = "Unknown Keylargo-based"; + pmac_mb.features = core99_features; + break; + case macio_pangea: + pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA; + pmac_mb.model_name = "Unknown Pangea-based"; + pmac_mb.features = pangea_features; + break; + case macio_intrepid: + pmac_mb.model_id = PMAC_TYPE_UNKNOWN_INTREPID; + pmac_mb.model_name = "Unknown Intrepid-based"; + pmac_mb.features = intrepid_features; + break; +#else /* CONFIG_POWER4 */ + case macio_keylargo2: + pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; + pmac_mb.model_name = "Unknown G5"; + pmac_mb.features = g5_features; + break; +#endif /* CONFIG_POWER4 */ + default: + return -ENODEV; + } +found: +#ifndef CONFIG_POWER4 + /* Fixup Hooper vs. Comet */ + if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { + u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); + if (!mach_id_ptr) + return -ENODEV; + /* Here, I used to disable the media-bay on comet. It + * appears this is wrong, the floppy connector is actually + * a kind of media-bay and works with the current driver. + */ + if (__raw_readl(mach_id_ptr) & 0x20000000UL) + pmac_mb.model_id = PMAC_TYPE_COMET; + iounmap(mach_id_ptr); + } +#endif /* CONFIG_POWER4 */ + +#ifdef CONFIG_6xx + /* Set default value of powersave_nap on machines that support it. + * It appears that uninorth rev 3 has a problem with it, we don't + * enable it on those. In theory, the flush-on-lock property is + * supposed to be set when not supported, but I'm not very confident + * that all Apple OF revs did it properly, I do it the paranoid way. + */ + while (uninorth_base && uninorth_rev > 3) { + struct device_node* np = find_path_device("/cpus"); + if (!np || !np->child) { + printk(KERN_WARNING "Can't find CPU(s) in device tree !\n"); + break; + } + np = np->child; + /* Nap mode not supported on SMP */ + if (np->sibling) + break; + /* Nap mode not supported if flush-on-lock property is present */ + if (get_property(np, "flush-on-lock", NULL)) + break; + powersave_nap = 1; + printk(KERN_INFO "Processor NAP mode on idle enabled.\n"); + break; + } + + /* On CPUs that support it (750FX), lowspeed by default during + * NAP mode + */ + powersave_lowspeed = 1; +#endif /* CONFIG_6xx */ +#ifdef CONFIG_POWER4 + powersave_nap = 1; +#endif + /* Check for "mobile" machine */ + if (model && (strncmp(model, "PowerBook", 9) == 0 + || strncmp(model, "iBook", 5) == 0)) + pmac_mb.board_flags |= PMAC_MB_MOBILE; + + + printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name); + return 0; +} + +/* Initialize the Core99 UniNorth host bridge and memory controller + */ +static void __init +probe_uninorth(void) +{ + unsigned long actrl; + + /* Locate core99 Uni-N */ + uninorth_node = of_find_node_by_name(NULL, "uni-n"); + /* Locate G5 u3 */ + if (uninorth_node == NULL) { + uninorth_node = of_find_node_by_name(NULL, "u3"); + uninorth_u3 = 1; + } + if (uninorth_node && uninorth_node->n_addrs > 0) { + unsigned long address = uninorth_node->addrs[0].address; + uninorth_base = ioremap(address, 0x40000); + uninorth_rev = in_be32(UN_REG(UNI_N_VERSION)); + if (uninorth_u3) + u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000); + } else + uninorth_node = NULL; + + if (!uninorth_node) + return; + + printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n", + uninorth_u3 ? "U3" : "UniNorth", uninorth_rev); + printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base); + + /* Set the arbitrer QAck delay according to what Apple does + */ + if (uninorth_rev < 0x11) { + actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK; + actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 : + UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT; + UN_OUT(UNI_N_ARB_CTRL, actrl); + } + + /* Some more magic as done by them in recent MacOS X on UniNorth + * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI + * memory timeout + */ + if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0) + UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff); +} + +static void __init +probe_one_macio(const char* name, const char* compat, int type) +{ + struct device_node* node; + int i; + volatile u32 __iomem * base; + u32* revp; + + node = find_devices(name); + if (!node || !node->n_addrs) + return; + if (compat) + do { + if (device_is_compatible(node, compat)) + break; + node = node->next; + } while (node); + if (!node) + return; + for(i=0; i= MAX_MACIO_CHIPS) { + printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n"); + printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name); + return; + } + base = ioremap(node->addrs[0].address, node->addrs[0].size); + if (!base) { + printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n"); + return; + } + if (type == macio_keylargo) { + u32* did = (u32 *)get_property(node, "device-id", NULL); + if (*did == 0x00000025) + type = macio_pangea; + if (*did == 0x0000003e) + type = macio_intrepid; + } + macio_chips[i].of_node = node; + macio_chips[i].type = type; + macio_chips[i].base = base; + macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON; + macio_chips[i].name = macio_names[type]; + revp = (u32 *)get_property(node, "revision-id", NULL); + if (revp) + macio_chips[i].rev = *revp; + printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n", + macio_names[type], macio_chips[i].rev, macio_chips[i].base); +} + +static int __init +probe_macios(void) +{ + /* Warning, ordering is important */ + probe_one_macio("gc", NULL, macio_grand_central); + probe_one_macio("ohare", NULL, macio_ohare); + probe_one_macio("pci106b,7", NULL, macio_ohareII); + probe_one_macio("mac-io", "keylargo", macio_keylargo); + probe_one_macio("mac-io", "paddington", macio_paddington); + probe_one_macio("mac-io", "gatwick", macio_gatwick); + probe_one_macio("mac-io", "heathrow", macio_heathrow); + probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2); + + /* Make sure the "main" macio chip appear first */ + if (macio_chips[0].type == macio_gatwick + && macio_chips[1].type == macio_heathrow) { + struct macio_chip temp = macio_chips[0]; + macio_chips[0] = macio_chips[1]; + macio_chips[1] = temp; + } + if (macio_chips[0].type == macio_ohareII + && macio_chips[1].type == macio_ohare) { + struct macio_chip temp = macio_chips[0]; + macio_chips[0] = macio_chips[1]; + macio_chips[1] = temp; + } + macio_chips[0].lbus.index = 0; + macio_chips[1].lbus.index = 1; + + return (macio_chips[0].of_node == NULL) ? -ENODEV : 0; +} + +static void __init +initial_serial_shutdown(struct device_node* np) +{ + int len; + struct slot_names_prop { + int count; + char name[1]; + } *slots; + char *conn; + int port_type = PMAC_SCC_ASYNC; + int modem = 0; + + slots = (struct slot_names_prop *)get_property(np, "slot-names", &len); + conn = get_property(np, "AAPL,connector", &len); + if (conn && (strcmp(conn, "infrared") == 0)) + port_type = PMAC_SCC_IRDA; + else if (device_is_compatible(np, "cobalt")) + modem = 1; + else if (slots && slots->count > 0) { + if (strcmp(slots->name, "IrDA") == 0) + port_type = PMAC_SCC_IRDA; + else if (strcmp(slots->name, "Modem") == 0) + modem = 1; + } + if (modem) + pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0); + pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0); +} + +static void __init +set_initial_features(void) +{ + struct device_node* np; + + /* That hack appears to be necessary for some StarMax motherboards + * but I'm not too sure it was audited for side-effects on other + * ohare based machines... + * Since I still have difficulties figuring the right way to + * differenciate them all and since that hack was there for a long + * time, I'll keep it around + */ + if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) { + struct macio_chip* macio = &macio_chips[0]; + MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES); + } else if (macio_chips[0].type == macio_ohare) { + struct macio_chip* macio = &macio_chips[0]; + MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); + } else if (macio_chips[1].type == macio_ohare) { + struct macio_chip* macio = &macio_chips[1]; + MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); + } + +#ifdef CONFIG_POWER4 + if (macio_chips[0].type == macio_keylargo2) { +#ifndef CONFIG_SMP + /* On SMP machines running UP, we have the second CPU eating + * bus cycles. We need to take it off the bus. This is done + * from pmac_smp for SMP kernels running on one CPU + */ + np = of_find_node_by_type(NULL, "cpu"); + if (np != NULL) + np = of_find_node_by_type(np, "cpu"); + if (np != NULL) { + g5_phy_disable_cpu1(); + of_node_put(np); + } +#endif /* CONFIG_SMP */ + /* Enable GMAC for now for PCI probing. It will be disabled + * later on after PCI probe + */ + np = of_find_node_by_name(NULL, "ethernet"); + while(np) { + if (device_is_compatible(np, "K2-GMAC")) + g5_gmac_enable(np, 0, 1); + np = of_find_node_by_name(np, "ethernet"); + } + + /* Enable FW before PCI probe. Will be disabled later on + * Note: We should have a batter way to check that we are + * dealing with uninorth internal cell and not a PCI cell + * on the external PCI. The code below works though. + */ + np = of_find_node_by_name(NULL, "firewire"); + while(np) { + if (device_is_compatible(np, "pci106b,5811")) { + macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; + g5_fw_enable(np, 0, 1); + } + np = of_find_node_by_name(np, "firewire"); + } + } +#else /* CONFIG_POWER4 */ + + if (macio_chips[0].type == macio_keylargo || + macio_chips[0].type == macio_pangea || + macio_chips[0].type == macio_intrepid) { + /* Enable GMAC for now for PCI probing. It will be disabled + * later on after PCI probe + */ + np = of_find_node_by_name(NULL, "ethernet"); + while(np) { + if (np->parent + && device_is_compatible(np->parent, "uni-north") + && device_is_compatible(np, "gmac")) + core99_gmac_enable(np, 0, 1); + np = of_find_node_by_name(np, "ethernet"); + } + + /* Enable FW before PCI probe. Will be disabled later on + * Note: We should have a batter way to check that we are + * dealing with uninorth internal cell and not a PCI cell + * on the external PCI. The code below works though. + */ + np = of_find_node_by_name(NULL, "firewire"); + while(np) { + if (np->parent + && device_is_compatible(np->parent, "uni-north") + && (device_is_compatible(np, "pci106b,18") || + device_is_compatible(np, "pci106b,30") || + device_is_compatible(np, "pci11c1,5811"))) { + macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; + core99_firewire_enable(np, 0, 1); + } + np = of_find_node_by_name(np, "firewire"); + } + + /* Enable ATA-100 before PCI probe. */ + np = of_find_node_by_name(NULL, "ata-6"); + while(np) { + if (np->parent + && device_is_compatible(np->parent, "uni-north") + && device_is_compatible(np, "kauai-ata")) { + core99_ata100_enable(np, 1); + } + np = of_find_node_by_name(np, "ata-6"); + } + + /* Switch airport off */ + np = find_devices("radio"); + while(np) { + if (np && np->parent == macio_chips[0].of_node) { + macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON; + core99_airport_enable(np, 0, 0); + } + np = np->next; + } + } + + /* On all machines that support sound PM, switch sound off */ + if (macio_chips[0].of_node) + pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, + macio_chips[0].of_node, 0, 0); + + /* While on some desktop G3s, we turn it back on */ + if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow + && (pmac_mb.model_id == PMAC_TYPE_GOSSAMER || + pmac_mb.model_id == PMAC_TYPE_SILK)) { + struct macio_chip* macio = &macio_chips[0]; + MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); + MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); + } + + /* Some machine models need the clock chip to be properly setup for + * clock spreading now. This should be a platform function but we + * don't do these at the moment + */ + pmac_tweak_clock_spreading(1); + +#endif /* CONFIG_POWER4 */ + + /* On all machines, switch modem & serial ports off */ + np = find_devices("ch-a"); + while(np) { + initial_serial_shutdown(np); + np = np->next; + } + np = find_devices("ch-b"); + while(np) { + initial_serial_shutdown(np); + np = np->next; + } +} + +void __init +pmac_feature_init(void) +{ + /* Detect the UniNorth memory controller */ + probe_uninorth(); + + /* Probe mac-io controllers */ + if (probe_macios()) { + printk(KERN_WARNING "No mac-io chip found\n"); + return; + } + + /* Setup low-level i2c stuffs */ + pmac_init_low_i2c(); + + /* Probe machine type */ + if (probe_motherboard()) + printk(KERN_WARNING "Unknown PowerMac !\n"); + + /* Set some initial features (turn off some chips that will + * be later turned on) + */ + set_initial_features(); +} + +int __init +pmac_feature_late_init(void) +{ + struct device_node* np; + + /* Request some resources late */ + if (uninorth_node) + request_OF_resource(uninorth_node, 0, NULL); + np = find_devices("hammerhead"); + if (np) + request_OF_resource(np, 0, NULL); + np = find_devices("interrupt-controller"); + if (np) + request_OF_resource(np, 0, NULL); + return 0; +} + +device_initcall(pmac_feature_late_init); + +#ifdef CONFIG_POWER4 + +static void dump_HT_speeds(char *name, u32 cfg, u32 frq) +{ + int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 }; + int bits[8] = { 8,16,0,32,2,4,0,0 }; + int freq = (frq >> 8) & 0xf; + + if (freqs[freq] == 0) + printk("%s: Unknown HT link frequency %x\n", name, freq); + else + printk("%s: %d MHz on main link, (%d in / %d out) bits width\n", + name, freqs[freq], + bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]); +} + +void __init pmac_check_ht_link(void) +{ + u32 ufreq, freq, ucfg, cfg; + struct device_node *pcix_node; + u8 px_bus, px_devfn; + struct pci_controller *px_hose; + + (void)in_be32(u3_ht + U3_HT_LINK_COMMAND); + ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG); + ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ); + dump_HT_speeds("U3 HyperTransport", cfg, freq); + + pcix_node = of_find_compatible_node(NULL, "pci", "pci-x"); + if (pcix_node == NULL) { + printk("No PCI-X bridge found\n"); + return; + } + if (pci_device_from_OF_node(pcix_node, &px_bus, &px_devfn) != 0) { + printk("PCI-X bridge found but not matched to pci\n"); + return; + } + px_hose = pci_find_hose_for_OF_device(pcix_node); + if (px_hose == NULL) { + printk("PCI-X bridge found but not matched to host\n"); + return; + } + early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg); + early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq); + dump_HT_speeds("PCI-X HT Uplink", cfg, freq); + early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg); + early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq); + dump_HT_speeds("PCI-X HT Downlink", cfg, freq); +} + +#endif /* CONFIG_POWER4 */ + +/* + * Early video resume hook + */ + +static void (*pmac_early_vresume_proc)(void *data); +static void *pmac_early_vresume_data; + +void pmac_set_early_video_resume(void (*proc)(void *data), void *data) +{ + if (_machine != _MACH_Pmac) + return; + preempt_disable(); + pmac_early_vresume_proc = proc; + pmac_early_vresume_data = data; + preempt_enable(); +} +EXPORT_SYMBOL(pmac_set_early_video_resume); + +void pmac_call_early_video_resume(void) +{ + if (pmac_early_vresume_proc) + pmac_early_vresume_proc(pmac_early_vresume_data); +} + +/* + * AGP related suspend/resume code + */ + +static struct pci_dev *pmac_agp_bridge; +static int (*pmac_agp_suspend)(struct pci_dev *bridge); +static int (*pmac_agp_resume)(struct pci_dev *bridge); + +void pmac_register_agp_pm(struct pci_dev *bridge, + int (*suspend)(struct pci_dev *bridge), + int (*resume)(struct pci_dev *bridge)) +{ + if (suspend || resume) { + pmac_agp_bridge = bridge; + pmac_agp_suspend = suspend; + pmac_agp_resume = resume; + return; + } + if (bridge != pmac_agp_bridge) + return; + pmac_agp_suspend = pmac_agp_resume = NULL; + return; +} +EXPORT_SYMBOL(pmac_register_agp_pm); + +void pmac_suspend_agp_for_card(struct pci_dev *dev) +{ + if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL) + return; + if (pmac_agp_bridge->bus != dev->bus) + return; + pmac_agp_suspend(pmac_agp_bridge); +} +EXPORT_SYMBOL(pmac_suspend_agp_for_card); + +void pmac_resume_agp_for_card(struct pci_dev *dev) +{ + if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL) + return; + if (pmac_agp_bridge->bus != dev->bus) + return; + pmac_agp_resume(pmac_agp_bridge); +} +EXPORT_SYMBOL(pmac_resume_agp_for_card); diff --git a/trunk/arch/ppc/platforms/pmac_low_i2c.c b/trunk/arch/ppc/platforms/pmac_low_i2c.c new file mode 100644 index 000000000000..08583fce1692 --- /dev/null +++ b/trunk/arch/ppc/platforms/pmac_low_i2c.c @@ -0,0 +1,511 @@ +/* + * arch/ppc/platforms/pmac_low_i2c.c + * + * Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * 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; either version + * 2 of the License, or (at your option) any later version. + * + * This file contains some low-level i2c access routines that + * need to be used by various bits of the PowerMac platform code + * at times where the real asynchronous & interrupt driven driver + * cannot be used. The API borrows some semantics from the darwin + * driver in order to ease the implementation of the platform + * properties parser + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_LOW_I2C_HOST 4 + +#if 1 +#define DBG(x...) do {\ + printk(KERN_DEBUG "KW:" x); \ + } while(0) +#else +#define DBGG(x...) +#endif + +struct low_i2c_host; + +typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len); + +struct low_i2c_host +{ + struct device_node *np; /* OF device node */ + struct semaphore mutex; /* Access mutex for use by i2c-keywest */ + low_i2c_func_t func; /* Access function */ + int is_open : 1; /* Poor man's access control */ + int mode; /* Current mode */ + int channel; /* Current channel */ + int num_channels; /* Number of channels */ + void __iomem * base; /* For keywest-i2c, base address */ + int bsteps; /* And register stepping */ + int speed; /* And speed */ +}; + +static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST]; + +/* No locking is necessary on allocation, we are running way before + * anything can race with us + */ +static struct low_i2c_host *find_low_i2c_host(struct device_node *np) +{ + int i; + + for (i = 0; i < MAX_LOW_I2C_HOST; i++) + if (low_i2c_hosts[i].np == np) + return &low_i2c_hosts[i]; + return NULL; +} + +/* + * + * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's) + * + */ + +/* + * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h, + * should be moved somewhere in include/asm-ppc/ + */ +/* Register indices */ +typedef enum { + reg_mode = 0, + reg_control, + reg_status, + reg_isr, + reg_ier, + reg_addr, + reg_subaddr, + reg_data +} reg_t; + + +/* Mode register */ +#define KW_I2C_MODE_100KHZ 0x00 +#define KW_I2C_MODE_50KHZ 0x01 +#define KW_I2C_MODE_25KHZ 0x02 +#define KW_I2C_MODE_DUMB 0x00 +#define KW_I2C_MODE_STANDARD 0x04 +#define KW_I2C_MODE_STANDARDSUB 0x08 +#define KW_I2C_MODE_COMBINED 0x0C +#define KW_I2C_MODE_MODE_MASK 0x0C +#define KW_I2C_MODE_CHAN_MASK 0xF0 + +/* Control register */ +#define KW_I2C_CTL_AAK 0x01 +#define KW_I2C_CTL_XADDR 0x02 +#define KW_I2C_CTL_STOP 0x04 +#define KW_I2C_CTL_START 0x08 + +/* Status register */ +#define KW_I2C_STAT_BUSY 0x01 +#define KW_I2C_STAT_LAST_AAK 0x02 +#define KW_I2C_STAT_LAST_RW 0x04 +#define KW_I2C_STAT_SDA 0x08 +#define KW_I2C_STAT_SCL 0x10 + +/* IER & ISR registers */ +#define KW_I2C_IRQ_DATA 0x01 +#define KW_I2C_IRQ_ADDR 0x02 +#define KW_I2C_IRQ_STOP 0x04 +#define KW_I2C_IRQ_START 0x08 +#define KW_I2C_IRQ_MASK 0x0F + +/* State machine states */ +enum { + state_idle, + state_addr, + state_read, + state_write, + state_stop, + state_dead +}; + +#define WRONG_STATE(name) do {\ + printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \ + name, __kw_state_names[state], isr); \ + } while(0) + +static const char *__kw_state_names[] = { + "state_idle", + "state_addr", + "state_read", + "state_write", + "state_stop", + "state_dead" +}; + +static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg) +{ + return in_8(host->base + (((unsigned)reg) << host->bsteps)); +} + +static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val) +{ + out_8(host->base + (((unsigned)reg) << host->bsteps), val); + (void)__kw_read_reg(host, reg_subaddr); +} + +#define kw_write_reg(reg, val) __kw_write_reg(host, reg, val) +#define kw_read_reg(reg) __kw_read_reg(host, reg) + + +/* Don't schedule, the g5 fan controller is too + * timing sensitive + */ +static u8 kw_wait_interrupt(struct low_i2c_host* host) +{ + int i; + u8 isr; + + for (i = 0; i < 200000; i++) { + isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK; + if (isr != 0) + return isr; + udelay(1); + } + return isr; +} + +static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr) +{ + u8 ack; + + if (isr == 0) { + if (state != state_stop) { + DBG("KW: Timeout !\n"); + *rc = -EIO; + goto stop; + } + if (state == state_stop) { + ack = kw_read_reg(reg_status); + if (!(ack & KW_I2C_STAT_BUSY)) { + state = state_idle; + kw_write_reg(reg_ier, 0x00); + } + } + return state; + } + + if (isr & KW_I2C_IRQ_ADDR) { + ack = kw_read_reg(reg_status); + if (state != state_addr) { + kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); + WRONG_STATE("KW_I2C_IRQ_ADDR"); + *rc = -EIO; + goto stop; + } + if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { + *rc = -ENODEV; + DBG("KW: NAK on address\n"); + return state_stop; + } else { + if (rw) { + state = state_read; + if (*len > 1) + kw_write_reg(reg_control, KW_I2C_CTL_AAK); + } else { + state = state_write; + kw_write_reg(reg_data, **data); + (*data)++; (*len)--; + } + } + kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); + } + + if (isr & KW_I2C_IRQ_DATA) { + if (state == state_read) { + **data = kw_read_reg(reg_data); + (*data)++; (*len)--; + kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); + if ((*len) == 0) + state = state_stop; + else if ((*len) == 1) + kw_write_reg(reg_control, 0); + } else if (state == state_write) { + ack = kw_read_reg(reg_status); + if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { + DBG("KW: nack on data write\n"); + *rc = -EIO; + goto stop; + } else if (*len) { + kw_write_reg(reg_data, **data); + (*data)++; (*len)--; + } else { + kw_write_reg(reg_control, KW_I2C_CTL_STOP); + state = state_stop; + *rc = 0; + } + kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); + } else { + kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); + WRONG_STATE("KW_I2C_IRQ_DATA"); + if (state != state_stop) { + *rc = -EIO; + goto stop; + } + } + } + + if (isr & KW_I2C_IRQ_STOP) { + kw_write_reg(reg_isr, KW_I2C_IRQ_STOP); + if (state != state_stop) { + WRONG_STATE("KW_I2C_IRQ_STOP"); + *rc = -EIO; + } + return state_idle; + } + + if (isr & KW_I2C_IRQ_START) + kw_write_reg(reg_isr, KW_I2C_IRQ_START); + + return state; + + stop: + kw_write_reg(reg_control, KW_I2C_CTL_STOP); + return state_stop; +} + +static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len) +{ + u8 mode_reg = host->speed; + int state = state_addr; + int rc = 0; + + /* Setup mode & subaddress if any */ + switch(host->mode) { + case pmac_low_i2c_mode_dumb: + printk(KERN_ERR "low_i2c: Dumb mode not supported !\n"); + return -EINVAL; + case pmac_low_i2c_mode_std: + mode_reg |= KW_I2C_MODE_STANDARD; + break; + case pmac_low_i2c_mode_stdsub: + mode_reg |= KW_I2C_MODE_STANDARDSUB; + kw_write_reg(reg_subaddr, subaddr); + break; + case pmac_low_i2c_mode_combined: + mode_reg |= KW_I2C_MODE_COMBINED; + kw_write_reg(reg_subaddr, subaddr); + break; + } + + /* Setup channel & clear pending irqs */ + kw_write_reg(reg_isr, kw_read_reg(reg_isr)); + kw_write_reg(reg_mode, mode_reg | (host->channel << 4)); + kw_write_reg(reg_status, 0); + + /* Set up address and r/w bit */ + kw_write_reg(reg_addr, addr); + + /* Start sending address & disable interrupt*/ + kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/); + kw_write_reg(reg_control, KW_I2C_CTL_XADDR); + + /* State machine, to turn into an interrupt handler */ + while(state != state_idle) { + u8 isr = kw_wait_interrupt(host); + state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr); + } + + return rc; +} + +static void keywest_low_i2c_add(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(NULL); + unsigned long *psteps, *prate, steps, aoffset = 0; + struct device_node *parent; + + if (host == NULL) { + printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", + np->full_name); + return; + } + memset(host, 0, sizeof(*host)); + + init_MUTEX(&host->mutex); + host->np = of_node_get(np); + psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL); + steps = psteps ? (*psteps) : 0x10; + for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++) + steps >>= 1; + parent = of_get_parent(np); + host->num_channels = 1; + if (parent && parent->name[0] == 'u') { + host->num_channels = 2; + aoffset = 3; + } + /* Select interface rate */ + host->speed = KW_I2C_MODE_100KHZ; + prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL); + if (prate) switch(*prate) { + case 100: + host->speed = KW_I2C_MODE_100KHZ; + break; + case 50: + host->speed = KW_I2C_MODE_50KHZ; + break; + case 25: + host->speed = KW_I2C_MODE_25KHZ; + break; + } + host->mode = pmac_low_i2c_mode_std; + host->base = ioremap(np->addrs[0].address + aoffset, + np->addrs[0].size); + host->func = keywest_low_i2c_func; +} + +/* + * + * PMU implementation + * + */ + + +#ifdef CONFIG_ADB_PMU + +static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len) +{ + // TODO + return -ENODEV; +} + +static void pmu_low_i2c_add(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(NULL); + + if (host == NULL) { + printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", + np->full_name); + return; + } + memset(host, 0, sizeof(*host)); + + init_MUTEX(&host->mutex); + host->np = of_node_get(np); + host->num_channels = 3; + host->mode = pmac_low_i2c_mode_std; + host->func = pmu_low_i2c_func; +} + +#endif /* CONFIG_ADB_PMU */ + +void __init pmac_init_low_i2c(void) +{ + struct device_node *np; + + /* Probe keywest-i2c busses */ + np = of_find_compatible_node(NULL, "i2c", "keywest-i2c"); + while(np) { + keywest_low_i2c_add(np); + np = of_find_compatible_node(np, "i2c", "keywest-i2c"); + } + +#ifdef CONFIG_ADB_PMU + /* Probe PMU busses */ + np = of_find_node_by_name(NULL, "via-pmu"); + if (np) + pmu_low_i2c_add(np); +#endif /* CONFIG_ADB_PMU */ + + /* TODO: Add CUDA support as well */ +} + +int pmac_low_i2c_lock(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + down(&host->mutex); + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_lock); + +int pmac_low_i2c_unlock(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + up(&host->mutex); + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_unlock); + + +int pmac_low_i2c_open(struct device_node *np, int channel) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + + if (channel >= host->num_channels) + return -EINVAL; + + down(&host->mutex); + host->is_open = 1; + host->channel = channel; + + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_open); + +int pmac_low_i2c_close(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + + host->is_open = 0; + up(&host->mutex); + + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_close); + +int pmac_low_i2c_setmode(struct device_node *np, int mode) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + WARN_ON(!host->is_open); + host->mode = mode; + + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_setmode); + +int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + WARN_ON(!host->is_open); + + return host->func(host, addrdir, subaddr, data, len); +} +EXPORT_SYMBOL(pmac_low_i2c_xfer); + diff --git a/trunk/arch/ppc/platforms/pmac_nvram.c b/trunk/arch/ppc/platforms/pmac_nvram.c new file mode 100644 index 000000000000..8c9b008c7226 --- /dev/null +++ b/trunk/arch/ppc/platforms/pmac_nvram.c @@ -0,0 +1,584 @@ +/* + * arch/ppc/platforms/pmac_nvram.c + * + * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * 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; either version + * 2 of the License, or (at your option) any later version. + * + * Todo: - add support for the OF persistent properties + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */ + +#define CORE99_SIGNATURE 0x5a +#define CORE99_ADLER_START 0x14 + +/* On Core99, nvram is either a sharp, a micron or an AMD flash */ +#define SM_FLASH_STATUS_DONE 0x80 +#define SM_FLASH_STATUS_ERR 0x38 +#define SM_FLASH_CMD_ERASE_CONFIRM 0xd0 +#define SM_FLASH_CMD_ERASE_SETUP 0x20 +#define SM_FLASH_CMD_RESET 0xff +#define SM_FLASH_CMD_WRITE_SETUP 0x40 +#define SM_FLASH_CMD_CLEAR_STATUS 0x50 +#define SM_FLASH_CMD_READ_STATUS 0x70 + +/* CHRP NVRAM header */ +struct chrp_header { + u8 signature; + u8 cksum; + u16 len; + char name[12]; + u8 data[0]; +}; + +struct core99_header { + struct chrp_header hdr; + u32 adler; + u32 generation; + u32 reserved[2]; +}; + +/* + * Read and write the non-volatile RAM on PowerMacs and CHRP machines. + */ +static int nvram_naddrs; +static volatile unsigned char *nvram_addr; +static volatile unsigned char *nvram_data; +static int nvram_mult, is_core_99; +static int core99_bank = 0; +static int nvram_partitions[3]; +static DEFINE_SPINLOCK(nv_lock); + +extern int pmac_newworld; +extern int system_running; + +static int (*core99_write_bank)(int bank, u8* datas); +static int (*core99_erase_bank)(int bank); + +static char *nvram_image; + + +static unsigned char core99_nvram_read_byte(int addr) +{ + if (nvram_image == NULL) + return 0xff; + return nvram_image[addr]; +} + +static void core99_nvram_write_byte(int addr, unsigned char val) +{ + if (nvram_image == NULL) + return; + nvram_image[addr] = val; +} + + +static unsigned char direct_nvram_read_byte(int addr) +{ + return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]); +} + +static void direct_nvram_write_byte(int addr, unsigned char val) +{ + out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val); +} + + +static unsigned char indirect_nvram_read_byte(int addr) +{ + unsigned char val; + unsigned long flags; + + spin_lock_irqsave(&nv_lock, flags); + out_8(nvram_addr, addr >> 5); + val = in_8(&nvram_data[(addr & 0x1f) << 4]); + spin_unlock_irqrestore(&nv_lock, flags); + + return val; +} + +static void indirect_nvram_write_byte(int addr, unsigned char val) +{ + unsigned long flags; + + spin_lock_irqsave(&nv_lock, flags); + out_8(nvram_addr, addr >> 5); + out_8(&nvram_data[(addr & 0x1f) << 4], val); + spin_unlock_irqrestore(&nv_lock, flags); +} + + +#ifdef CONFIG_ADB_PMU + +static void pmu_nvram_complete(struct adb_request *req) +{ + if (req->arg) + complete((struct completion *)req->arg); +} + +static unsigned char pmu_nvram_read_byte(int addr) +{ + struct adb_request req; + DECLARE_COMPLETION(req_complete); + + req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL; + if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM, + (addr >> 8) & 0xff, addr & 0xff)) + return 0xff; + if (system_state == SYSTEM_RUNNING) + wait_for_completion(&req_complete); + while (!req.complete) + pmu_poll(); + return req.reply[0]; +} + +static void pmu_nvram_write_byte(int addr, unsigned char val) +{ + struct adb_request req; + DECLARE_COMPLETION(req_complete); + + req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL; + if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM, + (addr >> 8) & 0xff, addr & 0xff, val)) + return; + if (system_state == SYSTEM_RUNNING) + wait_for_completion(&req_complete); + while (!req.complete) + pmu_poll(); +} + +#endif /* CONFIG_ADB_PMU */ + + +static u8 chrp_checksum(struct chrp_header* hdr) +{ + u8 *ptr; + u16 sum = hdr->signature; + for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++) + sum += *ptr; + while (sum > 0xFF) + sum = (sum & 0xFF) + (sum>>8); + return sum; +} + +static u32 core99_calc_adler(u8 *buffer) +{ + int cnt; + u32 low, high; + + buffer += CORE99_ADLER_START; + low = 1; + high = 0; + for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) { + if ((cnt % 5000) == 0) { + high %= 65521UL; + high %= 65521UL; + } + low += buffer[cnt]; + high += low; + } + low %= 65521UL; + high %= 65521UL; + + return (high << 16) | low; +} + +static u32 core99_check(u8* datas) +{ + struct core99_header* hdr99 = (struct core99_header*)datas; + + if (hdr99->hdr.signature != CORE99_SIGNATURE) { + DBG("Invalid signature\n"); + return 0; + } + if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) { + DBG("Invalid checksum\n"); + return 0; + } + if (hdr99->adler != core99_calc_adler(datas)) { + DBG("Invalid adler\n"); + return 0; + } + return hdr99->generation; +} + +static int sm_erase_bank(int bank) +{ + int stat, i; + unsigned long timeout; + + u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; + + DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank); + + out_8(base, SM_FLASH_CMD_ERASE_SETUP); + out_8(base, SM_FLASH_CMD_ERASE_CONFIRM); + timeout = 0; + do { + if (++timeout > 1000000) { + printk(KERN_ERR "nvram: Sharp/Miron flash erase timeout !\n"); + break; + } + out_8(base, SM_FLASH_CMD_READ_STATUS); + stat = in_8(base); + } while (!(stat & SM_FLASH_STATUS_DONE)); + + out_8(base, SM_FLASH_CMD_CLEAR_STATUS); + out_8(base, SM_FLASH_CMD_RESET); + + for (i=0; i 1000000) { + printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n"); + break; + } + out_8(base, SM_FLASH_CMD_READ_STATUS); + stat = in_8(base); + } while (!(stat & SM_FLASH_STATUS_DONE)); + if (!(stat & SM_FLASH_STATUS_DONE)) + break; + } + out_8(base, SM_FLASH_CMD_CLEAR_STATUS); + out_8(base, SM_FLASH_CMD_RESET); + for (i=0; i 1000000) { + printk(KERN_ERR "nvram: AMD flash erase timeout !\n"); + break; + } + stat = in_8(base) ^ in_8(base); + } while (stat != 0); + + /* Reset */ + out_8(base, 0xf0); + udelay(1); + + for (i=0; i 1000000) { + printk(KERN_ERR "nvram: AMD flash write timeout !\n"); + break; + } + stat = in_8(base) ^ in_8(base); + } while (stat != 0); + if (stat != 0) + break; + } + + /* Reset */ + out_8(base, 0xf0); + udelay(1); + + for (i=0; iname, "common")) + nvram_partitions[pmac_nvram_OF] = offset + 0x10; + if (!strcmp(hdr->name, "APL,MacOS75")) { + nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10; + nvram_partitions[pmac_nvram_NR] = offset + 0x110; + } + offset += (hdr->len * 0x10); + } while(offset < NVRAM_SIZE); + } else { + nvram_partitions[pmac_nvram_OF] = 0x1800; + nvram_partitions[pmac_nvram_XPRAM] = 0x1300; + nvram_partitions[pmac_nvram_NR] = 0x1400; + } + DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]); + DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]); + DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]); +} + +static void core99_nvram_sync(void) +{ + struct core99_header* hdr99; + unsigned long flags; + + if (!is_core_99 || !nvram_data || !nvram_image) + return; + + spin_lock_irqsave(&nv_lock, flags); + if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE, + NVRAM_SIZE)) + goto bail; + + DBG("Updating nvram...\n"); + + hdr99 = (struct core99_header*)nvram_image; + hdr99->generation++; + hdr99->hdr.signature = CORE99_SIGNATURE; + hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr); + hdr99->adler = core99_calc_adler(nvram_image); + core99_bank = core99_bank ? 0 : 1; + if (core99_erase_bank) + if (core99_erase_bank(core99_bank)) { + printk("nvram: Error erasing bank %d\n", core99_bank); + goto bail; + } + if (core99_write_bank) + if (core99_write_bank(core99_bank, nvram_image)) + printk("nvram: Error writing bank %d\n", core99_bank); + bail: + spin_unlock_irqrestore(&nv_lock, flags); + +#ifdef DEBUG + mdelay(2000); +#endif +} + +void __init pmac_nvram_init(void) +{ + struct device_node *dp; + + nvram_naddrs = 0; + + dp = find_devices("nvram"); + if (dp == NULL) { + printk(KERN_ERR "Can't find NVRAM device\n"); + return; + } + nvram_naddrs = dp->n_addrs; + is_core_99 = device_is_compatible(dp, "nvram,flash"); + if (is_core_99) { + int i; + u32 gen_bank0, gen_bank1; + + if (nvram_naddrs < 1) { + printk(KERN_ERR "nvram: no address\n"); + return; + } + nvram_image = alloc_bootmem(NVRAM_SIZE); + if (nvram_image == NULL) { + printk(KERN_ERR "nvram: can't allocate ram image\n"); + return; + } + nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2); + nvram_naddrs = 1; /* Make sure we get the correct case */ + + DBG("nvram: Checking bank 0...\n"); + + gen_bank0 = core99_check((u8 *)nvram_data); + gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE); + core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0; + + DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1); + DBG("nvram: Active bank is: %d\n", core99_bank); + + for (i=0; iaddrs[0].address + isa_mem_base, + dp->addrs[0].size); + nvram_mult = 1; + ppc_md.nvram_read_val = direct_nvram_read_byte; + ppc_md.nvram_write_val = direct_nvram_write_byte; + } else if (nvram_naddrs == 1) { + nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size); + nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE; + ppc_md.nvram_read_val = direct_nvram_read_byte; + ppc_md.nvram_write_val = direct_nvram_write_byte; + } else if (nvram_naddrs == 2) { + nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size); + nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size); + ppc_md.nvram_read_val = indirect_nvram_read_byte; + ppc_md.nvram_write_val = indirect_nvram_write_byte; + } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) { +#ifdef CONFIG_ADB_PMU + nvram_naddrs = -1; + ppc_md.nvram_read_val = pmu_nvram_read_byte; + ppc_md.nvram_write_val = pmu_nvram_write_byte; +#endif /* CONFIG_ADB_PMU */ + } else { + printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n", + nvram_naddrs); + } + lookup_partitions(); +} + +int pmac_get_partition(int partition) +{ + return nvram_partitions[partition]; +} + +u8 pmac_xpram_read(int xpaddr) +{ + int offset = nvram_partitions[pmac_nvram_XPRAM]; + + if (offset < 0) + return 0xff; + + return ppc_md.nvram_read_val(xpaddr + offset); +} + +void pmac_xpram_write(int xpaddr, u8 data) +{ + int offset = nvram_partitions[pmac_nvram_XPRAM]; + + if (offset < 0) + return; + + ppc_md.nvram_write_val(xpaddr + offset, data); +} + +EXPORT_SYMBOL(pmac_get_partition); +EXPORT_SYMBOL(pmac_xpram_read); +EXPORT_SYMBOL(pmac_xpram_write); diff --git a/trunk/arch/ppc/platforms/pmac_pci.c b/trunk/arch/ppc/platforms/pmac_pci.c new file mode 100644 index 000000000000..786295b6ddd0 --- /dev/null +++ b/trunk/arch/ppc/platforms/pmac_pci.c @@ -0,0 +1,1124 @@ +/* + * Support for PCI bridges found on Power Macintoshes. + * At present the "bandit" and "chaos" bridges are supported. + * Fortunately you access configuration space in the same + * way with either bridge. + * + * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au) + * + * 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; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#ifdef CONFIG_XMON +extern void xmon_printf(const char *fmt, ...); +#define DBG(x...) xmon_printf(x) +#else +#define DBG(x...) printk(x) +#endif +#else +#define DBG(x...) +#endif + +static int add_bridge(struct device_node *dev); +extern void pmac_check_ht_link(void); + +/* XXX Could be per-controller, but I don't think we risk anything by + * assuming we won't have both UniNorth and Bandit */ +static int has_uninorth; +#ifdef CONFIG_POWER4 +static struct pci_controller *u3_agp; +#endif /* CONFIG_POWER4 */ + +extern u8 pci_cache_line_size; +extern int pcibios_assign_bus_offset; + +struct device_node *k2_skiplist[2]; + +/* + * Magic constants for enabling cache coherency in the bandit/PSX bridge. + */ +#define BANDIT_DEVID_2 8 +#define BANDIT_REVID 3 + +#define BANDIT_DEVNUM 11 +#define BANDIT_MAGIC 0x50 +#define BANDIT_COHERENT 0x40 + +static int __init +fixup_one_level_bus_range(struct device_node *node, int higher) +{ + for (; node != 0;node = node->sibling) { + int * bus_range; + unsigned int *class_code; + int len; + + /* For PCI<->PCI bridges or CardBus bridges, we go down */ + class_code = (unsigned int *) get_property(node, "class-code", NULL); + if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && + (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) + continue; + bus_range = (int *) get_property(node, "bus-range", &len); + if (bus_range != NULL && len > 2 * sizeof(int)) { + if (bus_range[1] > higher) + higher = bus_range[1]; + } + higher = fixup_one_level_bus_range(node->child, higher); + } + return higher; +} + +/* This routine fixes the "bus-range" property of all bridges in the + * system since they tend to have their "last" member wrong on macs + * + * Note that the bus numbers manipulated here are OF bus numbers, they + * are not Linux bus numbers. + */ +static void __init +fixup_bus_range(struct device_node *bridge) +{ + int * bus_range; + int len; + + /* Lookup the "bus-range" property for the hose */ + bus_range = (int *) get_property(bridge, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s\n", + bridge->full_name); + return; + } + bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); +} + +/* + * Apple MacRISC (U3, UniNorth, Bandit, Chaos) PCI controllers. + * + * The "Bandit" version is present in all early PCI PowerMacs, + * and up to the first ones using Grackle. Some machines may + * have 2 bandit controllers (2 PCI busses). + * + * "Chaos" is used in some "Bandit"-type machines as a bridge + * for the separate display bus. It is accessed the same + * way as bandit, but cannot be probed for devices. It therefore + * has its own config access functions. + * + * The "UniNorth" version is present in all Core99 machines + * (iBook, G4, new IMacs, and all the recent Apple machines). + * It contains 3 controllers in one ASIC. + * + * The U3 is the bridge used on G5 machines. It contains an + * AGP bus which is dealt with the old UniNorth access routines + * and a HyperTransport bus which uses its own set of access + * functions. + */ + +#define MACRISC_CFA0(devfn, off) \ + ((1 << (unsigned long)PCI_SLOT(dev_fn)) \ + | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \ + | (((unsigned long)(off)) & 0xFCUL)) + +#define MACRISC_CFA1(bus, devfn, off) \ + ((((unsigned long)(bus)) << 16) \ + |(((unsigned long)(devfn)) << 8) \ + |(((unsigned long)(off)) & 0xFCUL) \ + |1UL) + +static void volatile __iomem * +macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset) +{ + unsigned int caddr; + + if (bus == hose->first_busno) { + if (dev_fn < (11 << 3)) + return NULL; + caddr = MACRISC_CFA0(dev_fn, offset); + } else + caddr = MACRISC_CFA1(bus, dev_fn, offset); + + /* Uninorth will return garbage if we don't read back the value ! */ + do { + out_le32(hose->cfg_addr, caddr); + } while (in_le32(hose->cfg_addr) != caddr); + + offset &= has_uninorth ? 0x07 : 0x03; + return hose->cfg_data + offset; +} + +static int +macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 *val) +{ + struct pci_controller *hose = bus->sysdata; + void volatile __iomem *addr; + + addr = macrisc_cfg_access(hose, bus->number, devfn, offset); + if (!addr) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + *val = in_8(addr); + break; + case 2: + *val = in_le16(addr); + break; + default: + *val = in_le32(addr); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int +macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 val) +{ + struct pci_controller *hose = bus->sysdata; + void volatile __iomem *addr; + + addr = macrisc_cfg_access(hose, bus->number, devfn, offset); + if (!addr) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + out_8(addr, val); + (void) in_8(addr); + break; + case 2: + out_le16(addr, val); + (void) in_le16(addr); + break; + default: + out_le32(addr, val); + (void) in_le32(addr); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops macrisc_pci_ops = +{ + macrisc_read_config, + macrisc_write_config +}; + +/* + * Verifiy that a specific (bus, dev_fn) exists on chaos + */ +static int +chaos_validate_dev(struct pci_bus *bus, int devfn, int offset) +{ + struct device_node *np; + u32 *vendor, *device; + + np = pci_busdev_to_OF_node(bus, devfn); + if (np == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + vendor = (u32 *)get_property(np, "vendor-id", NULL); + device = (u32 *)get_property(np, "device-id", NULL); + if (vendor == NULL || device == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + if ((*vendor == 0x106b) && (*device == 3) && (offset >= 0x10) + && (offset != 0x14) && (offset != 0x18) && (offset <= 0x24)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + return PCIBIOS_SUCCESSFUL; +} + +static int +chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 *val) +{ + int result = chaos_validate_dev(bus, devfn, offset); + if (result == PCIBIOS_BAD_REGISTER_NUMBER) + *val = ~0U; + if (result != PCIBIOS_SUCCESSFUL) + return result; + return macrisc_read_config(bus, devfn, offset, len, val); +} + +static int +chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 val) +{ + int result = chaos_validate_dev(bus, devfn, offset); + if (result != PCIBIOS_SUCCESSFUL) + return result; + return macrisc_write_config(bus, devfn, offset, len, val); +} + +static struct pci_ops chaos_pci_ops = +{ + chaos_read_config, + chaos_write_config +}; + +#ifdef CONFIG_POWER4 + +/* + * These versions of U3 HyperTransport config space access ops do not + * implement self-view of the HT host yet + */ + +#define U3_HT_CFA0(devfn, off) \ + ((((unsigned long)devfn) << 8) | offset) +#define U3_HT_CFA1(bus, devfn, off) \ + (U3_HT_CFA0(devfn, off) \ + + (((unsigned long)bus) << 16) \ + + 0x01000000UL) + +static void volatile __iomem * +u3_ht_cfg_access(struct pci_controller* hose, u8 bus, u8 devfn, u8 offset) +{ + if (bus == hose->first_busno) { + /* For now, we don't self probe U3 HT bridge */ + if (PCI_FUNC(devfn) != 0 || PCI_SLOT(devfn) > 7 || + PCI_SLOT(devfn) < 1) + return 0; + return hose->cfg_data + U3_HT_CFA0(devfn, offset); + } else + return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset); +} + +static int +u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 *val) +{ + struct pci_controller *hose = bus->sysdata; + void volatile __iomem *addr; + int i; + + struct device_node *np = pci_busdev_to_OF_node(bus, devfn); + if (np == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * When a device in K2 is powered down, we die on config + * cycle accesses. Fix that here. + */ + for (i=0; i<2; i++) + if (k2_skiplist[i] == np) { + switch (len) { + case 1: + *val = 0xff; break; + case 2: + *val = 0xffff; break; + default: + *val = 0xfffffffful; break; + } + return PCIBIOS_SUCCESSFUL; + } + + addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); + if (!addr) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + *val = in_8(addr); + break; + case 2: + *val = in_le16(addr); + break; + default: + *val = in_le32(addr); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int +u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 val) +{ + struct pci_controller *hose = bus->sysdata; + void volatile __iomem *addr; + int i; + + struct device_node *np = pci_busdev_to_OF_node(bus, devfn); + if (np == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * When a device in K2 is powered down, we die on config + * cycle accesses. Fix that here. + */ + for (i=0; i<2; i++) + if (k2_skiplist[i] == np) + return PCIBIOS_SUCCESSFUL; + + addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); + if (!addr) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + out_8(addr, val); + (void) in_8(addr); + break; + case 2: + out_le16(addr, val); + (void) in_le16(addr); + break; + default: + out_le32(addr, val); + (void) in_le32(addr); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops u3_ht_pci_ops = +{ + u3_ht_read_config, + u3_ht_write_config +}; + +#endif /* CONFIG_POWER4 */ + +/* + * For a bandit bridge, turn on cache coherency if necessary. + * N.B. we could clean this up using the hose ops directly. + */ +static void __init +init_bandit(struct pci_controller *bp) +{ + unsigned int vendev, magic; + int rev; + + /* read the word at offset 0 in config space for device 11 */ + out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID); + udelay(2); + vendev = in_le32(bp->cfg_data); + if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) + + PCI_VENDOR_ID_APPLE) { + /* read the revision id */ + out_le32(bp->cfg_addr, + (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID); + udelay(2); + rev = in_8(bp->cfg_data); + if (rev != BANDIT_REVID) + printk(KERN_WARNING + "Unknown revision %d for bandit\n", rev); + } else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) { + printk(KERN_WARNING "bandit isn't? (%x)\n", vendev); + return; + } + + /* read the word at offset 0x50 */ + out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC); + udelay(2); + magic = in_le32(bp->cfg_data); + if ((magic & BANDIT_COHERENT) != 0) + return; + magic |= BANDIT_COHERENT; + udelay(2); + out_le32(bp->cfg_data, magic); + printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n"); +} + + +/* + * Tweak the PCI-PCI bridge chip on the blue & white G3s. + */ +static void __init +init_p2pbridge(void) +{ + struct device_node *p2pbridge; + struct pci_controller* hose; + u8 bus, devfn; + u16 val; + + /* XXX it would be better here to identify the specific + PCI-PCI bridge chip we have. */ + if ((p2pbridge = find_devices("pci-bridge")) == 0 + || p2pbridge->parent == NULL + || strcmp(p2pbridge->parent->name, "pci") != 0) + return; + if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) { + DBG("Can't find PCI infos for PCI<->PCI bridge\n"); + return; + } + /* Warning: At this point, we have not yet renumbered all busses. + * So we must use OF walking to find out hose + */ + hose = pci_find_hose_for_OF_device(p2pbridge); + if (!hose) { + DBG("Can't find hose for PCI<->PCI bridge\n"); + return; + } + if (early_read_config_word(hose, bus, devfn, + PCI_BRIDGE_CONTROL, &val) < 0) { + printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n"); + return; + } + val &= ~PCI_BRIDGE_CTL_MASTER_ABORT; + early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val); +} + +/* + * Some Apple desktop machines have a NEC PD720100A USB2 controller + * on the motherboard. Open Firmware, on these, will disable the + * EHCI part of it so it behaves like a pair of OHCI's. This fixup + * code re-enables it ;) + */ +static void __init +fixup_nec_usb2(void) +{ + struct device_node *nec; + + for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) { + struct pci_controller *hose; + u32 data, *prop; + u8 bus, devfn; + + prop = (u32 *)get_property(nec, "vendor-id", NULL); + if (prop == NULL) + continue; + if (0x1033 != *prop) + continue; + prop = (u32 *)get_property(nec, "device-id", NULL); + if (prop == NULL) + continue; + if (0x0035 != *prop) + continue; + prop = (u32 *)get_property(nec, "reg", NULL); + if (prop == NULL) + continue; + devfn = (prop[0] >> 8) & 0xff; + bus = (prop[0] >> 16) & 0xff; + if (PCI_FUNC(devfn) != 0) + continue; + hose = pci_find_hose_for_OF_device(nec); + if (!hose) + continue; + early_read_config_dword(hose, bus, devfn, 0xe4, &data); + if (data & 1UL) { + printk("Found NEC PD720100A USB2 chip with disabled EHCI, fixing up...\n"); + data &= ~1UL; + early_write_config_dword(hose, bus, devfn, 0xe4, data); + early_write_config_byte(hose, bus, devfn | 2, PCI_INTERRUPT_LINE, + nec->intrs[0].line); + } + } +} + +void __init +pmac_find_bridges(void) +{ + struct device_node *np, *root; + struct device_node *ht = NULL; + + root = of_find_node_by_path("/"); + if (root == NULL) { + printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n"); + return; + } + for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) { + if (np->name == NULL) + continue; + if (strcmp(np->name, "bandit") == 0 + || strcmp(np->name, "chaos") == 0 + || strcmp(np->name, "pci") == 0) { + if (add_bridge(np) == 0) + of_node_get(np); + } + if (strcmp(np->name, "ht") == 0) { + of_node_get(np); + ht = np; + } + } + of_node_put(root); + + /* Probe HT last as it relies on the agp resources to be already + * setup + */ + if (ht && add_bridge(ht) != 0) + of_node_put(ht); + + init_p2pbridge(); + fixup_nec_usb2(); + + /* We are still having some issues with the Xserve G4, enabling + * some offset between bus number and domains for now when we + * assign all busses should help for now + */ + if (pci_assign_all_buses) + pcibios_assign_bus_offset = 0x10; + +#ifdef CONFIG_POWER4 + /* There is something wrong with DMA on U3/HT. I haven't figured out + * the details yet, but if I set the cache line size to 128 bytes like + * it should, I'm getting memory corruption caused by devices like + * sungem (even without the MWI bit set, but maybe sungem doesn't + * care). Right now, it appears that setting up a 64 bytes line size + * works properly, 64 bytes beeing the max transfer size of HT, I + * suppose this is related the way HT/PCI are hooked together. I still + * need to dive into more specs though to be really sure of what's + * going on. --BenH. + * + * Ok, apparently, it's just that HT can't do more than 64 bytes + * transactions. MWI seem to be meaningless there as well, it may + * be worth nop'ing out pci_set_mwi too though I haven't done that + * yet. + * + * Note that it's a bit different for whatever is in the AGP slot. + * For now, I don't care, but this can become a real issue, we + * should probably hook pci_set_mwi anyway to make sure it sets + * the real cache line size in there. + */ + if (machine_is_compatible("MacRISC4")) + pci_cache_line_size = 16; /* 64 bytes */ + + pmac_check_ht_link(); +#endif /* CONFIG_POWER4 */ +} + +#define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \ + | (((o) & ~3) << 24)) + +#define GRACKLE_PICR1_STG 0x00000040 +#define GRACKLE_PICR1_LOOPSNOOP 0x00000010 + +/* N.B. this is called before bridges is initialized, so we can't + use grackle_pcibios_{read,write}_config_dword. */ +static inline void grackle_set_stg(struct pci_controller* bp, int enable) +{ + unsigned int val; + + out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); + val = in_le32(bp->cfg_data); + val = enable? (val | GRACKLE_PICR1_STG) : + (val & ~GRACKLE_PICR1_STG); + out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); + out_le32(bp->cfg_data, val); + (void)in_le32(bp->cfg_data); +} + +static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable) +{ + unsigned int val; + + out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); + val = in_le32(bp->cfg_data); + val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) : + (val & ~GRACKLE_PICR1_LOOPSNOOP); + out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); + out_le32(bp->cfg_data, val); + (void)in_le32(bp->cfg_data); +} + +static int __init +setup_uninorth(struct pci_controller* hose, struct reg_property* addr) +{ + pci_assign_all_buses = 1; + has_uninorth = 1; + hose->ops = ¯isc_pci_ops; + hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000); + hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000); + /* We "know" that the bridge at f2000000 has the PCI slots. */ + return addr->address == 0xf2000000; +} + +static void __init +setup_bandit(struct pci_controller* hose, struct reg_property* addr) +{ + hose->ops = ¯isc_pci_ops; + hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000); + hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000); + init_bandit(hose); +} + +static void __init +setup_chaos(struct pci_controller* hose, struct reg_property* addr) +{ + /* assume a `chaos' bridge */ + hose->ops = &chaos_pci_ops; + hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000); + hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000); +} + +#ifdef CONFIG_POWER4 + +static void __init +setup_u3_agp(struct pci_controller* hose, struct reg_property* addr) +{ + /* On G5, we move AGP up to high bus number so we don't need + * to reassign bus numbers for HT. If we ever have P2P bridges + * on AGP, we'll have to move pci_assign_all_buses to the + * pci_controller structure so we enable it for AGP and not for + * HT childs. + * We hard code the address because of the different size of + * the reg address cell, we shall fix that by killing struct + * reg_property and using some accessor functions instead + */ + hose->first_busno = 0xf0; + hose->last_busno = 0xff; + has_uninorth = 1; + hose->ops = ¯isc_pci_ops; + hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); + hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000); + + u3_agp = hose; +} + +static void __init +setup_u3_ht(struct pci_controller* hose, struct reg_property *addr) +{ + struct device_node *np = (struct device_node *)hose->arch_data; + int i, cur; + + hose->ops = &u3_ht_pci_ops; + + /* We hard code the address because of the different size of + * the reg address cell, we shall fix that by killing struct + * reg_property and using some accessor functions instead + */ + hose->cfg_data = ioremap(0xf2000000, 0x02000000); + + /* + * /ht node doesn't expose a "ranges" property, so we "remove" regions that + * have been allocated to AGP. So far, this version of the code doesn't assign + * any of the 0xfxxxxxxx "fine" memory regions to /ht. + * We need to fix that sooner or later by either parsing all child "ranges" + * properties or figuring out the U3 address space decoding logic and + * then read its configuration register (if any). + */ + hose->io_base_phys = 0xf4000000; + hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000); + isa_io_base = (unsigned long) hose->io_base_virt; + hose->io_resource.name = np->full_name; + hose->io_resource.start = 0; + hose->io_resource.end = 0x003fffff; + hose->io_resource.flags = IORESOURCE_IO; + hose->pci_mem_offset = 0; + hose->first_busno = 0; + hose->last_busno = 0xef; + hose->mem_resources[0].name = np->full_name; + hose->mem_resources[0].start = 0x80000000; + hose->mem_resources[0].end = 0xefffffff; + hose->mem_resources[0].flags = IORESOURCE_MEM; + + if (u3_agp == NULL) { + DBG("U3 has no AGP, using full resource range\n"); + return; + } + + /* We "remove" the AGP resources from the resources allocated to HT, that + * is we create "holes". However, that code does assumptions that so far + * happen to be true (cross fingers...), typically that resources in the + * AGP node are properly ordered + */ + cur = 0; + for (i=0; i<3; i++) { + struct resource *res = &u3_agp->mem_resources[i]; + if (res->flags != IORESOURCE_MEM) + continue; + /* We don't care about "fine" resources */ + if (res->start >= 0xf0000000) + continue; + /* Check if it's just a matter of "shrinking" us in one direction */ + if (hose->mem_resources[cur].start == res->start) { + DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n", + cur, hose->mem_resources[cur].start, res->end + 1); + hose->mem_resources[cur].start = res->end + 1; + continue; + } + if (hose->mem_resources[cur].end == res->end) { + DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n", + cur, hose->mem_resources[cur].end, res->start - 1); + hose->mem_resources[cur].end = res->start - 1; + continue; + } + /* No, it's not the case, we need a hole */ + if (cur == 2) { + /* not enough resources to make a hole, we drop part of the range */ + printk(KERN_WARNING "Running out of resources for /ht host !\n"); + hose->mem_resources[cur].end = res->start - 1; + continue; + } + cur++; + DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n", + cur-1, res->start - 1, cur, res->end + 1); + hose->mem_resources[cur].name = np->full_name; + hose->mem_resources[cur].flags = IORESOURCE_MEM; + hose->mem_resources[cur].start = res->end + 1; + hose->mem_resources[cur].end = hose->mem_resources[cur-1].end; + hose->mem_resources[cur-1].end = res->start - 1; + } +} + +#endif /* CONFIG_POWER4 */ + +void __init +setup_grackle(struct pci_controller *hose) +{ + setup_indirect_pci(hose, 0xfec00000, 0xfee00000); + if (machine_is_compatible("AAPL,PowerBook1998")) + grackle_set_loop_snoop(hose, 1); +#if 0 /* Disabled for now, HW problems ??? */ + grackle_set_stg(hose, 1); +#endif +} + +/* + * We assume that if we have a G3 powermac, we have one bridge called + * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise, + * if we have one or more bandit or chaos bridges, we don't have a MPC106. + */ +static int __init +add_bridge(struct device_node *dev) +{ + int len; + struct pci_controller *hose; + struct reg_property *addr; + char* disp_name; + int *bus_range; + int primary = 1; + + DBG("Adding PCI host bridge %s\n", dev->full_name); + + addr = (struct reg_property *) get_property(dev, "reg", &len); + if (addr == NULL || len < sizeof(*addr)) { + printk(KERN_WARNING "Can't use %s: no address\n", + dev->full_name); + return -ENODEV; + } + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", + dev->full_name); + } + + hose = pcibios_alloc_controller(); + if (!hose) + return -ENOMEM; + hose->arch_data = dev; + hose->first_busno = bus_range ? bus_range[0] : 0; + hose->last_busno = bus_range ? bus_range[1] : 0xff; + + disp_name = NULL; +#ifdef CONFIG_POWER4 + if (device_is_compatible(dev, "u3-agp")) { + setup_u3_agp(hose, addr); + disp_name = "U3-AGP"; + primary = 0; + } else if (device_is_compatible(dev, "u3-ht")) { + setup_u3_ht(hose, addr); + disp_name = "U3-HT"; + primary = 1; + } else +#endif /* CONFIG_POWER4 */ + if (device_is_compatible(dev, "uni-north")) { + primary = setup_uninorth(hose, addr); + disp_name = "UniNorth"; + } else if (strcmp(dev->name, "pci") == 0) { + /* XXX assume this is a mpc106 (grackle) */ + setup_grackle(hose); + disp_name = "Grackle (MPC106)"; + } else if (strcmp(dev->name, "bandit") == 0) { + setup_bandit(hose, addr); + disp_name = "Bandit"; + } else if (strcmp(dev->name, "chaos") == 0) { + setup_chaos(hose, addr); + disp_name = "Chaos"; + primary = 0; + } + printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n", + disp_name, addr->address, hose->first_busno, hose->last_busno); + DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", + hose, hose->cfg_addr, hose->cfg_data); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pci_process_bridge_OF_ranges(hose, dev, primary); + + /* Fixup "bus-range" OF property */ + fixup_bus_range(dev); + + return 0; +} + +static void __init +pcibios_fixup_OF_interrupts(void) +{ + struct pci_dev* dev = NULL; + + /* + * Open Firmware often doesn't initialize the + * PCI_INTERRUPT_LINE config register properly, so we + * should find the device node and apply the interrupt + * obtained from the OF device-tree + */ + for_each_pci_dev(dev) { + struct device_node *node; + node = pci_device_to_OF_node(dev); + /* this is the node, see if it has interrupts */ + if (node && node->n_intrs > 0) + dev->irq = node->intrs[0].line; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } +} + +void __init +pmac_pcibios_fixup(void) +{ + /* Fixup interrupts according to OF tree */ + pcibios_fixup_OF_interrupts(); +} + +int +pmac_pci_enable_device_hook(struct pci_dev *dev, int initial) +{ + struct device_node* node; + int updatecfg = 0; + int uninorth_child; + + node = pci_device_to_OF_node(dev); + + /* We don't want to enable USB controllers absent from the OF tree + * (iBook second controller) + */ + if (dev->vendor == PCI_VENDOR_ID_APPLE + && (dev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10)) + && !node) { + printk(KERN_INFO "Apple USB OHCI %s disabled by firmware\n", + pci_name(dev)); + return -EINVAL; + } + + if (!node) + return 0; + + uninorth_child = node->parent && + device_is_compatible(node->parent, "uni-north"); + + /* Firewire & GMAC were disabled after PCI probe, the driver is + * claiming them, we must re-enable them now. + */ + if (uninorth_child && !strcmp(node->name, "firewire") && + (device_is_compatible(node, "pci106b,18") || + device_is_compatible(node, "pci106b,30") || + device_is_compatible(node, "pci11c1,5811"))) { + pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1); + pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1); + updatecfg = 1; + } + if (uninorth_child && !strcmp(node->name, "ethernet") && + device_is_compatible(node, "gmac")) { + pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1); + updatecfg = 1; + } + + if (updatecfg) { + u16 cmd; + + /* + * Make sure PCI is correctly configured + * + * We use old pci_bios versions of the function since, by + * default, gmac is not powered up, and so will be absent + * from the kernel initial PCI lookup. + * + * Should be replaced by 2.4 new PCI mechanisms and really + * register the device. + */ + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE; + pci_write_config_word(dev, PCI_COMMAND, cmd); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cache_line_size); + } + + return 0; +} + +/* We power down some devices after they have been probed. They'll + * be powered back on later on + */ +void __init +pmac_pcibios_after_init(void) +{ + struct device_node* nd; + +#ifdef CONFIG_BLK_DEV_IDE + struct pci_dev *dev = NULL; + + /* OF fails to initialize IDE controllers on macs + * (and maybe other machines) + * + * Ideally, this should be moved to the IDE layer, but we need + * to check specifically with Andre Hedrick how to do it cleanly + * since the common IDE code seem to care about the fact that the + * BIOS may have disabled a controller. + * + * -- BenH + */ + for_each_pci_dev(dev) { + if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE) + pci_enable_device(dev); + } +#endif /* CONFIG_BLK_DEV_IDE */ + + nd = find_devices("firewire"); + while (nd) { + if (nd->parent && (device_is_compatible(nd, "pci106b,18") || + device_is_compatible(nd, "pci106b,30") || + device_is_compatible(nd, "pci11c1,5811")) + && device_is_compatible(nd->parent, "uni-north")) { + pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0); + pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0); + } + nd = nd->next; + } + nd = find_devices("ethernet"); + while (nd) { + if (nd->parent && device_is_compatible(nd, "gmac") + && device_is_compatible(nd->parent, "uni-north")) + pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0); + nd = nd->next; + } +} + +void pmac_pci_fixup_cardbus(struct pci_dev* dev) +{ + if (_machine != _MACH_Pmac) + return; + /* + * Fix the interrupt routing on the various cardbus bridges + * used on powerbooks + */ + if (dev->vendor != PCI_VENDOR_ID_TI) + return; + if (dev->device == PCI_DEVICE_ID_TI_1130 || + dev->device == PCI_DEVICE_ID_TI_1131) { + u8 val; + /* Enable PCI interrupt */ + if (pci_read_config_byte(dev, 0x91, &val) == 0) + pci_write_config_byte(dev, 0x91, val | 0x30); + /* Disable ISA interrupt mode */ + if (pci_read_config_byte(dev, 0x92, &val) == 0) + pci_write_config_byte(dev, 0x92, val & ~0x06); + } + if (dev->device == PCI_DEVICE_ID_TI_1210 || + dev->device == PCI_DEVICE_ID_TI_1211 || + dev->device == PCI_DEVICE_ID_TI_1410 || + dev->device == PCI_DEVICE_ID_TI_1510) { + u8 val; + /* 0x8c == TI122X_IRQMUX, 2 says to route the INTA + signal out the MFUNC0 pin */ + if (pci_read_config_byte(dev, 0x8c, &val) == 0) + pci_write_config_byte(dev, 0x8c, (val & ~0x0f) | 2); + /* Disable ISA interrupt mode */ + if (pci_read_config_byte(dev, 0x92, &val) == 0) + pci_write_config_byte(dev, 0x92, val & ~0x06); + } +} + +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus); + +void pmac_pci_fixup_pciata(struct pci_dev* dev) +{ + u8 progif = 0; + + /* + * On PowerMacs, we try to switch any PCI ATA controller to + * fully native mode + */ + if (_machine != _MACH_Pmac) + return; + /* Some controllers don't have the class IDE */ + if (dev->vendor == PCI_VENDOR_ID_PROMISE) + switch(dev->device) { + case PCI_DEVICE_ID_PROMISE_20246: + case PCI_DEVICE_ID_PROMISE_20262: + case PCI_DEVICE_ID_PROMISE_20263: + case PCI_DEVICE_ID_PROMISE_20265: + case PCI_DEVICE_ID_PROMISE_20267: + case PCI_DEVICE_ID_PROMISE_20268: + case PCI_DEVICE_ID_PROMISE_20269: + case PCI_DEVICE_ID_PROMISE_20270: + case PCI_DEVICE_ID_PROMISE_20271: + case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20276: + case PCI_DEVICE_ID_PROMISE_20277: + goto good; + } + /* Others, check PCI class */ + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) + return; + good: + pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); + if ((progif & 5) != 5) { + printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n", pci_name(dev)); + (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); + if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || + (progif & 5) != 5) + printk(KERN_ERR "Rewrite of PROGIF failed !\n"); + } +} +DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata); + + +/* + * Disable second function on K2-SATA, it's broken + * and disable IO BARs on first one + */ +void pmac_pci_fixup_k2_sata(struct pci_dev* dev) +{ + int i; + u16 cmd; + + if (PCI_FUNC(dev->devfn) > 0) { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, cmd); + for (i = 0; i < 6; i++) { + dev->resource[i].start = dev->resource[i].end = 0; + dev->resource[i].flags = 0; + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0); + } + } else { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd &= ~PCI_COMMAND_IO; + pci_write_config_word(dev, PCI_COMMAND, cmd); + for (i = 0; i < 5; i++) { + dev->resource[i].start = dev->resource[i].end = 0; + dev->resource[i].flags = 0; + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0); + } + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, pmac_pci_fixup_k2_sata); diff --git a/trunk/arch/ppc/platforms/pmac_pic.c b/trunk/arch/ppc/platforms/pmac_pic.c new file mode 100644 index 000000000000..4742bf609357 --- /dev/null +++ b/trunk/arch/ppc/platforms/pmac_pic.c @@ -0,0 +1,693 @@ +/* + * Support for the interrupt controllers found on Power Macintosh, + * currently Apple's "Grand Central" interrupt controller in all + * it's incarnations. OpenPIC support used on newer machines is + * in a separate file + * + * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au) + * + * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * 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; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pmac_pic.h" + +/* + * XXX this should be in xmon.h, but putting it there means xmon.h + * has to include (to get irqreturn_t), which + * causes all sorts of problems. -- paulus + */ +extern irqreturn_t xmon_irq(int, void *, struct pt_regs *); + +struct pmac_irq_hw { + unsigned int event; + unsigned int enable; + unsigned int ack; + unsigned int level; +}; + +/* Default addresses */ +static volatile struct pmac_irq_hw *pmac_irq_hw[4] = { + (struct pmac_irq_hw *) 0xf3000020, + (struct pmac_irq_hw *) 0xf3000010, + (struct pmac_irq_hw *) 0xf4000020, + (struct pmac_irq_hw *) 0xf4000010, +}; + +#define GC_LEVEL_MASK 0x3ff00000 +#define OHARE_LEVEL_MASK 0x1ff00000 +#define HEATHROW_LEVEL_MASK 0x1ff00000 + +static int max_irqs; +static int max_real_irqs; +static u32 level_mask[4]; + +static DEFINE_SPINLOCK(pmac_pic_lock); + + +#define GATWICK_IRQ_POOL_SIZE 10 +static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; + +#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) +static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; + +/* + * Mark an irq as "lost". This is only used on the pmac + * since it can lose interrupts (see pmac_set_irq_mask). + * -- Cort + */ +void +__set_lost(unsigned long irq_nr, int nokick) +{ + if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) { + atomic_inc(&ppc_n_lost_interrupts); + if (!nokick) + set_dec(1); + } +} + +static void +pmac_mask_and_ack_irq(unsigned int irq_nr) +{ + unsigned long bit = 1UL << (irq_nr & 0x1f); + int i = irq_nr >> 5; + unsigned long flags; + + if ((unsigned)irq_nr >= max_irqs) + return; + + clear_bit(irq_nr, ppc_cached_irq_mask); + if (test_and_clear_bit(irq_nr, ppc_lost_interrupts)) + atomic_dec(&ppc_n_lost_interrupts); + spin_lock_irqsave(&pmac_pic_lock, flags); + out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); + out_le32(&pmac_irq_hw[i]->ack, bit); + do { + /* make sure ack gets to controller before we enable + interrupts */ + mb(); + } while((in_le32(&pmac_irq_hw[i]->enable) & bit) + != (ppc_cached_irq_mask[i] & bit)); + spin_unlock_irqrestore(&pmac_pic_lock, flags); +} + +static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) +{ + unsigned long bit = 1UL << (irq_nr & 0x1f); + int i = irq_nr >> 5; + unsigned long flags; + + if ((unsigned)irq_nr >= max_irqs) + return; + + spin_lock_irqsave(&pmac_pic_lock, flags); + /* enable unmasked interrupts */ + out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); + + do { + /* make sure mask gets to controller before we + return to user */ + mb(); + } while((in_le32(&pmac_irq_hw[i]->enable) & bit) + != (ppc_cached_irq_mask[i] & bit)); + + /* + * Unfortunately, setting the bit in the enable register + * when the device interrupt is already on *doesn't* set + * the bit in the flag register or request another interrupt. + */ + if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level)) + __set_lost((ulong)irq_nr, nokicklost); + spin_unlock_irqrestore(&pmac_pic_lock, flags); +} + +/* When an irq gets requested for the first client, if it's an + * edge interrupt, we clear any previous one on the controller + */ +static unsigned int pmac_startup_irq(unsigned int irq_nr) +{ + unsigned long bit = 1UL << (irq_nr & 0x1f); + int i = irq_nr >> 5; + + if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0) + out_le32(&pmac_irq_hw[i]->ack, bit); + set_bit(irq_nr, ppc_cached_irq_mask); + pmac_set_irq_mask(irq_nr, 0); + + return 0; +} + +static void pmac_mask_irq(unsigned int irq_nr) +{ + clear_bit(irq_nr, ppc_cached_irq_mask); + pmac_set_irq_mask(irq_nr, 0); + mb(); +} + +static void pmac_unmask_irq(unsigned int irq_nr) +{ + set_bit(irq_nr, ppc_cached_irq_mask); + pmac_set_irq_mask(irq_nr, 0); +} + +static void pmac_end_irq(unsigned int irq_nr) +{ + if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) + && irq_desc[irq_nr].action) { + set_bit(irq_nr, ppc_cached_irq_mask); + pmac_set_irq_mask(irq_nr, 1); + } +} + + +struct hw_interrupt_type pmac_pic = { + .typename = " PMAC-PIC ", + .startup = pmac_startup_irq, + .enable = pmac_unmask_irq, + .disable = pmac_mask_irq, + .ack = pmac_mask_and_ack_irq, + .end = pmac_end_irq, +}; + +struct hw_interrupt_type gatwick_pic = { + .typename = " GATWICK ", + .startup = pmac_startup_irq, + .enable = pmac_unmask_irq, + .disable = pmac_mask_irq, + .ack = pmac_mask_and_ack_irq, + .end = pmac_end_irq, +}; + +static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) +{ + int irq, bits; + + for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) { + int i = irq >> 5; + bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; + /* We must read level interrupts from the level register */ + bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]); + bits &= ppc_cached_irq_mask[i]; + if (bits == 0) + continue; + irq += __ilog2(bits); + __do_IRQ(irq, regs); + return IRQ_HANDLED; + } + printk("gatwick irq not from gatwick pic\n"); + return IRQ_NONE; +} + +int +pmac_get_irq(struct pt_regs *regs) +{ + int irq; + unsigned long bits = 0; + +#ifdef CONFIG_SMP + void psurge_smp_message_recv(struct pt_regs *); + + /* IPI's are a hack on the powersurge -- Cort */ + if ( smp_processor_id() != 0 ) { + psurge_smp_message_recv(regs); + return -2; /* ignore, already handled */ + } +#endif /* CONFIG_SMP */ + for (irq = max_real_irqs; (irq -= 32) >= 0; ) { + int i = irq >> 5; + bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; + /* We must read level interrupts from the level register */ + bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]); + bits &= ppc_cached_irq_mask[i]; + if (bits == 0) + continue; + irq += __ilog2(bits); + break; + } + + return irq; +} + +/* This routine will fix some missing interrupt values in the device tree + * on the gatwick mac-io controller used by some PowerBooks + */ +static void __init +pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base) +{ + struct device_node *node; + int count; + + memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool)); + node = gw->child; + count = 0; + while(node) + { + /* Fix SCC */ + if (strcasecmp(node->name, "escc") == 0) + if (node->child) { + if (node->child->n_intrs < 3) { + node->child->intrs = &gatwick_int_pool[count]; + count += 3; + } + node->child->n_intrs = 3; + node->child->intrs[0].line = 15+irq_base; + node->child->intrs[1].line = 4+irq_base; + node->child->intrs[2].line = 5+irq_base; + printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n", + node->child->intrs[0].line, + node->child->intrs[1].line, + node->child->intrs[2].line); + } + /* Fix media-bay & left SWIM */ + if (strcasecmp(node->name, "media-bay") == 0) { + struct device_node* ya_node; + + if (node->n_intrs == 0) + node->intrs = &gatwick_int_pool[count++]; + node->n_intrs = 1; + node->intrs[0].line = 29+irq_base; + printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n", + node->intrs[0].line); + + ya_node = node->child; + while(ya_node) + { + if (strcasecmp(ya_node->name, "floppy") == 0) { + if (ya_node->n_intrs < 2) { + ya_node->intrs = &gatwick_int_pool[count]; + count += 2; + } + ya_node->n_intrs = 2; + ya_node->intrs[0].line = 19+irq_base; + ya_node->intrs[1].line = 1+irq_base; + printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n", + ya_node->intrs[0].line, ya_node->intrs[1].line); + } + if (strcasecmp(ya_node->name, "ata4") == 0) { + if (ya_node->n_intrs < 2) { + ya_node->intrs = &gatwick_int_pool[count]; + count += 2; + } + ya_node->n_intrs = 2; + ya_node->intrs[0].line = 14+irq_base; + ya_node->intrs[1].line = 3+irq_base; + printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n", + ya_node->intrs[0].line, ya_node->intrs[1].line); + } + ya_node = ya_node->sibling; + } + } + node = node->sibling; + } + if (count > 10) { + printk("WARNING !! Gatwick interrupt pool overflow\n"); + printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE); + printk(" requested = %d\n", count); + } +} + +/* + * The PowerBook 3400/2400/3500 can have a combo ethernet/modem + * card which includes an ohare chip that acts as a second interrupt + * controller. If we find this second ohare, set it up and fix the + * interrupt value in the device tree for the ethernet chip. + */ +static int __init enable_second_ohare(void) +{ + unsigned char bus, devfn; + unsigned short cmd; + unsigned long addr; + struct device_node *irqctrler = find_devices("pci106b,7"); + struct device_node *ether; + + if (irqctrler == NULL || irqctrler->n_addrs <= 0) + return -1; + addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40); + pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20); + max_irqs = 64; + if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) { + struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler); + if (!hose) + printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); + else { + early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + cmd &= ~PCI_COMMAND_IO; + early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); + } + } + + /* Fix interrupt for the modem/ethernet combo controller. The number + in the device tree (27) is bogus (correct for the ethernet-only + board but not the combo ethernet/modem board). + The real interrupt is 28 on the second controller -> 28+32 = 60. + */ + ether = find_devices("pci1011,14"); + if (ether && ether->n_intrs > 0) { + ether->intrs[0].line = 60; + printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n", + ether->intrs[0].line); + } + + /* Return the interrupt number of the cascade */ + return irqctrler->intrs[0].line; +} + +#ifdef CONFIG_POWER4 +static irqreturn_t k2u3_action(int cpl, void *dev_id, struct pt_regs *regs) +{ + int irq; + + irq = openpic2_get_irq(regs); + if (irq != -1) + __do_IRQ(irq, regs); + return IRQ_HANDLED; +} + +static struct irqaction k2u3_cascade_action = { + .handler = k2u3_action, + .flags = 0, + .mask = CPU_MASK_NONE, + .name = "U3->K2 Cascade", +}; +#endif /* CONFIG_POWER4 */ + +#ifdef CONFIG_XMON +static struct irqaction xmon_action = { + .handler = xmon_irq, + .flags = 0, + .mask = CPU_MASK_NONE, + .name = "NMI - XMON" +}; +#endif + +static struct irqaction gatwick_cascade_action = { + .handler = gatwick_action, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "cascade", +}; + +void __init pmac_pic_init(void) +{ + int i; + struct device_node *irqctrler = NULL; + struct device_node *irqctrler2 = NULL; + struct device_node *np; + unsigned long addr; + int irq_cascade = -1; + + /* We first try to detect Apple's new Core99 chipset, since mac-io + * is quite different on those machines and contains an IBM MPIC2. + */ + np = find_type_devices("open-pic"); + while(np) { + if (np->parent && !strcmp(np->parent->name, "u3")) + irqctrler2 = np; + else + irqctrler = np; + np = np->next; + } + if (irqctrler != NULL) + { + if (irqctrler->n_addrs > 0) + { + unsigned char senses[128]; + + printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n", + irqctrler->addrs[0].address); + + prom_get_irq_senses(senses, 0, 128); + OpenPIC_InitSenses = senses; + OpenPIC_NumInitSenses = 128; + ppc_md.get_irq = openpic_get_irq; + pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler, 0, 0); + OpenPIC_Addr = ioremap(irqctrler->addrs[0].address, + irqctrler->addrs[0].size); + openpic_init(0); + +#ifdef CONFIG_POWER4 + if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 && + irqctrler2->n_addrs > 0) { + printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n", + irqctrler2->addrs[0].address, + irqctrler2->intrs[0].line); + pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0); + OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address, + irqctrler2->addrs[0].size); + prom_get_irq_senses(senses, PMAC_OPENPIC2_OFFSET, + PMAC_OPENPIC2_OFFSET+128); + OpenPIC_InitSenses = senses; + OpenPIC_NumInitSenses = 128; + openpic2_init(PMAC_OPENPIC2_OFFSET); + + if (setup_irq(irqctrler2->intrs[0].line, + &k2u3_cascade_action)) + printk("Unable to get OpenPIC IRQ for cascade\n"); + } +#endif /* CONFIG_POWER4 */ + +#ifdef CONFIG_XMON + { + struct device_node* pswitch; + int nmi_irq; + + pswitch = find_devices("programmer-switch"); + if (pswitch && pswitch->n_intrs) { + nmi_irq = pswitch->intrs[0].line; + openpic_init_nmi_irq(nmi_irq); + setup_irq(nmi_irq, &xmon_action); + } + } +#endif /* CONFIG_XMON */ + return; + } + irqctrler = NULL; + } + + /* Get the level/edge settings, assume if it's not + * a Grand Central nor an OHare, then it's an Heathrow + * (or Paddington). + */ + if (find_devices("gc")) + level_mask[0] = GC_LEVEL_MASK; + else if (find_devices("ohare")) { + level_mask[0] = OHARE_LEVEL_MASK; + /* We might have a second cascaded ohare */ + level_mask[1] = OHARE_LEVEL_MASK; + } else { + level_mask[0] = HEATHROW_LEVEL_MASK; + level_mask[1] = 0; + /* We might have a second cascaded heathrow */ + level_mask[2] = HEATHROW_LEVEL_MASK; + level_mask[3] = 0; + } + + /* + * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts, + * 1998 G3 Series PowerBooks have 128, + * other powermacs have 32. + * The combo ethernet/modem card for the Powerstar powerbooks + * (2400/3400/3500, ohare based) has a second ohare chip + * effectively making a total of 64. + */ + max_irqs = max_real_irqs = 32; + irqctrler = find_devices("mac-io"); + if (irqctrler) + { + max_real_irqs = 64; + if (irqctrler->next) + max_irqs = 128; + else + max_irqs = 64; + } + for ( i = 0; i < max_real_irqs ; i++ ) + irq_desc[i].handler = &pmac_pic; + + /* get addresses of first controller */ + if (irqctrler) { + if (irqctrler->n_addrs > 0) { + addr = (unsigned long) + ioremap(irqctrler->addrs[0].address, 0x40); + for (i = 0; i < 2; ++i) + pmac_irq_hw[i] = (volatile struct pmac_irq_hw*) + (addr + (2 - i) * 0x10); + } + + /* get addresses of second controller */ + irqctrler = irqctrler->next; + if (irqctrler && irqctrler->n_addrs > 0) { + addr = (unsigned long) + ioremap(irqctrler->addrs[0].address, 0x40); + for (i = 2; i < 4; ++i) + pmac_irq_hw[i] = (volatile struct pmac_irq_hw*) + (addr + (4 - i) * 0x10); + irq_cascade = irqctrler->intrs[0].line; + if (device_is_compatible(irqctrler, "gatwick")) + pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs); + } + } else { + /* older powermacs have a GC (grand central) or ohare at + f3000000, with interrupt control registers at f3000020. */ + addr = (unsigned long) ioremap(0xf3000000, 0x40); + pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20); + } + + /* PowerBooks 3400 and 3500 can have a second controller in a second + ohare chip, on the combo ethernet/modem card */ + if (machine_is_compatible("AAPL,3400/2400") + || machine_is_compatible("AAPL,3500")) + irq_cascade = enable_second_ohare(); + + /* disable all interrupts in all controllers */ + for (i = 0; i * 32 < max_irqs; ++i) + out_le32(&pmac_irq_hw[i]->enable, 0); + /* mark level interrupts */ + for (i = 0; i < max_irqs; i++) + if (level_mask[i >> 5] & (1UL << (i & 0x1f))) + irq_desc[i].status = IRQ_LEVEL; + + /* get interrupt line of secondary interrupt controller */ + if (irq_cascade >= 0) { + printk(KERN_INFO "irq: secondary controller on irq %d\n", + (int)irq_cascade); + for ( i = max_real_irqs ; i < max_irqs ; i++ ) + irq_desc[i].handler = &gatwick_pic; + setup_irq(irq_cascade, &gatwick_cascade_action); + } + printk("System has %d possible interrupts\n", max_irqs); + if (max_irqs != max_real_irqs) + printk(KERN_DEBUG "%d interrupts on main controller\n", + max_real_irqs); + +#ifdef CONFIG_XMON + setup_irq(20, &xmon_action); +#endif /* CONFIG_XMON */ +} + +#ifdef CONFIG_PM +/* + * These procedures are used in implementing sleep on the powerbooks. + * sleep_save_intrs() saves the states of all interrupt enables + * and disables all interrupts except for the nominated one. + * sleep_restore_intrs() restores the states of all interrupt enables. + */ +unsigned long sleep_save_mask[2]; + +/* This used to be passed by the PMU driver but that link got + * broken with the new driver model. We use this tweak for now... + */ +static int pmacpic_find_viaint(void) +{ + int viaint = -1; + +#ifdef CONFIG_ADB_PMU + struct device_node *np; + + if (pmu_get_model() != PMU_OHARE_BASED) + goto not_found; + np = of_find_node_by_name(NULL, "via-pmu"); + if (np == NULL) + goto not_found; + viaint = np->intrs[0].line; +#endif /* CONFIG_ADB_PMU */ + +not_found: + return viaint; +} + +static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state) +{ + int viaint = pmacpic_find_viaint(); + + sleep_save_mask[0] = ppc_cached_irq_mask[0]; + sleep_save_mask[1] = ppc_cached_irq_mask[1]; + ppc_cached_irq_mask[0] = 0; + ppc_cached_irq_mask[1] = 0; + if (viaint > 0) + set_bit(viaint, ppc_cached_irq_mask); + out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]); + if (max_real_irqs > 32) + out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]); + (void)in_le32(&pmac_irq_hw[0]->event); + /* make sure mask gets to controller before we return to caller */ + mb(); + (void)in_le32(&pmac_irq_hw[0]->enable); + + return 0; +} + +static int pmacpic_resume(struct sys_device *sysdev) +{ + int i; + + out_le32(&pmac_irq_hw[0]->enable, 0); + if (max_real_irqs > 32) + out_le32(&pmac_irq_hw[1]->enable, 0); + mb(); + for (i = 0; i < max_real_irqs; ++i) + if (test_bit(i, sleep_save_mask)) + pmac_unmask_irq(i); + + return 0; +} + +#endif /* CONFIG_PM */ + +static struct sysdev_class pmacpic_sysclass = { + set_kset_name("pmac_pic"), +}; + +static struct sys_device device_pmacpic = { + .id = 0, + .cls = &pmacpic_sysclass, +}; + +static struct sysdev_driver driver_pmacpic = { +#ifdef CONFIG_PM + .suspend = &pmacpic_suspend, + .resume = &pmacpic_resume, +#endif /* CONFIG_PM */ +}; + +static int __init init_pmacpic_sysfs(void) +{ + if (max_irqs == 0) + return -ENODEV; + + printk(KERN_DEBUG "Registering pmac pic with sysfs...\n"); + sysdev_class_register(&pmacpic_sysclass); + sysdev_register(&device_pmacpic); + sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic); + return 0; +} + +subsys_initcall(init_pmacpic_sysfs); + diff --git a/trunk/arch/ppc/platforms/pmac_pic.h b/trunk/arch/ppc/platforms/pmac_pic.h new file mode 100644 index 000000000000..664103dfeef9 --- /dev/null +++ b/trunk/arch/ppc/platforms/pmac_pic.h @@ -0,0 +1,11 @@ +#ifndef __PPC_PLATFORMS_PMAC_PIC_H +#define __PPC_PLATFORMS_PMAC_PIC_H + +#include + +extern struct hw_interrupt_type pmac_pic; + +void pmac_pic_init(void); +int pmac_get_irq(struct pt_regs *regs); + +#endif /* __PPC_PLATFORMS_PMAC_PIC_H */ diff --git a/trunk/arch/ppc/platforms/pmac_setup.c b/trunk/arch/ppc/platforms/pmac_setup.c new file mode 100644 index 000000000000..55d2beffe560 --- /dev/null +++ b/trunk/arch/ppc/platforms/pmac_setup.c @@ -0,0 +1,745 @@ +/* + * arch/ppc/platforms/setup.c + * + * PowerPC version + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Adapted for Power Macintosh by Paul Mackerras + * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) + * + * Derived from "arch/alpha/kernel/setup.c" + * Copyright (C) 1995 Linus Torvalds + * + * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * 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; either version + * 2 of the License, or (at your option) any later version. + * + */ + +/* + * bootup setup stuff.. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pmac_pic.h" +#include "mem_pieces.h" + +#undef SHOW_GATWICK_IRQS + +extern long pmac_time_init(void); +extern unsigned long pmac_get_rtc_time(void); +extern int pmac_set_rtc_time(unsigned long nowtime); +extern void pmac_read_rtc_time(void); +extern void pmac_calibrate_decr(void); +extern void pmac_pcibios_fixup(void); +extern void pmac_find_bridges(void); +extern unsigned long pmac_ide_get_base(int index); +extern void pmac_ide_init_hwif_ports(hw_regs_t *hw, + unsigned long data_port, unsigned long ctrl_port, int *irq); + +extern void pmac_nvram_update(void); +extern unsigned char pmac_nvram_read_byte(int addr); +extern void pmac_nvram_write_byte(int addr, unsigned char val); +extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial); +extern void pmac_pcibios_after_init(void); +extern int of_show_percpuinfo(struct seq_file *m, int i); + +struct device_node *memory_node; + +unsigned char drive_info; + +int ppc_override_l2cr = 0; +int ppc_override_l2cr_value; +int has_l2cache = 0; + +static int current_root_goodness = -1; + +extern int pmac_newworld; + +#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ + +extern void zs_kgdb_hook(int tty_num); +static void ohare_init(void); +#ifdef CONFIG_BOOTX_TEXT +static void pmac_progress(char *s, unsigned short hex); +#endif + +sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN; + +#ifdef CONFIG_SMP +extern struct smp_ops_t psurge_smp_ops; +extern struct smp_ops_t core99_smp_ops; +#endif /* CONFIG_SMP */ + +static int +pmac_show_cpuinfo(struct seq_file *m) +{ + struct device_node *np; + char *pp; + int plen; + int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO, + NULL, PMAC_MB_INFO_MODEL, 0); + unsigned int mbflags = (unsigned int)pmac_call_feature(PMAC_FTR_GET_MB_INFO, + NULL, PMAC_MB_INFO_FLAGS, 0); + char* mbname; + + if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (int)&mbname) != 0) + mbname = "Unknown"; + + /* find motherboard type */ + seq_printf(m, "machine\t\t: "); + np = find_devices("device-tree"); + if (np != NULL) { + pp = (char *) get_property(np, "model", NULL); + if (pp != NULL) + seq_printf(m, "%s\n", pp); + else + seq_printf(m, "PowerMac\n"); + pp = (char *) get_property(np, "compatible", &plen); + if (pp != NULL) { + seq_printf(m, "motherboard\t:"); + while (plen > 0) { + int l = strlen(pp) + 1; + seq_printf(m, " %s", pp); + plen -= l; + pp += l; + } + seq_printf(m, "\n"); + } + } else + seq_printf(m, "PowerMac\n"); + + /* print parsed model */ + seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname); + seq_printf(m, "pmac flags\t: %08x\n", mbflags); + + /* find l2 cache info */ + np = find_devices("l2-cache"); + if (np == 0) + np = find_type_devices("cache"); + if (np != 0) { + unsigned int *ic = (unsigned int *) + get_property(np, "i-cache-size", NULL); + unsigned int *dc = (unsigned int *) + get_property(np, "d-cache-size", NULL); + seq_printf(m, "L2 cache\t:"); + has_l2cache = 1; + if (get_property(np, "cache-unified", NULL) != 0 && dc) { + seq_printf(m, " %dK unified", *dc / 1024); + } else { + if (ic) + seq_printf(m, " %dK instruction", *ic / 1024); + if (dc) + seq_printf(m, "%s %dK data", + (ic? " +": ""), *dc / 1024); + } + pp = get_property(np, "ram-type", NULL); + if (pp) + seq_printf(m, " %s", pp); + seq_printf(m, "\n"); + } + + /* find ram info */ + np = find_devices("memory"); + if (np != 0) { + int n; + struct reg_property *reg = (struct reg_property *) + get_property(np, "reg", &n); + + if (reg != 0) { + unsigned long total = 0; + + for (n /= sizeof(struct reg_property); n > 0; --n) + total += (reg++)->size; + seq_printf(m, "memory\t\t: %luMB\n", total >> 20); + } + } + + /* Checks "l2cr-value" property in the registry */ + np = find_devices("cpus"); + if (np == 0) + np = find_type_devices("cpu"); + if (np != 0) { + unsigned int *l2cr = (unsigned int *) + get_property(np, "l2cr-value", NULL); + if (l2cr != 0) { + seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr); + } + } + + /* Indicate newworld/oldworld */ + seq_printf(m, "pmac-generation\t: %s\n", + pmac_newworld ? "NewWorld" : "OldWorld"); + + + return 0; +} + +static int +pmac_show_percpuinfo(struct seq_file *m, int i) +{ +#ifdef CONFIG_CPU_FREQ_PMAC + extern unsigned int pmac_get_one_cpufreq(int i); + unsigned int freq = pmac_get_one_cpufreq(i); + if (freq != 0) { + seq_printf(m, "clock\t\t: %dMHz\n", freq/1000); + return 0; + } +#endif /* CONFIG_CPU_FREQ_PMAC */ + return of_show_percpuinfo(m, i); +} + +static volatile u32 *sysctrl_regs; + +void __init +pmac_setup_arch(void) +{ + struct device_node *cpu; + int *fp; + unsigned long pvr; + + pvr = PVR_VER(mfspr(SPRN_PVR)); + + /* Set loops_per_jiffy to a half-way reasonable value, + for use until calibrate_delay gets called. */ + cpu = find_type_devices("cpu"); + if (cpu != 0) { + fp = (int *) get_property(cpu, "clock-frequency", NULL); + if (fp != 0) { + if (pvr == 4 || pvr >= 8) + /* 604, G3, G4 etc. */ + loops_per_jiffy = *fp / HZ; + else + /* 601, 603, etc. */ + loops_per_jiffy = *fp / (2*HZ); + } else + loops_per_jiffy = 50000000 / HZ; + } + + /* this area has the CPU identification register + and some registers used by smp boards */ + sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000); + ohare_init(); + + /* Lookup PCI hosts */ + pmac_find_bridges(); + + /* Checks "l2cr-value" property in the registry */ + if (cpu_has_feature(CPU_FTR_L2CR)) { + struct device_node *np = find_devices("cpus"); + if (np == 0) + np = find_type_devices("cpu"); + if (np != 0) { + unsigned int *l2cr = (unsigned int *) + get_property(np, "l2cr-value", NULL); + if (l2cr != 0) { + ppc_override_l2cr = 1; + ppc_override_l2cr_value = *l2cr; + _set_L2CR(0); + _set_L2CR(ppc_override_l2cr_value); + } + } + } + + if (ppc_override_l2cr) + printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n", + ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000) + ? "enabled" : "disabled"); + +#ifdef CONFIG_KGDB + zs_kgdb_hook(0); +#endif + +#ifdef CONFIG_ADB_CUDA + find_via_cuda(); +#else + if (find_devices("via-cuda")) { + printk("WARNING ! Your machine is Cuda based but your kernel\n"); + printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n"); + } +#endif +#ifdef CONFIG_ADB_PMU + find_via_pmu(); +#else + if (find_devices("via-pmu")) { + printk("WARNING ! Your machine is PMU based but your kernel\n"); + printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); + } +#endif +#ifdef CONFIG_NVRAM + pmac_nvram_init(); +#endif +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif + ROOT_DEV = DEFAULT_ROOT_DEVICE; + +#ifdef CONFIG_SMP + /* Check for Core99 */ + if (find_devices("uni-n") || find_devices("u3")) + smp_ops = &core99_smp_ops; + else + smp_ops = &psurge_smp_ops; +#endif /* CONFIG_SMP */ + + pci_create_OF_bus_map(); +} + +static void __init ohare_init(void) +{ + /* + * Turn on the L2 cache. + * We assume that we have a PSX memory controller iff + * we have an ohare I/O controller. + */ + if (find_devices("ohare") != NULL) { + if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) { + if (sysctrl_regs[4] & 0x10) + sysctrl_regs[4] |= 0x04000020; + else + sysctrl_regs[4] |= 0x04000000; + if(has_l2cache) + printk(KERN_INFO "Level 2 cache enabled\n"); + } + } +} + +extern char *bootpath; +extern char *bootdevice; +void *boot_host; +int boot_target; +int boot_part; +extern dev_t boot_dev; + +#ifdef CONFIG_SCSI +void __init +note_scsi_host(struct device_node *node, void *host) +{ + int l; + char *p; + + l = strlen(node->full_name); + if (bootpath != NULL && bootdevice != NULL + && strncmp(node->full_name, bootdevice, l) == 0 + && (bootdevice[l] == '/' || bootdevice[l] == 0)) { + boot_host = host; + /* + * There's a bug in OF 1.0.5. (Why am I not surprised.) + * If you pass a path like scsi/sd@1:0 to canon, it returns + * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0 + * That is, the scsi target number doesn't get preserved. + * So we pick the target number out of bootpath and use that. + */ + p = strstr(bootpath, "/sd@"); + if (p != NULL) { + p += 4; + boot_target = simple_strtoul(p, NULL, 10); + p = strchr(p, ':'); + if (p != NULL) + boot_part = simple_strtoul(p + 1, NULL, 10); + } + } +} +#endif + +#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) +static dev_t __init +find_ide_boot(void) +{ + char *p; + int n; + dev_t __init pmac_find_ide_boot(char *bootdevice, int n); + + if (bootdevice == NULL) + return 0; + p = strrchr(bootdevice, '/'); + if (p == NULL) + return 0; + n = p - bootdevice; + + return pmac_find_ide_boot(bootdevice, n); +} +#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */ + +static void __init +find_boot_device(void) +{ +#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) + boot_dev = find_ide_boot(); +#endif +} + +static int initializing = 1; +/* TODO: Merge the suspend-to-ram with the common code !!! + * currently, this is a stub implementation for suspend-to-disk + * only + */ + +#ifdef CONFIG_SOFTWARE_SUSPEND + +static int pmac_pm_prepare(suspend_state_t state) +{ + printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); + + return 0; +} + +static int pmac_pm_enter(suspend_state_t state) +{ + printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); + + /* Giveup the lazy FPU & vec so we don't have to back them + * up from the low level code + */ + enable_kernel_fp(); + +#ifdef CONFIG_ALTIVEC + if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC) + enable_kernel_altivec(); +#endif /* CONFIG_ALTIVEC */ + + return 0; +} + +static int pmac_pm_finish(suspend_state_t state) +{ + printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); + + /* Restore userland MMU context */ + set_context(current->active_mm->context, current->active_mm->pgd); + + return 0; +} + +static struct pm_ops pmac_pm_ops = { + .pm_disk_mode = PM_DISK_SHUTDOWN, + .prepare = pmac_pm_prepare, + .enter = pmac_pm_enter, + .finish = pmac_pm_finish, +}; + +#endif /* CONFIG_SOFTWARE_SUSPEND */ + +static int pmac_late_init(void) +{ + initializing = 0; +#ifdef CONFIG_SOFTWARE_SUSPEND + pm_set_ops(&pmac_pm_ops); +#endif /* CONFIG_SOFTWARE_SUSPEND */ + return 0; +} + +late_initcall(pmac_late_init); + +/* can't be __init - can be called whenever a disk is first accessed */ +void +note_bootable_part(dev_t dev, int part, int goodness) +{ + static int found_boot = 0; + char *p; + + if (!initializing) + return; + if ((goodness <= current_root_goodness) && + ROOT_DEV != DEFAULT_ROOT_DEVICE) + return; + p = strstr(saved_command_line, "root="); + if (p != NULL && (p == saved_command_line || p[-1] == ' ')) + return; + + if (!found_boot) { + find_boot_device(); + found_boot = 1; + } + if (!boot_dev || dev == boot_dev) { + ROOT_DEV = dev + part; + boot_dev = 0; + current_root_goodness = goodness; + } +} + +static void +pmac_restart(char *cmd) +{ +#ifdef CONFIG_ADB_CUDA + struct adb_request req; +#endif /* CONFIG_ADB_CUDA */ + + switch (sys_ctrler) { +#ifdef CONFIG_ADB_CUDA + case SYS_CTRLER_CUDA: + cuda_request(&req, NULL, 2, CUDA_PACKET, + CUDA_RESET_SYSTEM); + for (;;) + cuda_poll(); + break; +#endif /* CONFIG_ADB_CUDA */ +#ifdef CONFIG_ADB_PMU + case SYS_CTRLER_PMU: + pmu_restart(); + break; +#endif /* CONFIG_ADB_PMU */ + default: ; + } +} + +static void +pmac_power_off(void) +{ +#ifdef CONFIG_ADB_CUDA + struct adb_request req; +#endif /* CONFIG_ADB_CUDA */ + + switch (sys_ctrler) { +#ifdef CONFIG_ADB_CUDA + case SYS_CTRLER_CUDA: + cuda_request(&req, NULL, 2, CUDA_PACKET, + CUDA_POWERDOWN); + for (;;) + cuda_poll(); + break; +#endif /* CONFIG_ADB_CUDA */ +#ifdef CONFIG_ADB_PMU + case SYS_CTRLER_PMU: + pmu_shutdown(); + break; +#endif /* CONFIG_ADB_PMU */ + default: ; + } +} + +static void +pmac_halt(void) +{ + pmac_power_off(); +} + +/* + * Read in a property describing some pieces of memory. + */ + +static int __init +get_mem_prop(char *name, struct mem_pieces *mp) +{ + struct reg_property *rp; + int i, s; + unsigned int *ip; + int nac = prom_n_addr_cells(memory_node); + int nsc = prom_n_size_cells(memory_node); + + ip = (unsigned int *) get_property(memory_node, name, &s); + if (ip == NULL) { + printk(KERN_ERR "error: couldn't get %s property on /memory\n", + name); + return 0; + } + s /= (nsc + nac) * 4; + rp = mp->regions; + for (i = 0; i < s; ++i, ip += nac+nsc) { + if (nac >= 2 && ip[nac-2] != 0) + continue; + rp->address = ip[nac-1]; + if (nsc >= 2 && ip[nac+nsc-2] != 0) + rp->size = ~0U; + else + rp->size = ip[nac+nsc-1]; + ++rp; + } + mp->n_regions = rp - mp->regions; + + /* Make sure the pieces are sorted. */ + mem_pieces_sort(mp); + mem_pieces_coalesce(mp); + return 1; +} + +/* + * On systems with Open Firmware, collect information about + * physical RAM and which pieces are already in use. + * At this point, we have (at least) the first 8MB mapped with a BAT. + * Our text, data, bss use something over 1MB, starting at 0. + * Open Firmware may be using 1MB at the 4MB point. + */ +unsigned long __init +pmac_find_end_of_memory(void) +{ + unsigned long a, total; + struct mem_pieces phys_mem; + + /* + * Find out where physical memory is, and check that it + * starts at 0 and is contiguous. It seems that RAM is + * always physically contiguous on Power Macintoshes. + * + * Supporting discontiguous physical memory isn't hard, + * it just makes the virtual <-> physical mapping functions + * more complicated (or else you end up wasting space + * in mem_map). + */ + memory_node = find_devices("memory"); + if (memory_node == NULL || !get_mem_prop("reg", &phys_mem) + || phys_mem.n_regions == 0) + panic("No RAM??"); + a = phys_mem.regions[0].address; + if (a != 0) + panic("RAM doesn't start at physical address 0"); + total = phys_mem.regions[0].size; + + if (phys_mem.n_regions > 1) { + printk("RAM starting at 0x%x is not contiguous\n", + phys_mem.regions[1].address); + printk("Using RAM from 0 to 0x%lx\n", total-1); + } + + return total; +} + +void __init +pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + /* isa_io_base gets set in pmac_find_bridges */ + isa_mem_base = PMAC_ISA_MEM_BASE; + pci_dram_offset = PMAC_PCI_DRAM_OFFSET; + ISA_DMA_THRESHOLD = ~0L; + DMA_MODE_READ = 1; + DMA_MODE_WRITE = 2; + + ppc_md.setup_arch = pmac_setup_arch; + ppc_md.show_cpuinfo = pmac_show_cpuinfo; + ppc_md.show_percpuinfo = pmac_show_percpuinfo; + ppc_md.init_IRQ = pmac_pic_init; + ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */ + + ppc_md.pcibios_fixup = pmac_pcibios_fixup; + ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook; + ppc_md.pcibios_after_init = pmac_pcibios_after_init; + ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; + + ppc_md.restart = pmac_restart; + ppc_md.power_off = pmac_power_off; + ppc_md.halt = pmac_halt; + + ppc_md.time_init = pmac_time_init; + ppc_md.set_rtc_time = pmac_set_rtc_time; + ppc_md.get_rtc_time = pmac_get_rtc_time; + ppc_md.calibrate_decr = pmac_calibrate_decr; + + ppc_md.find_end_of_memory = pmac_find_end_of_memory; + + ppc_md.feature_call = pmac_do_feature_call; + +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) +#ifdef CONFIG_BLK_DEV_IDE_PMAC + ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; + ppc_ide_md.default_io_base = pmac_ide_get_base; +#endif /* CONFIG_BLK_DEV_IDE_PMAC */ +#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */ + +#ifdef CONFIG_BOOTX_TEXT + ppc_md.progress = pmac_progress; +#endif /* CONFIG_BOOTX_TEXT */ + + if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0); + +} + +#ifdef CONFIG_BOOTX_TEXT +static void __init +pmac_progress(char *s, unsigned short hex) +{ + if (boot_text_mapped) { + btext_drawstring(s); + btext_drawchar('\n'); + } +} +#endif /* CONFIG_BOOTX_TEXT */ + +static int __init +pmac_declare_of_platform_devices(void) +{ + struct device_node *np; + + np = find_devices("uni-n"); + if (np) { + for (np = np->child; np != NULL; np = np->sibling) + if (strncmp(np->name, "i2c", 3) == 0) { + of_platform_device_create(np, "uni-n-i2c", + NULL); + break; + } + } + np = find_devices("u3"); + if (np) { + for (np = np->child; np != NULL; np = np->sibling) + if (strncmp(np->name, "i2c", 3) == 0) { + of_platform_device_create(np, "u3-i2c", + NULL); + break; + } + } + + np = find_devices("valkyrie"); + if (np) + of_platform_device_create(np, "valkyrie", NULL); + np = find_devices("platinum"); + if (np) + of_platform_device_create(np, "platinum", NULL); + + return 0; +} + +device_initcall(pmac_declare_of_platform_devices); diff --git a/trunk/arch/ppc/platforms/pmac_sleep.S b/trunk/arch/ppc/platforms/pmac_sleep.S new file mode 100644 index 000000000000..22b113d19b24 --- /dev/null +++ b/trunk/arch/ppc/platforms/pmac_sleep.S @@ -0,0 +1,396 @@ +/* + * This file contains sleep low-level functions for PowerBook G3. + * Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org) + * and Paul Mackerras (paulus@samba.org). + * + * 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; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAGIC 0x4c617273 /* 'Lars' */ + +/* + * Structure for storing CPU registers on the stack. + */ +#define SL_SP 0 +#define SL_PC 4 +#define SL_MSR 8 +#define SL_SDR1 0xc +#define SL_SPRG0 0x10 /* 4 sprg's */ +#define SL_DBAT0 0x20 +#define SL_IBAT0 0x28 +#define SL_DBAT1 0x30 +#define SL_IBAT1 0x38 +#define SL_DBAT2 0x40 +#define SL_IBAT2 0x48 +#define SL_DBAT3 0x50 +#define SL_IBAT3 0x58 +#define SL_TB 0x60 +#define SL_R2 0x68 +#define SL_CR 0x6c +#define SL_R12 0x70 /* r12 to r31 */ +#define SL_SIZE (SL_R12 + 80) + + .section .text + .align 5 + +#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) + +/* This gets called by via-pmu.c late during the sleep process. + * The PMU was already send the sleep command and will shut us down + * soon. We need to save all that is needed and setup the wakeup + * vector that will be called by the ROM on wakeup + */ +_GLOBAL(low_sleep_handler) +#ifndef CONFIG_6xx + blr +#else + mflr r0 + stw r0,4(r1) + stwu r1,-SL_SIZE(r1) + mfcr r0 + stw r0,SL_CR(r1) + stw r2,SL_R2(r1) + stmw r12,SL_R12(r1) + + /* Save MSR & SDR1 */ + mfmsr r4 + stw r4,SL_MSR(r1) + mfsdr1 r4 + stw r4,SL_SDR1(r1) + + /* Get a stable timebase and save it */ +1: mftbu r4 + stw r4,SL_TB(r1) + mftb r5 + stw r5,SL_TB+4(r1) + mftbu r3 + cmpw r3,r4 + bne 1b + + /* Save SPRGs */ + mfsprg r4,0 + stw r4,SL_SPRG0(r1) + mfsprg r4,1 + stw r4,SL_SPRG0+4(r1) + mfsprg r4,2 + stw r4,SL_SPRG0+8(r1) + mfsprg r4,3 + stw r4,SL_SPRG0+12(r1) + + /* Save BATs */ + mfdbatu r4,0 + stw r4,SL_DBAT0(r1) + mfdbatl r4,0 + stw r4,SL_DBAT0+4(r1) + mfdbatu r4,1 + stw r4,SL_DBAT1(r1) + mfdbatl r4,1 + stw r4,SL_DBAT1+4(r1) + mfdbatu r4,2 + stw r4,SL_DBAT2(r1) + mfdbatl r4,2 + stw r4,SL_DBAT2+4(r1) + mfdbatu r4,3 + stw r4,SL_DBAT3(r1) + mfdbatl r4,3 + stw r4,SL_DBAT3+4(r1) + mfibatu r4,0 + stw r4,SL_IBAT0(r1) + mfibatl r4,0 + stw r4,SL_IBAT0+4(r1) + mfibatu r4,1 + stw r4,SL_IBAT1(r1) + mfibatl r4,1 + stw r4,SL_IBAT1+4(r1) + mfibatu r4,2 + stw r4,SL_IBAT2(r1) + mfibatl r4,2 + stw r4,SL_IBAT2+4(r1) + mfibatu r4,3 + stw r4,SL_IBAT3(r1) + mfibatl r4,3 + stw r4,SL_IBAT3+4(r1) + + /* Backup various CPU config stuffs */ + bl __save_cpu_setup + + /* The ROM can wake us up via 2 different vectors: + * - On wallstreet & lombard, we must write a magic + * value 'Lars' at address 4 and a pointer to a + * memory location containing the PC to resume from + * at address 0. + * - On Core99, we must store the wakeup vector at + * address 0x80 and eventually it's parameters + * at address 0x84. I've have some trouble with those + * parameters however and I no longer use them. + */ + lis r5,grackle_wake_up@ha + addi r5,r5,grackle_wake_up@l + tophys(r5,r5) + stw r5,SL_PC(r1) + lis r4,KERNELBASE@h + tophys(r5,r1) + addi r5,r5,SL_PC + lis r6,MAGIC@ha + addi r6,r6,MAGIC@l + stw r5,0(r4) + stw r6,4(r4) + /* Setup stuffs at 0x80-0x84 for Core99 */ + lis r3,core99_wake_up@ha + addi r3,r3,core99_wake_up@l + tophys(r3,r3) + stw r3,0x80(r4) + stw r5,0x84(r4) + /* Store a pointer to our backup storage into + * a kernel global + */ + lis r3,sleep_storage@ha + addi r3,r3,sleep_storage@l + stw r5,0(r3) + + .globl low_cpu_die +low_cpu_die: + /* Flush & disable all caches */ + bl flush_disable_caches + + /* Turn off data relocation. */ + mfmsr r3 /* Save MSR in r7 */ + rlwinm r3,r3,0,28,26 /* Turn off DR bit */ + sync + mtmsr r3 + isync + +BEGIN_FTR_SECTION + /* Flush any pending L2 data prefetches to work around HW bug */ + sync + lis r3,0xfff0 + lwz r0,0(r3) /* perform cache-inhibited load to ROM */ + sync /* (caches are disabled at this point) */ +END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) + +/* + * Set the HID0 and MSR for sleep. + */ + mfspr r2,SPRN_HID0 + rlwinm r2,r2,0,10,7 /* clear doze, nap */ + oris r2,r2,HID0_SLEEP@h + sync + isync + mtspr SPRN_HID0,r2 + sync + +/* This loop puts us back to sleep in case we have a spurrious + * wakeup so that the host bridge properly stays asleep. The + * CPU will be turned off, either after a known time (about 1 + * second) on wallstreet & lombard, or as soon as the CPU enters + * SLEEP mode on core99 + */ + mfmsr r2 + oris r2,r2,MSR_POW@h +1: sync + mtmsr r2 + isync + b 1b + +/* + * Here is the resume code. + */ + + +/* + * Core99 machines resume here + * r4 has the physical address of SL_PC(sp) (unused) + */ +_GLOBAL(core99_wake_up) + /* Make sure HID0 no longer contains any sleep bit and that data cache + * is disabled + */ + mfspr r3,SPRN_HID0 + rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */ + rlwinm 3,r3,0,18,15 /* clear DCE, ICE */ + mtspr SPRN_HID0,r3 + sync + isync + + /* sanitize MSR */ + mfmsr r3 + ori r3,r3,MSR_EE|MSR_IP + xori r3,r3,MSR_EE|MSR_IP + sync + isync + mtmsr r3 + sync + isync + + /* Recover sleep storage */ + lis r3,sleep_storage@ha + addi r3,r3,sleep_storage@l + tophys(r3,r3) + lwz r1,0(r3) + + /* Pass thru to older resume code ... */ +/* + * Here is the resume code for older machines. + * r1 has the physical address of SL_PC(sp). + */ + +grackle_wake_up: + + /* Restore the kernel's segment registers before + * we do any r1 memory access as we are not sure they + * are in a sane state above the first 256Mb region + */ + li r0,16 /* load up segment register values */ + mtctr r0 /* for context 0 */ + lis r3,0x2000 /* Ku = 1, VSID = 0 */ + li r4,0 +3: mtsrin r3,r4 + addi r3,r3,0x111 /* increment VSID */ + addis r4,r4,0x1000 /* address of next segment */ + bdnz 3b + sync + isync + + subi r1,r1,SL_PC + + /* Restore various CPU config stuffs */ + bl __restore_cpu_setup + + /* Make sure all FPRs have been initialized */ + bl reloc_offset + bl __init_fpu_registers + + /* Invalidate & enable L1 cache, we don't care about + * whatever the ROM may have tried to write to memory + */ + bl __inval_enable_L1 + + /* Restore the BATs, and SDR1. Then we can turn on the MMU. */ + lwz r4,SL_SDR1(r1) + mtsdr1 r4 + lwz r4,SL_SPRG0(r1) + mtsprg 0,r4 + lwz r4,SL_SPRG0+4(r1) + mtsprg 1,r4 + lwz r4,SL_SPRG0+8(r1) + mtsprg 2,r4 + lwz r4,SL_SPRG0+12(r1) + mtsprg 3,r4 + + lwz r4,SL_DBAT0(r1) + mtdbatu 0,r4 + lwz r4,SL_DBAT0+4(r1) + mtdbatl 0,r4 + lwz r4,SL_DBAT1(r1) + mtdbatu 1,r4 + lwz r4,SL_DBAT1+4(r1) + mtdbatl 1,r4 + lwz r4,SL_DBAT2(r1) + mtdbatu 2,r4 + lwz r4,SL_DBAT2+4(r1) + mtdbatl 2,r4 + lwz r4,SL_DBAT3(r1) + mtdbatu 3,r4 + lwz r4,SL_DBAT3+4(r1) + mtdbatl 3,r4 + lwz r4,SL_IBAT0(r1) + mtibatu 0,r4 + lwz r4,SL_IBAT0+4(r1) + mtibatl 0,r4 + lwz r4,SL_IBAT1(r1) + mtibatu 1,r4 + lwz r4,SL_IBAT1+4(r1) + mtibatl 1,r4 + lwz r4,SL_IBAT2(r1) + mtibatu 2,r4 + lwz r4,SL_IBAT2+4(r1) + mtibatl 2,r4 + lwz r4,SL_IBAT3(r1) + mtibatu 3,r4 + lwz r4,SL_IBAT3+4(r1) + mtibatl 3,r4 + +BEGIN_FTR_SECTION + li r4,0 + mtspr SPRN_DBAT4U,r4 + mtspr SPRN_DBAT4L,r4 + mtspr SPRN_DBAT5U,r4 + mtspr SPRN_DBAT5L,r4 + mtspr SPRN_DBAT6U,r4 + mtspr SPRN_DBAT6L,r4 + mtspr SPRN_DBAT7U,r4 + mtspr SPRN_DBAT7L,r4 + mtspr SPRN_IBAT4U,r4 + mtspr SPRN_IBAT4L,r4 + mtspr SPRN_IBAT5U,r4 + mtspr SPRN_IBAT5L,r4 + mtspr SPRN_IBAT6U,r4 + mtspr SPRN_IBAT6L,r4 + mtspr SPRN_IBAT7U,r4 + mtspr SPRN_IBAT7L,r4 +END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS) + + /* Flush all TLBs */ + lis r4,0x1000 +1: addic. r4,r4,-0x1000 + tlbie r4 + blt 1b + sync + + /* restore the MSR and turn on the MMU */ + lwz r3,SL_MSR(r1) + bl turn_on_mmu + + /* get back the stack pointer */ + tovirt(r1,r1) + + /* Restore TB */ + li r3,0 + mttbl r3 + lwz r3,SL_TB(r1) + lwz r4,SL_TB+4(r1) + mttbu r3 + mttbl r4 + + /* Restore the callee-saved registers and return */ + lwz r0,SL_CR(r1) + mtcr r0 + lwz r2,SL_R2(r1) + lmw r12,SL_R12(r1) + addi r1,r1,SL_SIZE + lwz r0,4(r1) + mtlr r0 + blr + +turn_on_mmu: + mflr r4 + tovirt(r4,r4) + mtsrr0 r4 + mtsrr1 r3 + sync + isync + rfi + +#endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */ + + .section .data + .balign L1_CACHE_BYTES +sleep_storage: + .long 0 + .balign L1_CACHE_BYTES, 0 + +#endif /* CONFIG_6xx */ + .section .text diff --git a/trunk/arch/ppc/platforms/pmac_smp.c b/trunk/arch/ppc/platforms/pmac_smp.c new file mode 100644 index 000000000000..26ff26238f03 --- /dev/null +++ b/trunk/arch/ppc/platforms/pmac_smp.c @@ -0,0 +1,692 @@ +/* + * SMP support for power macintosh. + * + * We support both the old "powersurge" SMP architecture + * and the current Core99 (G4 PowerMac) machines. + * + * Note that we don't support the very first rev. of + * Apple/DayStar 2 CPUs board, the one with the funky + * watchdog. Hopefully, none of these should be there except + * maybe internally to Apple. I should probably still add some + * code to detect this card though and disable SMP. --BenH. + * + * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net) + * and Ben Herrenschmidt . + * + * Support for DayStar quad CPU cards + * Copyright (C) XLR8, Inc. 1994-2000 + * + * 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; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Powersurge (old powermac SMP) support. + */ + +extern void __secondary_start_pmac_0(void); + +/* Addresses for powersurge registers */ +#define HAMMERHEAD_BASE 0xf8000000 +#define HHEAD_CONFIG 0x90 +#define HHEAD_SEC_INTR 0xc0 + +/* register for interrupting the primary processor on the powersurge */ +/* N.B. this is actually the ethernet ROM! */ +#define PSURGE_PRI_INTR 0xf3019000 + +/* register for storing the start address for the secondary processor */ +/* N.B. this is the PCI config space address register for the 1st bridge */ +#define PSURGE_START 0xf2800000 + +/* Daystar/XLR8 4-CPU card */ +#define PSURGE_QUAD_REG_ADDR 0xf8800000 + +#define PSURGE_QUAD_IRQ_SET 0 +#define PSURGE_QUAD_IRQ_CLR 1 +#define PSURGE_QUAD_IRQ_PRIMARY 2 +#define PSURGE_QUAD_CKSTOP_CTL 3 +#define PSURGE_QUAD_PRIMARY_ARB 4 +#define PSURGE_QUAD_BOARD_ID 6 +#define PSURGE_QUAD_WHICH_CPU 7 +#define PSURGE_QUAD_CKSTOP_RDBK 8 +#define PSURGE_QUAD_RESET_CTL 11 + +#define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v))) +#define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f) +#define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v))) +#define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v))) + +/* virtual addresses for the above */ +static volatile u8 __iomem *hhead_base; +static volatile u8 __iomem *quad_base; +static volatile u32 __iomem *psurge_pri_intr; +static volatile u8 __iomem *psurge_sec_intr; +static volatile u32 __iomem *psurge_start; + +/* values for psurge_type */ +#define PSURGE_NONE -1 +#define PSURGE_DUAL 0 +#define PSURGE_QUAD_OKEE 1 +#define PSURGE_QUAD_COTTON 2 +#define PSURGE_QUAD_ICEGRASS 3 + +/* what sort of powersurge board we have */ +static int psurge_type = PSURGE_NONE; + +/* L2 and L3 cache settings to pass from CPU0 to CPU1 */ +volatile static long int core99_l2_cache; +volatile static long int core99_l3_cache; + +/* Timebase freeze GPIO */ +static unsigned int core99_tb_gpio; + +/* Sync flag for HW tb sync */ +static volatile int sec_tb_reset = 0; +static unsigned int pri_tb_hi, pri_tb_lo; +static unsigned int pri_tb_stamp; + +static void __devinit core99_init_caches(int cpu) +{ + if (!cpu_has_feature(CPU_FTR_L2CR)) + return; + + if (cpu == 0) { + core99_l2_cache = _get_L2CR(); + printk("CPU0: L2CR is %lx\n", core99_l2_cache); + } else { + printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR()); + _set_L2CR(0); + _set_L2CR(core99_l2_cache); + printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache); + } + + if (!cpu_has_feature(CPU_FTR_L3CR)) + return; + + if (cpu == 0){ + core99_l3_cache = _get_L3CR(); + printk("CPU0: L3CR is %lx\n", core99_l3_cache); + } else { + printk("CPU%d: L3CR was %lx\n", cpu, _get_L3CR()); + _set_L3CR(0); + _set_L3CR(core99_l3_cache); + printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache); + } +} + +/* + * Set and clear IPIs for powersurge. + */ +static inline void psurge_set_ipi(int cpu) +{ + if (psurge_type == PSURGE_NONE) + return; + if (cpu == 0) + in_be32(psurge_pri_intr); + else if (psurge_type == PSURGE_DUAL) + out_8(psurge_sec_intr, 0); + else + PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu); +} + +static inline void psurge_clr_ipi(int cpu) +{ + if (cpu > 0) { + switch(psurge_type) { + case PSURGE_DUAL: + out_8(psurge_sec_intr, ~0); + case PSURGE_NONE: + break; + default: + PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu); + } + } +} + +/* + * On powersurge (old SMP powermac architecture) we don't have + * separate IPIs for separate messages like openpic does. Instead + * we have a bitmap for each processor, where a 1 bit means that + * the corresponding message is pending for that processor. + * Ideally each cpu's entry would be in a different cache line. + * -- paulus. + */ +static unsigned long psurge_smp_message[NR_CPUS]; + +void psurge_smp_message_recv(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + int msg; + + /* clear interrupt */ + psurge_clr_ipi(cpu); + + if (num_online_cpus() < 2) + return; + + /* make sure there is a message there */ + for (msg = 0; msg < 4; msg++) + if (test_and_clear_bit(msg, &psurge_smp_message[cpu])) + smp_message_recv(msg, regs); +} + +irqreturn_t psurge_primary_intr(int irq, void *d, struct pt_regs *regs) +{ + psurge_smp_message_recv(regs); + return IRQ_HANDLED; +} + +static void smp_psurge_message_pass(int target, int msg) +{ + int i; + + if (num_online_cpus() < 2) + return; + + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) + continue; + if (target == MSG_ALL + || (target == MSG_ALL_BUT_SELF && i != smp_processor_id()) + || target == i) { + set_bit(msg, &psurge_smp_message[i]); + psurge_set_ipi(i); + } + } +} + +/* + * Determine a quad card presence. We read the board ID register, we + * force the data bus to change to something else, and we read it again. + * It it's stable, then the register probably exist (ugh !) + */ +static int __init psurge_quad_probe(void) +{ + int type; + unsigned int i; + + type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID); + if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS + || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) + return PSURGE_DUAL; + + /* looks OK, try a slightly more rigorous test */ + /* bogus is not necessarily cacheline-aligned, + though I don't suppose that really matters. -- paulus */ + for (i = 0; i < 100; i++) { + volatile u32 bogus[8]; + bogus[(0+i)%8] = 0x00000000; + bogus[(1+i)%8] = 0x55555555; + bogus[(2+i)%8] = 0xFFFFFFFF; + bogus[(3+i)%8] = 0xAAAAAAAA; + bogus[(4+i)%8] = 0x33333333; + bogus[(5+i)%8] = 0xCCCCCCCC; + bogus[(6+i)%8] = 0xCCCCCCCC; + bogus[(7+i)%8] = 0x33333333; + wmb(); + asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory"); + mb(); + if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) + return PSURGE_DUAL; + } + return type; +} + +static void __init psurge_quad_init(void) +{ + int procbits; + + if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351); + procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU); + if (psurge_type == PSURGE_QUAD_ICEGRASS) + PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); + else + PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits); + mdelay(33); + out_8(psurge_sec_intr, ~0); + PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits); + PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); + if (psurge_type != PSURGE_QUAD_ICEGRASS) + PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits); + PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits); + mdelay(33); + PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits); + mdelay(33); + PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits); + mdelay(33); +} + +static int __init smp_psurge_probe(void) +{ + int i, ncpus; + + /* We don't do SMP on the PPC601 -- paulus */ + if (PVR_VER(mfspr(SPRN_PVR)) == 1) + return 1; + + /* + * The powersurge cpu board can be used in the generation + * of powermacs that have a socket for an upgradeable cpu card, + * including the 7500, 8500, 9500, 9600. + * The device tree doesn't tell you if you have 2 cpus because + * OF doesn't know anything about the 2nd processor. + * Instead we look for magic bits in magic registers, + * in the hammerhead memory controller in the case of the + * dual-cpu powersurge board. -- paulus. + */ + if (find_devices("hammerhead") == NULL) + return 1; + + hhead_base = ioremap(HAMMERHEAD_BASE, 0x800); + quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024); + psurge_sec_intr = hhead_base + HHEAD_SEC_INTR; + + psurge_type = psurge_quad_probe(); + if (psurge_type != PSURGE_DUAL) { + psurge_quad_init(); + /* All released cards using this HW design have 4 CPUs */ + ncpus = 4; + } else { + iounmap(quad_base); + if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) { + /* not a dual-cpu card */ + iounmap(hhead_base); + psurge_type = PSURGE_NONE; + return 1; + } + ncpus = 2; + } + + psurge_start = ioremap(PSURGE_START, 4); + psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); + + /* this is not actually strictly necessary -- paulus. */ + for (i = 1; i < ncpus; ++i) + smp_hw_index[i] = i; + + if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); + + return ncpus; +} + +static void __init smp_psurge_kick_cpu(int nr) +{ + unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8; + unsigned long a; + + /* may need to flush here if secondary bats aren't setup */ + for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32) + asm volatile("dcbf 0,%0" : : "r" (a) : "memory"); + asm volatile("sync"); + + if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353); + + out_be32(psurge_start, start); + mb(); + + psurge_set_ipi(nr); + udelay(10); + psurge_clr_ipi(nr); + + if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354); +} + +/* + * With the dual-cpu powersurge board, the decrementers and timebases + * of both cpus are frozen after the secondary cpu is started up, + * until we give the secondary cpu another interrupt. This routine + * uses this to get the timebases synchronized. + * -- paulus. + */ +static void __init psurge_dual_sync_tb(int cpu_nr) +{ + int t; + + set_dec(tb_ticks_per_jiffy); + set_tb(0, 0); + last_jiffy_stamp(cpu_nr) = 0; + + if (cpu_nr > 0) { + mb(); + sec_tb_reset = 1; + return; + } + + /* wait for the secondary to have reset its TB before proceeding */ + for (t = 10000000; t > 0 && !sec_tb_reset; --t) + ; + + /* now interrupt the secondary, starting both TBs */ + psurge_set_ipi(1); + + smp_tb_synchronized = 1; +} + +static struct irqaction psurge_irqaction = { + .handler = psurge_primary_intr, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "primary IPI", +}; + +static void __init smp_psurge_setup_cpu(int cpu_nr) +{ + + if (cpu_nr == 0) { + /* If we failed to start the second CPU, we should still + * send it an IPI to start the timebase & DEC or we might + * have them stuck. + */ + if (num_online_cpus() < 2) { + if (psurge_type == PSURGE_DUAL) + psurge_set_ipi(1); + return; + } + /* reset the entry point so if we get another intr we won't + * try to startup again */ + out_be32(psurge_start, 0x100); + if (setup_irq(30, &psurge_irqaction)) + printk(KERN_ERR "Couldn't get primary IPI interrupt"); + } + + if (psurge_type == PSURGE_DUAL) + psurge_dual_sync_tb(cpu_nr); +} + +void __init smp_psurge_take_timebase(void) +{ + /* Dummy implementation */ +} + +void __init smp_psurge_give_timebase(void) +{ + /* Dummy implementation */ +} + +static int __init smp_core99_probe(void) +{ +#ifdef CONFIG_6xx + extern int powersave_nap; +#endif + struct device_node *cpus, *firstcpu; + int i, ncpus = 0, boot_cpu = -1; + u32 *tbprop = NULL; + + if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345); + cpus = firstcpu = find_type_devices("cpu"); + while(cpus != NULL) { + u32 *regprop = (u32 *)get_property(cpus, "reg", NULL); + char *stateprop = (char *)get_property(cpus, "state", NULL); + if (regprop != NULL && stateprop != NULL && + !strncmp(stateprop, "running", 7)) + boot_cpu = *regprop; + ++ncpus; + cpus = cpus->next; + } + if (boot_cpu == -1) + printk(KERN_WARNING "Couldn't detect boot CPU !\n"); + if (boot_cpu != 0) + printk(KERN_WARNING "Boot CPU is %d, unsupported setup !\n", boot_cpu); + + if (machine_is_compatible("MacRISC4")) { + extern struct smp_ops_t core99_smp_ops; + + core99_smp_ops.take_timebase = smp_generic_take_timebase; + core99_smp_ops.give_timebase = smp_generic_give_timebase; + } else { + if (firstcpu != NULL) + tbprop = (u32 *)get_property(firstcpu, "timebase-enable", NULL); + if (tbprop) + core99_tb_gpio = *tbprop; + else + core99_tb_gpio = KL_GPIO_TB_ENABLE; + } + + if (ncpus > 1) { + openpic_request_IPIs(); + for (i = 1; i < ncpus; ++i) + smp_hw_index[i] = i; +#ifdef CONFIG_6xx + powersave_nap = 0; +#endif + core99_init_caches(0); + } + + return ncpus; +} + +static void __devinit smp_core99_kick_cpu(int nr) +{ + unsigned long save_vector, new_vector; + unsigned long flags; + + volatile unsigned long *vector + = ((volatile unsigned long *)(KERNELBASE+0x100)); + if (nr < 0 || nr > 3) + return; + if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346); + + local_irq_save(flags); + local_irq_disable(); + + /* Save reset vector */ + save_vector = *vector; + + /* Setup fake reset vector that does + * b __secondary_start_pmac_0 + nr*8 - KERNELBASE + */ + new_vector = (unsigned long) __secondary_start_pmac_0 + nr * 8; + *vector = 0x48000002 + new_vector - KERNELBASE; + + /* flush data cache and inval instruction cache */ + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + /* Put some life in our friend */ + pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0); + + /* FIXME: We wait a bit for the CPU to take the exception, I should + * instead wait for the entry code to set something for me. Well, + * ideally, all that crap will be done in prom.c and the CPU left + * in a RAM-based wait loop like CHRP. + */ + mdelay(1); + + /* Restore our exception vector */ + *vector = save_vector; + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + local_irq_restore(flags); + if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347); +} + +static void __devinit smp_core99_setup_cpu(int cpu_nr) +{ + /* Setup L2/L3 */ + if (cpu_nr != 0) + core99_init_caches(cpu_nr); + + /* Setup openpic */ + do_openpic_setup_cpu(); + + if (cpu_nr == 0) { +#ifdef CONFIG_POWER4 + extern void g5_phy_disable_cpu1(void); + + /* If we didn't start the second CPU, we must take + * it off the bus + */ + if (machine_is_compatible("MacRISC4") && + num_online_cpus() < 2) + g5_phy_disable_cpu1(); +#endif /* CONFIG_POWER4 */ + if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); + } +} + +/* not __init, called in sleep/wakeup code */ +void smp_core99_take_timebase(void) +{ + unsigned long flags; + + /* tell the primary we're here */ + sec_tb_reset = 1; + mb(); + + /* wait for the primary to set pri_tb_hi/lo */ + while (sec_tb_reset < 2) + mb(); + + /* set our stuff the same as the primary */ + local_irq_save(flags); + set_dec(1); + set_tb(pri_tb_hi, pri_tb_lo); + last_jiffy_stamp(smp_processor_id()) = pri_tb_stamp; + mb(); + + /* tell the primary we're done */ + sec_tb_reset = 0; + mb(); + local_irq_restore(flags); +} + +/* not __init, called in sleep/wakeup code */ +void smp_core99_give_timebase(void) +{ + unsigned long flags; + unsigned int t; + + /* wait for the secondary to be in take_timebase */ + for (t = 100000; t > 0 && !sec_tb_reset; --t) + udelay(10); + if (!sec_tb_reset) { + printk(KERN_WARNING "Timeout waiting sync on second CPU\n"); + return; + } + + /* freeze the timebase and read it */ + /* disable interrupts so the timebase is disabled for the + shortest possible time */ + local_irq_save(flags); + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4); + pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0); + mb(); + pri_tb_hi = get_tbu(); + pri_tb_lo = get_tbl(); + pri_tb_stamp = last_jiffy_stamp(smp_processor_id()); + mb(); + + /* tell the secondary we're ready */ + sec_tb_reset = 2; + mb(); + + /* wait for the secondary to have taken it */ + for (t = 100000; t > 0 && sec_tb_reset; --t) + udelay(10); + if (sec_tb_reset) + printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n"); + else + smp_tb_synchronized = 1; + + /* Now, restart the timebase by leaving the GPIO to an open collector */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0); + pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0); + local_irq_restore(flags); +} + + +/* PowerSurge-style Macs */ +struct smp_ops_t psurge_smp_ops = { + .message_pass = smp_psurge_message_pass, + .probe = smp_psurge_probe, + .kick_cpu = smp_psurge_kick_cpu, + .setup_cpu = smp_psurge_setup_cpu, + .give_timebase = smp_psurge_give_timebase, + .take_timebase = smp_psurge_take_timebase, +}; + +/* Core99 Macs (dual G4s) */ +struct smp_ops_t core99_smp_ops = { + .message_pass = smp_openpic_message_pass, + .probe = smp_core99_probe, + .kick_cpu = smp_core99_kick_cpu, + .setup_cpu = smp_core99_setup_cpu, + .give_timebase = smp_core99_give_timebase, + .take_timebase = smp_core99_take_timebase, +}; + +#ifdef CONFIG_HOTPLUG_CPU + +int __cpu_disable(void) +{ + cpu_clear(smp_processor_id(), cpu_online_map); + + /* XXX reset cpu affinity here */ + openpic_set_priority(0xf); + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + mb(); + udelay(20); + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + return 0; +} + +extern void low_cpu_die(void) __attribute__((noreturn)); /* in pmac_sleep.S */ +static int cpu_dead[NR_CPUS]; + +void cpu_die(void) +{ + local_irq_disable(); + cpu_dead[smp_processor_id()] = 1; + mb(); + low_cpu_die(); +} + +void __cpu_die(unsigned int cpu) +{ + int timeout; + + timeout = 1000; + while (!cpu_dead[cpu]) { + if (--timeout == 0) { + printk("CPU %u refused to die!\n", cpu); + break; + } + msleep(1); + } + cpu_callin_map[cpu] = 0; + cpu_dead[cpu] = 0; +} + +#endif diff --git a/trunk/arch/ppc/platforms/pmac_time.c b/trunk/arch/ppc/platforms/pmac_time.c new file mode 100644 index 000000000000..edb9fcc64790 --- /dev/null +++ b/trunk/arch/ppc/platforms/pmac_time.c @@ -0,0 +1,291 @@ +/* + * Support for periodic interrupts (100 per second) and for getting + * the current time from the RTC on Power Macintoshes. + * + * We use the decrementer register for our periodic interrupts. + * + * Paul Mackerras August 1996. + * Copyright (C) 1996 Paul Mackerras. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Apparently the RTC stores seconds since 1 Jan 1904 */ +#define RTC_OFFSET 2082844800 + +/* + * Calibrate the decrementer frequency with the VIA timer 1. + */ +#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */ + +/* VIA registers */ +#define RS 0x200 /* skip between registers */ +#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ +#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ +#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ +#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ +#define ACR (11*RS) /* Auxiliary control register */ +#define IFR (13*RS) /* Interrupt flag register */ + +/* Bits in ACR */ +#define T1MODE 0xc0 /* Timer 1 mode */ +#define T1MODE_CONT 0x40 /* continuous interrupts */ + +/* Bits in IFR and IER */ +#define T1_INT 0x40 /* Timer 1 interrupt */ + +extern struct timezone sys_tz; + +long __init +pmac_time_init(void) +{ +#ifdef CONFIG_NVRAM + s32 delta = 0; + int dst; + + delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16; + delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8; + delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb); + if (delta & 0x00800000UL) + delta |= 0xFF000000UL; + dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0); + printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60, + dst ? "on" : "off"); + return delta; +#else + return 0; +#endif +} + +unsigned long +pmac_get_rtc_time(void) +{ +#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) + struct adb_request req; + unsigned long now; +#endif + + /* Get the time from the RTC */ + switch (sys_ctrler) { +#ifdef CONFIG_ADB_CUDA + case SYS_CTRLER_CUDA: + if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) + return 0; + while (!req.complete) + cuda_poll(); + if (req.reply_len != 7) + printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", + req.reply_len); + now = (req.reply[3] << 24) + (req.reply[4] << 16) + + (req.reply[5] << 8) + req.reply[6]; + return now - RTC_OFFSET; +#endif /* CONFIG_ADB_CUDA */ +#ifdef CONFIG_ADB_PMU + case SYS_CTRLER_PMU: + if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) + return 0; + while (!req.complete) + pmu_poll(); + if (req.reply_len != 4) + printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", + req.reply_len); + now = (req.reply[0] << 24) + (req.reply[1] << 16) + + (req.reply[2] << 8) + req.reply[3]; + return now - RTC_OFFSET; +#endif /* CONFIG_ADB_PMU */ + default: ; + } + return 0; +} + +int +pmac_set_rtc_time(unsigned long nowtime) +{ +#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) + struct adb_request req; +#endif + + nowtime += RTC_OFFSET; + + switch (sys_ctrler) { +#ifdef CONFIG_ADB_CUDA + case SYS_CTRLER_CUDA: + if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, + nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) + return 0; + while (!req.complete) + cuda_poll(); + if ((req.reply_len != 3) && (req.reply_len != 7)) + printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", + req.reply_len); + return 1; +#endif /* CONFIG_ADB_CUDA */ +#ifdef CONFIG_ADB_PMU + case SYS_CTRLER_PMU: + if (pmu_request(&req, NULL, 5, PMU_SET_RTC, + nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) + return 0; + while (!req.complete) + pmu_poll(); + if (req.reply_len != 0) + printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", + req.reply_len); + return 1; +#endif /* CONFIG_ADB_PMU */ + default: + return 0; + } +} + +/* + * Calibrate the decrementer register using VIA timer 1. + * This is used both on powermacs and CHRP machines. + */ +int __init +via_calibrate_decr(void) +{ + struct device_node *vias; + volatile unsigned char __iomem *via; + int count = VIA_TIMER_FREQ_6 / 100; + unsigned int dstart, dend; + + vias = find_devices("via-cuda"); + if (vias == 0) + vias = find_devices("via-pmu"); + if (vias == 0) + vias = find_devices("via"); + if (vias == 0 || vias->n_addrs == 0) + return 0; + via = ioremap(vias->addrs[0].address, vias->addrs[0].size); + + /* set timer 1 for continuous interrupts */ + out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT); + /* set the counter to a small value */ + out_8(&via[T1CH], 2); + /* set the latch to `count' */ + out_8(&via[T1LL], count); + out_8(&via[T1LH], count >> 8); + /* wait until it hits 0 */ + while ((in_8(&via[IFR]) & T1_INT) == 0) + ; + dstart = get_dec(); + /* clear the interrupt & wait until it hits 0 again */ + in_8(&via[T1CL]); + while ((in_8(&via[IFR]) & T1_INT) == 0) + ; + dend = get_dec(); + + tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100); + tb_to_us = mulhwu_scale_factor(dstart - dend, 60000); + + printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n", + tb_ticks_per_jiffy, dstart - dend); + + iounmap(via); + + return 1; +} + +#ifdef CONFIG_PM +/* + * Reset the time after a sleep. + */ +static int +time_sleep_notify(struct pmu_sleep_notifier *self, int when) +{ + static unsigned long time_diff; + unsigned long flags; + unsigned long seq; + + switch (when) { + case PBOOK_SLEEP_NOW: + do { + seq = read_seqbegin_irqsave(&xtime_lock, flags); + time_diff = xtime.tv_sec - pmac_get_rtc_time(); + } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); + break; + case PBOOK_WAKE: + write_seqlock_irqsave(&xtime_lock, flags); + xtime.tv_sec = pmac_get_rtc_time() + time_diff; + xtime.tv_nsec = 0; + last_rtc_update = xtime.tv_sec; + write_sequnlock_irqrestore(&xtime_lock, flags); + break; + } + return PBOOK_SLEEP_OK; +} + +static struct pmu_sleep_notifier time_sleep_notifier = { + time_sleep_notify, SLEEP_LEVEL_MISC, +}; +#endif /* CONFIG_PM */ + +/* + * Query the OF and get the decr frequency. + * This was taken from the pmac time_init() when merging the prep/pmac + * time functions. + */ +void __init +pmac_calibrate_decr(void) +{ + struct device_node *cpu; + unsigned int freq, *fp; + +#ifdef CONFIG_PM + pmu_register_sleep_notifier(&time_sleep_notifier); +#endif /* CONFIG_PM */ + + /* We assume MacRISC2 machines have correct device-tree + * calibration. That's better since the VIA itself seems + * to be slightly off. --BenH + */ + if (!machine_is_compatible("MacRISC2") && + !machine_is_compatible("MacRISC3") && + !machine_is_compatible("MacRISC4")) + if (via_calibrate_decr()) + return; + + /* Special case: QuickSilver G4s seem to have a badly calibrated + * timebase-frequency in OF, VIA is much better on these. We should + * probably implement calibration based on the KL timer on these + * machines anyway... -BenH + */ + if (machine_is_compatible("PowerMac3,5")) + if (via_calibrate_decr()) + return; + /* + * The cpu node should have a timebase-frequency property + * to tell us the rate at which the decrementer counts. + */ + cpu = find_type_devices("cpu"); + if (cpu == 0) + panic("can't find cpu node in time_init"); + fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL); + if (fp == 0) + panic("can't get cpu timebase frequency"); + freq = *fp; + printk("time_init: decrementer frequency = %u.%.6u MHz\n", + freq/1000000, freq%1000000); + tb_ticks_per_jiffy = freq / HZ; + tb_to_us = mulhwu_scale_factor(freq, 1000000); +} diff --git a/trunk/arch/ppc/syslib/Makefile b/trunk/arch/ppc/syslib/Makefile index 159dcd92a6d1..84ef03018d0e 100644 --- a/trunk/arch/ppc/syslib/Makefile +++ b/trunk/arch/ppc/syslib/Makefile @@ -39,6 +39,8 @@ obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \ ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o obj-$(CONFIG_PCI_QSPAN) += qspan_pci.o obj-$(CONFIG_PPC_OF) += prom_init.o prom.o +obj-$(CONFIG_PPC_PMAC) += open_pic.o +obj-$(CONFIG_POWER4) += open_pic2.o obj-$(CONFIG_PPC_CHRP) += open_pic.o obj-$(CONFIG_PPC_PREP) += open_pic.o todc_time.o obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o diff --git a/trunk/arch/ppc/syslib/prom.c b/trunk/arch/ppc/syslib/prom.c index 482f837fd373..af4deace49e0 100644 --- a/trunk/arch/ppc/syslib/prom.c +++ b/trunk/arch/ppc/syslib/prom.c @@ -70,6 +70,8 @@ int use_of_interrupt_tree; struct device_node *dflt_interrupt_controller; int num_interrupt_controllers; +int pmac_newworld; + extern unsigned int rtas_entry; /* physical pointer */ extern struct device_node *allnodes; @@ -121,13 +123,22 @@ finish_device_tree(void) unsigned long mem = (unsigned long) klimit; struct device_node *np; - /* All CHRPs now use the interrupt tree */ + /* All newworld pmac machines and CHRPs now use the interrupt tree */ for (np = allnodes; np != NULL; np = np->allnext) { if (get_property(np, "interrupt-parent", NULL)) { use_of_interrupt_tree = 1; break; } } + if (_machine == _MACH_Pmac && use_of_interrupt_tree) + pmac_newworld = 1; + +#ifdef CONFIG_BOOTX_TEXT + if (boot_infos && pmac_newworld) { + prom_print("WARNING ! BootX/miBoot booting is not supported on this machine\n"); + prom_print(" You should use an Open Firmware bootloader\n"); + } +#endif /* CONFIG_BOOTX_TEXT */ if (use_of_interrupt_tree) { /* @@ -423,10 +434,16 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start) * those machines, we want to offset interrupts from the * second openpic by 128 -- BenH */ - if (num_interrupt_controllers > 1 + if (_machine != _MACH_Pmac && num_interrupt_controllers > 1 && ic != NULL && get_property(ic, "interrupt-parent", NULL) == NULL) offset = 16; + else if (_machine == _MACH_Pmac && num_interrupt_controllers > 1 + && ic != NULL && ic->parent != NULL) { + char *name = get_property(ic->parent, "name", NULL); + if (name && !strcmp(name, "u3")) + offset = 128; + } np->intrs[i].line = irq[0] + offset; if (n > 1) diff --git a/trunk/arch/ppc/xmon/start.c b/trunk/arch/ppc/xmon/start.c index 4344cbe9b5c5..c80177f8ec04 100644 --- a/trunk/arch/ppc/xmon/start.c +++ b/trunk/arch/ppc/xmon/start.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -26,9 +27,11 @@ static volatile unsigned char *sccc, *sccd; unsigned int TXRDY, RXRDY, DLAB; static int xmon_expect(const char *str, unsigned int timeout); +static int use_serial; static int use_screen; static int via_modem; static int xmon_use_sccb; +static struct device_node *channel_node; #define TB_SPEED 25000000 @@ -109,21 +112,96 @@ xmon_map_scc(void) #ifdef CONFIG_PPC_MULTIPLATFORM volatile unsigned char *base; + if (_machine == _MACH_Pmac) { + struct device_node *np; + unsigned long addr; +#ifdef CONFIG_BOOTX_TEXT + if (!use_screen && !use_serial + && !machine_is_compatible("iMac")) { + /* see if there is a keyboard in the device tree + with a parent of type "adb" */ + for (np = find_devices("keyboard"); np; np = np->next) + if (np->parent && np->parent->type + && strcmp(np->parent->type, "adb") == 0) + break; + + /* needs to be hacked if xmon_printk is to be used + from within find_via_pmu() */ +#ifdef CONFIG_ADB_PMU + if (np != NULL && boot_text_mapped && find_via_pmu()) + use_screen = 1; +#endif +#ifdef CONFIG_ADB_CUDA + if (np != NULL && boot_text_mapped && find_via_cuda()) + use_screen = 1; +#endif + } + if (!use_screen && (np = find_devices("escc")) != NULL) { + /* + * look for the device node for the serial port + * we're using and see if it says it has a modem + */ + char *name = xmon_use_sccb? "ch-b": "ch-a"; + char *slots; + int l; + + np = np->child; + while (np != NULL && strcmp(np->name, name) != 0) + np = np->sibling; + if (np != NULL) { + /* XXX should parse this properly */ + channel_node = np; + slots = get_property(np, "slot-names", &l); + if (slots != NULL && l >= 10 + && strcmp(slots+4, "Modem") == 0) + via_modem = 1; + } + } + btext_drawstring("xmon uses "); + if (use_screen) + btext_drawstring("screen and keyboard\n"); + else { + if (via_modem) + btext_drawstring("modem on "); + btext_drawstring(xmon_use_sccb? "printer": "modem"); + btext_drawstring(" port\n"); + } + +#endif /* CONFIG_BOOTX_TEXT */ + +#ifdef CHRP_ESCC + addr = 0xc1013020; +#else + addr = 0xf3013020; +#endif + TXRDY = 4; + RXRDY = 1; + + np = find_devices("mac-io"); + if (np && np->n_addrs) + addr = np->addrs[0].address + 0x13020; + base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE); + sccc = base + (addr & ~PAGE_MASK); + sccd = sccc + 0x10; + + } #ifdef CONFIG_PPC_CHRP - base = (volatile unsigned char *) isa_io_base; - if (_machine == _MACH_chrp) - base = (volatile unsigned char *) - ioremap(chrp_find_phys_io_base(), 0x1000); - - sccc = base + 0x3fd; - sccd = base + 0x3f8; - if (xmon_use_sccb) { - sccc -= 0x100; - sccd -= 0x100; + else { + base = (volatile unsigned char *) isa_io_base; + if (_machine == _MACH_chrp) + base = (volatile unsigned char *) + ioremap(chrp_find_phys_io_base(), 0x1000); + + sccc = base + 0x3fd; + sccd = base + 0x3f8; + if (xmon_use_sccb) { + sccc -= 0x100; + sccd -= 0x100; + } + TXRDY = 0x20; + RXRDY = 1; + DLAB = 0x80; } - TXRDY = 0x20; - RXRDY = 1; - DLAB = 0x80; #endif /* CONFIG_PPC_CHRP */ #elif defined(CONFIG_GEMINI) /* should already be mapped by the kernel boot */ @@ -307,6 +385,16 @@ xmon_read_poll(void) return *sccd; } +static unsigned char scc_inittab[] = { + 13, 0, /* set baud rate divisor */ + 12, 1, + 14, 1, /* baud rate gen enable, src=rtxc */ + 11, 0x50, /* clocks = br gen */ + 5, 0xea, /* tx 8 bits, assert DTR & RTS */ + 4, 0x46, /* x16 clock, 1 stop */ + 3, 0xc1, /* rx enable, 8 bits */ +}; + void xmon_init_scc(void) { @@ -319,6 +407,43 @@ xmon_init_scc(void) sccd[3] = 3; eieio(); /* LCR = 8N1 */ sccd[1] = 0; eieio(); /* IER = 0 */ } + else if ( _machine == _MACH_Pmac ) + { + int i, x; + + if (channel_node != 0) + pmac_call_feature( + PMAC_FTR_SCC_ENABLE, + channel_node, + PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1); + printk(KERN_INFO "Serial port locked ON by debugger !\n"); + if (via_modem && channel_node != 0) { + unsigned int t0; + + pmac_call_feature( + PMAC_FTR_MODEM_ENABLE, + channel_node, 0, 1); + printk(KERN_INFO "Modem powered up by debugger !\n"); + t0 = readtb(); + while (readtb() - t0 < 3*TB_SPEED) + eieio(); + } + /* use the B channel if requested */ + if (xmon_use_sccb) { + sccc = (volatile unsigned char *) + ((unsigned long)sccc & ~0x20); + sccd = sccc + 0x10; + } + for (i = 20000; i != 0; --i) { + x = *sccc; eieio(); + } + *sccc = 9; eieio(); /* reset A or B side */ + *sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio(); + for (i = 0; i < sizeof(scc_inittab); ++i) { + *sccc = scc_inittab[i]; + eieio(); + } + } scc_initialized = 1; if (via_modem) { for (;;) { @@ -507,9 +632,19 @@ xmon_fgets(char *str, int nb, void *f) void xmon_enter(void) { +#ifdef CONFIG_ADB_PMU + if (_machine == _MACH_Pmac) { + pmu_suspend(); + } +#endif } void xmon_leave(void) { +#ifdef CONFIG_ADB_PMU + if (_machine == _MACH_Pmac) { + pmu_resume(); + } +#endif } diff --git a/trunk/arch/ppc/xmon/xmon.c b/trunk/arch/ppc/xmon/xmon.c index bdaf6597b4c2..9075a7538e26 100644 --- a/trunk/arch/ppc/xmon/xmon.c +++ b/trunk/arch/ppc/xmon/xmon.c @@ -16,6 +16,9 @@ #include #include #include +#ifdef CONFIG_PMAC_BACKLIGHT +#include +#endif #include "nonstdio.h" #include "privinst.h" @@ -257,6 +260,16 @@ int xmon(struct pt_regs *excp) */ #endif /* CONFIG_SMP */ remove_bpts(); +#ifdef CONFIG_PMAC_BACKLIGHT + if( setjmp(bus_error_jmp) == 0 ) { + debugger_fault_handler = handle_fault; + sync(); + set_backlight_enable(1); + set_backlight_level(BACKLIGHT_MAX); + sync(); + } + debugger_fault_handler = NULL; +#endif /* CONFIG_PMAC_BACKLIGHT */ cmd = cmds(excp); if (cmd == 's') { xmon_trace[smp_processor_id()] = SSTEP; diff --git a/trunk/arch/s390/crypto/aes_s390.c b/trunk/arch/s390/crypto/aes_s390.c index c5ca2dc5d428..7a1033d8e00f 100644 --- a/trunk/arch/s390/crypto/aes_s390.c +++ b/trunk/arch/s390/crypto/aes_s390.c @@ -114,108 +114,80 @@ static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out, const u8 *in, unsigned int nbytes) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(AES_BLOCK_SIZE - 1); switch (sctx->key_len) { case 16: - ret = crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); + crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes); break; case 24: - ret = crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); + crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes); break; case 32: - ret = crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); + crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes); break; } - return nbytes; + return nbytes & ~(AES_BLOCK_SIZE - 1); } static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out, const u8 *in, unsigned int nbytes) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(AES_BLOCK_SIZE - 1); switch (sctx->key_len) { case 16: - ret = crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); + crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes); break; case 24: - ret = crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); + crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes); break; case 32: - ret = crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); + crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes); break; } - return nbytes; + return nbytes & ~(AES_BLOCK_SIZE - 1); } static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out, const u8 *in, unsigned int nbytes) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(AES_BLOCK_SIZE - 1); memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE); switch (sctx->key_len) { case 16: - ret = crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); + crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes); break; case 24: - ret = crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); + crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes); break; case 32: - ret = crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); + crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes); break; } memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE); - return nbytes; + return nbytes & ~(AES_BLOCK_SIZE - 1); } static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, const u8 *in, unsigned int nbytes) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(AES_BLOCK_SIZE - 1); memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE); switch (sctx->key_len) { case 16: - ret = crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); + crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes); break; case 24: - ret = crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); + crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes); break; case 32: - ret = crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); + crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes); break; } - return nbytes; + return nbytes & ~(AES_BLOCK_SIZE - 1); } diff --git a/trunk/arch/s390/crypto/des_s390.c b/trunk/arch/s390/crypto/des_s390.c index e3c37aa0a199..a38bb2a3eef6 100644 --- a/trunk/arch/s390/crypto/des_s390.c +++ b/trunk/arch/s390/crypto/des_s390.c @@ -15,8 +15,10 @@ */ #include #include +#include +#include +#include #include - #include "crypt_s390.h" #include "crypto_des.h" @@ -44,92 +46,38 @@ struct crypt_s390_des3_192_ctx { u8 key[DES3_192_KEY_SIZE]; }; -static int des_setkey(void *ctx, const u8 *key, unsigned int keylen, - u32 *flags) +static int +des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) { - struct crypt_s390_des_ctx *dctx = ctx; + struct crypt_s390_des_ctx *dctx; int ret; - /* test if key is valid (not a weak key) */ + dctx = ctx; + //test if key is valid (not a weak key) ret = crypto_des_check_key(key, keylen, flags); - if (ret == 0) + if (ret == 0){ memcpy(dctx->key, key, keylen); + } return ret; } -static void des_encrypt(void *ctx, u8 *out, const u8 *in) -{ - struct crypt_s390_des_ctx *dctx = ctx; - - crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, out, in, DES_BLOCK_SIZE); -} - -static void des_decrypt(void *ctx, u8 *out, const u8 *in) -{ - struct crypt_s390_des_ctx *dctx = ctx; - - crypt_s390_km(KM_DEA_DECRYPT, dctx->key, out, in, DES_BLOCK_SIZE); -} - -static unsigned int des_encrypt_ecb(const struct cipher_desc *desc, u8 *out, - const u8 *in, unsigned int nbytes) -{ - struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(DES_BLOCK_SIZE - 1); - ret = crypt_s390_km(KM_DEA_ENCRYPT, sctx->key, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); - - return nbytes; -} -static unsigned int des_decrypt_ecb(const struct cipher_desc *desc, u8 *out, - const u8 *in, unsigned int nbytes) +static void +des_encrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(DES_BLOCK_SIZE - 1); - ret = crypt_s390_km(KM_DEA_DECRYPT, sctx->key, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); + struct crypt_s390_des_ctx *dctx; - return nbytes; + dctx = ctx; + crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); } -static unsigned int des_encrypt_cbc(const struct cipher_desc *desc, u8 *out, - const u8 *in, unsigned int nbytes) +static void +des_decrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; + struct crypt_s390_des_ctx *dctx; - /* only use complete blocks */ - nbytes &= ~(DES_BLOCK_SIZE - 1); - - memcpy(sctx->iv, desc->info, DES_BLOCK_SIZE); - ret = crypt_s390_kmc(KMC_DEA_ENCRYPT, &sctx->iv, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); - - memcpy(desc->info, sctx->iv, DES_BLOCK_SIZE); - return nbytes; -} - -static unsigned int des_decrypt_cbc(const struct cipher_desc *desc, u8 *out, - const u8 *in, unsigned int nbytes) -{ - struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(DES_BLOCK_SIZE - 1); - - memcpy(&sctx->iv, desc->info, DES_BLOCK_SIZE); - ret = crypt_s390_kmc(KMC_DEA_DECRYPT, &sctx->iv, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); - - return nbytes; + dctx = ctx; + crypt_s390_km(KM_DEA_DECRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); } static struct crypto_alg des_alg = { @@ -139,19 +87,12 @@ static struct crypto_alg des_alg = { .cra_ctxsize = sizeof(struct crypt_s390_des_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(des_alg.cra_list), - .cra_u = { - .cipher = { - .cia_min_keysize = DES_KEY_SIZE, - .cia_max_keysize = DES_KEY_SIZE, - .cia_setkey = des_setkey, - .cia_encrypt = des_encrypt, - .cia_decrypt = des_decrypt, - .cia_encrypt_ecb = des_encrypt_ecb, - .cia_decrypt_ecb = des_decrypt_ecb, - .cia_encrypt_cbc = des_encrypt_cbc, - .cia_decrypt_cbc = des_decrypt_cbc, - } - } + .cra_u = { .cipher = { + .cia_min_keysize = DES_KEY_SIZE, + .cia_max_keysize = DES_KEY_SIZE, + .cia_setkey = des_setkey, + .cia_encrypt = des_encrypt, + .cia_decrypt = des_decrypt } } }; /* @@ -166,18 +107,20 @@ static struct crypto_alg des_alg = { * Implementers MUST reject keys that exhibit this property. * */ -static int des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, - u32 *flags) +static int +des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) { int i, ret; - struct crypt_s390_des3_128_ctx *dctx = ctx; + struct crypt_s390_des3_128_ctx *dctx; const u8* temp_key = key; + dctx = ctx; if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; return -EINVAL; } - for (i = 0; i < 2; i++, temp_key += DES_KEY_SIZE) { + for (i = 0; i < 2; i++, temp_key += DES_KEY_SIZE) { ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); if (ret < 0) return ret; @@ -186,85 +129,24 @@ static int des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, return 0; } -static void des3_128_encrypt(void *ctx, u8 *dst, const u8 *src) +static void +des3_128_encrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des3_128_ctx *dctx = ctx; + struct crypt_s390_des3_128_ctx *dctx; + dctx = ctx; crypt_s390_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src, - DES3_128_BLOCK_SIZE); + DES3_128_BLOCK_SIZE); } -static void des3_128_decrypt(void *ctx, u8 *dst, const u8 *src) +static void +des3_128_decrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des3_128_ctx *dctx = ctx; + struct crypt_s390_des3_128_ctx *dctx; + dctx = ctx; crypt_s390_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src, - DES3_128_BLOCK_SIZE); -} - -static unsigned int des3_128_encrypt_ecb(const struct cipher_desc *desc, - u8 *out, const u8 *in, - unsigned int nbytes) -{ - struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(DES3_128_BLOCK_SIZE - 1); - ret = crypt_s390_km(KM_TDEA_128_ENCRYPT, sctx->key, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); - - return nbytes; -} - -static unsigned int des3_128_decrypt_ecb(const struct cipher_desc *desc, - u8 *out, const u8 *in, - unsigned int nbytes) -{ - struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(DES3_128_BLOCK_SIZE - 1); - ret = crypt_s390_km(KM_TDEA_128_DECRYPT, sctx->key, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); - - return nbytes; -} - -static unsigned int des3_128_encrypt_cbc(const struct cipher_desc *desc, - u8 *out, const u8 *in, - unsigned int nbytes) -{ - struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(DES3_128_BLOCK_SIZE - 1); - - memcpy(sctx->iv, desc->info, DES3_128_BLOCK_SIZE); - ret = crypt_s390_kmc(KMC_TDEA_128_ENCRYPT, &sctx->iv, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); - - memcpy(desc->info, sctx->iv, DES3_128_BLOCK_SIZE); - return nbytes; -} - -static unsigned int des3_128_decrypt_cbc(const struct cipher_desc *desc, - u8 *out, const u8 *in, - unsigned int nbytes) -{ - struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(DES3_128_BLOCK_SIZE - 1); - - memcpy(&sctx->iv, desc->info, DES3_128_BLOCK_SIZE); - ret = crypt_s390_kmc(KMC_TDEA_128_DECRYPT, &sctx->iv, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); - - return nbytes; + DES3_128_BLOCK_SIZE); } static struct crypto_alg des3_128_alg = { @@ -274,19 +156,12 @@ static struct crypto_alg des3_128_alg = { .cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list), - .cra_u = { - .cipher = { - .cia_min_keysize = DES3_128_KEY_SIZE, - .cia_max_keysize = DES3_128_KEY_SIZE, - .cia_setkey = des3_128_setkey, - .cia_encrypt = des3_128_encrypt, - .cia_decrypt = des3_128_decrypt, - .cia_encrypt_ecb = des3_128_encrypt_ecb, - .cia_decrypt_ecb = des3_128_decrypt_ecb, - .cia_encrypt_cbc = des3_128_encrypt_cbc, - .cia_decrypt_cbc = des3_128_decrypt_cbc, - } - } + .cra_u = { .cipher = { + .cia_min_keysize = DES3_128_KEY_SIZE, + .cia_max_keysize = DES3_128_KEY_SIZE, + .cia_setkey = des3_128_setkey, + .cia_encrypt = des3_128_encrypt, + .cia_decrypt = des3_128_decrypt } } }; /* @@ -302,108 +177,50 @@ static struct crypto_alg des3_128_alg = { * property. * */ -static int des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, - u32 *flags) +static int +des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) { int i, ret; - struct crypt_s390_des3_192_ctx *dctx = ctx; - const u8* temp_key = key; + struct crypt_s390_des3_192_ctx *dctx; + const u8* temp_key; + dctx = ctx; + temp_key = key; if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], - DES_KEY_SIZE))) { + DES_KEY_SIZE))) { *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; return -EINVAL; } for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) { ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); - if (ret < 0) + if (ret < 0){ return ret; + } } memcpy(dctx->key, key, keylen); return 0; } -static void des3_192_encrypt(void *ctx, u8 *dst, const u8 *src) +static void +des3_192_encrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des3_192_ctx *dctx = ctx; + struct crypt_s390_des3_192_ctx *dctx; + dctx = ctx; crypt_s390_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src, - DES3_192_BLOCK_SIZE); + DES3_192_BLOCK_SIZE); } -static void des3_192_decrypt(void *ctx, u8 *dst, const u8 *src) +static void +des3_192_decrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des3_192_ctx *dctx = ctx; + struct crypt_s390_des3_192_ctx *dctx; + dctx = ctx; crypt_s390_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src, - DES3_192_BLOCK_SIZE); -} - -static unsigned int des3_192_encrypt_ecb(const struct cipher_desc *desc, - u8 *out, const u8 *in, - unsigned int nbytes) -{ - struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(DES3_192_BLOCK_SIZE - 1); - ret = crypt_s390_km(KM_TDEA_192_ENCRYPT, sctx->key, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); - - return nbytes; -} - -static unsigned int des3_192_decrypt_ecb(const struct cipher_desc *desc, - u8 *out, const u8 *in, - unsigned int nbytes) -{ - struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(DES3_192_BLOCK_SIZE - 1); - ret = crypt_s390_km(KM_TDEA_192_DECRYPT, sctx->key, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); - - return nbytes; -} - -static unsigned int des3_192_encrypt_cbc(const struct cipher_desc *desc, - u8 *out, const u8 *in, - unsigned int nbytes) -{ - struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(DES3_192_BLOCK_SIZE - 1); - - memcpy(sctx->iv, desc->info, DES3_192_BLOCK_SIZE); - ret = crypt_s390_kmc(KMC_TDEA_192_ENCRYPT, &sctx->iv, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); - - memcpy(desc->info, sctx->iv, DES3_192_BLOCK_SIZE); - return nbytes; -} - -static unsigned int des3_192_decrypt_cbc(const struct cipher_desc *desc, - u8 *out, const u8 *in, - unsigned int nbytes) -{ - struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm); - int ret; - - /* only use complete blocks */ - nbytes &= ~(DES3_192_BLOCK_SIZE - 1); - - memcpy(&sctx->iv, desc->info, DES3_192_BLOCK_SIZE); - ret = crypt_s390_kmc(KMC_TDEA_192_DECRYPT, &sctx->iv, out, in, nbytes); - BUG_ON((ret < 0) || (ret != nbytes)); - - return nbytes; + DES3_192_BLOCK_SIZE); } static struct crypto_alg des3_192_alg = { @@ -413,43 +230,44 @@ static struct crypto_alg des3_192_alg = { .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list), - .cra_u = { - .cipher = { - .cia_min_keysize = DES3_192_KEY_SIZE, - .cia_max_keysize = DES3_192_KEY_SIZE, - .cia_setkey = des3_192_setkey, - .cia_encrypt = des3_192_encrypt, - .cia_decrypt = des3_192_decrypt, - .cia_encrypt_ecb = des3_192_encrypt_ecb, - .cia_decrypt_ecb = des3_192_decrypt_ecb, - .cia_encrypt_cbc = des3_192_encrypt_cbc, - .cia_decrypt_cbc = des3_192_decrypt_cbc, - } - } + .cra_u = { .cipher = { + .cia_min_keysize = DES3_192_KEY_SIZE, + .cia_max_keysize = DES3_192_KEY_SIZE, + .cia_setkey = des3_192_setkey, + .cia_encrypt = des3_192_encrypt, + .cia_decrypt = des3_192_decrypt } } }; -static int init(void) + + +static int +init(void) { - int ret = 0; + int ret; if (!crypt_s390_func_available(KM_DEA_ENCRYPT) || !crypt_s390_func_available(KM_TDEA_128_ENCRYPT) || - !crypt_s390_func_available(KM_TDEA_192_ENCRYPT)) + !crypt_s390_func_available(KM_TDEA_192_ENCRYPT)){ return -ENOSYS; + } - ret |= (crypto_register_alg(&des_alg) == 0) ? 0:1; - ret |= (crypto_register_alg(&des3_128_alg) == 0) ? 0:2; - ret |= (crypto_register_alg(&des3_192_alg) == 0) ? 0:4; - if (ret) { + ret = 0; + ret |= (crypto_register_alg(&des_alg) == 0)? 0:1; + ret |= (crypto_register_alg(&des3_128_alg) == 0)? 0:2; + ret |= (crypto_register_alg(&des3_192_alg) == 0)? 0:4; + if (ret){ crypto_unregister_alg(&des3_192_alg); crypto_unregister_alg(&des3_128_alg); crypto_unregister_alg(&des_alg); return -EEXIST; } + + printk(KERN_INFO "crypt_s390: des_s390 loaded.\n"); return 0; } -static void __exit fini(void) +static void __exit +fini(void) { crypto_unregister_alg(&des3_192_alg); crypto_unregister_alg(&des3_128_alg); diff --git a/trunk/arch/s390/crypto/sha256_s390.c b/trunk/arch/s390/crypto/sha256_s390.c index 1ec5e92b3454..b75bdbd476c7 100644 --- a/trunk/arch/s390/crypto/sha256_s390.c +++ b/trunk/arch/s390/crypto/sha256_s390.c @@ -51,7 +51,6 @@ static void sha256_update(void *ctx, const u8 *data, unsigned int len) { struct s390_sha256_ctx *sctx = ctx; unsigned int index; - int ret; /* how much is already in the buffer? */ index = sctx->count / 8 & 0x3f; @@ -59,29 +58,15 @@ static void sha256_update(void *ctx, const u8 *data, unsigned int len) /* update message bit length */ sctx->count += len * 8; - if ((index + len) < SHA256_BLOCK_SIZE) - goto store; - - /* process one stored block */ - if (index) { + /* process one block */ + if ((index + len) >= SHA256_BLOCK_SIZE) { memcpy(sctx->buf + index, data, SHA256_BLOCK_SIZE - index); - ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, - SHA256_BLOCK_SIZE); - BUG_ON(ret != SHA256_BLOCK_SIZE); + crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, + SHA256_BLOCK_SIZE); data += SHA256_BLOCK_SIZE - index; len -= SHA256_BLOCK_SIZE - index; } - /* process as many blocks as possible */ - if (len >= SHA256_BLOCK_SIZE) { - ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, data, - len & ~(SHA256_BLOCK_SIZE - 1)); - BUG_ON(ret != (len & ~(SHA256_BLOCK_SIZE - 1))); - data += ret; - len -= ret; - } - -store: /* anything left? */ if (len) memcpy(sctx->buf + index , data, len); @@ -134,9 +119,9 @@ static struct crypto_alg alg = { .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { .digest = { .dia_digestsize = SHA256_DIGEST_SIZE, - .dia_init = sha256_init, - .dia_update = sha256_update, - .dia_final = sha256_final } } + .dia_init = sha256_init, + .dia_update = sha256_update, + .dia_final = sha256_final } } }; static int init(void) diff --git a/trunk/arch/s390/kernel/process.c b/trunk/arch/s390/kernel/process.c index 008c74526fd3..2ff90a1a1056 100644 --- a/trunk/arch/s390/kernel/process.c +++ b/trunk/arch/s390/kernel/process.c @@ -58,18 +58,10 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); */ unsigned long thread_saved_pc(struct task_struct *tsk) { - struct stack_frame *sf, *low, *high; + struct stack_frame *sf; - if (!tsk || !task_stack_page(tsk)) - return 0; - low = task_stack_page(tsk); - high = (struct stack_frame *) task_pt_regs(tsk); - sf = (struct stack_frame *) (tsk->thread.ksp & PSW_ADDR_INSN); - if (sf <= low || sf > high) - return 0; - sf = (struct stack_frame *) (sf->back_chain & PSW_ADDR_INSN); - if (sf <= low || sf > high) - return 0; + sf = (struct stack_frame *) tsk->thread.ksp; + sf = (struct stack_frame *) sf->back_chain; return sf->gprs[8]; } diff --git a/trunk/arch/s390/kernel/setup.c b/trunk/arch/s390/kernel/setup.c index de8784267473..b03847d100d9 100644 --- a/trunk/arch/s390/kernel/setup.c +++ b/trunk/arch/s390/kernel/setup.c @@ -268,7 +268,7 @@ static void do_machine_restart_nonsmp(char * __unused) reipl_diag(); if (MACHINE_IS_VM) - cpcmd ("IPL", NULL, 0, NULL); + cpcmd ("IPL", NULL, 0); else reipl (0x10000 | S390_lowcore.ipl_device); } @@ -276,14 +276,14 @@ static void do_machine_restart_nonsmp(char * __unused) static void do_machine_halt_nonsmp(void) { if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) - cpcmd(vmhalt_cmd, NULL, 0, NULL); + cpcmd(vmhalt_cmd, NULL, 0); signal_processor(smp_processor_id(), sigp_stop_and_store_status); } static void do_machine_power_off_nonsmp(void) { if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) - cpcmd(vmpoff_cmd, NULL, 0, NULL); + cpcmd(vmpoff_cmd, NULL, 0); signal_processor(smp_processor_id(), sigp_stop_and_store_status); } @@ -315,11 +315,6 @@ void machine_power_off(void) _machine_power_off(); } -/* - * Dummy power off function. - */ -void (*pm_power_off)(void) = machine_power_off; - static void __init add_memory_hole(unsigned long start, unsigned long end) { diff --git a/trunk/arch/s390/kernel/time.c b/trunk/arch/s390/kernel/time.c index 7c0fe152a111..b0d8ca8e5eeb 100644 --- a/trunk/arch/s390/kernel/time.c +++ b/trunk/arch/s390/kernel/time.c @@ -214,7 +214,7 @@ void account_ticks(struct pt_regs *regs) #endif #ifdef CONFIG_VIRT_CPU_ACCOUNTING - account_tick_vtime(current); + account_user_vtime(current); #else while (ticks--) update_process_times(user_mode(regs)); diff --git a/trunk/arch/s390/kernel/vtime.c b/trunk/arch/s390/kernel/vtime.c index dfe6f0856617..22a895ecb7a4 100644 --- a/trunk/arch/s390/kernel/vtime.c +++ b/trunk/arch/s390/kernel/vtime.c @@ -32,7 +32,7 @@ DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); * Update process times based on virtual cpu times stored by entry.S * to the lowcore fields user_timer, system_timer & steal_clock. */ -void account_tick_vtime(struct task_struct *tsk) +void account_user_vtime(struct task_struct *tsk) { cputime_t cputime; __u64 timer, clock; @@ -72,31 +72,6 @@ void account_tick_vtime(struct task_struct *tsk) run_posix_cpu_timers(tsk); } -/* - * Update process times based on virtual cpu times stored by entry.S - * to the lowcore fields user_timer, system_timer & steal_clock. - */ -void account_vtime(struct task_struct *tsk) -{ - cputime_t cputime; - __u64 timer; - - timer = S390_lowcore.last_update_timer; - asm volatile (" STPT %0" /* Store current cpu timer value */ - : "=m" (S390_lowcore.last_update_timer) ); - S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; - - cputime = S390_lowcore.user_timer >> 12; - S390_lowcore.user_timer -= cputime << 12; - S390_lowcore.steal_clock -= cputime << 12; - account_user_time(tsk, cputime); - - cputime = S390_lowcore.system_timer >> 12; - S390_lowcore.system_timer -= cputime << 12; - S390_lowcore.steal_clock -= cputime << 12; - account_system_time(tsk, 0, cputime); -} - /* * Update process times based on virtual cpu times stored by entry.S * to the lowcore fields user_timer, system_timer & steal_clock. diff --git a/trunk/arch/s390/lib/Makefile b/trunk/arch/s390/lib/Makefile index f20b51ff1d86..d9b97b3c597f 100644 --- a/trunk/arch/s390/lib/Makefile +++ b/trunk/arch/s390/lib/Makefile @@ -4,6 +4,5 @@ EXTRA_AFLAGS := -traditional -lib-y += delay.o string.o +lib-y += delay.o string.o spinlock.o lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o) -lib-$(CONFIG_SMP) += spinlock.o \ No newline at end of file diff --git a/trunk/arch/s390/lib/spinlock.c b/trunk/arch/s390/lib/spinlock.c index 60f80a4eed4e..68d79c502081 100644 --- a/trunk/arch/s390/lib/spinlock.c +++ b/trunk/arch/s390/lib/spinlock.c @@ -13,6 +13,7 @@ #include #include +atomic_t spin_retry_counter; int spin_retry = 1000; /** @@ -44,6 +45,7 @@ _raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc) _diag44(); count = spin_retry; } + atomic_inc(&spin_retry_counter); if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0) return; } @@ -56,6 +58,7 @@ _raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc) int count = spin_retry; while (count-- > 0) { + atomic_inc(&spin_retry_counter); if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0) return 1; } @@ -74,6 +77,7 @@ _raw_read_lock_wait(raw_rwlock_t *rw) _diag44(); count = spin_retry; } + atomic_inc(&spin_retry_counter); old = rw->lock & 0x7fffffffU; if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old) return; @@ -88,6 +92,7 @@ _raw_read_trylock_retry(raw_rwlock_t *rw) int count = spin_retry; while (count-- > 0) { + atomic_inc(&spin_retry_counter); old = rw->lock & 0x7fffffffU; if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old) return 1; @@ -106,6 +111,7 @@ _raw_write_lock_wait(raw_rwlock_t *rw) _diag44(); count = spin_retry; } + atomic_inc(&spin_retry_counter); if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0) return; } @@ -118,6 +124,7 @@ _raw_write_trylock_retry(raw_rwlock_t *rw) int count = spin_retry; while (count-- > 0) { + atomic_inc(&spin_retry_counter); if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0) return 1; } diff --git a/trunk/arch/um/Makefile b/trunk/arch/um/Makefile index 45435ff589c1..322972fd064e 100644 --- a/trunk/arch/um/Makefile +++ b/trunk/arch/um/Makefile @@ -67,8 +67,7 @@ USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \ # in CFLAGS. Otherwise, it would cause ld to complain about the two different # errnos. -CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \ - -Dmktime=kernel_mktime +CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask CFLAGS += $(call cc-option,-fno-unit-at-a-time,) include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) diff --git a/trunk/block/genhd.c b/trunk/block/genhd.c index db57546a709d..f1ed83f3f083 100644 --- a/trunk/block/genhd.c +++ b/trunk/block/genhd.c @@ -38,100 +38,34 @@ static inline int major_to_index(int major) return major % MAX_PROBE_HASH; } -struct blkdev_info { - int index; - struct blk_major_name *bd; -}; - -/* - * iterate over a list of blkdev_info structures. allows - * the major_names array to be iterated over from outside this file - * must be called with the block_subsys_sem held - */ -void *get_next_blkdev(void *dev) -{ - struct blkdev_info *info; - - if (dev == NULL) { - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - goto out; - info->index=0; - info->bd = major_names[info->index]; - if (info->bd) - goto out; - } else { - info = dev; - } - - while (info->index < ARRAY_SIZE(major_names)) { - if (info->bd) - info->bd = info->bd->next; - if (info->bd) - goto out; - /* - * No devices on this chain, move to the next - */ - info->index++; - info->bd = (info->index < ARRAY_SIZE(major_names)) ? - major_names[info->index] : NULL; - if (info->bd) - goto out; - } - -out: - return info; -} - -void *acquire_blkdev_list(void) -{ - down(&block_subsys_sem); - return get_next_blkdev(NULL); -} - -void release_blkdev_list(void *dev) -{ - up(&block_subsys_sem); - kfree(dev); -} - - -/* - * Count the number of records in the blkdev_list. - * must be called with the block_subsys_sem held - */ -int count_blkdev_list(void) +#ifdef CONFIG_PROC_FS +/* get block device names in somewhat random order */ +int get_blkdev_list(char *p, int used) { struct blk_major_name *n; - int i, count; + int i, len; - count = 0; + len = snprintf(p, (PAGE_SIZE-used), "\nBlock devices:\n"); + down(&block_subsys_sem); for (i = 0; i < ARRAY_SIZE(major_names); i++) { - for (n = major_names[i]; n; n = n->next) - count++; + for (n = major_names[i]; n; n = n->next) { + /* + * If the curent string plus the 5 extra characters + * in the line would run us off the page, then we're done + */ + if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE) + goto page_full; + len += sprintf(p+len, "%3d %s\n", + n->major, n->name); + } } +page_full: + up(&block_subsys_sem); - return count; -} - -/* - * extract the major and name values from a blkdev_info struct - * passed in as a void to *dev. Must be called with - * block_subsys_sem held - */ -int get_blkdev_info(void *dev, int *major, char **name) -{ - struct blkdev_info *info = dev; - - if (info->bd == NULL) - return 1; - - *major = info->bd->major; - *name = info->bd->name; - return 0; + return len; } - +#endif int register_blkdev(unsigned int major, const char *name) { diff --git a/trunk/drivers/acpi/ec.c b/trunk/drivers/acpi/ec.c index 3758b558d2b5..7e1a445955bc 100644 --- a/trunk/drivers/acpi/ec.c +++ b/trunk/drivers/acpi/ec.c @@ -153,7 +153,7 @@ static int acpi_ec_polling_mode = EC_POLLING; Transaction Management -------------------------------------------------------------------------- */ -static u32 acpi_ec_read_status(union acpi_ec *ec) +static inline u32 acpi_ec_read_status(union acpi_ec *ec) { u32 status = 0; diff --git a/trunk/drivers/base/firmware_class.c b/trunk/drivers/base/firmware_class.c index e97e911ebf7a..3d384e3d34de 100644 --- a/trunk/drivers/base/firmware_class.c +++ b/trunk/drivers/base/firmware_class.c @@ -48,7 +48,7 @@ struct firmware_priv { struct timer_list timeout; }; -static void +static inline void fw_load_abort(struct firmware_priv *fw_priv) { set_bit(FW_STATUS_ABORT, &fw_priv->status); diff --git a/trunk/drivers/block/loop.c b/trunk/drivers/block/loop.c index 5f6d1a5cce11..864729046e22 100644 --- a/trunk/drivers/block/loop.c +++ b/trunk/drivers/block/loop.c @@ -294,7 +294,7 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec, * This helper just factors out common code between do_lo_send_direct_write() * and do_lo_send_write(). */ -static int __do_lo_send_write(struct file *file, +static inline int __do_lo_send_write(struct file *file, u8 __user *buf, const int len, loff_t pos) { ssize_t bw; diff --git a/trunk/drivers/block/pktcdvd.c b/trunk/drivers/block/pktcdvd.c index 93affeeef7bd..51b7a5c5b77a 100644 --- a/trunk/drivers/block/pktcdvd.c +++ b/trunk/drivers/block/pktcdvd.c @@ -247,7 +247,7 @@ static inline struct pkt_rb_node *pkt_rbtree_next(struct pkt_rb_node *node) return rb_entry(n, struct pkt_rb_node, rb_node); } -static void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node) +static inline void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node) { rb_erase(&node->rb_node, &pd->bio_queue); mempool_free(node, pd->rb_pool); @@ -315,7 +315,7 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod /* * Add a bio to a single linked list defined by its head and tail pointers. */ -static void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail) +static inline void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail) { bio->bi_next = NULL; if (*list_tail) { diff --git a/trunk/drivers/bluetooth/hci_bcsp.c b/trunk/drivers/bluetooth/hci_bcsp.c index 7bd4ef904115..8fddfdfd0fbd 100644 --- a/trunk/drivers/bluetooth/hci_bcsp.c +++ b/trunk/drivers/bluetooth/hci_bcsp.c @@ -494,7 +494,7 @@ static inline void bcsp_unslip_one_byte(struct bcsp_struct *bcsp, unsigned char } } -static void bcsp_complete_rx_pkt(struct hci_uart *hu) +static inline void bcsp_complete_rx_pkt(struct hci_uart *hu) { struct bcsp_struct *bcsp = hu->priv; int pass_up; diff --git a/trunk/drivers/char/drm/r128_state.c b/trunk/drivers/char/drm/r128_state.c index a080cdd6081e..caeecc2c36da 100644 --- a/trunk/drivers/char/drm/r128_state.c +++ b/trunk/drivers/char/drm/r128_state.c @@ -220,7 +220,7 @@ static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv) ADVANCE_RING(); } -static void r128_emit_state(drm_r128_private_t * dev_priv) +static __inline__ void r128_emit_state(drm_r128_private_t * dev_priv) { drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; diff --git a/trunk/drivers/char/watchdog/Kconfig b/trunk/drivers/char/watchdog/Kconfig index c0dfcf273f0a..a6544790af60 100644 --- a/trunk/drivers/char/watchdog/Kconfig +++ b/trunk/drivers/char/watchdog/Kconfig @@ -395,38 +395,12 @@ config MACHZ_WDT To compile this driver as a module, choose M here: the module will be called machzwd. -config SBC_EPX_C3_WATCHDOG - tristate "Winsystems SBC EPX-C3 watchdog" - depends on WATCHDOG && X86 - ---help--- - This is the driver for the built-in watchdog timer on the EPX-C3 - Single-board computer made by Winsystems, Inc. - - *Note*: This hardware watchdog is not probeable and thus there - is no way to know if writing to its IO address will corrupt - your system or have any real effect. The only way to be sure - that this driver does what you want is to make sure you - are runnning it on an EPX-C3 from Winsystems with the watchdog - timer at IO address 0x1ee and 0x1ef. It will write to both those - IO ports. Basically, the assumption is made that if you compile - this driver into your kernel and/or load it as a module, that you - know what you are doing and that you are in fact running on an - EPX-C3 board! - - To compile this driver as a module, choose M here: the - module will be called sbc_epx_c3. - - # PowerPC Architecture config 8xx_WDT tristate "MPC8xx Watchdog Timer" depends on WATCHDOG && 8xx -config 83xx_WDT - tristate "MPC83xx Watchdog Timer" - depends on WATCHDOG && PPC_83xx - config MV64X60_WDT tristate "MV64X60 (Marvell Discovery) Watchdog Timer" depends on WATCHDOG && MV64X60 diff --git a/trunk/drivers/char/watchdog/Makefile b/trunk/drivers/char/watchdog/Makefile index 36c0b282b8ba..cfd0a3987710 100644 --- a/trunk/drivers/char/watchdog/Makefile +++ b/trunk/drivers/char/watchdog/Makefile @@ -52,11 +52,9 @@ obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o -obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o # PowerPC Architecture obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o -obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o diff --git a/trunk/drivers/char/watchdog/mpc83xx_wdt.c b/trunk/drivers/char/watchdog/mpc83xx_wdt.c deleted file mode 100644 index 5d6f5061603a..000000000000 --- a/trunk/drivers/char/watchdog/mpc83xx_wdt.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * mpc83xx_wdt.c - MPC83xx watchdog userspace interface - * - * Authors: Dave Updegraff - * Kumar Gala - * Attribution: from 83xx_wst: Florian Schirmer - * ..and from sc520_wdt - * - * Note: it appears that you can only actually ENABLE or DISABLE the thing - * once after POR. Once enabled, you cannot disable, and vice versa. - * - * 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; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct mpc83xx_wdt { - __be32 res0; - __be32 swcrr; /* System watchdog control register */ -#define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */ -#define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */ -#define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/ -#define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */ - __be32 swcnr; /* System watchdog count register */ - u8 res1[2]; - __be16 swsrr; /* System watchdog service register */ - u8 res2[0xF0]; -}; - -static struct mpc83xx_wdt __iomem *wd_base; - -static u16 timeout = 0xffff; -module_param(timeout, ushort, 0); -MODULE_PARM_DESC(timeout, "Watchdog timeout in ticks. (0swsrr, 0x556c); - out_be16(&wd_base->swsrr, 0xaa39); - spin_unlock(&wdt_spinlock); -} - -static ssize_t mpc83xx_wdt_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - if (count) - mpc83xx_wdt_keepalive(); - return count; -} - -static int mpc83xx_wdt_open(struct inode *inode, struct file *file) -{ - u32 tmp = SWCRR_SWEN; - if (test_and_set_bit(0, &wdt_is_open)) - return -EBUSY; - - /* Once we start the watchdog we can't stop it */ - __module_get(THIS_MODULE); - - /* Good, fire up the show */ - if (prescale) - tmp |= SWCRR_SWPR; - if (reset) - tmp |= SWCRR_SWRI; - - tmp |= timeout << 16; - - out_be32(&wd_base->swcrr, tmp); - - return nonseekable_open(inode, file); -} - -static int mpc83xx_wdt_release(struct inode *inode, struct file *file) -{ - printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n"); - mpc83xx_wdt_keepalive(); - clear_bit(0, &wdt_is_open); - return 0; -} - -static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - void __user *argp = (void __user *)arg; - int __user *p = argp; - static struct watchdog_info ident = { - .options = WDIOF_KEEPALIVEPING, - .firmware_version = 1, - .identity = "MPC83xx", - }; - - switch (cmd) { - case WDIOC_GETSUPPORT: - return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; - case WDIOC_KEEPALIVE: - mpc83xx_wdt_keepalive(); - return 0; - case WDIOC_GETTIMEOUT: - return put_user(timeout_sec, p); - default: - return -ENOIOCTLCMD; - } -} - -static struct file_operations mpc83xx_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = mpc83xx_wdt_write, - .ioctl = mpc83xx_wdt_ioctl, - .open = mpc83xx_wdt_open, - .release = mpc83xx_wdt_release, -}; - -static struct miscdevice mpc83xx_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &mpc83xx_wdt_fops, -}; - -static int __devinit mpc83xx_wdt_probe(struct platform_device *dev) -{ - struct resource *r; - int ret; - unsigned int *freq = dev->dev.platform_data; - - /* get a pointer to the register memory */ - r = platform_get_resource(dev, IORESOURCE_MEM, 0); - - if (!r) { - ret = -ENODEV; - goto err_out; - } - - wd_base = ioremap(r->start, sizeof (struct mpc83xx_wdt)); - - if (wd_base == NULL) { - ret = -ENOMEM; - goto err_out; - } - - ret = misc_register(&mpc83xx_wdt_miscdev); - if (ret) { - printk(KERN_ERR "cannot register miscdev on minor=%d " - "(err=%d)\n", - WATCHDOG_MINOR, ret); - goto err_unmap; - } - - /* Calculate the timeout in seconds */ - if (prescale) - timeout_sec = (timeout * 0x10000) / (*freq); - else - timeout_sec = timeout / (*freq); - - printk(KERN_INFO "WDT driver for MPC83xx initialized. " - "mode:%s timeout=%d (%d seconds)\n", - reset ? "reset":"interrupt", timeout, timeout_sec); - - spin_lock_init(&wdt_spinlock); - - return 0; - -err_unmap: - iounmap(wd_base); -err_out: - return ret; -} - -static int __devexit mpc83xx_wdt_remove(struct platform_device *dev) -{ - misc_deregister(&mpc83xx_wdt_miscdev); - iounmap(wd_base); - - return 0; -} - -static struct platform_driver mpc83xx_wdt_driver = { - .probe = mpc83xx_wdt_probe, - .remove = __devexit_p(mpc83xx_wdt_remove), - .driver = { - .name = "mpc83xx_wdt", - }, -}; - -static int __init mpc83xx_wdt_init(void) -{ - return platform_driver_register(&mpc83xx_wdt_driver); -} - -static void __exit mpc83xx_wdt_exit(void) -{ - platform_driver_unregister(&mpc83xx_wdt_driver); -} - -module_init(mpc83xx_wdt_init); -module_exit(mpc83xx_wdt_exit); - -MODULE_AUTHOR("Dave Updegraff, Kumar Gala"); -MODULE_DESCRIPTION("Driver for watchdog timer in MPC83xx uProcessor"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/trunk/drivers/char/watchdog/sa1100_wdt.c b/trunk/drivers/char/watchdog/sa1100_wdt.c index b474ea52d6e8..fb88b4041dca 100644 --- a/trunk/drivers/char/watchdog/sa1100_wdt.c +++ b/trunk/drivers/char/watchdog/sa1100_wdt.c @@ -74,7 +74,7 @@ static int sa1100dog_release(struct inode *inode, struct file *file) return 0; } -static ssize_t sa1100dog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) +static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) { if (len) /* Refresh OSMR3 timer. */ @@ -96,20 +96,20 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, switch (cmd) { case WDIOC_GETSUPPORT: - ret = copy_to_user((struct watchdog_info __user *)arg, &ident, + ret = copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)) ? -EFAULT : 0; break; case WDIOC_GETSTATUS: - ret = put_user(0, (int __user *)arg); + ret = put_user(0, (int *)arg); break; case WDIOC_GETBOOTSTATUS: - ret = put_user(boot_status, (int __user *)arg); + ret = put_user(boot_status, (int *)arg); break; case WDIOC_SETTIMEOUT: - ret = get_user(time, (int __user *)arg); + ret = get_user(time, (int *)arg); if (ret) break; @@ -123,7 +123,7 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, /*fall through*/ case WDIOC_GETTIMEOUT: - ret = put_user(pre_margin / OSCR_FREQ, (int __user *)arg); + ret = put_user(pre_margin / OSCR_FREQ, (int *)arg); break; case WDIOC_KEEPALIVE: diff --git a/trunk/drivers/char/watchdog/sbc_epx_c3.c b/trunk/drivers/char/watchdog/sbc_epx_c3.c deleted file mode 100644 index 951764614ebf..000000000000 --- a/trunk/drivers/char/watchdog/sbc_epx_c3.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * SBC EPX C3 0.1 A Hardware Watchdog Device for the Winsystems EPX-C3 - * single board computer - * - * (c) Copyright 2006 Calin A. Culianu , 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; either version - * 2 of the License, or (at your option) any later version. - * - * based on softdog.c by Alan Cox - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PFX "epx_c3: " -static int epx_c3_alive; - -#define WATCHDOG_TIMEOUT 1 /* 1 sec default timeout */ - -static int nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - -#define EPXC3_WATCHDOG_CTL_REG 0x1ee /* write 1 to enable, 0 to disable */ -#define EPXC3_WATCHDOG_PET_REG 0x1ef /* write anything to pet once enabled */ - -static void epx_c3_start(void) -{ - outb(1, EPXC3_WATCHDOG_CTL_REG); -} - -static void epx_c3_stop(void) -{ - - outb(0, EPXC3_WATCHDOG_CTL_REG); - - printk(KERN_INFO PFX "Stopped watchdog timer.\n"); -} - -static void epx_c3_pet(void) -{ - outb(1, EPXC3_WATCHDOG_PET_REG); -} - -/* - * Allow only one person to hold it open - */ -static int epx_c3_open(struct inode *inode, struct file *file) -{ - if (epx_c3_alive) - return -EBUSY; - - if (nowayout) - __module_get(THIS_MODULE); - - /* Activate timer */ - epx_c3_start(); - epx_c3_pet(); - - epx_c3_alive = 1; - printk(KERN_INFO "Started watchdog timer.\n"); - - return nonseekable_open(inode, file); -} - -static int epx_c3_release(struct inode *inode, struct file *file) -{ - /* Shut off the timer. - * Lock it in if it's a module and we defined ...NOWAYOUT */ - if (!nowayout) - epx_c3_stop(); /* Turn the WDT off */ - - epx_c3_alive = 0; - - return 0; -} - -static ssize_t epx_c3_write(struct file *file, const char *data, - size_t len, loff_t *ppos) -{ - /* Refresh the timer. */ - if (len) - epx_c3_pet(); - return len; -} - -static int epx_c3_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int options, retval = -EINVAL; - static struct watchdog_info ident = { - .options = WDIOF_KEEPALIVEPING | - WDIOF_MAGICCLOSE, - .firmware_version = 0, - .identity = "Winsystems EPX-C3 H/W Watchdog", - }; - - switch (cmd) { - case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, - &ident, sizeof(ident))) - return -EFAULT; - return 0; - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(0,(int *)arg); - case WDIOC_KEEPALIVE: - epx_c3_pet(); - return 0; - case WDIOC_GETTIMEOUT: - return put_user(WATCHDOG_TIMEOUT,(int *)arg); - case WDIOC_SETOPTIONS: { - if (get_user(options, (int *)arg)) - return -EFAULT; - - if (options & WDIOS_DISABLECARD) { - epx_c3_stop(); - retval = 0; - } - - if (options & WDIOS_ENABLECARD) { - epx_c3_start(); - retval = 0; - } - - return retval; - } - default: - return -ENOIOCTLCMD; - } -} - -static int epx_c3_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if (code == SYS_DOWN || code == SYS_HALT) - epx_c3_stop(); /* Turn the WDT off */ - - return NOTIFY_DONE; -} - -static struct file_operations epx_c3_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = epx_c3_write, - .ioctl = epx_c3_ioctl, - .open = epx_c3_open, - .release = epx_c3_release, -}; - -static struct miscdevice epx_c3_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &epx_c3_fops, -}; - -static struct notifier_block epx_c3_notifier = { - .notifier_call = epx_c3_notify_sys, -}; - -static const char banner[] __initdata = - KERN_INFO PFX "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n"; - -static int __init watchdog_init(void) -{ - int ret; - - ret = register_reboot_notifier(&epx_c3_notifier); - if (ret) { - printk(KERN_ERR PFX "cannot register reboot notifier " - "(err=%d)\n", ret); - return ret; - } - - ret = misc_register(&epx_c3_miscdev); - if (ret) { - printk(KERN_ERR PFX "cannot register miscdev on minor=%d " - "(err=%d)\n", WATCHDOG_MINOR, ret); - unregister_reboot_notifier(&epx_c3_notifier); - return ret; - } - - printk(banner); - - return 0; -} - -static void __exit watchdog_exit(void) -{ - misc_deregister(&epx_c3_miscdev); - unregister_reboot_notifier(&epx_c3_notifier); -} - -module_init(watchdog_init); -module_exit(watchdog_exit); - -MODULE_AUTHOR("Calin A. Culianu "); -MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC. Note that there is no way to probe for this device -- so only use it if you are *sure* you are runnning on this specific SBC system from Winsystems! It writes to IO ports 0x1ee and 0x1ef!"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/trunk/drivers/cpufreq/cpufreq.c b/trunk/drivers/cpufreq/cpufreq.c index 277a843a87a6..a9163d02983a 100644 --- a/trunk/drivers/cpufreq/cpufreq.c +++ b/trunk/drivers/cpufreq/cpufreq.c @@ -41,6 +41,7 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock); /* internal prototypes */ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); static void handle_update(void *data); +static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci); /** * Two notifier lists: the "policy" list is involved in the @@ -126,7 +127,7 @@ static unsigned int debug_ratelimit = 1; static unsigned int disable_ratelimit = 1; static DEFINE_SPINLOCK(disable_ratelimit_lock); -static void cpufreq_debug_enable_ratelimit(void) +static inline void cpufreq_debug_enable_ratelimit(void) { unsigned long flags; @@ -136,7 +137,7 @@ static void cpufreq_debug_enable_ratelimit(void) spin_unlock_irqrestore(&disable_ratelimit_lock, flags); } -static void cpufreq_debug_disable_ratelimit(void) +static inline void cpufreq_debug_disable_ratelimit(void) { unsigned long flags; @@ -205,7 +206,7 @@ static inline void cpufreq_debug_disable_ratelimit(void) { return; } static unsigned long l_p_j_ref; static unsigned int l_p_j_ref_freq; -static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) +static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { if (ci->flags & CPUFREQ_CONST_LOOPS) return; diff --git a/trunk/drivers/firmware/dell_rbu.c b/trunk/drivers/firmware/dell_rbu.c index fdb8b042e64d..dfedb777d8c9 100644 --- a/trunk/drivers/firmware/dell_rbu.c +++ b/trunk/drivers/firmware/dell_rbu.c @@ -49,7 +49,7 @@ MODULE_AUTHOR("Abhay Salunke "); MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); MODULE_LICENSE("GPL"); -MODULE_VERSION("3.2"); +MODULE_VERSION("3.1"); #define BIOS_SCAN_LIMIT 0xffffffff #define MAX_IMAGE_LENGTH 16 @@ -564,10 +564,12 @@ static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, static void callbackfn_rbu(const struct firmware *fw, void *context) { - rbu_data.entry_created = 0; + int rc = 0; - if (!fw || !fw->size) + if (!fw || !fw->size) { + rbu_data.entry_created = 0; return; + } spin_lock(&rbu_data.lock); if (!strcmp(image_type, "mono")) { @@ -590,6 +592,15 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) } else pr_debug("invalid image type specified.\n"); spin_unlock(&rbu_data.lock); + + rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, + "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); + if (rc) + printk(KERN_ERR + "dell_rbu:%s request_firmware_nowait failed" + " %d\n", __FUNCTION__, rc); + else + rbu_data.entry_created = 1; } static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, @@ -724,7 +735,14 @@ static int __init dcdrbu_init(void) sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_packet_size_attr); - rbu_data.entry_created = 0; + rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, + "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); + if (rc) + printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" + " failed %d\n", __FUNCTION__, rc); + else + rbu_data.entry_created = 1; + return rc; } diff --git a/trunk/drivers/ide/ide-cd.c b/trunk/drivers/ide/ide-cd.c index 3325660f7248..ef09a7ef2396 100644 --- a/trunk/drivers/ide/ide-cd.c +++ b/trunk/drivers/ide/ide-cd.c @@ -980,7 +980,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, * and attempt to recover if there are problems. Returns 0 if everything's * ok; nonzero if the request has been terminated. */ -static +static inline int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) { if (ireason == 2) @@ -1539,7 +1539,7 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) /* * Write handling */ -static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) +static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) { /* Two notes about IDE interrupt reason here - 0 means that * the drive wants to receive data from us, 2 means that diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c index ca25f9e3d0f4..245b508208df 100644 --- a/trunk/drivers/ide/ide-disk.c +++ b/trunk/drivers/ide/ide-disk.c @@ -477,7 +477,7 @@ static inline int idedisk_supports_lba48(const struct hd_driveid *id) && id->lba_capacity_2; } -static void idedisk_check_hpa(ide_drive_t *drive) +static inline void idedisk_check_hpa(ide_drive_t *drive) { unsigned long long capacity, set_max; int lba48 = idedisk_supports_lba48(drive->id); diff --git a/trunk/drivers/ide/ide-taskfile.c b/trunk/drivers/ide/ide-taskfile.c index 9834dce4e20f..62ebefd6394a 100644 --- a/trunk/drivers/ide/ide-taskfile.c +++ b/trunk/drivers/ide/ide-taskfile.c @@ -308,7 +308,7 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write) ide_pio_sector(drive, write); } -static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, +static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq, unsigned int write) { if (rq->bio) /* fs request */ diff --git a/trunk/drivers/infiniband/core/cm.c b/trunk/drivers/infiniband/core/cm.c index 2514de3480d8..c06b18102b6a 100644 --- a/trunk/drivers/infiniband/core/cm.c +++ b/trunk/drivers/infiniband/core/cm.c @@ -856,7 +856,7 @@ static void cm_format_req(struct cm_req_msg *req_msg, param->private_data_len); } -static int cm_validate_req_param(struct ib_cm_req_param *param) +static inline int cm_validate_req_param(struct ib_cm_req_param *param) { /* peer-to-peer not supported */ if (param->peer_to_peer) @@ -1005,7 +1005,7 @@ static inline int cm_is_active_peer(__be64 local_ca_guid, __be64 remote_ca_guid, (be32_to_cpu(local_qpn) > be32_to_cpu(remote_qpn)))); } -static void cm_format_paths_from_req(struct cm_req_msg *req_msg, +static inline void cm_format_paths_from_req(struct cm_req_msg *req_msg, struct ib_sa_path_rec *primary_path, struct ib_sa_path_rec *alt_path) { diff --git a/trunk/drivers/isdn/hisax/avm_pci.c b/trunk/drivers/isdn/hisax/avm_pci.c index 4abe5ff10e72..5d8ee7368f7b 100644 --- a/trunk/drivers/isdn/hisax/avm_pci.c +++ b/trunk/drivers/isdn/hisax/avm_pci.c @@ -358,7 +358,7 @@ hdlc_fill_fifo(struct BCState *bcs) } } -static void +static inline void HDLC_irq(struct BCState *bcs, u_int stat) { int len; struct sk_buff *skb; diff --git a/trunk/drivers/isdn/hisax/diva.c b/trunk/drivers/isdn/hisax/diva.c index b0ff1cc97d7c..b62d6b30b72b 100644 --- a/trunk/drivers/isdn/hisax/diva.c +++ b/trunk/drivers/isdn/hisax/diva.c @@ -476,7 +476,7 @@ Memhscx_fill_fifo(struct BCState *bcs) } } -static void +static inline void Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) { u_char r; diff --git a/trunk/drivers/isdn/hisax/hscx_irq.c b/trunk/drivers/isdn/hisax/hscx_irq.c index 7b1ad5e4ecda..5fe9d42d03a3 100644 --- a/trunk/drivers/isdn/hisax/hscx_irq.c +++ b/trunk/drivers/isdn/hisax/hscx_irq.c @@ -119,7 +119,7 @@ hscx_fill_fifo(struct BCState *bcs) } } -static void +static inline void hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) { u_char r; @@ -221,7 +221,7 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) } } -static void +static inline void hscx_int_main(struct IsdnCardState *cs, u_char val) { diff --git a/trunk/drivers/isdn/hisax/jade_irq.c b/trunk/drivers/isdn/hisax/jade_irq.c index 1f201af15a0f..08563400e4fd 100644 --- a/trunk/drivers/isdn/hisax/jade_irq.c +++ b/trunk/drivers/isdn/hisax/jade_irq.c @@ -110,7 +110,7 @@ jade_fill_fifo(struct BCState *bcs) } -static void +static inline void jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) { u_char r; diff --git a/trunk/drivers/md/bitmap.c b/trunk/drivers/md/bitmap.c index eae4473eadde..76a189ceb529 100644 --- a/trunk/drivers/md/bitmap.c +++ b/trunk/drivers/md/bitmap.c @@ -200,7 +200,7 @@ static int bitmap_checkpage(struct bitmap *bitmap, unsigned long page, int creat /* if page is completely empty, put it back on the free list, or dealloc it */ /* if page was hijacked, unmark the flag so it might get alloced next time */ /* Note: lock should be held when calling this */ -static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) +static inline void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) { char *ptr; diff --git a/trunk/drivers/md/dm-crypt.c b/trunk/drivers/md/dm-crypt.c index e7a650f9ca07..a601a427885c 100644 --- a/trunk/drivers/md/dm-crypt.c +++ b/trunk/drivers/md/dm-crypt.c @@ -228,7 +228,7 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = { }; -static int +static inline int crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, struct scatterlist *in, unsigned int length, int write, sector_t sector) diff --git a/trunk/drivers/md/dm-ioctl.c b/trunk/drivers/md/dm-ioctl.c index 1235135b384b..561bda5011e0 100644 --- a/trunk/drivers/md/dm-ioctl.c +++ b/trunk/drivers/md/dm-ioctl.c @@ -598,7 +598,7 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) /* * Always use UUID for lookups if it's present, otherwise use name or dev. */ -static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) +static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) { if (*param->uuid) return __get_uuid_cell(param->uuid); @@ -608,7 +608,7 @@ static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) return dm_get_mdptr(huge_decode_dev(param->dev)); } -static struct mapped_device *find_device(struct dm_ioctl *param) +static inline struct mapped_device *find_device(struct dm_ioctl *param) { struct hash_cell *hc; struct mapped_device *md = NULL; diff --git a/trunk/drivers/md/dm-snap.c b/trunk/drivers/md/dm-snap.c index 87727d84dbba..4b9dd8fb1e5c 100644 --- a/trunk/drivers/md/dm-snap.c +++ b/trunk/drivers/md/dm-snap.c @@ -691,7 +691,7 @@ static void copy_callback(int read_err, unsigned int write_err, void *context) /* * Dispatches the copy operation to kcopyd. */ -static void start_copy(struct pending_exception *pe) +static inline void start_copy(struct pending_exception *pe) { struct dm_snapshot *s = pe->snap; struct io_region src, dest; diff --git a/trunk/drivers/md/dm.c b/trunk/drivers/md/dm.c index 8c16359f8b01..097d1e540090 100644 --- a/trunk/drivers/md/dm.c +++ b/trunk/drivers/md/dm.c @@ -293,7 +293,7 @@ struct dm_table *dm_get_table(struct mapped_device *md) * Decrements the number of outstanding ios that a bio has been * cloned into, completing the original io if necc. */ -static void dec_pending(struct dm_io *io, int error) +static inline void dec_pending(struct dm_io *io, int error) { if (error) io->error = error; diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index d39f584cd8b3..a06ff91f27e2 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio) } } -static void free_r1bio(r1bio_t *r1_bio) +static inline void free_r1bio(r1bio_t *r1_bio) { conf_t *conf = mddev_to_conf(r1_bio->mddev); @@ -190,7 +190,7 @@ static void free_r1bio(r1bio_t *r1_bio) mempool_free(r1_bio, conf->r1bio_pool); } -static void put_buf(r1bio_t *r1_bio) +static inline void put_buf(r1bio_t *r1_bio) { conf_t *conf = mddev_to_conf(r1_bio->mddev); int i; diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index 9130d051b474..9e658e519a27 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio) } } -static void free_r10bio(r10bio_t *r10_bio) +static inline void free_r10bio(r10bio_t *r10_bio) { conf_t *conf = mddev_to_conf(r10_bio->mddev); @@ -190,7 +190,7 @@ static void free_r10bio(r10bio_t *r10_bio) mempool_free(r10_bio, conf->r10bio_pool); } -static void put_buf(r10bio_t *r10_bio) +static inline void put_buf(r10bio_t *r10_bio) { conf_t *conf = mddev_to_conf(r10_bio->mddev); diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c index 25976bfb6f9c..54f4a9847e38 100644 --- a/trunk/drivers/md/raid5.c +++ b/trunk/drivers/md/raid5.c @@ -69,7 +69,7 @@ static void print_raid5_conf (raid5_conf_t *conf); -static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) +static inline void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) { if (atomic_dec_and_test(&sh->count)) { if (!list_empty(&sh->lru)) @@ -118,7 +118,7 @@ static inline void remove_hash(struct stripe_head *sh) hlist_del_init(&sh->hash); } -static void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) +static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) { struct hlist_head *hp = stripe_hash(conf, sh->sector); @@ -178,7 +178,7 @@ static int grow_buffers(struct stripe_head *sh, int num) static void raid5_build_block (struct stripe_head *sh, int i); -static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) +static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) { raid5_conf_t *conf = sh->raid_conf; int disks = conf->raid_disks, i; @@ -1415,7 +1415,7 @@ static void handle_stripe(struct stripe_head *sh) } } -static void raid5_activate_delayed(raid5_conf_t *conf) +static inline void raid5_activate_delayed(raid5_conf_t *conf) { if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { while (!list_empty(&conf->delayed_list)) { @@ -1431,7 +1431,7 @@ static void raid5_activate_delayed(raid5_conf_t *conf) } } -static void activate_bit_delay(raid5_conf_t *conf) +static inline void activate_bit_delay(raid5_conf_t *conf) { /* device_lock is held */ struct list_head head; diff --git a/trunk/drivers/md/raid6main.c b/trunk/drivers/md/raid6main.c index f618a53b98be..8c823d686a60 100644 --- a/trunk/drivers/md/raid6main.c +++ b/trunk/drivers/md/raid6main.c @@ -88,7 +88,7 @@ static inline int raid6_next_disk(int disk, int raid_disks) static void print_raid6_conf (raid6_conf_t *conf); -static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) +static inline void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) { if (atomic_dec_and_test(&sh->count)) { if (!list_empty(&sh->lru)) @@ -197,7 +197,7 @@ static int grow_buffers(struct stripe_head *sh, int num) static void raid6_build_block (struct stripe_head *sh, int i); -static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) +static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) { raid6_conf_t *conf = sh->raid_conf; int disks = conf->raid_disks, i; @@ -1577,7 +1577,7 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) } } -static void raid6_activate_delayed(raid6_conf_t *conf) +static inline void raid6_activate_delayed(raid6_conf_t *conf) { if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { while (!list_empty(&conf->delayed_list)) { @@ -1593,7 +1593,7 @@ static void raid6_activate_delayed(raid6_conf_t *conf) } } -static void activate_bit_delay(raid6_conf_t *conf) +static inline void activate_bit_delay(raid6_conf_t *conf) { /* device_lock is held */ struct list_head head; diff --git a/trunk/drivers/media/video/tvp5150.c b/trunk/drivers/media/video/tvp5150.c index 9094fa9f2ecb..e86b522938fd 100644 --- a/trunk/drivers/media/video/tvp5150.c +++ b/trunk/drivers/media/video/tvp5150.c @@ -93,7 +93,7 @@ struct tvp5150 { int sat; }; -static int tvp5150_read(struct i2c_client *c, unsigned char addr) +static inline int tvp5150_read(struct i2c_client *c, unsigned char addr) { unsigned char buffer[1]; int rc; diff --git a/trunk/drivers/media/video/zoran_card.c b/trunk/drivers/media/video/zoran_card.c index 246e67cd8b51..ea3288661a34 100644 --- a/trunk/drivers/media/video/zoran_card.c +++ b/trunk/drivers/media/video/zoran_card.c @@ -995,7 +995,7 @@ test_interrupts (struct zoran *zr) static int __devinit zr36057_init (struct zoran *zr) { - u32 *mem; + unsigned long mem; void *vdev; unsigned mem_needed; int j; @@ -1058,10 +1058,10 @@ zr36057_init (struct zoran *zr) "%s: zr36057_init() - kmalloc (STAT_COM) failed\n", ZR_DEVNAME(zr)); kfree(vdev); - kfree(mem); + kfree((void *)mem); return -ENOMEM; } - zr->stat_com = mem; + zr->stat_com = (u32 *) mem; for (j = 0; j < BUZ_NUM_STAT_COM; j++) { zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */ } diff --git a/trunk/drivers/message/fusion/mptlan.c b/trunk/drivers/message/fusion/mptlan.c index 73f59528212a..0b1b72825ae2 100644 --- a/trunk/drivers/message/fusion/mptlan.c +++ b/trunk/drivers/message/fusion/mptlan.c @@ -844,7 +844,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static void +static inline void mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) /* * @priority: 0 = put it on the timer queue, 1 = put it on the immediate queue @@ -866,7 +866,7 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int +static inline int mpt_lan_receive_skb(struct net_device *dev, struct sk_buff *skb) { struct mpt_lan_priv *priv = dev->priv; diff --git a/trunk/drivers/mmc/mmc_block.c b/trunk/drivers/mmc/mmc_block.c index 5b014c370e80..9b7c37e0e574 100644 --- a/trunk/drivers/mmc/mmc_block.c +++ b/trunk/drivers/mmc/mmc_block.c @@ -462,10 +462,9 @@ static int mmc_blk_probe(struct mmc_card *card) if (err) goto out; - printk(KERN_INFO "%s: %s %s %lluKiB %s\n", + printk(KERN_INFO "%s: %s %s %luKiB %s\n", md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), - (unsigned long long)(get_capacity(md->disk) >> 1), - md->read_only ? "(ro)" : ""); + get_capacity(md->disk) >> 1, md->read_only ? "(ro)" : ""); mmc_set_drvdata(card, md); add_disk(md->disk); diff --git a/trunk/drivers/mtd/devices/doc2000.c b/trunk/drivers/mtd/devices/doc2000.c index e4345cf744a2..be5e88b3888d 100644 --- a/trunk/drivers/mtd/devices/doc2000.c +++ b/trunk/drivers/mtd/devices/doc2000.c @@ -138,7 +138,7 @@ static inline int DoC_WaitReady(struct DiskOnChip *doc) bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ -static int DoC_Command(struct DiskOnChip *doc, unsigned char command, +static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command, unsigned char xtraflags) { void __iomem *docptr = doc->virtadr; diff --git a/trunk/drivers/mtd/devices/doc2001.c b/trunk/drivers/mtd/devices/doc2001.c index 681a9c73a2a3..fcb28a6fd89f 100644 --- a/trunk/drivers/mtd/devices/doc2001.c +++ b/trunk/drivers/mtd/devices/doc2001.c @@ -103,7 +103,7 @@ static inline int DoC_WaitReady(void __iomem * docptr) with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ -static void DoC_Command(void __iomem * docptr, unsigned char command, +static inline void DoC_Command(void __iomem * docptr, unsigned char command, unsigned char xtraflags) { /* Assert the CLE (Command Latch Enable) line to the flash chip */ diff --git a/trunk/drivers/mtd/devices/doc2001plus.c b/trunk/drivers/mtd/devices/doc2001plus.c index 5f57f29efee4..0595cc7324b2 100644 --- a/trunk/drivers/mtd/devices/doc2001plus.c +++ b/trunk/drivers/mtd/devices/doc2001plus.c @@ -118,7 +118,7 @@ static inline void DoC_CheckASIC(void __iomem * docptr) /* DoC_Command: Send a flash command to the flash chip through the Flash * command register. Need 2 Write Pipeline Terminates to complete send. */ -static void DoC_Command(void __iomem * docptr, unsigned char command, +static inline void DoC_Command(void __iomem * docptr, unsigned char command, unsigned char xtraflags) { WriteDOC(command, docptr, Mplus_FlashCmd); diff --git a/trunk/drivers/mtd/nand/diskonchip.c b/trunk/drivers/mtd/nand/diskonchip.c index ec5e45e4e4ef..21d4e8f4b7af 100644 --- a/trunk/drivers/mtd/nand/diskonchip.c +++ b/trunk/drivers/mtd/nand/diskonchip.c @@ -1506,7 +1506,7 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd) return 1; } -static int __init doc_probe(unsigned long physadr) +static inline int __init doc_probe(unsigned long physadr) { unsigned char ChipID; struct mtd_info *mtd; diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index 171999e67eec..5c15f3e9ea07 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -1387,7 +1387,7 @@ config FORCEDETH config CS89x0 tristate "CS89x0 support" - depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X) + depends on NET_PCI && (ISA || ARCH_IXDP2X01 || ARCH_PNX010X) ---help--- Support for CS89x0 chipset based Ethernet cards. If you have a network (Ethernet) card of this type, say Y and read the diff --git a/trunk/drivers/net/cs89x0.c b/trunk/drivers/net/cs89x0.c index fab6586d87e9..e2cfde7e31ec 100644 --- a/trunk/drivers/net/cs89x0.c +++ b/trunk/drivers/net/cs89x0.c @@ -87,12 +87,6 @@ Deepak Saxena : dsaxena@plexity.net : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support - Dmitry Pervushin : dpervushin@ru.mvista.com - : PNX010X platform support - - Deepak Saxena : dsaxena@plexity.net - : Intel IXDP2351 platform support - */ /* Always include 'config.h' first in case the user wants to turn on @@ -177,10 +171,6 @@ static unsigned int cs8900_irq_map[] = {12,0,0,0}; static unsigned int netcard_portlist[] __initdata = { 0x0300, 0}; static unsigned int cs8900_irq_map[] = {1,0,0,0}; -#elif defined(CONFIG_MACH_IXDP2351) -static unsigned int netcard_portlist[] __initdata = {IXDP2351_VIRT_CS8900_BASE, 0}; -static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0}; -#include #elif defined(CONFIG_ARCH_IXDP2X01) #include static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; @@ -348,55 +338,45 @@ struct net_device * __init cs89x0_probe(int unit) } #endif -#if defined(CONFIG_MACH_IXDP2351) -static u16 -readword(unsigned long base_addr, int portno) -{ - return __raw_readw(base_addr + (portno << 1)); -} - -static void -writeword(unsigned long base_addr, int portno, u16 value) -{ - __raw_writew(value, base_addr + (portno << 1)); -} -#elif defined(CONFIG_ARCH_IXDP2X01) -static u16 +#if defined(CONFIG_ARCH_IXDP2X01) +static int readword(unsigned long base_addr, int portno) { - return __raw_readl(base_addr + (portno << 1)); + return (u16)__raw_readl(base_addr + (portno << 1)); } static void -writeword(unsigned long base_addr, int portno, u16 value) +writeword(unsigned long base_addr, int portno, int value) { - __raw_writel(value, base_addr + (portno << 1)); + __raw_writel((u16)value, base_addr + (portno << 1)); } -#elif defined(CONFIG_ARCH_PNX010X) -static u16 +#else +#if defined(CONFIG_ARCH_PNX010X) +static int readword(unsigned long base_addr, int portno) { return inw(base_addr + (portno << 1)); } static void -writeword(unsigned long base_addr, int portno, u16 value) +writeword(unsigned long base_addr, int portno, int value) { outw(value, base_addr + (portno << 1)); } #else -static u16 +static int readword(unsigned long base_addr, int portno) { return inw(base_addr + portno); } static void -writeword(unsigned long base_addr, int portno, u16 value) +writeword(unsigned long base_addr, int portno, int value) { outw(value, base_addr + portno); } #endif +#endif static void readwords(unsigned long base_addr, int portno, void *buf, int length) @@ -404,11 +384,11 @@ readwords(unsigned long base_addr, int portno, void *buf, int length) u8 *buf8 = (u8 *)buf; do { - u16 tmp16; + u32 tmp32; - tmp16 = readword(base_addr, portno); - *buf8++ = (u8)tmp16; - *buf8++ = (u8)(tmp16 >> 8); + tmp32 = readword(base_addr, portno); + *buf8++ = (u8)tmp32; + *buf8++ = (u8)(tmp32 >> 8); } while (--length); } @@ -418,23 +398,23 @@ writewords(unsigned long base_addr, int portno, void *buf, int length) u8 *buf8 = (u8 *)buf; do { - u16 tmp16; + u32 tmp32; - tmp16 = *buf8++; - tmp16 |= (*buf8++) << 8; - writeword(base_addr, portno, tmp16); + tmp32 = *buf8++; + tmp32 |= (*buf8++) << 8; + writeword(base_addr, portno, tmp32); } while (--length); } -static u16 -readreg(struct net_device *dev, u16 regno) +static int +readreg(struct net_device *dev, int regno) { writeword(dev->base_addr, ADD_PORT, regno); return readword(dev->base_addr, DATA_PORT); } static void -writereg(struct net_device *dev, u16 regno, u16 value) +writereg(struct net_device *dev, int regno, int value) { writeword(dev->base_addr, ADD_PORT, regno); writeword(dev->base_addr, DATA_PORT, value); @@ -800,7 +780,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) } else { i = lp->isa_config & INT_NO_MASK; if (lp->chip_type == CS8900) { -#if defined(CONFIG_MACH_IXDP2351) || defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X) +#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X) i = cs8900_irq_map[0]; #else /* Translate the IRQ using the IRQ mapping table. */ @@ -1032,7 +1012,7 @@ dma_rx(struct net_device *dev) void __init reset_chip(struct net_device *dev) { -#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) +#ifndef CONFIG_ARCH_IXDP2X01 struct net_local *lp = netdev_priv(dev); int ioaddr = dev->base_addr; #endif @@ -1043,7 +1023,7 @@ void __init reset_chip(struct net_device *dev) /* wait 30 ms */ msleep(30); -#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) +#ifndef CONFIG_ARCH_IXDP2X01 if (lp->chip_type != CS8900) { /* Hardware problem requires PNP registers to be reconfigured after a reset */ writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT); @@ -1307,7 +1287,7 @@ net_open(struct net_device *dev) else #endif { -#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) +#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) if (((1 << dev->irq) & lp->irq_map) == 0) { printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", dev->name, dev->irq, lp->irq_map); diff --git a/trunk/drivers/net/e100.c b/trunk/drivers/net/e100.c index 4726722a0635..23de22631c64 100644 --- a/trunk/drivers/net/e100.c +++ b/trunk/drivers/net/e100.c @@ -592,7 +592,7 @@ static inline void e100_write_flush(struct nic *nic) (void)readb(&nic->csr->scb.status); } -static void e100_enable_irq(struct nic *nic) +static inline void e100_enable_irq(struct nic *nic) { unsigned long flags; @@ -602,7 +602,7 @@ static void e100_enable_irq(struct nic *nic) e100_write_flush(nic); } -static void e100_disable_irq(struct nic *nic) +static inline void e100_disable_irq(struct nic *nic) { unsigned long flags; @@ -791,7 +791,7 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) #define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ #define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) +static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) { unsigned long flags; unsigned int i; @@ -822,7 +822,7 @@ static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) return err; } -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, +static inline int e100_exec_cb(struct nic *nic, struct sk_buff *skb, void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) { struct cb *cb; @@ -1567,7 +1567,7 @@ static void e100_watchdog(unsigned long data) mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD); } -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, +static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb, struct sk_buff *skb) { cb->command = nic->tx_command; @@ -1617,7 +1617,7 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) return 0; } -static int e100_tx_clean(struct nic *nic) +static inline int e100_tx_clean(struct nic *nic) { struct cb *cb; int tx_cleaned = 0; @@ -1728,7 +1728,7 @@ static inline void e100_start_receiver(struct nic *nic, struct rx *rx) } #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) +static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) { if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + NET_IP_ALIGN))) return -ENOMEM; @@ -1762,7 +1762,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) return 0; } -static int e100_rx_indicate(struct nic *nic, struct rx *rx, +static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, unsigned int *work_done, unsigned int work_to_do) { struct sk_buff *skb = rx->skb; @@ -1822,7 +1822,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, return 0; } -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, +static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done, unsigned int work_to_do) { struct rx *rx; diff --git a/trunk/drivers/net/sb1000.c b/trunk/drivers/net/sb1000.c index 76139478c3df..d6388e1533f0 100644 --- a/trunk/drivers/net/sb1000.c +++ b/trunk/drivers/net/sb1000.c @@ -94,7 +94,7 @@ static inline int card_wait_for_busy_clear(const int ioaddr[], const char* name); static inline int card_wait_for_ready(const int ioaddr[], const char* name, unsigned char in[]); -static int card_send_command(const int ioaddr[], const char* name, +static inline int card_send_command(const int ioaddr[], const char* name, const unsigned char out[], unsigned char in[]); /* SB1000 hardware routines to be used during frame rx interrupt */ @@ -309,7 +309,7 @@ card_wait_for_ready(const int ioaddr[], const char* name, unsigned char in[]) } /* Card Send Command (cannot be used during an interrupt) */ -static int +static inline int card_send_command(const int ioaddr[], const char* name, const unsigned char out[], unsigned char in[]) { diff --git a/trunk/drivers/net/wireless/Kconfig b/trunk/drivers/net/wireless/Kconfig index c1a6e69f7905..e90687495ccc 100644 --- a/trunk/drivers/net/wireless/Kconfig +++ b/trunk/drivers/net/wireless/Kconfig @@ -160,7 +160,7 @@ config IPW2100 . If you want to compile the driver as a module ( = code which can be - inserted in and remvoed from the running kernel whenever you want), + inserted in and removed from the running kernel whenever you want), say M here and read . The module will be called ipw2100.ko. @@ -213,7 +213,7 @@ config IPW2200 . If you want to compile the driver as a module ( = code which can be - inserted in and remvoed from the running kernel whenever you want), + inserted in and removed from the running kernel whenever you want), say M here and read . The module will be called ipw2200.ko. diff --git a/trunk/drivers/net/wireless/hostap/hostap_80211_rx.c b/trunk/drivers/net/wireless/hostap/hostap_80211_rx.c index 4b13b76425c1..ffac50899454 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_80211_rx.c +++ b/trunk/drivers/net/wireless/hostap/hostap_80211_rx.c @@ -435,7 +435,7 @@ static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb, } -static int +static inline int hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb, struct hostap_80211_rx_status *rx_stats, u16 type, u16 stype) @@ -499,7 +499,7 @@ hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb, /* Called only as a tasklet (software IRQ) */ -static struct net_device *prism2_rx_get_wds(local_info_t *local, +static inline struct net_device *prism2_rx_get_wds(local_info_t *local, u8 *addr) { struct hostap_interface *iface = NULL; @@ -519,7 +519,7 @@ static struct net_device *prism2_rx_get_wds(local_info_t *local, } -static int +static inline int hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr, u16 fc, struct net_device **wds) { @@ -615,7 +615,7 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb) /* Called only as a tasklet (software IRQ) */ -static int +static inline int hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, struct ieee80211_crypt_data *crypt) { @@ -654,7 +654,7 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, /* Called only as a tasklet (software IRQ) */ -static int +static inline int hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb, int keyidx, struct ieee80211_crypt_data *crypt) { diff --git a/trunk/drivers/net/wireless/hostap/hostap_hw.c b/trunk/drivers/net/wireless/hostap/hostap_hw.c index b1f142d9e232..abfae7fedebc 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_hw.c +++ b/trunk/drivers/net/wireless/hostap/hostap_hw.c @@ -253,7 +253,7 @@ static void prism2_clear_cmd_queue(local_info_t *local) * @dev: pointer to net_device * @entry: Prism2 command queue entry to be issued */ -static int hfa384x_cmd_issue(struct net_device *dev, +static inline int hfa384x_cmd_issue(struct net_device *dev, struct hostap_cmd_queue *entry) { struct hostap_interface *iface; @@ -743,7 +743,7 @@ static void prism2_cmd_ev(struct net_device *dev) } -static int hfa384x_wait_offset(struct net_device *dev, u16 o_off) +static inline int hfa384x_wait_offset(struct net_device *dev, u16 o_off) { int tries = HFA384X_BAP_BUSY_TIMEOUT; int res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY; @@ -1904,7 +1904,7 @@ static int prism2_tx_80211(struct sk_buff *skb, struct net_device *dev) * and will try to get the correct fid eventually. */ #define EXTRA_FID_READ_TESTS -static u16 prism2_read_fid_reg(struct net_device *dev, u16 reg) +static inline u16 prism2_read_fid_reg(struct net_device *dev, u16 reg) { #ifdef EXTRA_FID_READ_TESTS u16 val, val2, val3; @@ -2581,7 +2581,7 @@ static void prism2_ev_tick(struct net_device *dev) /* Called only from hardware IRQ */ -static void prism2_check_magic(local_info_t *local) +static inline void prism2_check_magic(local_info_t *local) { /* at least PCI Prism2.5 with bus mastering seems to sometimes * return 0x0000 in SWSUPPORT0 for unknown reason, but re-reading the diff --git a/trunk/drivers/net/wireless/ipw2100.c b/trunk/drivers/net/wireless/ipw2100.c index 7518384f34d9..cf05661fb1bd 100644 --- a/trunk/drivers/net/wireless/ipw2100.c +++ b/trunk/drivers/net/wireless/ipw2100.c @@ -411,7 +411,7 @@ static inline void write_nic_dword_auto_inc(struct net_device *dev, u32 val) write_register(dev, IPW_REG_AUTOINCREMENT_DATA, val); } -static void write_nic_memory(struct net_device *dev, u32 addr, u32 len, +static inline void write_nic_memory(struct net_device *dev, u32 addr, u32 len, const u8 * buf) { u32 aligned_addr; @@ -449,7 +449,7 @@ static void write_nic_memory(struct net_device *dev, u32 addr, u32 len, *buf); } -static void read_nic_memory(struct net_device *dev, u32 addr, u32 len, +static inline void read_nic_memory(struct net_device *dev, u32 addr, u32 len, u8 * buf) { u32 aligned_addr; @@ -657,7 +657,7 @@ static void printk_buf(int level, const u8 * data, u32 len) #define MAX_RESET_BACKOFF 10 -static void schedule_reset(struct ipw2100_priv *priv) +static inline void schedule_reset(struct ipw2100_priv *priv) { unsigned long now = get_seconds(); @@ -1130,7 +1130,7 @@ static inline void ipw2100_hw_set_gpio(struct ipw2100_priv *priv) write_register(priv->net_dev, IPW_REG_GPIO, reg); } -static int rf_kill_active(struct ipw2100_priv *priv) +static inline int rf_kill_active(struct ipw2100_priv *priv) { #define MAX_RF_KILL_CHECKS 5 #define RF_KILL_CHECK_DELAY 40 @@ -2177,7 +2177,7 @@ static const char *frame_types[] = { }; #endif -static int ipw2100_alloc_skb(struct ipw2100_priv *priv, +static inline int ipw2100_alloc_skb(struct ipw2100_priv *priv, struct ipw2100_rx_packet *packet) { packet->skb = dev_alloc_skb(sizeof(struct ipw2100_rx)); @@ -2201,7 +2201,7 @@ static int ipw2100_alloc_skb(struct ipw2100_priv *priv, #define SEARCH_SNAPSHOT 1 #define SNAPSHOT_ADDR(ofs) (priv->snapshot[((ofs) >> 12) & 0xff] + ((ofs) & 0xfff)) -static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) +static inline int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) { int i; if (priv->snapshot[0]) @@ -2221,7 +2221,7 @@ static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) return 1; } -static void ipw2100_snapshot_free(struct ipw2100_priv *priv) +static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv) { int i; if (!priv->snapshot[0]) @@ -2231,7 +2231,7 @@ static void ipw2100_snapshot_free(struct ipw2100_priv *priv) priv->snapshot[0] = NULL; } -static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, +static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, size_t len, int mode) { u32 i, j; @@ -2288,7 +2288,7 @@ static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH]; #endif -static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) +static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) { #ifdef CONFIG_IPW2100_DEBUG_C3 struct ipw2100_status *status = &priv->status_queue.drv[i]; @@ -2346,7 +2346,7 @@ static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) schedule_reset(priv); } -static void isr_rx(struct ipw2100_priv *priv, int i, +static inline void isr_rx(struct ipw2100_priv *priv, int i, struct ieee80211_rx_stats *stats) { struct ipw2100_status *status = &priv->status_queue.drv[i]; @@ -2425,7 +2425,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i, priv->rx_queue.drv[i].host_addr = packet->dma_addr; } -static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) +static inline int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) { struct ipw2100_status *status = &priv->status_queue.drv[i]; struct ipw2100_rx *u = priv->rx_buffers[i].rxp; @@ -2481,7 +2481,7 @@ static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) * The WRITE index is cached in the variable 'priv->rx_queue.next'. * */ -static void __ipw2100_rx_process(struct ipw2100_priv *priv) +static inline void __ipw2100_rx_process(struct ipw2100_priv *priv) { struct ipw2100_bd_queue *rxq = &priv->rx_queue; struct ipw2100_status_queue *sq = &priv->status_queue; @@ -2634,7 +2634,7 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv) * for use by future command and data packets. * */ -static int __ipw2100_tx_process(struct ipw2100_priv *priv) +static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) { struct ipw2100_bd_queue *txq = &priv->tx_queue; struct ipw2100_bd *tbd; diff --git a/trunk/drivers/net/wireless/ipw2200.c b/trunk/drivers/net/wireless/ipw2200.c index 819be2b6b7df..cdfe50207757 100644 --- a/trunk/drivers/net/wireless/ipw2200.c +++ b/trunk/drivers/net/wireless/ipw2200.c @@ -813,7 +813,7 @@ static void ipw_bg_led_link_off(void *data) up(&priv->sem); } -static void __ipw_led_activity_on(struct ipw_priv *priv) +static inline void __ipw_led_activity_on(struct ipw_priv *priv) { u32 led; @@ -1508,7 +1508,7 @@ static ssize_t store_direct_dword(struct device *d, static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO, show_direct_dword, store_direct_dword); -static int rf_kill_active(struct ipw_priv *priv) +static inline int rf_kill_active(struct ipw_priv *priv) { if (0 == (ipw_read32(priv, 0x30) & 0x10000)) priv->status |= STATUS_RF_KILL_HW; @@ -2359,7 +2359,7 @@ static inline void eeprom_write_reg(struct ipw_priv *p, u32 data) } /* perform a chip select operation */ -static void eeprom_cs(struct ipw_priv *priv) +static inline void eeprom_cs(struct ipw_priv *priv) { eeprom_write_reg(priv, 0); eeprom_write_reg(priv, EEPROM_BIT_CS); @@ -2368,7 +2368,7 @@ static void eeprom_cs(struct ipw_priv *priv) } /* perform a chip select operation */ -static void eeprom_disable_cs(struct ipw_priv *priv) +static inline void eeprom_disable_cs(struct ipw_priv *priv) { eeprom_write_reg(priv, EEPROM_BIT_CS); eeprom_write_reg(priv, 0); @@ -2475,7 +2475,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv) IPW_DEBUG_TRACE("<<\n"); } -static void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count) +static inline void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count) { count >>= 2; if (!count) @@ -2772,7 +2772,7 @@ static inline int ipw_alive(struct ipw_priv *priv) return ipw_read32(priv, 0x90) == 0xd55555d5; } -static int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask, +static inline int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask, int timeout) { int i = 0; @@ -3150,7 +3150,7 @@ static int ipw_get_fw(struct ipw_priv *priv, #define IPW_RX_BUF_SIZE (3000) -static void ipw_rx_queue_reset(struct ipw_priv *priv, +static inline void ipw_rx_queue_reset(struct ipw_priv *priv, struct ipw_rx_queue *rxq) { unsigned long flags; @@ -3608,7 +3608,7 @@ static void ipw_tx_queue_free(struct ipw_priv *priv) ipw_queue_tx_free(priv, &priv->txq[3]); } -static void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid) +static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid) { /* First 3 bytes are manufacturer */ bssid[0] = priv->mac_addr[0]; @@ -3622,7 +3622,7 @@ static void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid) bssid[0] |= 0x02; /* set local assignment bit (IEEE802) */ } -static u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid) +static inline u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid) { struct ipw_station_entry entry; int i; @@ -3655,7 +3655,7 @@ static u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid) return i; } -static u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid) +static inline u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid) { int i; @@ -3794,7 +3794,7 @@ static void inline average_init(struct average *avg) memset(avg, 0, sizeof(*avg)); } -static void average_add(struct average *avg, s16 val) +static void inline average_add(struct average *avg, s16 val) { avg->sum -= avg->entries[avg->pos]; avg->sum += val; @@ -3805,7 +3805,7 @@ static void average_add(struct average *avg, s16 val) } } -static s16 average_value(struct average *avg) +static s16 inline average_value(struct average *avg) { if (!unlikely(avg->init)) { if (avg->pos) @@ -3847,7 +3847,7 @@ static void ipw_reset_stats(struct ipw_priv *priv) } -static u32 ipw_get_max_rate(struct ipw_priv *priv) +static inline u32 ipw_get_max_rate(struct ipw_priv *priv) { u32 i = 0x80000000; u32 mask = priv->rates_mask; @@ -4087,7 +4087,7 @@ static void ipw_bg_gather_stats(void *data) * roaming_threshold -> disassociate_threshold, scan and roam for better signal. * Above disassociate threshold, give up and stop scanning. * Roaming is disabled if disassociate_threshold <= roaming_threshold */ -static void ipw_handle_missed_beacon(struct ipw_priv *priv, +static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, int missed_count) { priv->notif_missed_beacons = missed_count; @@ -4157,7 +4157,7 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv, * Handle host notification packet. * Called from interrupt routine */ -static void ipw_rx_notification(struct ipw_priv *priv, +static inline void ipw_rx_notification(struct ipw_priv *priv, struct ipw_rx_notification *notif) { notif->size = le16_to_cpu(notif->size); @@ -5095,7 +5095,7 @@ static int ipw_compatible_rates(struct ipw_priv *priv, return 1; } -static void ipw_copy_rates(struct ipw_supported_rates *dest, +static inline void ipw_copy_rates(struct ipw_supported_rates *dest, const struct ipw_supported_rates *src) { u8 i; @@ -5856,7 +5856,7 @@ static void ipw_debug_config(struct ipw_priv *priv) #define ipw_debug_config(x) do {} while (0) #endif -static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) +static inline void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) { /* TODO: Verify that this works... */ struct ipw_fixed_rate fr = { @@ -7634,7 +7634,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, } #endif -static int is_network_packet(struct ipw_priv *priv, +static inline int is_network_packet(struct ipw_priv *priv, struct ieee80211_hdr_4addr *header) { /* Filter incoming packets to determine if they are targetted toward @@ -7672,7 +7672,7 @@ static int is_network_packet(struct ipw_priv *priv, #define IPW_PACKET_RETRY_TIME HZ -static int is_duplicate_packet(struct ipw_priv *priv, +static inline int is_duplicate_packet(struct ipw_priv *priv, struct ieee80211_hdr_4addr *header) { u16 sc = le16_to_cpu(header->seq_ctl); @@ -9581,7 +9581,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev) /* net device stuff */ -static void init_sys_config(struct ipw_sys_config *sys_config) +static inline void init_sys_config(struct ipw_sys_config *sys_config) { memset(sys_config, 0, sizeof(struct ipw_sys_config)); sys_config->bt_coexistence = 1; /* We may need to look into prvStaBtConfig */ @@ -9627,7 +9627,7 @@ modify to send one tfd per fragment instead of using chunking. otherwise we need to heavily modify the ieee80211_skb_to_txb. */ -static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, +static inline int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, int pri) { struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) diff --git a/trunk/drivers/net/wireless/wavelan.c b/trunk/drivers/net/wireless/wavelan.c index ff192e96268a..b0d8b5b03152 100644 --- a/trunk/drivers/net/wireless/wavelan.c +++ b/trunk/drivers/net/wireless/wavelan.c @@ -102,7 +102,7 @@ static inline void hacr_write(unsigned long ioaddr, u16 hacr) * Write to card's Host Adapter Command Register. Include a delay for * those times when it is needed. */ -static void hacr_write_slow(unsigned long ioaddr, u16 hacr) +static inline void hacr_write_slow(unsigned long ioaddr, u16 hacr) { hacr_write(ioaddr, hacr); /* delay might only be needed sometimes */ @@ -242,7 +242,7 @@ static void psa_write(unsigned long ioaddr, u16 hacr, int o, /* Offset in PSA */ * The Windows drivers don't use the CRC, but the AP and the PtP tool * depend on it. */ -static u16 psa_crc(u8 * psa, /* The PSA */ +static inline u16 psa_crc(u8 * psa, /* The PSA */ int size) { /* Number of short for CRC */ int byte_cnt; /* Loop on the PSA */ @@ -310,7 +310,7 @@ static void update_psa_checksum(struct net_device * dev, unsigned long ioaddr, u /* * Write 1 byte to the MMC. */ -static void mmc_out(unsigned long ioaddr, u16 o, u8 d) +static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d) { int count = 0; @@ -326,7 +326,7 @@ static void mmc_out(unsigned long ioaddr, u16 o, u8 d) * Routine to write bytes to the Modem Management Controller. * We start at the end because it is the way it should be! */ -static void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n) +static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n) { o += n; b += n; @@ -340,7 +340,7 @@ static void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n) * Read a byte from the MMC. * Optimised version for 1 byte, avoid using memory. */ -static u8 mmc_in(unsigned long ioaddr, u16 o) +static inline u8 mmc_in(unsigned long ioaddr, u16 o) { int count = 0; @@ -587,7 +587,7 @@ static void wv_ack(struct net_device * dev) * Set channel attention bit and busy wait until command has * completed, then acknowledge completion of the command. */ -static int wv_synchronous_cmd(struct net_device * dev, const char *str) +static inline int wv_synchronous_cmd(struct net_device * dev, const char *str) { net_local *lp = (net_local *) dev->priv; unsigned long ioaddr = dev->base_addr; @@ -633,7 +633,7 @@ static int wv_synchronous_cmd(struct net_device * dev, const char *str) * Configuration commands completion interrupt. * Check if done, and if OK. */ -static int +static inline int wv_config_complete(struct net_device * dev, unsigned long ioaddr, net_local * lp) { unsigned short mcs_addr; @@ -843,7 +843,7 @@ if (lp->tx_n_in_use > 0) * wavelan_interrupt is not an option), so you may experience * delays sometimes. */ -static void wv_82586_reconfig(struct net_device * dev) +static inline void wv_82586_reconfig(struct net_device * dev) { net_local *lp = (net_local *) dev->priv; unsigned long flags; @@ -1281,7 +1281,7 @@ static inline void wv_packet_info(u8 * p, /* Packet to dump */ * This is the information which is displayed by the driver at startup. * There are lots of flags for configuring it to your liking. */ -static void wv_init_info(struct net_device * dev) +static inline void wv_init_info(struct net_device * dev) { short ioaddr = dev->base_addr; net_local *lp = (net_local *) dev->priv; @@ -1502,7 +1502,7 @@ static int wavelan_set_mac_address(struct net_device * dev, void *addr) * It's a bit complicated and you don't really want to look into it. * (called in wavelan_ioctl) */ -static int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */ +static inline int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */ iw_freq * frequency) { const int BAND_NUM = 10; /* Number of bands */ @@ -1677,7 +1677,7 @@ static int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */ /* * Give the list of available frequencies. */ -static int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */ +static inline int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */ iw_freq * list, /* List of frequencies to fill */ int max) { /* Maximum number of frequencies */ @@ -2489,7 +2489,7 @@ static iw_stats *wavelan_get_wireless_stats(struct net_device * dev) * Note: if any errors occur, the packet is "dropped on the floor". * (called by wv_packet_rcv()) */ -static void +static inline void wv_packet_read(struct net_device * dev, u16 buf_off, int sksize) { net_local *lp = (net_local *) dev->priv; @@ -2585,7 +2585,7 @@ wv_packet_read(struct net_device * dev, u16 buf_off, int sksize) * (called in wavelan_interrupt()). * Note : the spinlock is already grabbed for us. */ -static void wv_receive(struct net_device * dev) +static inline void wv_receive(struct net_device * dev) { unsigned long ioaddr = dev->base_addr; net_local *lp = (net_local *) dev->priv; @@ -2768,7 +2768,7 @@ static void wv_receive(struct net_device * dev) * * (called in wavelan_packet_xmit()) */ -static int wv_packet_write(struct net_device * dev, void *buf, short length) +static inline int wv_packet_write(struct net_device * dev, void *buf, short length) { net_local *lp = (net_local *) dev->priv; unsigned long ioaddr = dev->base_addr; @@ -2964,7 +2964,7 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev) * Routine to initialize the Modem Management Controller. * (called by wv_hw_reset()) */ -static int wv_mmc_init(struct net_device * dev) +static inline int wv_mmc_init(struct net_device * dev) { unsigned long ioaddr = dev->base_addr; net_local *lp = (net_local *) dev->priv; @@ -3136,7 +3136,7 @@ static int wv_mmc_init(struct net_device * dev) * Start the receive unit. * (called by wv_hw_reset()) */ -static int wv_ru_start(struct net_device * dev) +static inline int wv_ru_start(struct net_device * dev) { net_local *lp = (net_local *) dev->priv; unsigned long ioaddr = dev->base_addr; @@ -3228,7 +3228,7 @@ static int wv_ru_start(struct net_device * dev) * * (called by wv_hw_reset()) */ -static int wv_cu_start(struct net_device * dev) +static inline int wv_cu_start(struct net_device * dev) { net_local *lp = (net_local *) dev->priv; unsigned long ioaddr = dev->base_addr; @@ -3329,7 +3329,7 @@ static int wv_cu_start(struct net_device * dev) * * (called by wv_hw_reset()) */ -static int wv_82586_start(struct net_device * dev) +static inline int wv_82586_start(struct net_device * dev) { net_local *lp = (net_local *) dev->priv; unsigned long ioaddr = dev->base_addr; @@ -3641,7 +3641,7 @@ static void wv_82586_config(struct net_device * dev) * WaveLAN controller (i82586). * (called by wavelan_close()) */ -static void wv_82586_stop(struct net_device * dev) +static inline void wv_82586_stop(struct net_device * dev) { net_local *lp = (net_local *) dev->priv; unsigned long ioaddr = dev->base_addr; diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index ef4c687e7c01..9c25654b1e75 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -1635,7 +1635,7 @@ dasd_setup_queue(struct dasd_device * device) blk_queue_max_hw_segments(device->request_queue, -1L); blk_queue_max_segment_size(device->request_queue, -1L); blk_queue_segment_boundary(device->request_queue, -1L); - blk_queue_ordered(device->request_queue, QUEUE_ORDERED_TAG, NULL); + blk_queue_ordered(device->request_queue, 1); } /* diff --git a/trunk/drivers/s390/cio/airq.c b/trunk/drivers/s390/cio/airq.c index cd2cc28e16a7..83e6a060668e 100644 --- a/trunk/drivers/s390/cio/airq.c +++ b/trunk/drivers/s390/cio/airq.c @@ -2,12 +2,12 @@ * drivers/s390/cio/airq.c * S/390 common I/O routines -- support for adapter interruptions * - * $Revision: 1.15 $ + * $Revision: 1.12 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Ingo Adlung (adlung@de.ibm.com) - * Cornelia Huck (cornelia.huck@de.ibm.com) + * Cornelia Huck (cohuck@de.ibm.com) * Arnd Bergmann (arndb@de.ibm.com) */ diff --git a/trunk/drivers/s390/cio/blacklist.c b/trunk/drivers/s390/cio/blacklist.c index 72f27c151c09..daf21e03b21d 100644 --- a/trunk/drivers/s390/cio/blacklist.c +++ b/trunk/drivers/s390/cio/blacklist.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/blacklist.c * S/390 common I/O routines -- blacklisting of specific devices - * $Revision: 1.42 $ + * $Revision: 1.39 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Ingo Adlung (adlung@de.ibm.com) - * Cornelia Huck (cornelia.huck@de.ibm.com) + * Cornelia Huck (cohuck@de.ibm.com) * Arnd Bergmann (arndb@de.ibm.com) */ diff --git a/trunk/drivers/s390/cio/ccwgroup.c b/trunk/drivers/s390/cio/ccwgroup.c index 6c077ad71edc..503a568e47c3 100644 --- a/trunk/drivers/s390/cio/ccwgroup.c +++ b/trunk/drivers/s390/cio/ccwgroup.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/ccwgroup.c * bus driver for ccwgroup - * $Revision: 1.35 $ + * $Revision: 1.33 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Arnd Bergmann (arndb@de.ibm.com) - * Cornelia Huck (cornelia.huck@de.ibm.com) + * Cornelia Huck (cohuck@de.ibm.com) */ #include #include diff --git a/trunk/drivers/s390/cio/chsc.c b/trunk/drivers/s390/cio/chsc.c index 2cbb724791a8..7270808c02d1 100644 --- a/trunk/drivers/s390/cio/chsc.c +++ b/trunk/drivers/s390/cio/chsc.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/chsc.c * S/390 common I/O routines -- channel subsystem call - * $Revision: 1.128 $ + * $Revision: 1.126 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Ingo Adlung (adlung@de.ibm.com) - * Cornelia Huck (cornelia.huck@de.ibm.com) + * Cornelia Huck (cohuck@de.ibm.com) * Arnd Bergmann (arndb@de.ibm.com) */ diff --git a/trunk/drivers/s390/cio/cio.c b/trunk/drivers/s390/cio/cio.c index 6223b06d27d5..7376bc87206d 100644 --- a/trunk/drivers/s390/cio/cio.c +++ b/trunk/drivers/s390/cio/cio.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls - * $Revision: 1.140 $ + * $Revision: 1.138 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Ingo Adlung (adlung@de.ibm.com) - * Cornelia Huck (cornelia.huck@de.ibm.com) + * Cornelia Huck (cohuck@de.ibm.com) * Arnd Bergmann (arndb@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) */ diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index 516108779f60..2d319fb812ca 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/css.c * driver for channel subsystem - * $Revision: 1.96 $ + * $Revision: 1.93 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Arnd Bergmann (arndb@de.ibm.com) - * Cornelia Huck (cornelia.huck@de.ibm.com) + * Cornelia Huck (cohuck@de.ibm.com) */ #include #include diff --git a/trunk/drivers/s390/cio/css.h b/trunk/drivers/s390/cio/css.h index b6375861cb37..aa5ab5d4547c 100644 --- a/trunk/drivers/s390/cio/css.h +++ b/trunk/drivers/s390/cio/css.h @@ -147,7 +147,7 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); struct channel_subsystem { u8 cssid; int valid; - struct channel_path *chps[__MAX_CHPID + 1]; + struct channel_path *chps[__MAX_CHPID]; struct device device; struct pgid global_pgid; }; diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index a67e7e60e330..eb73605a0527 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/device.c * bus driver for ccw devices - * $Revision: 1.140 $ + * $Revision: 1.137 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Arnd Bergmann (arndb@de.ibm.com) - * Cornelia Huck (cornelia.huck@de.ibm.com) + * Cornelia Huck (cohuck@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) */ #include diff --git a/trunk/drivers/s390/cio/device_fsm.c b/trunk/drivers/s390/cio/device_fsm.c index b302779e7cff..23d12b65e5fa 100644 --- a/trunk/drivers/s390/cio/device_fsm.c +++ b/trunk/drivers/s390/cio/device_fsm.c @@ -4,7 +4,7 @@ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation - * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) + * Author(s): Cornelia Huck(cohuck@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) */ diff --git a/trunk/drivers/s390/cio/device_id.c b/trunk/drivers/s390/cio/device_id.c index e60b2d8103b8..04ceba343db8 100644 --- a/trunk/drivers/s390/cio/device_id.c +++ b/trunk/drivers/s390/cio/device_id.c @@ -3,7 +3,7 @@ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation - * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) + * Author(s): Cornelia Huck(cohuck@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) * * Sense ID functions. diff --git a/trunk/drivers/s390/cio/device_ops.c b/trunk/drivers/s390/cio/device_ops.c index 8b0218949b62..143b6c25a4e6 100644 --- a/trunk/drivers/s390/cio/device_ops.c +++ b/trunk/drivers/s390/cio/device_ops.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/device_ops.c * - * $Revision: 1.61 $ + * $Revision: 1.58 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) - * Cornelia Huck (cornelia.huck@de.ibm.com) + * Cornelia Huck (cohuck@de.ibm.com) */ #include #include diff --git a/trunk/drivers/s390/cio/device_pgid.c b/trunk/drivers/s390/cio/device_pgid.c index d2a5b04d7cba..052832d03d38 100644 --- a/trunk/drivers/s390/cio/device_pgid.c +++ b/trunk/drivers/s390/cio/device_pgid.c @@ -3,7 +3,7 @@ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation - * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) + * Author(s): Cornelia Huck(cohuck@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) * * Path Group ID functions. diff --git a/trunk/drivers/s390/cio/device_status.c b/trunk/drivers/s390/cio/device_status.c index dad4dd9887c9..db09c209098b 100644 --- a/trunk/drivers/s390/cio/device_status.c +++ b/trunk/drivers/s390/cio/device_status.c @@ -3,7 +3,7 @@ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation - * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) + * Author(s): Cornelia Huck(cohuck@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) * * Status accumulation and basic sense functions. diff --git a/trunk/drivers/s390/cio/qdio.c b/trunk/drivers/s390/cio/qdio.c index 77be2c39bfe4..30a836ffc31f 100644 --- a/trunk/drivers/s390/cio/qdio.c +++ b/trunk/drivers/s390/cio/qdio.c @@ -7,7 +7,7 @@ * * Copyright 2000,2002 IBM Corporation * Author(s): Utz Bacher - * 2.6 cio integration by Cornelia Huck + * 2.6 cio integration by Cornelia Huck * * Restriction: only 63 iqdio subchannels would have its own indicator, * after that, subsequent subchannels share one indicator @@ -56,7 +56,7 @@ #include "ioasm.h" #include "chsc.h" -#define VERSION_QDIO_C "$Revision: 1.117 $" +#define VERSION_QDIO_C "$Revision: 1.114 $" /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher "); diff --git a/trunk/drivers/s390/net/ctcmain.c b/trunk/drivers/s390/net/ctcmain.c index 1901feef07d9..0db4f57a6a95 100644 --- a/trunk/drivers/s390/net/ctcmain.c +++ b/trunk/drivers/s390/net/ctcmain.c @@ -1,5 +1,5 @@ /* - * $Id: ctcmain.c,v 1.79 2006/01/11 11:32:18 cohuck Exp $ + * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $ * * CTC / ESCON network driver * @@ -8,7 +8,7 @@ * Fixes by : Jochen Röhrig (roehrig@de.ibm.com) * Arnaldo Carvalho de Melo Peter Tiedemann (ptiedem@de.ibm.com) - * Driver Model stuff by : Cornelia Huck + * Driver Model stuff by : Cornelia Huck * * Documentation used: * - Principles of Operation (IBM doc#: SA22-7201-06) @@ -37,7 +37,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.79 $ + * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $ * */ #undef DEBUG @@ -248,7 +248,7 @@ static void print_banner(void) { static int printed = 0; - char vbuf[] = "$Revision: 1.79 $"; + char vbuf[] = "$Revision: 1.78 $"; char *version = vbuf; if (printed) diff --git a/trunk/drivers/s390/net/cu3088.c b/trunk/drivers/s390/net/cu3088.c index 2014fb7a4881..77dacb465732 100644 --- a/trunk/drivers/s390/net/cu3088.c +++ b/trunk/drivers/s390/net/cu3088.c @@ -1,11 +1,11 @@ /* - * $Id: cu3088.c,v 1.38 2006/01/12 14:33:09 cohuck Exp $ + * $Id: cu3088.c,v 1.36 2005/10/25 14:37:17 cohuck Exp $ * * CTC / LCS ccw_device driver * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Arnd Bergmann - * Cornelia Huck + * Cornelia Huck * * 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 diff --git a/trunk/drivers/s390/net/netiucv.c b/trunk/drivers/s390/net/netiucv.c index ac4c4b83fe17..69425a7a6e98 100644 --- a/trunk/drivers/s390/net/netiucv.c +++ b/trunk/drivers/s390/net/netiucv.c @@ -1,13 +1,12 @@ /* - * $Id: netiucv.c,v 1.69 2006/01/12 14:33:09 cohuck Exp $ + * $Id: netiucv.c,v 1.66 2005/05/11 08:10:17 holzheu Exp $ * * IUCV network driver * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) * - * Sysfs integration and all bugs therein by Cornelia Huck - * (cornelia.huck@de.ibm.com) + * Driverfs integration and all bugs therein by Cornelia Huck(cohuck@de.ibm.com) * * Documentation used: * the source of the original IUCV driver by: @@ -31,7 +30,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV network driver $Revision: 1.69 $ + * RELEASE-TAG: IUCV network driver $Revision: 1.66 $ * */ @@ -2077,7 +2076,7 @@ DRIVER_ATTR(remove, 0200, NULL, remove_write); static void netiucv_banner(void) { - char vbuf[] = "$Revision: 1.69 $"; + char vbuf[] = "$Revision: 1.66 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { diff --git a/trunk/drivers/s390/s390_rdev.c b/trunk/drivers/s390/s390_rdev.c index 206518c7d332..566cc3d185b6 100644 --- a/trunk/drivers/s390/s390_rdev.c +++ b/trunk/drivers/s390/s390_rdev.c @@ -1,11 +1,11 @@ /* * drivers/s390/s390_rdev.c * s390 root device - * $Revision: 1.4 $ + * $Revision: 1.2 $ * * Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH, * IBM Corporation - * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) + * Author(s): Cornelia Huck (cohuck@de.ibm.com) * Carsten Otte (cotte@de.ibm.com) */ diff --git a/trunk/drivers/scsi/aic7xxx_old.c b/trunk/drivers/scsi/aic7xxx_old.c index 770f1647e4d6..33d56c344944 100644 --- a/trunk/drivers/scsi/aic7xxx_old.c +++ b/trunk/drivers/scsi/aic7xxx_old.c @@ -1290,7 +1290,7 @@ static void aic7xxx_check_scbs(struct aic7xxx_host *p, char *buffer); * ***************************************************************************/ -static unsigned char +static inline unsigned char aic_inb(struct aic7xxx_host *p, long port) { #ifdef MMAPIO @@ -1309,7 +1309,7 @@ aic_inb(struct aic7xxx_host *p, long port) #endif } -static void +static inline void aic_outb(struct aic7xxx_host *p, unsigned char val, long port) { #ifdef MMAPIO diff --git a/trunk/drivers/scsi/iscsi_tcp.c b/trunk/drivers/scsi/iscsi_tcp.c index 780bfcc67096..1b495afe6d17 100644 --- a/trunk/drivers/scsi/iscsi_tcp.c +++ b/trunk/drivers/scsi/iscsi_tcp.c @@ -1418,7 +1418,7 @@ iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ctask->digest_count = 4; } -static int +static inline int iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_buf *buf, uint32_t *digest, int final) { diff --git a/trunk/drivers/scsi/libata-core.c b/trunk/drivers/scsi/libata-core.c index 99bae8369ab2..f55b9b3f7b37 100644 --- a/trunk/drivers/scsi/libata-core.c +++ b/trunk/drivers/scsi/libata-core.c @@ -1747,7 +1747,7 @@ static const struct { { ATA_SHIFT_PIO, XFER_PIO_0 }, }; -static u8 base_from_shift(unsigned int shift) +static inline u8 base_from_shift(unsigned int shift) { int i; diff --git a/trunk/drivers/scsi/megaraid/megaraid_mbox.c b/trunk/drivers/scsi/megaraid/megaraid_mbox.c index bf9f7f7ba354..d18a4bc2498c 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_mbox.c +++ b/trunk/drivers/scsi/megaraid/megaraid_mbox.c @@ -1266,7 +1266,7 @@ megaraid_mbox_teardown_dma_pools(adapter_t *adapter) * return the scb from the head of the free list. NULL if there are none * available **/ -static scb_t * +static inline scb_t * megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp) { struct list_head *head = &adapter->kscb_pool; @@ -1329,7 +1329,7 @@ megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb) * * prepare the scatter-gather list */ -static int +static inline int megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) { struct scatterlist *sgl; @@ -1402,7 +1402,7 @@ megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) * * post the command to the controller if mailbox is availble. */ -static int +static inline int mbox_post_cmd(adapter_t *adapter, scb_t *scb) { mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); @@ -2070,7 +2070,7 @@ megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb, * * Returns: 1 if the interrupt is valid, 0 otherwise */ -static int +static inline int megaraid_ack_sequence(adapter_t *adapter) { mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); @@ -2208,7 +2208,7 @@ megaraid_isr(int irq, void *devp, struct pt_regs *regs) * * DMA sync if required. */ -static void +static inline void megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb) { mbox_ccb_t *ccb; diff --git a/trunk/drivers/scsi/megaraid/megaraid_sas.c b/trunk/drivers/scsi/megaraid/megaraid_sas.c index 511ed52a5807..c0bb8061401f 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_sas.c +++ b/trunk/drivers/scsi/megaraid/megaraid_sas.c @@ -81,7 +81,7 @@ static DEFINE_MUTEX(megasas_async_queue_mutex); * * Returns a free command from the pool */ -static struct megasas_cmd *megasas_get_cmd(struct megasas_instance +static inline struct megasas_cmd *megasas_get_cmd(struct megasas_instance *instance) { unsigned long flags; @@ -263,7 +263,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, * If successful, this function returns the number of SG elements. Otherwise, * it returnes -1. */ -static int +static inline int megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl) { @@ -311,7 +311,7 @@ megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp, * If successful, this function returns the number of SG elements. Otherwise, * it returnes -1. */ -static int +static inline int megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl) { @@ -360,7 +360,7 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, * This function prepares CDB commands. These are typcially pass-through * commands to the devices. */ -static int +static inline int megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, struct megasas_cmd *cmd) { @@ -441,7 +441,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, * * Frames (and accompanying SGLs) for regular SCSI IOs use this function. */ -static int +static inline int megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, struct megasas_cmd *cmd) { @@ -563,7 +563,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, * @scp: SCSI command * @frame_count: [OUT] Number of frames used to prepare this command */ -static struct megasas_cmd *megasas_build_cmd(struct megasas_instance +static inline struct megasas_cmd *megasas_build_cmd(struct megasas_instance *instance, struct scsi_cmnd *scp, int *frame_count) @@ -914,7 +914,7 @@ megasas_complete_abort(struct megasas_instance *instance, * @instance: Adapter soft state * @cmd: Completed command */ -static void +static inline void megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd) { dma_addr_t buf_h; @@ -958,7 +958,7 @@ megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd) * an alternate status (as in the case of aborted * commands) */ -static void +static inline void megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, u8 alt_status) { @@ -1105,7 +1105,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, * SCSI mid-layer instead of the status * returned by the FW */ -static int +static inline int megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) { u32 status; diff --git a/trunk/drivers/scsi/sr.c b/trunk/drivers/scsi/sr.c index 997f8e30509b..dd8050392d01 100644 --- a/trunk/drivers/scsi/sr.c +++ b/trunk/drivers/scsi/sr.c @@ -151,7 +151,7 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk) return cd; } -static void scsi_cd_put(struct scsi_cd *cd) +static inline void scsi_cd_put(struct scsi_cd *cd) { struct scsi_device *sdev = cd->device; diff --git a/trunk/drivers/serial/8250.c b/trunk/drivers/serial/8250.c index d9ce8c549416..fb610c3634a4 100644 --- a/trunk/drivers/serial/8250.c +++ b/trunk/drivers/serial/8250.c @@ -2454,7 +2454,6 @@ static struct platform_driver serial8250_isa_driver = { .resume = serial8250_resume, .driver = { .name = "serial8250", - .owner = THIS_MODULE, }, }; @@ -2595,30 +2594,21 @@ static int __init serial8250_init(void) if (ret) goto out; - ret = platform_driver_register(&serial8250_isa_driver); - if (ret) - goto unreg_uart_drv; - - serial8250_isa_devs = platform_device_alloc("serial8250", - PLAT8250_DEV_LEGACY); - if (!serial8250_isa_devs) { - ret = -ENOMEM; - goto unreg_plat_drv; + serial8250_isa_devs = platform_device_register_simple("serial8250", + PLAT8250_DEV_LEGACY, NULL, 0); + if (IS_ERR(serial8250_isa_devs)) { + ret = PTR_ERR(serial8250_isa_devs); + goto unreg; } - ret = platform_device_add(serial8250_isa_devs); - if (ret) - goto put_dev; - serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev); - goto out; + ret = platform_driver_register(&serial8250_isa_driver); + if (ret == 0) + goto out; - put_dev: - platform_device_put(serial8250_isa_devs); - unreg_plat_drv: - platform_driver_unregister(&serial8250_isa_driver); - unreg_uart_drv: + platform_device_unregister(serial8250_isa_devs); + unreg: uart_unregister_driver(&serial8250_reg); out: return ret; diff --git a/trunk/drivers/serial/Kconfig b/trunk/drivers/serial/Kconfig index 5e7199f7b59c..843717275d49 100644 --- a/trunk/drivers/serial/Kconfig +++ b/trunk/drivers/serial/Kconfig @@ -190,6 +190,7 @@ config SERIAL_8250_BOCA To compile this driver as a module, choose M here: the module will be called 8250_boca. + config SERIAL_8250_HUB6 tristate "Support Hub6 cards" depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS @@ -847,7 +848,7 @@ config SERIAL_M32R_SIO_CONSOLE config SERIAL_M32R_PLDSIO bool "M32R SIO I/F on a PLD" - depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PLAT_USRV || PLAT_M32700UT) + depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PALT_USRV || PLAT_M32700UT) default n help Say Y here if you want to use the M32R serial controller @@ -916,12 +917,4 @@ config SERIAL_SGI_IOC4 and wish to use the serial ports on this card, say Y. Otherwise, say N. -config SERIAL_SGI_IOC3 - tristate "SGI Altix IOC3 serial support" - depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC3 - select SERIAL_CORE - help - If you have an SGI Altix with an IOC3 serial card, - say Y or M. Otherwise, say N. - endmenu diff --git a/trunk/drivers/serial/Makefile b/trunk/drivers/serial/Makefile index eaf8e01db198..24a583e482bb 100644 --- a/trunk/drivers/serial/Makefile +++ b/trunk/drivers/serial/Makefile @@ -56,5 +56,4 @@ obj-$(CONFIG_SERIAL_JSM) += jsm/ obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o -obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o obj-$(CONFIG_SERIAL_AT91) += at91_serial.o diff --git a/trunk/drivers/serial/imx.c b/trunk/drivers/serial/imx.c index 587cc6a95114..5c098be9346b 100644 --- a/trunk/drivers/serial/imx.c +++ b/trunk/drivers/serial/imx.c @@ -499,7 +499,7 @@ imx_set_termios(struct uart_port *port, struct termios *termios, ucr2 |= UCR2_STPB; if (termios->c_cflag & PARENB) { ucr2 |= UCR2_PREN; - if (termios->c_cflag & PARODD) + if (!(termios->c_cflag & PARODD)) ucr2 |= UCR2_PROE; } diff --git a/trunk/drivers/serial/ioc3_serial.c b/trunk/drivers/serial/ioc3_serial.c deleted file mode 100644 index 8097cd91f16b..000000000000 --- a/trunk/drivers/serial/ioc3_serial.c +++ /dev/null @@ -1,2197 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved. - */ - -/* - * This file contains a module version of the ioc3 serial driver. This - * includes all the support functions needed (support functions, etc.) - * and the serial driver itself. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Interesting things about the ioc3 - */ - -#define LOGICAL_PORTS 2 /* rs232(0) and rs422(1) */ -#define PORTS_PER_CARD 2 -#define LOGICAL_PORTS_PER_CARD (PORTS_PER_CARD * LOGICAL_PORTS) -#define MAX_CARDS 8 -#define MAX_LOGICAL_PORTS (LOGICAL_PORTS_PER_CARD * MAX_CARDS) - -/* determine given the sio_ir what port it applies to */ -#define GET_PORT_FROM_SIO_IR(_x) (_x & SIO_IR_SA) ? 0 : 1 - - -/* - * we have 2 logical ports (rs232, rs422) for each physical port - * evens are rs232, odds are rs422 - */ -#define GET_PHYSICAL_PORT(_x) ((_x) >> 1) -#define GET_LOGICAL_PORT(_x) ((_x) & 1) -#define IS_PHYSICAL_PORT(_x) !((_x) & 1) -#define IS_RS232(_x) !((_x) & 1) - -static unsigned int Num_of_ioc3_cards; -static unsigned int Submodule_slot; - -/* defining this will get you LOTS of great debug info */ -//#define DEBUG_INTERRUPTS -#define DPRINT_CONFIG(_x...) ; -//#define DPRINT_CONFIG(_x...) printk _x -#define NOT_PROGRESS() ; -//#define NOT_PROGRESS() printk("%s : fails %d\n", __FUNCTION__, __LINE__) - -/* number of characters we want to transmit to the lower level at a time */ -#define MAX_CHARS 256 -#define FIFO_SIZE (MAX_CHARS-1) /* it's a uchar */ - -/* Device name we're using */ -#define DEVICE_NAME "ttySIOC" -#define DEVICE_MAJOR 204 -#define DEVICE_MINOR 116 - -/* flags for next_char_state */ -#define NCS_BREAK 0x1 -#define NCS_PARITY 0x2 -#define NCS_FRAMING 0x4 -#define NCS_OVERRUN 0x8 - -/* cause we need SOME parameters ... */ -#define MIN_BAUD_SUPPORTED 1200 -#define MAX_BAUD_SUPPORTED 115200 - -/* protocol types supported */ -#define PROTO_RS232 0 -#define PROTO_RS422 1 - -/* Notification types */ -#define N_DATA_READY 0x01 -#define N_OUTPUT_LOWAT 0x02 -#define N_BREAK 0x04 -#define N_PARITY_ERROR 0x08 -#define N_FRAMING_ERROR 0x10 -#define N_OVERRUN_ERROR 0x20 -#define N_DDCD 0x40 -#define N_DCTS 0x80 - -#define N_ALL_INPUT (N_DATA_READY | N_BREAK \ - | N_PARITY_ERROR | N_FRAMING_ERROR \ - | N_OVERRUN_ERROR | N_DDCD | N_DCTS) - -#define N_ALL_OUTPUT N_OUTPUT_LOWAT - -#define N_ALL_ERRORS (N_PARITY_ERROR | N_FRAMING_ERROR \ - | N_OVERRUN_ERROR) - -#define N_ALL (N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK \ - | N_PARITY_ERROR | N_FRAMING_ERROR \ - | N_OVERRUN_ERROR | N_DDCD | N_DCTS) - -#define SER_CLK_SPEED(prediv) ((22000000 << 1) / prediv) -#define SER_DIVISOR(x, clk) (((clk) + (x) * 8) / ((x) * 16)) -#define DIVISOR_TO_BAUD(div, clk) ((clk) / 16 / (div)) - -/* Some masks */ -#define LCR_MASK_BITS_CHAR (UART_LCR_WLEN5 | UART_LCR_WLEN6 \ - | UART_LCR_WLEN7 | UART_LCR_WLEN8) -#define LCR_MASK_STOP_BITS (UART_LCR_STOP) - -#define PENDING(_a, _p) (readl(&(_p)->vma->sio_ir) & (_a)->ic_enable) - -#define RING_BUF_SIZE 4096 -#define BUF_SIZE_BIT SBBR_L_SIZE -#define PROD_CONS_MASK PROD_CONS_PTR_4K - -#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4) - -/* driver specific - one per card */ -struct ioc3_card { - struct { - /* uart ports are allocated here */ - struct uart_port icp_uart_port[LOGICAL_PORTS]; - /* the ioc3_port used for this port */ - struct ioc3_port *icp_port; - } ic_port[PORTS_PER_CARD]; - /* currently enabled interrupts */ - uint32_t ic_enable; -}; - -/* Local port info for each IOC3 serial port */ -struct ioc3_port { - /* handy reference material */ - struct uart_port *ip_port; - struct ioc3_card *ip_card; - struct ioc3_driver_data *ip_idd; - struct ioc3_submodule *ip_is; - - /* pci mem addresses for this port */ - struct ioc3_serialregs __iomem *ip_serial_regs; - struct ioc3_uartregs __iomem *ip_uart_regs; - - /* Ring buffer page for this port */ - dma_addr_t ip_dma_ringbuf; - /* vaddr of ring buffer */ - struct ring_buffer *ip_cpu_ringbuf; - - /* Rings for this port */ - struct ring *ip_inring; - struct ring *ip_outring; - - /* Hook to port specific values */ - struct port_hooks *ip_hooks; - - spinlock_t ip_lock; - - /* Various rx/tx parameters */ - int ip_baud; - int ip_tx_lowat; - int ip_rx_timeout; - - /* Copy of notification bits */ - int ip_notify; - - /* Shadow copies of various registers so we don't need to PIO - * read them constantly - */ - uint32_t ip_sscr; - uint32_t ip_tx_prod; - uint32_t ip_rx_cons; - unsigned char ip_flags; -}; - -/* tx low water mark. We need to notify the driver whenever tx is getting - * close to empty so it can refill the tx buffer and keep things going. - * Let's assume that if we interrupt 1 ms before the tx goes idle, we'll - * have no trouble getting in more chars in time (I certainly hope so). - */ -#define TX_LOWAT_LATENCY 1000 -#define TX_LOWAT_HZ (1000000 / TX_LOWAT_LATENCY) -#define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ) - -/* Flags per port */ -#define INPUT_HIGH 0x01 - /* used to signify that we have turned off the rx_high - * temporarily - we need to drain the fifo and don't - * want to get blasted with interrupts. - */ -#define DCD_ON 0x02 - /* DCD state is on */ -#define LOWAT_WRITTEN 0x04 -#define READ_ABORTED 0x08 - /* the read was aborted - used to avaoid infinate looping - * in the interrupt handler - */ -#define INPUT_ENABLE 0x10 - -/* Since each port has different register offsets and bitmasks - * for everything, we'll store those that we need in tables so we - * don't have to be constantly checking the port we are dealing with. - */ -struct port_hooks { - uint32_t intr_delta_dcd; - uint32_t intr_delta_cts; - uint32_t intr_tx_mt; - uint32_t intr_rx_timer; - uint32_t intr_rx_high; - uint32_t intr_tx_explicit; - uint32_t intr_clear; - uint32_t intr_all; - char rs422_select_pin; -}; - -static struct port_hooks hooks_array[PORTS_PER_CARD] = { - /* values for port A */ - { - .intr_delta_dcd = SIO_IR_SA_DELTA_DCD, - .intr_delta_cts = SIO_IR_SA_DELTA_CTS, - .intr_tx_mt = SIO_IR_SA_TX_MT, - .intr_rx_timer = SIO_IR_SA_RX_TIMER, - .intr_rx_high = SIO_IR_SA_RX_HIGH, - .intr_tx_explicit = SIO_IR_SA_TX_EXPLICIT, - .intr_clear = (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL - | SIO_IR_SA_RX_HIGH - | SIO_IR_SA_RX_TIMER - | SIO_IR_SA_DELTA_DCD - | SIO_IR_SA_DELTA_CTS - | SIO_IR_SA_INT - | SIO_IR_SA_TX_EXPLICIT - | SIO_IR_SA_MEMERR), - .intr_all = SIO_IR_SA, - .rs422_select_pin = GPPR_UARTA_MODESEL_PIN, - }, - - /* values for port B */ - { - .intr_delta_dcd = SIO_IR_SB_DELTA_DCD, - .intr_delta_cts = SIO_IR_SB_DELTA_CTS, - .intr_tx_mt = SIO_IR_SB_TX_MT, - .intr_rx_timer = SIO_IR_SB_RX_TIMER, - .intr_rx_high = SIO_IR_SB_RX_HIGH, - .intr_tx_explicit = SIO_IR_SB_TX_EXPLICIT, - .intr_clear = (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL - | SIO_IR_SB_RX_HIGH - | SIO_IR_SB_RX_TIMER - | SIO_IR_SB_DELTA_DCD - | SIO_IR_SB_DELTA_CTS - | SIO_IR_SB_INT - | SIO_IR_SB_TX_EXPLICIT - | SIO_IR_SB_MEMERR), - .intr_all = SIO_IR_SB, - .rs422_select_pin = GPPR_UARTB_MODESEL_PIN, - } -}; - -struct ring_entry { - union { - struct { - uint32_t alldata; - uint32_t allsc; - } all; - struct { - char data[4]; /* data bytes */ - char sc[4]; /* status/control */ - } s; - } u; -}; - -/* Test the valid bits in any of the 4 sc chars using "allsc" member */ -#define RING_ANY_VALID \ - ((uint32_t)(RXSB_MODEM_VALID | RXSB_DATA_VALID) * 0x01010101) - -#define ring_sc u.s.sc -#define ring_data u.s.data -#define ring_allsc u.all.allsc - -/* Number of entries per ring buffer. */ -#define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry)) - -/* An individual ring */ -struct ring { - struct ring_entry entries[ENTRIES_PER_RING]; -}; - -/* The whole enchilada */ -struct ring_buffer { - struct ring TX_A; - struct ring RX_A; - struct ring TX_B; - struct ring RX_B; -}; - -/* Get a ring from a port struct */ -#define RING(_p, _wh) &(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh) - -/* for Infinite loop detection */ -#define MAXITER 10000000 - - -/** - * set_baud - Baud rate setting code - * @port: port to set - * @baud: baud rate to use - */ -static int set_baud(struct ioc3_port *port, int baud) -{ - int divisor; - int actual_baud; - int diff; - int lcr, prediv; - struct ioc3_uartregs __iomem *uart; - - for (prediv = 6; prediv < 64; prediv++) { - divisor = SER_DIVISOR(baud, SER_CLK_SPEED(prediv)); - if (!divisor) - continue; /* invalid divisor */ - actual_baud = DIVISOR_TO_BAUD(divisor, SER_CLK_SPEED(prediv)); - - diff = actual_baud - baud; - if (diff < 0) - diff = -diff; - - /* if we're within 1% we've found a match */ - if (diff * 100 <= actual_baud) - break; - } - - /* if the above loop completed, we didn't match - * the baud rate. give up. - */ - if (prediv == 64) { - NOT_PROGRESS(); - return 1; - } - - uart = port->ip_uart_regs; - lcr = readb(&uart->iu_lcr); - - writeb(lcr | UART_LCR_DLAB, &uart->iu_lcr); - writeb((unsigned char)divisor, &uart->iu_dll); - writeb((unsigned char)(divisor >> 8), &uart->iu_dlm); - writeb((unsigned char)prediv, &uart->iu_scr); - writeb((unsigned char)lcr, &uart->iu_lcr); - - return 0; -} - -/** - * get_ioc3_port - given a uart port, return the control structure - * @the_port: uart port to find - */ -static struct ioc3_port *get_ioc3_port(struct uart_port *the_port) -{ - struct ioc3_driver_data *idd = dev_get_drvdata(the_port->dev); - struct ioc3_card *card_ptr = idd->data[Submodule_slot]; - int ii, jj; - - if (!card_ptr) { - NOT_PROGRESS(); - return NULL; - } - for (ii = 0; ii < PORTS_PER_CARD; ii++) { - for (jj = 0; jj < LOGICAL_PORTS; jj++) { - if (the_port == &card_ptr->ic_port[ii].icp_uart_port[jj]) - return card_ptr->ic_port[ii].icp_port; - } - } - NOT_PROGRESS(); - return NULL; -} - -/** - * port_init - Initialize the sio and ioc3 hardware for a given port - * called per port from attach... - * @port: port to initialize - */ -static int inline port_init(struct ioc3_port *port) -{ - uint32_t sio_cr; - struct port_hooks *hooks = port->ip_hooks; - struct ioc3_uartregs __iomem *uart; - int reset_loop_counter = 0xfffff; - struct ioc3_driver_data *idd = port->ip_idd; - - /* Idle the IOC3 serial interface */ - writel(SSCR_RESET, &port->ip_serial_regs->sscr); - - /* Wait until any pending bus activity for this port has ceased */ - do { - sio_cr = readl(&idd->vma->sio_cr); - if (reset_loop_counter-- <= 0) { - printk(KERN_WARNING - "IOC3 unable to come out of reset" - " scr 0x%x\n", sio_cr); - return -1; - } - } while (!(sio_cr & SIO_CR_ARB_DIAG_IDLE) && - (((sio_cr &= SIO_CR_ARB_DIAG) == SIO_CR_ARB_DIAG_TXA) - || sio_cr == SIO_CR_ARB_DIAG_TXB - || sio_cr == SIO_CR_ARB_DIAG_RXA - || sio_cr == SIO_CR_ARB_DIAG_RXB)); - - /* Finish reset sequence */ - writel(0, &port->ip_serial_regs->sscr); - - /* Once RESET is done, reload cached tx_prod and rx_cons values - * and set rings to empty by making prod == cons - */ - port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK; - writel(port->ip_tx_prod, &port->ip_serial_regs->stpir); - port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; - writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir); - - /* Disable interrupts for this 16550 */ - uart = port->ip_uart_regs; - writeb(0, &uart->iu_lcr); - writeb(0, &uart->iu_ier); - - /* Set the default baud */ - set_baud(port, port->ip_baud); - - /* Set line control to 8 bits no parity */ - writeb(UART_LCR_WLEN8 | 0, &uart->iu_lcr); - /* UART_LCR_STOP == 1 stop */ - - /* Enable the FIFOs */ - writeb(UART_FCR_ENABLE_FIFO, &uart->iu_fcr); - /* then reset 16550 FIFOs */ - writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, - &uart->iu_fcr); - - /* Clear modem control register */ - writeb(0, &uart->iu_mcr); - - /* Clear deltas in modem status register */ - writel(0, &port->ip_serial_regs->shadow); - - /* Only do this once per port pair */ - if (port->ip_hooks == &hooks_array[0]) { - unsigned long ring_pci_addr; - uint32_t __iomem *sbbr_l, *sbbr_h; - - sbbr_l = &idd->vma->sbbr_l; - sbbr_h = &idd->vma->sbbr_h; - ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf; - DPRINT_CONFIG(("%s: ring_pci_addr 0x%p\n", - __FUNCTION__, (void *)ring_pci_addr)); - - writel((unsigned int)((uint64_t) ring_pci_addr >> 32), sbbr_h); - writel((unsigned int)ring_pci_addr | BUF_SIZE_BIT, sbbr_l); - } - - /* Set the receive timeout value to 10 msec */ - writel(SRTR_HZ / 100, &port->ip_serial_regs->srtr); - - /* Set rx threshold, enable DMA */ - /* Set high water mark at 3/4 of full ring */ - port->ip_sscr = (ENTRIES_PER_RING * 3 / 4); - - /* uart experiences pauses at high baud rate reducing actual - * throughput by 10% or so unless we enable high speed polling - * XXX when this hardware bug is resolved we should revert to - * normal polling speed - */ - port->ip_sscr |= SSCR_HIGH_SPD; - - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - - /* Disable and clear all serial related interrupt bits */ - port->ip_card->ic_enable &= ~hooks->intr_clear; - ioc3_disable(port->ip_is, idd, hooks->intr_clear); - ioc3_ack(port->ip_is, idd, hooks->intr_clear); - return 0; -} - -/** - * enable_intrs - enable interrupts - * @port: port to enable - * @mask: mask to use - */ -static void enable_intrs(struct ioc3_port *port, uint32_t mask) -{ - if ((port->ip_card->ic_enable & mask) != mask) { - port->ip_card->ic_enable |= mask; - ioc3_enable(port->ip_is, port->ip_idd, mask); - } -} - -/** - * local_open - local open a port - * @port: port to open - */ -static inline int local_open(struct ioc3_port *port) -{ - int spiniter = 0; - - port->ip_flags = INPUT_ENABLE; - - /* Pause the DMA interface if necessary */ - if (port->ip_sscr & SSCR_DMA_EN) { - writel(port->ip_sscr | SSCR_DMA_PAUSE, - &port->ip_serial_regs->sscr); - while ((readl(&port->ip_serial_regs->sscr) - & SSCR_PAUSE_STATE) == 0) { - spiniter++; - if (spiniter > MAXITER) { - NOT_PROGRESS(); - return -1; - } - } - } - - /* Reset the input fifo. If the uart received chars while the port - * was closed and DMA is not enabled, the uart may have a bunch of - * chars hanging around in its rx fifo which will not be discarded - * by rclr in the upper layer. We must get rid of them here. - */ - writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR, - &port->ip_uart_regs->iu_fcr); - - writeb(UART_LCR_WLEN8, &port->ip_uart_regs->iu_lcr); - /* UART_LCR_STOP == 1 stop */ - - /* Re-enable DMA, set default threshold to intr whenever there is - * data available. - */ - port->ip_sscr &= ~SSCR_RX_THRESHOLD; - port->ip_sscr |= 1; /* default threshold */ - - /* Plug in the new sscr. This implicitly clears the DMA_PAUSE - * flag if it was set above - */ - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - port->ip_tx_lowat = 1; - return 0; -} - -/** - * set_rx_timeout - Set rx timeout and threshold values. - * @port: port to use - * @timeout: timeout value in ticks - */ -static inline int set_rx_timeout(struct ioc3_port *port, int timeout) -{ - int threshold; - - port->ip_rx_timeout = timeout; - - /* Timeout is in ticks. Let's figure out how many chars we - * can receive at the current baud rate in that interval - * and set the rx threshold to that amount. There are 4 chars - * per ring entry, so we'll divide the number of chars that will - * arrive in timeout by 4. - * So .... timeout * baud / 10 / HZ / 4, with HZ = 100. - */ - threshold = timeout * port->ip_baud / 4000; - if (threshold == 0) - threshold = 1; /* otherwise we'll intr all the time! */ - - if ((unsigned)threshold > (unsigned)SSCR_RX_THRESHOLD) - return 1; - - port->ip_sscr &= ~SSCR_RX_THRESHOLD; - port->ip_sscr |= threshold; - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - - /* Now set the rx timeout to the given value - * again timeout * SRTR_HZ / HZ - */ - timeout = timeout * SRTR_HZ / 100; - if (timeout > SRTR_CNT) - timeout = SRTR_CNT; - writel(timeout, &port->ip_serial_regs->srtr); - return 0; -} - -/** - * config_port - config the hardware - * @port: port to config - * @baud: baud rate for the port - * @byte_size: data size - * @stop_bits: number of stop bits - * @parenb: parity enable ? - * @parodd: odd parity ? - */ -static inline int -config_port(struct ioc3_port *port, - int baud, int byte_size, int stop_bits, int parenb, int parodd) -{ - char lcr, sizebits; - int spiniter = 0; - - DPRINT_CONFIG(("%s: line %d baud %d byte_size %d stop %d parenb %d " - "parodd %d\n", - __FUNCTION__, ((struct uart_port *)port->ip_port)->line, - baud, byte_size, stop_bits, parenb, parodd)); - - if (set_baud(port, baud)) - return 1; - - switch (byte_size) { - case 5: - sizebits = UART_LCR_WLEN5; - break; - case 6: - sizebits = UART_LCR_WLEN6; - break; - case 7: - sizebits = UART_LCR_WLEN7; - break; - case 8: - sizebits = UART_LCR_WLEN8; - break; - default: - return 1; - } - - /* Pause the DMA interface if necessary */ - if (port->ip_sscr & SSCR_DMA_EN) { - writel(port->ip_sscr | SSCR_DMA_PAUSE, - &port->ip_serial_regs->sscr); - while ((readl(&port->ip_serial_regs->sscr) - & SSCR_PAUSE_STATE) == 0) { - spiniter++; - if (spiniter > MAXITER) - return -1; - } - } - - /* Clear relevant fields in lcr */ - lcr = readb(&port->ip_uart_regs->iu_lcr); - lcr &= ~(LCR_MASK_BITS_CHAR | UART_LCR_EPAR | - UART_LCR_PARITY | LCR_MASK_STOP_BITS); - - /* Set byte size in lcr */ - lcr |= sizebits; - - /* Set parity */ - if (parenb) { - lcr |= UART_LCR_PARITY; - if (!parodd) - lcr |= UART_LCR_EPAR; - } - - /* Set stop bits */ - if (stop_bits) - lcr |= UART_LCR_STOP /* 2 stop bits */ ; - - writeb(lcr, &port->ip_uart_regs->iu_lcr); - - /* Re-enable the DMA interface if necessary */ - if (port->ip_sscr & SSCR_DMA_EN) { - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - } - port->ip_baud = baud; - - /* When we get within this number of ring entries of filling the - * entire ring on tx, place an EXPLICIT intr to generate a lowat - * notification when output has drained. - */ - port->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4; - if (port->ip_tx_lowat == 0) - port->ip_tx_lowat = 1; - - set_rx_timeout(port, 2); - return 0; -} - -/** - * do_write - Write bytes to the port. Returns the number of bytes - * actually written. Called from transmit_chars - * @port: port to use - * @buf: the stuff to write - * @len: how many bytes in 'buf' - */ -static inline int do_write(struct ioc3_port *port, char *buf, int len) -{ - int prod_ptr, cons_ptr, total = 0; - struct ring *outring; - struct ring_entry *entry; - struct port_hooks *hooks = port->ip_hooks; - - BUG_ON(!(len >= 0)); - - prod_ptr = port->ip_tx_prod; - cons_ptr = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK; - outring = port->ip_outring; - - /* Maintain a 1-entry red-zone. The ring buffer is full when - * (cons - prod) % ring_size is 1. Rather than do this subtraction - * in the body of the loop, I'll do it now. - */ - cons_ptr = (cons_ptr - (int)sizeof(struct ring_entry)) & PROD_CONS_MASK; - - /* Stuff the bytes into the output */ - while ((prod_ptr != cons_ptr) && (len > 0)) { - int xx; - - /* Get 4 bytes (one ring entry) at a time */ - entry = (struct ring_entry *)((caddr_t) outring + prod_ptr); - - /* Invalidate all entries */ - entry->ring_allsc = 0; - - /* Copy in some bytes */ - for (xx = 0; (xx < 4) && (len > 0); xx++) { - entry->ring_data[xx] = *buf++; - entry->ring_sc[xx] = TXCB_VALID; - len--; - total++; - } - - /* If we are within some small threshold of filling up the - * entire ring buffer, we must place an EXPLICIT intr here - * to generate a lowat interrupt in case we subsequently - * really do fill up the ring and the caller goes to sleep. - * No need to place more than one though. - */ - if (!(port->ip_flags & LOWAT_WRITTEN) && - ((cons_ptr - prod_ptr) & PROD_CONS_MASK) - <= port->ip_tx_lowat * (int)sizeof(struct ring_entry)) { - port->ip_flags |= LOWAT_WRITTEN; - entry->ring_sc[0] |= TXCB_INT_WHEN_DONE; - } - - /* Go on to next entry */ - prod_ptr += sizeof(struct ring_entry); - prod_ptr &= PROD_CONS_MASK; - } - - /* If we sent something, start DMA if necessary */ - if (total > 0 && !(port->ip_sscr & SSCR_DMA_EN)) { - port->ip_sscr |= SSCR_DMA_EN; - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - } - - /* Store the new producer pointer. If tx is disabled, we stuff the - * data into the ring buffer, but we don't actually start tx. - */ - if (!uart_tx_stopped(port->ip_port)) { - writel(prod_ptr, &port->ip_serial_regs->stpir); - - /* If we are now transmitting, enable tx_mt interrupt so we - * can disable DMA if necessary when the tx finishes. - */ - if (total > 0) - enable_intrs(port, hooks->intr_tx_mt); - } - port->ip_tx_prod = prod_ptr; - - return total; -} - -/** - * disable_intrs - disable interrupts - * @port: port to enable - * @mask: mask to use - */ -static inline void disable_intrs(struct ioc3_port *port, uint32_t mask) -{ - if (port->ip_card->ic_enable & mask) { - ioc3_disable(port->ip_is, port->ip_idd, mask); - port->ip_card->ic_enable &= ~mask; - } -} - -/** - * set_notification - Modify event notification - * @port: port to use - * @mask: events mask - * @set_on: set ? - */ -static int set_notification(struct ioc3_port *port, int mask, int set_on) -{ - struct port_hooks *hooks = port->ip_hooks; - uint32_t intrbits, sscrbits; - - BUG_ON(!mask); - - intrbits = sscrbits = 0; - - if (mask & N_DATA_READY) - intrbits |= (hooks->intr_rx_timer | hooks->intr_rx_high); - if (mask & N_OUTPUT_LOWAT) - intrbits |= hooks->intr_tx_explicit; - if (mask & N_DDCD) { - intrbits |= hooks->intr_delta_dcd; - sscrbits |= SSCR_RX_RING_DCD; - } - if (mask & N_DCTS) - intrbits |= hooks->intr_delta_cts; - - if (set_on) { - enable_intrs(port, intrbits); - port->ip_notify |= mask; - port->ip_sscr |= sscrbits; - } else { - disable_intrs(port, intrbits); - port->ip_notify &= ~mask; - port->ip_sscr &= ~sscrbits; - } - - /* We require DMA if either DATA_READY or DDCD notification is - * currently requested. If neither of these is requested and - * there is currently no tx in progress, DMA may be disabled. - */ - if (port->ip_notify & (N_DATA_READY | N_DDCD)) - port->ip_sscr |= SSCR_DMA_EN; - else if (!(port->ip_card->ic_enable & hooks->intr_tx_mt)) - port->ip_sscr &= ~SSCR_DMA_EN; - - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - return 0; -} - -/** - * set_mcr - set the master control reg - * @the_port: port to use - * @mask1: mcr mask - * @mask2: shadow mask - */ -static inline int set_mcr(struct uart_port *the_port, - int mask1, int mask2) -{ - struct ioc3_port *port = get_ioc3_port(the_port); - uint32_t shadow; - int spiniter = 0; - char mcr; - - if (!port) - return -1; - - /* Pause the DMA interface if necessary */ - if (port->ip_sscr & SSCR_DMA_EN) { - writel(port->ip_sscr | SSCR_DMA_PAUSE, - &port->ip_serial_regs->sscr); - while ((readl(&port->ip_serial_regs->sscr) - & SSCR_PAUSE_STATE) == 0) { - spiniter++; - if (spiniter > MAXITER) - return -1; - } - } - shadow = readl(&port->ip_serial_regs->shadow); - mcr = (shadow & 0xff000000) >> 24; - - /* Set new value */ - mcr |= mask1; - shadow |= mask2; - writeb(mcr, &port->ip_uart_regs->iu_mcr); - writel(shadow, &port->ip_serial_regs->shadow); - - /* Re-enable the DMA interface if necessary */ - if (port->ip_sscr & SSCR_DMA_EN) { - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - } - return 0; -} - -/** - * ioc3_set_proto - set the protocol for the port - * @port: port to use - * @proto: protocol to use - */ -static int ioc3_set_proto(struct ioc3_port *port, int proto) -{ - struct port_hooks *hooks = port->ip_hooks; - - switch (proto) { - default: - case PROTO_RS232: - /* Clear the appropriate GIO pin */ - DPRINT_CONFIG(("%s: rs232\n", __FUNCTION__)); - writel(0, (&port->ip_idd->vma->gppr[0] - + hooks->rs422_select_pin)); - break; - - case PROTO_RS422: - /* Set the appropriate GIO pin */ - DPRINT_CONFIG(("%s: rs422\n", __FUNCTION__)); - writel(1, (&port->ip_idd->vma->gppr[0] - + hooks->rs422_select_pin)); - break; - } - return 0; -} - -/** - * transmit_chars - upper level write, called with the_port->lock - * @the_port: port to write - */ -static void transmit_chars(struct uart_port *the_port) -{ - int xmit_count, tail, head; - int result; - char *start; - struct tty_struct *tty; - struct ioc3_port *port = get_ioc3_port(the_port); - struct uart_info *info; - - if (!the_port) - return; - if (!port) - return; - - info = the_port->info; - tty = info->tty; - - if (uart_circ_empty(&info->xmit) || uart_tx_stopped(the_port)) { - /* Nothing to do or hw stopped */ - set_notification(port, N_ALL_OUTPUT, 0); - return; - } - - head = info->xmit.head; - tail = info->xmit.tail; - start = (char *)&info->xmit.buf[tail]; - - /* write out all the data or until the end of the buffer */ - xmit_count = (head < tail) ? (UART_XMIT_SIZE - tail) : (head - tail); - if (xmit_count > 0) { - result = do_write(port, start, xmit_count); - if (result > 0) { - /* booking */ - xmit_count -= result; - the_port->icount.tx += result; - /* advance the pointers */ - tail += result; - tail &= UART_XMIT_SIZE - 1; - info->xmit.tail = tail; - start = (char *)&info->xmit.buf[tail]; - } - } - if (uart_circ_chars_pending(&info->xmit) < WAKEUP_CHARS) - uart_write_wakeup(the_port); - - if (uart_circ_empty(&info->xmit)) { - set_notification(port, N_OUTPUT_LOWAT, 0); - } else { - set_notification(port, N_OUTPUT_LOWAT, 1); - } -} - -/** - * ioc3_change_speed - change the speed of the port - * @the_port: port to change - * @new_termios: new termios settings - * @old_termios: old termios settings - */ -static void -ioc3_change_speed(struct uart_port *the_port, - struct termios *new_termios, struct termios *old_termios) -{ - struct ioc3_port *port = get_ioc3_port(the_port); - unsigned int cflag; - int baud; - int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; - struct uart_info *info = the_port->info; - - cflag = new_termios->c_cflag; - - switch (cflag & CSIZE) { - case CS5: - new_data = 5; - break; - case CS6: - new_data = 6; - break; - case CS7: - new_data = 7; - break; - case CS8: - new_data = 8; - break; - default: - /* cuz we always need a default ... */ - new_data = 5; - break; - } - if (cflag & CSTOPB) { - new_stop = 1; - } - if (cflag & PARENB) { - new_parity_enable = 1; - if (cflag & PARODD) - new_parity = 1; - } - baud = uart_get_baud_rate(the_port, new_termios, old_termios, - MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED); - DPRINT_CONFIG(("%s: returned baud %d for line %d\n", __FUNCTION__, baud, - the_port->line)); - - if (!the_port->fifosize) - the_port->fifosize = FIFO_SIZE; - uart_update_timeout(the_port, cflag, baud); - - the_port->ignore_status_mask = N_ALL_INPUT; - - info->tty->low_latency = 1; - - if (I_IGNPAR(info->tty)) - the_port->ignore_status_mask &= ~(N_PARITY_ERROR - | N_FRAMING_ERROR); - if (I_IGNBRK(info->tty)) { - the_port->ignore_status_mask &= ~N_BREAK; - if (I_IGNPAR(info->tty)) - the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; - } - if (!(cflag & CREAD)) { - /* ignore everything */ - the_port->ignore_status_mask &= ~N_DATA_READY; - } - - if (cflag & CRTSCTS) { - /* enable hardware flow control */ - port->ip_sscr |= SSCR_HFC_EN; - } - else { - /* disable hardware flow control */ - port->ip_sscr &= ~SSCR_HFC_EN; - } - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - - /* Set the configuration and proper notification call */ - DPRINT_CONFIG(("%s : port 0x%p line %d cflag 0%o " - "config_port(baud %d data %d stop %d penable %d " - " parity %d), notification 0x%x\n", - __FUNCTION__, (void *)port, the_port->line, cflag, baud, - new_data, new_stop, new_parity_enable, new_parity, - the_port->ignore_status_mask)); - - if ((config_port(port, baud, /* baud */ - new_data, /* byte size */ - new_stop, /* stop bits */ - new_parity_enable, /* set parity */ - new_parity)) >= 0) { /* parity 1==odd */ - set_notification(port, the_port->ignore_status_mask, 1); - } -} - -/** - * ic3_startup_local - Start up the serial port - returns >= 0 if no errors - * @the_port: Port to operate on - */ -static inline int ic3_startup_local(struct uart_port *the_port) -{ - struct ioc3_port *port; - - if (!the_port) { - NOT_PROGRESS(); - return -1; - } - - port = get_ioc3_port(the_port); - if (!port) { - NOT_PROGRESS(); - return -1; - } - - local_open(port); - - /* set the protocol */ - ioc3_set_proto(port, IS_RS232(the_port->line) ? PROTO_RS232 : - PROTO_RS422); - return 0; -} - -/* - * ioc3_cb_output_lowat - called when the output low water mark is hit - * @port: port to output - */ -static void ioc3_cb_output_lowat(struct ioc3_port *port) -{ - unsigned long pflags; - - /* the_port->lock is set on the call here */ - if (port->ip_port) { - spin_lock_irqsave(&port->ip_port->lock, pflags); - transmit_chars(port->ip_port); - spin_unlock_irqrestore(&port->ip_port->lock, pflags); - } -} - -/* - * ioc3_cb_post_ncs - called for some basic errors - * @port: port to use - * @ncs: event - */ -static void ioc3_cb_post_ncs(struct uart_port *the_port, int ncs) -{ - struct uart_icount *icount; - - icount = &the_port->icount; - - if (ncs & NCS_BREAK) - icount->brk++; - if (ncs & NCS_FRAMING) - icount->frame++; - if (ncs & NCS_OVERRUN) - icount->overrun++; - if (ncs & NCS_PARITY) - icount->parity++; -} - -/** - * do_read - Read in bytes from the port. Return the number of bytes - * actually read. - * @the_port: port to use - * @buf: place to put the stuff we read - * @len: how big 'buf' is - */ - -static inline int do_read(struct uart_port *the_port, char *buf, int len) -{ - int prod_ptr, cons_ptr, total; - struct ioc3_port *port = get_ioc3_port(the_port); - struct ring *inring; - struct ring_entry *entry; - struct port_hooks *hooks = port->ip_hooks; - int byte_num; - char *sc; - int loop_counter; - - BUG_ON(!(len >= 0)); - BUG_ON(!port); - - /* There is a nasty timing issue in the IOC3. When the rx_timer - * expires or the rx_high condition arises, we take an interrupt. - * At some point while servicing the interrupt, we read bytes from - * the ring buffer and re-arm the rx_timer. However the rx_timer is - * not started until the first byte is received *after* it is armed, - * and any bytes pending in the rx construction buffers are not drained - * to memory until either there are 4 bytes available or the rx_timer - * expires. This leads to a potential situation where data is left - * in the construction buffers forever - 1 to 3 bytes were received - * after the interrupt was generated but before the rx_timer was - * re-armed. At that point as long as no subsequent bytes are received - * the timer will never be started and the bytes will remain in the - * construction buffer forever. The solution is to execute a DRAIN - * command after rearming the timer. This way any bytes received before - * the DRAIN will be drained to memory, and any bytes received after - * the DRAIN will start the TIMER and be drained when it expires. - * Luckily, this only needs to be done when the DMA buffer is empty - * since there is no requirement that this function return all - * available data as long as it returns some. - */ - /* Re-arm the timer */ - - writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir); - - prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; - cons_ptr = port->ip_rx_cons; - - if (prod_ptr == cons_ptr) { - int reset_dma = 0; - - /* Input buffer appears empty, do a flush. */ - - /* DMA must be enabled for this to work. */ - if (!(port->ip_sscr & SSCR_DMA_EN)) { - port->ip_sscr |= SSCR_DMA_EN; - reset_dma = 1; - } - - /* Potential race condition: we must reload the srpir after - * issuing the drain command, otherwise we could think the rx - * buffer is empty, then take a very long interrupt, and when - * we come back it's full and we wait forever for the drain to - * complete. - */ - writel(port->ip_sscr | SSCR_RX_DRAIN, - &port->ip_serial_regs->sscr); - prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; - - /* We must not wait for the DRAIN to complete unless there are - * at least 8 bytes (2 ring entries) available to receive the - * data otherwise the DRAIN will never complete and we'll - * deadlock here. - * In fact, to make things easier, I'll just ignore the flush if - * there is any data at all now available. - */ - if (prod_ptr == cons_ptr) { - loop_counter = 0; - while (readl(&port->ip_serial_regs->sscr) & - SSCR_RX_DRAIN) { - loop_counter++; - if (loop_counter > MAXITER) - return -1; - } - - /* SIGH. We have to reload the prod_ptr *again* since - * the drain may have caused it to change - */ - prod_ptr = readl(&port->ip_serial_regs->srpir) - & PROD_CONS_MASK; - } - if (reset_dma) { - port->ip_sscr &= ~SSCR_DMA_EN; - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - } - } - inring = port->ip_inring; - port->ip_flags &= ~READ_ABORTED; - - total = 0; - loop_counter = 0xfffff; /* to avoid hangs */ - - /* Grab bytes from the hardware */ - while ((prod_ptr != cons_ptr) && (len > 0)) { - entry = (struct ring_entry *)((caddr_t) inring + cons_ptr); - - if (loop_counter-- <= 0) { - printk(KERN_WARNING "IOC3 serial: " - "possible hang condition/" - "port stuck on read (line %d).\n", - the_port->line); - break; - } - - /* According to the producer pointer, this ring entry - * must contain some data. But if the PIO happened faster - * than the DMA, the data may not be available yet, so let's - * wait until it arrives. - */ - if ((entry->ring_allsc & RING_ANY_VALID) == 0) { - /* Indicate the read is aborted so we don't disable - * the interrupt thinking that the consumer is - * congested. - */ - port->ip_flags |= READ_ABORTED; - len = 0; - break; - } - - /* Load the bytes/status out of the ring entry */ - for (byte_num = 0; byte_num < 4 && len > 0; byte_num++) { - sc = &(entry->ring_sc[byte_num]); - - /* Check for change in modem state or overrun */ - if ((*sc & RXSB_MODEM_VALID) - && (port->ip_notify & N_DDCD)) { - /* Notify upper layer if DCD dropped */ - if ((port->ip_flags & DCD_ON) - && !(*sc & RXSB_DCD)) { - /* If we have already copied some data, - * return it. We'll pick up the carrier - * drop on the next pass. That way we - * don't throw away the data that has - * already been copied back to - * the caller's buffer. - */ - if (total > 0) { - len = 0; - break; - } - port->ip_flags &= ~DCD_ON; - - /* Turn off this notification so the - * carrier drop protocol won't see it - * again when it does a read. - */ - *sc &= ~RXSB_MODEM_VALID; - - /* To keep things consistent, we need - * to update the consumer pointer so - * the next reader won't come in and - * try to read the same ring entries - * again. This must be done here before - * the dcd change. - */ - - if ((entry->ring_allsc & RING_ANY_VALID) - == 0) { - cons_ptr += (int)sizeof - (struct ring_entry); - cons_ptr &= PROD_CONS_MASK; - } - writel(cons_ptr, - &port->ip_serial_regs->srcir); - port->ip_rx_cons = cons_ptr; - - /* Notify upper layer of carrier drop */ - if ((port->ip_notify & N_DDCD) - && port->ip_port) { - uart_handle_dcd_change - (port->ip_port, 0); - wake_up_interruptible - (&the_port->info-> - delta_msr_wait); - } - - /* If we had any data to return, we - * would have returned it above. - */ - return 0; - } - } - if (*sc & RXSB_MODEM_VALID) { - /* Notify that an input overrun occurred */ - if ((*sc & RXSB_OVERRUN) - && (port->ip_notify & N_OVERRUN_ERROR)) { - ioc3_cb_post_ncs(the_port, NCS_OVERRUN); - } - /* Don't look at this byte again */ - *sc &= ~RXSB_MODEM_VALID; - } - - /* Check for valid data or RX errors */ - if ((*sc & RXSB_DATA_VALID) && - ((*sc & (RXSB_PAR_ERR - | RXSB_FRAME_ERR | RXSB_BREAK)) - && (port->ip_notify & (N_PARITY_ERROR - | N_FRAMING_ERROR - | N_BREAK)))) { - /* There is an error condition on the next byte. - * If we have already transferred some bytes, - * we'll stop here. Otherwise if this is the - * first byte to be read, we'll just transfer - * it alone after notifying the - * upper layer of its status. - */ - if (total > 0) { - len = 0; - break; - } else { - if ((*sc & RXSB_PAR_ERR) && - (port-> - ip_notify & N_PARITY_ERROR)) { - ioc3_cb_post_ncs(the_port, - NCS_PARITY); - } - if ((*sc & RXSB_FRAME_ERR) && - (port-> - ip_notify & N_FRAMING_ERROR)) { - ioc3_cb_post_ncs(the_port, - NCS_FRAMING); - } - if ((*sc & RXSB_BREAK) - && (port->ip_notify & N_BREAK)) { - ioc3_cb_post_ncs - (the_port, NCS_BREAK); - } - len = 1; - } - } - if (*sc & RXSB_DATA_VALID) { - *sc &= ~RXSB_DATA_VALID; - *buf = entry->ring_data[byte_num]; - buf++; - len--; - total++; - } - } - - /* If we used up this entry entirely, go on to the next one, - * otherwise we must have run out of buffer space, so - * leave the consumer pointer here for the next read in case - * there are still unread bytes in this entry. - */ - if ((entry->ring_allsc & RING_ANY_VALID) == 0) { - cons_ptr += (int)sizeof(struct ring_entry); - cons_ptr &= PROD_CONS_MASK; - } - } - - /* Update consumer pointer and re-arm rx timer interrupt */ - writel(cons_ptr, &port->ip_serial_regs->srcir); - port->ip_rx_cons = cons_ptr; - - /* If we have now dipped below the rx high water mark and we have - * rx_high interrupt turned off, we can now turn it back on again. - */ - if ((port->ip_flags & INPUT_HIGH) && (((prod_ptr - cons_ptr) - & PROD_CONS_MASK) < - ((port-> - ip_sscr & - SSCR_RX_THRESHOLD) - << PROD_CONS_PTR_OFF))) { - port->ip_flags &= ~INPUT_HIGH; - enable_intrs(port, hooks->intr_rx_high); - } - return total; -} - -/** - * receive_chars - upper level read. - * @the_port: port to read from - */ -static int receive_chars(struct uart_port *the_port) -{ - struct tty_struct *tty; - unsigned char ch[MAX_CHARS]; - int read_count = 0, read_room, flip = 0; - struct uart_info *info = the_port->info; - struct ioc3_port *port = get_ioc3_port(the_port); - unsigned long pflags; - - /* Make sure all the pointers are "good" ones */ - if (!info) - return 0; - if (!info->tty) - return 0; - - if (!(port->ip_flags & INPUT_ENABLE)) - return 0; - - spin_lock_irqsave(&the_port->lock, pflags); - tty = info->tty; - - read_count = do_read(the_port, ch, MAX_CHARS); - if (read_count > 0) { - flip = 1; - read_room = tty_buffer_request_room(tty, read_count); - tty_insert_flip_string(tty, ch, read_room); - the_port->icount.rx += read_count; - } - spin_unlock_irqrestore(&the_port->lock, pflags); - - if (flip) - tty_flip_buffer_push(tty); - - return read_count; -} - -/** - * ioc3uart_intr_one - lowest level (per port) interrupt handler. - * @is : submodule - * @idd: driver data - * @pending: interrupts to handle - * @regs: pt_regs - */ - -static int inline -ioc3uart_intr_one(struct ioc3_submodule *is, - struct ioc3_driver_data *idd, - unsigned int pending, struct pt_regs *regs) -{ - int port_num = GET_PORT_FROM_SIO_IR(pending); - struct port_hooks *hooks; - unsigned int rx_high_rd_aborted = 0; - unsigned long flags; - struct uart_port *the_port; - struct ioc3_port *port; - int loop_counter; - struct ioc3_card *card_ptr; - unsigned int sio_ir; - - card_ptr = idd->data[is->id]; - port = card_ptr->ic_port[port_num].icp_port; - hooks = port->ip_hooks; - - /* Possible race condition here: The tx_mt interrupt bit may be - * cleared without the intervention of the interrupt handler, - * e.g. by a write. If the top level interrupt handler reads a - * tx_mt, then some other processor does a write, starting up - * output, then we come in here, see the tx_mt and stop DMA, the - * output started by the other processor will hang. Thus we can - * only rely on tx_mt being legitimate if it is read while the - * port lock is held. Therefore this bit must be ignored in the - * passed in interrupt mask which was read by the top level - * interrupt handler since the port lock was not held at the time - * it was read. We can only rely on this bit being accurate if it - * is read while the port lock is held. So we'll clear it for now, - * and reload it later once we have the port lock. - */ - - sio_ir = pending & ~(hooks->intr_tx_mt); - spin_lock_irqsave(&port->ip_lock, flags); - - loop_counter = MAXITER; /* to avoid hangs */ - - do { - uint32_t shadow; - - if (loop_counter-- <= 0) { - printk(KERN_WARNING "IOC3 serial: " - "possible hang condition/" - "port stuck on interrupt (line %d).\n", - ((struct uart_port *)port->ip_port)->line); - break; - } - /* Handle a DCD change */ - if (sio_ir & hooks->intr_delta_dcd) { - ioc3_ack(is, idd, hooks->intr_delta_dcd); - shadow = readl(&port->ip_serial_regs->shadow); - - if ((port->ip_notify & N_DDCD) - && (shadow & SHADOW_DCD) - && (port->ip_port)) { - the_port = port->ip_port; - uart_handle_dcd_change(the_port, - shadow & SHADOW_DCD); - wake_up_interruptible - (&the_port->info->delta_msr_wait); - } else if ((port->ip_notify & N_DDCD) - && !(shadow & SHADOW_DCD)) { - /* Flag delta DCD/no DCD */ - uart_handle_dcd_change(port->ip_port, - shadow & SHADOW_DCD); - port->ip_flags |= DCD_ON; - } - } - - /* Handle a CTS change */ - if (sio_ir & hooks->intr_delta_cts) { - ioc3_ack(is, idd, hooks->intr_delta_cts); - shadow = readl(&port->ip_serial_regs->shadow); - - if ((port->ip_notify & N_DCTS) && (port->ip_port)) { - the_port = port->ip_port; - uart_handle_cts_change(the_port, shadow - & SHADOW_CTS); - wake_up_interruptible - (&the_port->info->delta_msr_wait); - } - } - - /* rx timeout interrupt. Must be some data available. Put this - * before the check for rx_high since servicing this condition - * may cause that condition to clear. - */ - if (sio_ir & hooks->intr_rx_timer) { - ioc3_ack(is, idd, hooks->intr_rx_timer); - if ((port->ip_notify & N_DATA_READY) - && (port->ip_port)) { - receive_chars(port->ip_port); - } - } - - /* rx high interrupt. Must be after rx_timer. */ - else if (sio_ir & hooks->intr_rx_high) { - /* Data available, notify upper layer */ - if ((port->ip_notify & N_DATA_READY) && port->ip_port) { - receive_chars(port->ip_port); - } - - /* We can't ACK this interrupt. If receive_chars didn't - * cause the condition to clear, we'll have to disable - * the interrupt until the data is drained. - * If the read was aborted, don't disable the interrupt - * as this may cause us to hang indefinitely. An - * aborted read generally means that this interrupt - * hasn't been delivered to the cpu yet anyway, even - * though we see it as asserted when we read the sio_ir. - */ - if ((sio_ir = PENDING(card_ptr, idd)) - & hooks->intr_rx_high) { - if (port->ip_flags & READ_ABORTED) { - rx_high_rd_aborted++; - } - else { - card_ptr->ic_enable &= ~hooks->intr_rx_high; - port->ip_flags |= INPUT_HIGH; - } - } - } - - /* We got a low water interrupt: notify upper layer to - * send more data. Must come before tx_mt since servicing - * this condition may cause that condition to clear. - */ - if (sio_ir & hooks->intr_tx_explicit) { - port->ip_flags &= ~LOWAT_WRITTEN; - ioc3_ack(is, idd, hooks->intr_tx_explicit); - if (port->ip_notify & N_OUTPUT_LOWAT) - ioc3_cb_output_lowat(port); - } - - /* Handle tx_mt. Must come after tx_explicit. */ - else if (sio_ir & hooks->intr_tx_mt) { - /* If we are expecting a lowat notification - * and we get to this point it probably means that for - * some reason the tx_explicit didn't work as expected - * (that can legitimately happen if the output buffer is - * filled up in just the right way). - * So send the notification now. - */ - if (port->ip_notify & N_OUTPUT_LOWAT) { - ioc3_cb_output_lowat(port); - - /* We need to reload the sio_ir since the lowat - * call may have caused another write to occur, - * clearing the tx_mt condition. - */ - sio_ir = PENDING(card_ptr, idd); - } - - /* If the tx_mt condition still persists even after the - * lowat call, we've got some work to do. - */ - if (sio_ir & hooks->intr_tx_mt) { - /* If we are not currently expecting DMA input, - * and the transmitter has just gone idle, - * there is no longer any reason for DMA, so - * disable it. - */ - if (!(port->ip_notify - & (N_DATA_READY | N_DDCD))) { - BUG_ON(!(port->ip_sscr - & SSCR_DMA_EN)); - port->ip_sscr &= ~SSCR_DMA_EN; - writel(port->ip_sscr, - &port->ip_serial_regs->sscr); - } - /* Prevent infinite tx_mt interrupt */ - card_ptr->ic_enable &= ~hooks->intr_tx_mt; - } - } - sio_ir = PENDING(card_ptr, idd); - - /* if the read was aborted and only hooks->intr_rx_high, - * clear hooks->intr_rx_high, so we do not loop forever. - */ - - if (rx_high_rd_aborted && (sio_ir == hooks->intr_rx_high)) { - sio_ir &= ~hooks->intr_rx_high; - } - } while (sio_ir & hooks->intr_all); - - spin_unlock_irqrestore(&port->ip_lock, flags); - ioc3_enable(is, idd, card_ptr->ic_enable); - return 0; -} - -/** - * ioc3uart_intr - field all serial interrupts - * @is : submodule - * @idd: driver data - * @pending: interrupts to handle - * @regs: pt_regs - * - */ - -static int ioc3uart_intr(struct ioc3_submodule *is, - struct ioc3_driver_data *idd, - unsigned int pending, struct pt_regs *regs) -{ - int ret = 0; - - /* - * The upper level interrupt handler sends interrupts for both ports - * here. So we need to call for each port with its interrupts. - */ - - if (pending & SIO_IR_SA) - ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SA, regs); - if (pending & SIO_IR_SB) - ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SB, regs); - - return ret; -} - -/** - * ic3_type - * @port: Port to operate with (we ignore since we only have one port) - * - */ -static const char *ic3_type(struct uart_port *the_port) -{ - if (IS_RS232(the_port->line)) - return "SGI IOC3 Serial [rs232]"; - else - return "SGI IOC3 Serial [rs422]"; -} - -/** - * ic3_tx_empty - Is the transmitter empty? - * @port: Port to operate on - * - */ -static unsigned int ic3_tx_empty(struct uart_port *the_port) -{ - unsigned int ret = 0; - struct ioc3_port *port = get_ioc3_port(the_port); - - if (readl(&port->ip_serial_regs->shadow) & SHADOW_TEMT) - ret = TIOCSER_TEMT; - return ret; -} - -/** - * ic3_stop_tx - stop the transmitter - * @port: Port to operate on - * - */ -static void ic3_stop_tx(struct uart_port *the_port) -{ - struct ioc3_port *port = get_ioc3_port(the_port); - - if (port) - set_notification(port, N_OUTPUT_LOWAT, 0); -} - -/** - * ic3_stop_rx - stop the receiver - * @port: Port to operate on - * - */ -static void ic3_stop_rx(struct uart_port *the_port) -{ - struct ioc3_port *port = get_ioc3_port(the_port); - - if (port) - port->ip_flags &= ~INPUT_ENABLE; -} - -/** - * null_void_function - * @port: Port to operate on - * - */ -static void null_void_function(struct uart_port *the_port) -{ -} - -/** - * ic3_shutdown - shut down the port - free irq and disable - * @port: port to shut down - * - */ -static void ic3_shutdown(struct uart_port *the_port) -{ - unsigned long port_flags; - struct ioc3_port *port; - struct uart_info *info; - - port = get_ioc3_port(the_port); - if (!port) - return; - - info = the_port->info; - wake_up_interruptible(&info->delta_msr_wait); - - spin_lock_irqsave(&the_port->lock, port_flags); - set_notification(port, N_ALL, 0); - spin_unlock_irqrestore(&the_port->lock, port_flags); -} - -/** - * ic3_set_mctrl - set control lines (dtr, rts, etc) - * @port: Port to operate on - * @mctrl: Lines to set/unset - * - */ -static void ic3_set_mctrl(struct uart_port *the_port, unsigned int mctrl) -{ - unsigned char mcr = 0; - - if (mctrl & TIOCM_RTS) - mcr |= UART_MCR_RTS; - if (mctrl & TIOCM_DTR) - mcr |= UART_MCR_DTR; - if (mctrl & TIOCM_OUT1) - mcr |= UART_MCR_OUT1; - if (mctrl & TIOCM_OUT2) - mcr |= UART_MCR_OUT2; - if (mctrl & TIOCM_LOOP) - mcr |= UART_MCR_LOOP; - - set_mcr(the_port, mcr, SHADOW_DTR); -} - -/** - * ic3_get_mctrl - get control line info - * @port: port to operate on - * - */ -static unsigned int ic3_get_mctrl(struct uart_port *the_port) -{ - struct ioc3_port *port = get_ioc3_port(the_port); - uint32_t shadow; - unsigned int ret = 0; - - if (!port) - return 0; - - shadow = readl(&port->ip_serial_regs->shadow); - if (shadow & SHADOW_DCD) - ret |= TIOCM_CD; - if (shadow & SHADOW_DR) - ret |= TIOCM_DSR; - if (shadow & SHADOW_CTS) - ret |= TIOCM_CTS; - return ret; -} - -/** - * ic3_start_tx - Start transmitter. Called with the_port->lock - * @port: Port to operate on - * - */ -static void ic3_start_tx(struct uart_port *the_port) -{ - struct ioc3_port *port = get_ioc3_port(the_port); - - if (port) { - set_notification(port, N_OUTPUT_LOWAT, 1); - enable_intrs(port, port->ip_hooks->intr_tx_mt); - } -} - -/** - * ic3_break_ctl - handle breaks - * @port: Port to operate on - * @break_state: Break state - * - */ -static void ic3_break_ctl(struct uart_port *the_port, int break_state) -{ -} - -/** - * ic3_startup - Start up the serial port - always return 0 (We're always on) - * @port: Port to operate on - * - */ -static int ic3_startup(struct uart_port *the_port) -{ - int retval; - struct ioc3_port *port; - struct ioc3_card *card_ptr; - unsigned long port_flags; - - if (!the_port) { - NOT_PROGRESS(); - return -ENODEV; - } - port = get_ioc3_port(the_port); - if (!port) { - NOT_PROGRESS(); - return -ENODEV; - } - card_ptr = port->ip_card; - port->ip_port = the_port; - - if (!card_ptr) { - NOT_PROGRESS(); - return -ENODEV; - } - - /* Start up the serial port */ - spin_lock_irqsave(&the_port->lock, port_flags); - retval = ic3_startup_local(the_port); - spin_unlock_irqrestore(&the_port->lock, port_flags); - return retval; -} - -/** - * ic3_set_termios - set termios stuff - * @port: port to operate on - * @termios: New settings - * @termios: Old - * - */ -static void -ic3_set_termios(struct uart_port *the_port, - struct termios *termios, struct termios *old_termios) -{ - unsigned long port_flags; - - spin_lock_irqsave(&the_port->lock, port_flags); - ioc3_change_speed(the_port, termios, old_termios); - spin_unlock_irqrestore(&the_port->lock, port_flags); -} - -/** - * ic3_request_port - allocate resources for port - no op.... - * @port: port to operate on - * - */ -static int ic3_request_port(struct uart_port *port) -{ - return 0; -} - -/* Associate the uart functions above - given to serial core */ -static struct uart_ops ioc3_ops = { - .tx_empty = ic3_tx_empty, - .set_mctrl = ic3_set_mctrl, - .get_mctrl = ic3_get_mctrl, - .stop_tx = ic3_stop_tx, - .start_tx = ic3_start_tx, - .stop_rx = ic3_stop_rx, - .enable_ms = null_void_function, - .break_ctl = ic3_break_ctl, - .startup = ic3_startup, - .shutdown = ic3_shutdown, - .set_termios = ic3_set_termios, - .type = ic3_type, - .release_port = null_void_function, - .request_port = ic3_request_port, -}; - -/* - * Boot-time initialization code - */ - -static struct uart_driver ioc3_uart = { - .owner = THIS_MODULE, - .driver_name = "ioc3_serial", - .dev_name = DEVICE_NAME, - .major = DEVICE_MAJOR, - .minor = DEVICE_MINOR, - .nr = MAX_LOGICAL_PORTS -}; - -/** - * ioc3_serial_core_attach - register with serial core - * This is done during pci probing - * @is: submodule struct for this - * @idd: handle for this card - */ -static inline int ioc3_serial_core_attach( struct ioc3_submodule *is, - struct ioc3_driver_data *idd) -{ - struct ioc3_port *port; - struct uart_port *the_port; - struct ioc3_card *card_ptr = idd->data[is->id]; - int ii, phys_port; - struct pci_dev *pdev = idd->pdev; - - DPRINT_CONFIG(("%s: attach pdev 0x%p - card_ptr 0x%p\n", - __FUNCTION__, pdev, (void *)card_ptr)); - - if (!card_ptr) - return -ENODEV; - - /* once around for each logical port on this card */ - for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) { - phys_port = GET_PHYSICAL_PORT(ii); - the_port = &card_ptr->ic_port[phys_port]. - icp_uart_port[GET_LOGICAL_PORT(ii)]; - port = card_ptr->ic_port[phys_port].icp_port; - port->ip_port = the_port; - - DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p [%d/%d]\n", - __FUNCTION__, (void *)the_port, (void *)port, - phys_port, ii)); - - /* membase, iobase and mapbase just need to be non-0 */ - the_port->membase = (unsigned char __iomem *)1; - the_port->iobase = (pdev->bus->number << 16) | ii; - the_port->line = (Num_of_ioc3_cards << 2) | ii; - the_port->mapbase = 1; - the_port->type = PORT_16550A; - the_port->fifosize = FIFO_SIZE; - the_port->ops = &ioc3_ops; - the_port->irq = idd->irq_io; - the_port->dev = &pdev->dev; - - if (uart_add_one_port(&ioc3_uart, the_port) < 0) { - printk(KERN_WARNING - "%s: unable to add port %d bus %d\n", - __FUNCTION__, the_port->line, pdev->bus->number); - } else { - DPRINT_CONFIG(("IOC3 serial port %d irq %d bus %d\n", - the_port->line, the_port->irq, pdev->bus->number)); - } - - /* all ports are rs232 for now */ - if (IS_PHYSICAL_PORT(ii)) - ioc3_set_proto(port, PROTO_RS232); - } - return 0; -} - -/** - * ioc3uart_remove - register detach function - * @is: submodule struct for this submodule - * @idd: ioc3 driver data for this submodule - */ - -static int ioc3uart_remove(struct ioc3_submodule *is, - struct ioc3_driver_data *idd) -{ - struct ioc3_card *card_ptr = idd->data[is->id]; - struct uart_port *the_port; - struct ioc3_port *port; - int ii; - - if (card_ptr) { - for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) { - the_port = &card_ptr->ic_port[GET_PHYSICAL_PORT(ii)]. - icp_uart_port[GET_LOGICAL_PORT(ii)]; - if (the_port) - uart_remove_one_port(&ioc3_uart, the_port); - port = card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].icp_port; - if (port && IS_PHYSICAL_PORT(ii) - && (GET_PHYSICAL_PORT(ii) == 0)) { - pci_free_consistent(port->ip_idd->pdev, - TOTAL_RING_BUF_SIZE, - (void *)port->ip_cpu_ringbuf, - port->ip_dma_ringbuf); - kfree(port); - card_ptr->ic_port[GET_PHYSICAL_PORT(ii)]. - icp_port = NULL; - } - } - kfree(card_ptr); - idd->data[is->id] = NULL; - } - return 0; -} - -/** - * ioc3uart_probe - card probe function called from shim driver - * @is: submodule struct for this submodule - * @idd: ioc3 driver data for this card - */ - -static int __devinit -ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) -{ - struct pci_dev *pdev = idd->pdev; - struct ioc3_card *card_ptr; - int ret = 0; - struct ioc3_port *port; - struct ioc3_port *ports[PORTS_PER_CARD]; - int phys_port; - - DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, is, idd)); - - card_ptr = kmalloc(sizeof(struct ioc3_card), GFP_KERNEL); - if (!card_ptr) { - printk(KERN_WARNING "ioc3_attach_one" - ": unable to get memory for the IOC3\n"); - return -ENOMEM; - } - memset(card_ptr, 0, sizeof(struct ioc3_card)); - idd->data[is->id] = card_ptr; - Submodule_slot = is->id; - - writel(((UARTA_BASE >> 3) << SIO_CR_SER_A_BASE_SHIFT) | - ((UARTB_BASE >> 3) << SIO_CR_SER_B_BASE_SHIFT) | - (0xf << SIO_CR_CMD_PULSE_SHIFT), &idd->vma->sio_cr); - - pci_write_config_dword(pdev, PCI_LAT, 0xff00); - - /* Enable serial port mode select generic PIO pins as outputs */ - ioc3_gpcr_set(idd, GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL); - - /* Create port structures for each port */ - for (phys_port = 0; phys_port < PORTS_PER_CARD; phys_port++) { - port = kmalloc(sizeof(struct ioc3_port), GFP_KERNEL); - if (!port) { - printk(KERN_WARNING - "IOC3 serial memory not available for port\n"); - goto out4; - } - memset(port, 0, sizeof(struct ioc3_port)); - spin_lock_init(&port->ip_lock); - - /* we need to remember the previous ones, to point back to - * them farther down - setting up the ring buffers. - */ - ports[phys_port] = port; - - /* init to something useful */ - card_ptr->ic_port[phys_port].icp_port = port; - port->ip_is = is; - port->ip_idd = idd; - port->ip_baud = 9600; - port->ip_card = card_ptr; - port->ip_hooks = &hooks_array[phys_port]; - - /* Setup each port */ - if (phys_port == 0) { - port->ip_serial_regs = &idd->vma->port_a; - port->ip_uart_regs = &idd->vma->sregs.uarta; - - DPRINT_CONFIG(("%s : Port A ip_serial_regs 0x%p " - "ip_uart_regs 0x%p\n", - __FUNCTION__, - (void *)port->ip_serial_regs, - (void *)port->ip_uart_regs)); - - /* setup ring buffers */ - port->ip_cpu_ringbuf = pci_alloc_consistent(pdev, - TOTAL_RING_BUF_SIZE, &port->ip_dma_ringbuf); - - BUG_ON(!((((int64_t) port->ip_dma_ringbuf) & - (TOTAL_RING_BUF_SIZE - 1)) == 0)); - port->ip_inring = RING(port, RX_A); - port->ip_outring = RING(port, TX_A); - DPRINT_CONFIG(("%s : Port A ip_cpu_ringbuf 0x%p " - "ip_dma_ringbuf 0x%p, ip_inring 0x%p " - "ip_outring 0x%p\n", - __FUNCTION__, - (void *)port->ip_cpu_ringbuf, - (void *)port->ip_dma_ringbuf, - (void *)port->ip_inring, - (void *)port->ip_outring)); - } - else { - port->ip_serial_regs = &idd->vma->port_b; - port->ip_uart_regs = &idd->vma->sregs.uartb; - - DPRINT_CONFIG(("%s : Port B ip_serial_regs 0x%p " - "ip_uart_regs 0x%p\n", - __FUNCTION__, - (void *)port->ip_serial_regs, - (void *)port->ip_uart_regs)); - - /* share the ring buffers */ - port->ip_dma_ringbuf = - ports[phys_port - 1]->ip_dma_ringbuf; - port->ip_cpu_ringbuf = - ports[phys_port - 1]->ip_cpu_ringbuf; - port->ip_inring = RING(port, RX_B); - port->ip_outring = RING(port, TX_B); - DPRINT_CONFIG(("%s : Port B ip_cpu_ringbuf 0x%p " - "ip_dma_ringbuf 0x%p, ip_inring 0x%p " - "ip_outring 0x%p\n", - __FUNCTION__, - (void *)port->ip_cpu_ringbuf, - (void *)port->ip_dma_ringbuf, - (void *)port->ip_inring, - (void *)port->ip_outring)); - } - - DPRINT_CONFIG(("%s : port %d [addr 0x%p] card_ptr 0x%p", - __FUNCTION__, - phys_port, (void *)port, (void *)card_ptr)); - DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n", - (void *)port->ip_serial_regs, - (void *)port->ip_uart_regs)); - - /* Initialize the hardware for IOC3 */ - port_init(port); - - DPRINT_CONFIG(("%s: phys_port %d port 0x%p inring 0x%p " - "outring 0x%p\n", - __FUNCTION__, - phys_port, (void *)port, - (void *)port->ip_inring, - (void *)port->ip_outring)); - - } - - /* register port with the serial core */ - - if ((ret = ioc3_serial_core_attach(is, idd))) - goto out4; - - Num_of_ioc3_cards++; - - return ret; - - /* error exits that give back resources */ -out4: - kfree(card_ptr); - return ret; -} - -static struct ioc3_submodule ioc3uart_submodule = { - .name = "IOC3uart", - .probe = ioc3uart_probe, - .remove = ioc3uart_remove, - /* call .intr for both ports initially */ - .irq_mask = SIO_IR_SA | SIO_IR_SB, - .intr = ioc3uart_intr, - .owner = THIS_MODULE, -}; - -/** - * ioc3_detect - module init called, - */ -static int __devinit ioc3uart_init(void) -{ - int ret; - - /* register with serial core */ - if ((ret = uart_register_driver(&ioc3_uart)) < 0) { - printk(KERN_WARNING - "%s: Couldn't register IOC3 uart serial driver\n", - __FUNCTION__); - return ret; - } - ret = ioc3_register_submodule(&ioc3uart_submodule); - if (ret) - uart_unregister_driver(&ioc3_uart); - return ret; -} - -static void __devexit ioc3uart_exit(void) -{ - ioc3_unregister_submodule(&ioc3uart_submodule); - uart_unregister_driver(&ioc3_uart); -} - -module_init(ioc3uart_init); -module_exit(ioc3uart_exit); - -MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) "); -MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC3 card"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/serial/pmac_zilog.c b/trunk/drivers/serial/pmac_zilog.c index 4e03a87f3fb4..5f52883e64d2 100644 --- a/trunk/drivers/serial/pmac_zilog.c +++ b/trunk/drivers/serial/pmac_zilog.c @@ -69,6 +69,7 @@ #include #include #include +#include #if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -1592,7 +1593,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state) state = pmz_uart_reg.state + uap->port.line; mutex_lock(&pmz_irq_mutex); - mutex_lock(&state->mutex); + down(&state->sem); spin_lock_irqsave(&uap->port.lock, flags); @@ -1623,7 +1624,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state) /* Shut the chip down */ pmz_set_scc_power(uap, 0); - mutex_unlock(&state->mutex); + up(&state->sem); mutex_unlock(&pmz_irq_mutex); pmz_debug("suspend, switching complete\n"); @@ -1652,7 +1653,7 @@ static int pmz_resume(struct macio_dev *mdev) state = pmz_uart_reg.state + uap->port.line; mutex_lock(&pmz_irq_mutex); - mutex_lock(&state->mutex); + down(&state->sem); spin_lock_irqsave(&uap->port.lock, flags); if (!ZS_IS_OPEN(uap) && !ZS_IS_CONS(uap)) { @@ -1684,7 +1685,7 @@ static int pmz_resume(struct macio_dev *mdev) } bail: - mutex_unlock(&state->mutex); + up(&state->sem); mutex_unlock(&pmz_irq_mutex); /* Right now, we deal with delay by blocking here, I'll be diff --git a/trunk/drivers/serial/serial_core.c b/trunk/drivers/serial/serial_core.c index 943770470b9d..2ca620900bcc 100644 --- a/trunk/drivers/serial/serial_core.c +++ b/trunk/drivers/serial/serial_core.c @@ -638,7 +638,7 @@ static int uart_set_info(struct uart_state *state, * module insertion/removal doesn't change anything * under us. */ - mutex_lock(&state->mutex); + down(&state->sem); change_irq = new_serial.irq != port->irq; @@ -797,7 +797,7 @@ static int uart_set_info(struct uart_state *state, } else retval = uart_startup(state, 1); exit: - mutex_unlock(&state->mutex); + up(&state->sem); return retval; } @@ -834,7 +834,7 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file) struct uart_port *port = state->port; int result = -EIO; - mutex_lock(&state->mutex); + down(&state->sem); if ((!file || !tty_hung_up_p(file)) && !(tty->flags & (1 << TTY_IO_ERROR))) { result = port->mctrl; @@ -843,7 +843,7 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file) result |= port->ops->get_mctrl(port); spin_unlock_irq(&port->lock); } - mutex_unlock(&state->mutex); + up(&state->sem); return result; } @@ -856,13 +856,13 @@ uart_tiocmset(struct tty_struct *tty, struct file *file, struct uart_port *port = state->port; int ret = -EIO; - mutex_lock(&state->mutex); + down(&state->sem); if ((!file || !tty_hung_up_p(file)) && !(tty->flags & (1 << TTY_IO_ERROR))) { uart_update_mctrl(port, set, clear); ret = 0; } - mutex_unlock(&state->mutex); + up(&state->sem); return ret; } @@ -873,12 +873,12 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state) BUG_ON(!kernel_locked()); - mutex_lock(&state->mutex); + down(&state->sem); if (port->type != PORT_UNKNOWN) port->ops->break_ctl(port, break_state); - mutex_unlock(&state->mutex); + up(&state->sem); } static int uart_do_autoconfig(struct uart_state *state) @@ -894,7 +894,7 @@ static int uart_do_autoconfig(struct uart_state *state) * changing, and hence any extra opens of the port while * we're auto-configuring. */ - if (mutex_lock_interruptible(&state->mutex)) + if (down_interruptible(&state->sem)) return -ERESTARTSYS; ret = -EBUSY; @@ -920,7 +920,7 @@ static int uart_do_autoconfig(struct uart_state *state) ret = uart_startup(state, 1); } - mutex_unlock(&state->mutex); + up(&state->sem); return ret; } @@ -1074,7 +1074,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, if (ret != -ENOIOCTLCMD) goto out; - mutex_lock(&state->mutex); + down(&state->sem); if (tty_hung_up_p(filp)) { ret = -EIO; @@ -1098,7 +1098,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, } } out_up: - mutex_unlock(&state->mutex); + up(&state->sem); out: return ret; } @@ -1186,7 +1186,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) DPRINTK("uart_close(%d) called\n", port->line); - mutex_lock(&state->mutex); + down(&state->sem); if (tty_hung_up_p(filp)) goto done; @@ -1260,7 +1260,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) wake_up_interruptible(&state->info->open_wait); done: - mutex_unlock(&state->mutex); + up(&state->sem); } static void uart_wait_until_sent(struct tty_struct *tty, int timeout) @@ -1334,7 +1334,7 @@ static void uart_hangup(struct tty_struct *tty) BUG_ON(!kernel_locked()); DPRINTK("uart_hangup(%d)\n", state->port->line); - mutex_lock(&state->mutex); + down(&state->sem); if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) { uart_flush_buffer(tty); uart_shutdown(state); @@ -1344,7 +1344,7 @@ static void uart_hangup(struct tty_struct *tty) wake_up_interruptible(&state->info->open_wait); wake_up_interruptible(&state->info->delta_msr_wait); } - mutex_unlock(&state->mutex); + up(&state->sem); } /* @@ -1447,9 +1447,9 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) if (mctrl & TIOCM_CAR) break; - mutex_unlock(&state->mutex); + up(&state->sem); schedule(); - mutex_lock(&state->mutex); + down(&state->sem); if (signal_pending(current)) break; @@ -1475,7 +1475,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) mutex_lock(&port_mutex); state = drv->state + line; - if (mutex_lock_interruptible(&state->mutex)) { + if (down_interruptible(&state->sem)) { state = ERR_PTR(-ERESTARTSYS); goto out; } @@ -1483,7 +1483,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) state->count++; if (!state->port) { state->count--; - mutex_unlock(&state->mutex); + up(&state->sem); state = ERR_PTR(-ENXIO); goto out; } @@ -1504,7 +1504,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) (unsigned long)state); } else { state->count--; - mutex_unlock(&state->mutex); + up(&state->sem); state = ERR_PTR(-ENOMEM); } } @@ -1571,7 +1571,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) if (tty_hung_up_p(filp)) { retval = -EAGAIN; state->count--; - mutex_unlock(&state->mutex); + up(&state->sem); goto fail; } @@ -1591,7 +1591,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) */ if (retval == 0) retval = uart_block_til_ready(filp, state); - mutex_unlock(&state->mutex); + up(&state->sem); /* * If this is the first open to succeed, adjust things to suit. @@ -1867,7 +1867,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) { struct uart_state *state = drv->state + port->line; - mutex_lock(&state->mutex); + down(&state->sem); if (state->info && state->info->flags & UIF_INITIALIZED) { struct uart_ops *ops = port->ops; @@ -1896,7 +1896,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) uart_change_pm(state, 3); - mutex_unlock(&state->mutex); + up(&state->sem); return 0; } @@ -1905,7 +1905,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) { struct uart_state *state = drv->state + port->line; - mutex_lock(&state->mutex); + down(&state->sem); uart_change_pm(state, 0); @@ -1954,7 +1954,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) } } - mutex_unlock(&state->mutex); + up(&state->sem); return 0; } @@ -2049,7 +2049,7 @@ uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state) if (info && info->tty) tty_vhangup(info->tty); - mutex_lock(&state->mutex); + down(&state->sem); state->info = NULL; @@ -2072,7 +2072,7 @@ uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state) kfree(info); } - mutex_unlock(&state->mutex); + up(&state->sem); } static struct tty_operations uart_ops = { @@ -2161,7 +2161,7 @@ int uart_register_driver(struct uart_driver *drv) state->close_delay = 500; /* .5 seconds */ state->closing_wait = 30000; /* 30 seconds */ - mutex_init(&state->mutex); + init_MUTEX(&state->sem); } retval = tty_register_driver(normal); diff --git a/trunk/drivers/sn/Kconfig b/trunk/drivers/sn/Kconfig index d95265b187a3..13b8d249da5c 100644 --- a/trunk/drivers/sn/Kconfig +++ b/trunk/drivers/sn/Kconfig @@ -17,18 +17,4 @@ config SGI_IOC4 If you have an SGI Altix with an IOC4-based I/O controller say Y. Otherwise say N. -config SGI_IOC3 - tristate "SGI IOC3 Base IO support" - depends on (IA64_GENERIC || IA64_SGI_SN2) - default m - ---help--- - This option enables basic support for the SGI IOC3-based Base IO - controller card. This option does not enable any specific - functions on such a card, but provides necessary infrastructure - for other drivers to utilize. - - If you have an SGI Altix with an IOC3-based - I/O controller or a PCI IOC3 serial card say Y. - Otherwise say N. - endmenu diff --git a/trunk/drivers/sn/Makefile b/trunk/drivers/sn/Makefile index 2cda011597c0..c2a284185372 100644 --- a/trunk/drivers/sn/Makefile +++ b/trunk/drivers/sn/Makefile @@ -4,4 +4,3 @@ # obj-$(CONFIG_SGI_IOC4) += ioc4.o -obj-$(CONFIG_SGI_IOC3) += ioc3.o diff --git a/trunk/drivers/sn/ioc3.c b/trunk/drivers/sn/ioc3.c deleted file mode 100644 index aaa009f4a7bf..000000000000 --- a/trunk/drivers/sn/ioc3.c +++ /dev/null @@ -1,851 +0,0 @@ -/* - * SGI IOC3 master driver and IRQ demuxer - * - * Copyright (c) 2005 Stanislaw Skowronek - * Heavily based on similar work by: - * Brent Casavant - IOC4 master driver - * Pat Gefre - IOC3 serial port IRQ demuxer - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define IOC3_PCI_SIZE 0x100000 - -static LIST_HEAD(ioc3_devices); -static int ioc3_counter; -static DECLARE_RWSEM(ioc3_devices_rwsem); - -static struct ioc3_submodule *ioc3_submodules[IOC3_MAX_SUBMODULES]; -static struct ioc3_submodule *ioc3_ethernet; -static rwlock_t ioc3_submodules_lock = RW_LOCK_UNLOCKED; - -/* NIC probing code */ - -#define GPCR_MLAN_EN 0x00200000 /* enable MCR to pin 8 */ - -static inline unsigned mcr_pack(unsigned pulse, unsigned sample) -{ - return (pulse << 10) | (sample << 2); -} - -static int nic_wait(struct ioc3_driver_data *idd) -{ - volatile unsigned mcr; - - do { - mcr = (volatile unsigned)idd->vma->mcr; - } while (!(mcr & 2)); - - return mcr & 1; -} - -static int nic_reset(struct ioc3_driver_data *idd) -{ - int presence; - unsigned long flags; - - local_irq_save(flags); - idd->vma->mcr = mcr_pack(500, 65); - presence = nic_wait(idd); - local_irq_restore(flags); - - udelay(500); - - return presence; -} - -static inline int nic_read_bit(struct ioc3_driver_data *idd) -{ - int result; - unsigned long flags; - - local_irq_save(flags); - idd->vma->mcr = mcr_pack(6, 13); - result = nic_wait(idd); - local_irq_restore(flags); - - udelay(500); - - return result; -} - -static inline void nic_write_bit(struct ioc3_driver_data *idd, int bit) -{ - if (bit) - idd->vma->mcr = mcr_pack(6, 110); - else - idd->vma->mcr = mcr_pack(80, 30); - - nic_wait(idd); -} - -static unsigned nic_read_byte(struct ioc3_driver_data *idd) -{ - unsigned result = 0; - int i; - - for (i = 0; i < 8; i++) - result = (result >> 1) | (nic_read_bit(idd) << 7); - - return result; -} - -static void nic_write_byte(struct ioc3_driver_data *idd, int byte) -{ - int i, bit; - - for (i = 8; i; i--) { - bit = byte & 1; - byte >>= 1; - - nic_write_bit(idd, bit); - } -} - -static unsigned long -nic_find(struct ioc3_driver_data *idd, int *last, unsigned long addr) -{ - int a, b, index, disc; - - nic_reset(idd); - - /* Search ROM. */ - nic_write_byte(idd, 0xF0); - - /* Algorithm from ``Book of iButton Standards''. */ - for (index = 0, disc = 0; index < 64; index++) { - a = nic_read_bit(idd); - b = nic_read_bit(idd); - - if (a && b) { - printk(KERN_WARNING "IOC3 NIC search failed.\n"); - *last = 0; - return 0; - } - - if (!a && !b) { - if (index == *last) { - addr |= 1UL << index; - } else if (index > *last) { - addr &= ~(1UL << index); - disc = index; - } else if ((addr & (1UL << index)) == 0) - disc = index; - nic_write_bit(idd, (addr>>index)&1); - continue; - } else { - if (a) - addr |= 1UL << index; - else - addr &= ~(1UL << index); - nic_write_bit(idd, a); - continue; - } - } - *last = disc; - return addr; -} - -static void nic_addr(struct ioc3_driver_data *idd, unsigned long addr) -{ - int index; - - nic_reset(idd); - nic_write_byte(idd, 0xF0); - for (index = 0; index < 64; index++) { - nic_read_bit(idd); - nic_read_bit(idd); - nic_write_bit(idd, (addr>>index)&1); - } -} - -static void crc16_byte(unsigned int *crc, unsigned char db) -{ - int i; - - for(i=0;i<8;i++) { - *crc <<= 1; - if((db^(*crc>>16)) & 1) - *crc ^= 0x8005; - db >>= 1; - } - *crc &= 0xFFFF; -} - -static unsigned int crc16_area(unsigned char *dbs, int size, unsigned int crc) -{ - while(size--) - crc16_byte(&crc, *(dbs++)); - return crc; -} - -static void crc8_byte(unsigned int *crc, unsigned char db) -{ - int i,f; - - for(i=0;i<8;i++) { - f = (*crc ^ db) & 1; - *crc >>= 1; - db >>= 1; - if(f) - *crc ^= 0x8c; - } - *crc &= 0xff; -} - -static unsigned int crc8_addr(unsigned long addr) -{ - int i; - unsigned int crc = 0x00; - - for(i=0;i<8;i++) - crc8_byte(&crc, addr>>(i<<3)); - return crc; -} - -static void -read_redir_page(struct ioc3_driver_data *idd, unsigned long addr, int page, - unsigned char *redir, unsigned char *data) -{ - int loops = 16, i; - - while(redir[page] != 0xFF) { - page = redir[page]^0xFF; - loops--; - if(loops<0) { - printk(KERN_ERR "IOC3: NIC circular redirection\n"); - return; - } - } - loops = 3; - while(loops>0) { - nic_addr(idd, addr); - nic_write_byte(idd, 0xF0); - nic_write_byte(idd, (page << 5) & 0xE0); - nic_write_byte(idd, (page >> 3) & 0x1F); - for(i=0;i<0x20;i++) - data[i] = nic_read_byte(idd); - if(crc16_area(data, 0x20, 0x0000) == 0x800d) - return; - loops--; - } - printk(KERN_ERR "IOC3: CRC error in data page\n"); - for(i=0;i<0x20;i++) - data[i] = 0x00; -} - -static void -read_redir_map(struct ioc3_driver_data *idd, unsigned long addr, - unsigned char *redir) -{ - int i,j,loops = 3,crc_ok; - unsigned int crc; - - while(loops>0) { - crc_ok = 1; - nic_addr(idd, addr); - nic_write_byte(idd, 0xAA); - nic_write_byte(idd, 0x00); - nic_write_byte(idd, 0x01); - for(i=0;i<64;i+=8) { - for(j=0;j<8;j++) - redir[i+j] = nic_read_byte(idd); - crc = crc16_area(redir+i, 8, (i==0)?0x8707:0x0000); - crc16_byte(&crc, nic_read_byte(idd)); - crc16_byte(&crc, nic_read_byte(idd)); - if(crc != 0x800d) - crc_ok = 0; - } - if(crc_ok) - return; - loops--; - } - printk(KERN_ERR "IOC3: CRC error in redirection page\n"); - for(i=0;i<64;i++) - redir[i] = 0xFF; -} - -static void read_nic(struct ioc3_driver_data *idd, unsigned long addr) -{ - unsigned char redir[64]; - unsigned char data[64],part[32]; - int i,j; - - /* read redirections */ - read_redir_map(idd, addr, redir); - /* read data pages */ - read_redir_page(idd, addr, 0, redir, data); - read_redir_page(idd, addr, 1, redir, data+32); - /* assemble the part # */ - j=0; - for(i=0;i<19;i++) - if(data[i+11] != ' ') - part[j++] = data[i+11]; - for(i=0;i<6;i++) - if(data[i+32] != ' ') - part[j++] = data[i+32]; - part[j] = 0; - /* skip Octane power supplies */ - if(!strncmp(part, "060-0035-", 9)) - return; - if(!strncmp(part, "060-0038-", 9)) - return; - strcpy(idd->nic_part, part); - /* assemble the serial # */ - j=0; - for(i=0;i<10;i++) - if(data[i+1] != ' ') - idd->nic_serial[j++] = data[i+1]; - idd->nic_serial[j] = 0; -} - -static void read_mac(struct ioc3_driver_data *idd, unsigned long addr) -{ - int i, loops = 3; - unsigned char data[13]; - - while(loops>0) { - nic_addr(idd, addr); - nic_write_byte(idd, 0xF0); - nic_write_byte(idd, 0x00); - nic_write_byte(idd, 0x00); - nic_read_byte(idd); - for(i=0;i<13;i++) - data[i] = nic_read_byte(idd); - if(crc16_area(data, 13, 0x0000) == 0x800d) { - for(i=10;i>4;i--) - idd->nic_mac[10-i] = data[i]; - return; - } - loops--; - } - printk(KERN_ERR "IOC3: CRC error in MAC address\n"); - for(i=0;i<6;i++) - idd->nic_mac[i] = 0x00; -} - -static void probe_nic(struct ioc3_driver_data *idd) -{ - int save = 0, loops = 3; - unsigned long first, addr; - - idd->vma->gpcr_s = GPCR_MLAN_EN; - - while(loops>0) { - idd->nic_part[0] = 0; - idd->nic_serial[0] = 0; - addr = first = nic_find(idd, &save, 0); - if(!first) - return; - while(1) { - if(crc8_addr(addr)) - break; - else { - switch(addr & 0xFF) { - case 0x0B: - read_nic(idd, addr); - break; - case 0x09: - case 0x89: - case 0x91: - read_mac(idd, addr); - break; - } - } - addr = nic_find(idd, &save, addr); - if(addr == first) - return; - } - loops--; - } - printk(KERN_ERR "IOC3: CRC error in NIC address\n"); -} - -/* Interrupts */ - -static inline void -write_ireg(struct ioc3_driver_data *idd, uint32_t val, int which) -{ - unsigned long flags; - - spin_lock_irqsave(&idd->ir_lock, flags); - switch (which) { - case IOC3_W_IES: - writel(val, &idd->vma->sio_ies); - break; - case IOC3_W_IEC: - writel(val, &idd->vma->sio_iec); - break; - } - spin_unlock_irqrestore(&idd->ir_lock, flags); -} -static inline uint32_t get_pending_intrs(struct ioc3_driver_data *idd) -{ - unsigned long flag; - uint32_t intrs = 0; - - spin_lock_irqsave(&idd->ir_lock, flag); - intrs = readl(&idd->vma->sio_ir); - intrs &= readl(&idd->vma->sio_ies); - spin_unlock_irqrestore(&idd->ir_lock, flag); - return intrs; -} - -static irqreturn_t ioc3_intr_io(int irq, void *arg, struct pt_regs *regs) -{ - unsigned long flags; - struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg; - int handled = 1, id; - unsigned int pending; - - read_lock_irqsave(&ioc3_submodules_lock, flags); - - if(idd->dual_irq && idd->vma->eisr) { - /* send Ethernet IRQ to the driver */ - if(ioc3_ethernet && idd->active[ioc3_ethernet->id] && - ioc3_ethernet->intr) { - handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, - idd, 0, regs); - } - } - pending = get_pending_intrs(idd); /* look at the IO IRQs */ - - for(id=0;idactive[id] && ioc3_submodules[id] - && (pending & ioc3_submodules[id]->irq_mask) - && ioc3_submodules[id]->intr) { - write_ireg(idd, ioc3_submodules[id]->irq_mask, - IOC3_W_IEC); - if(!ioc3_submodules[id]->intr(ioc3_submodules[id], - idd, pending & ioc3_submodules[id]->irq_mask, - regs)) - pending &= ~ioc3_submodules[id]->irq_mask; - if (ioc3_submodules[id]->reset_mask) - write_ireg(idd, ioc3_submodules[id]->irq_mask, - IOC3_W_IES); - } - } - read_unlock_irqrestore(&ioc3_submodules_lock, flags); - if(pending) { - printk(KERN_WARNING - "IOC3: Pending IRQs 0x%08x discarded and disabled\n",pending); - write_ireg(idd, pending, IOC3_W_IEC); - handled = 1; - } - return handled?IRQ_HANDLED:IRQ_NONE; -} - -static irqreturn_t ioc3_intr_eth(int irq, void *arg, struct pt_regs *regs) -{ - unsigned long flags; - struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg; - int handled = 1; - - if(!idd->dual_irq) - return IRQ_NONE; - read_lock_irqsave(&ioc3_submodules_lock, flags); - if(ioc3_ethernet && idd->active[ioc3_ethernet->id] - && ioc3_ethernet->intr) - handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, idd, 0, - regs); - read_unlock_irqrestore(&ioc3_submodules_lock, flags); - return handled?IRQ_HANDLED:IRQ_NONE; -} - -void ioc3_enable(struct ioc3_submodule *is, - struct ioc3_driver_data *idd, unsigned int irqs) -{ - write_ireg(idd, irqs & is->irq_mask, IOC3_W_IES); -} - -void ioc3_ack(struct ioc3_submodule *is, struct ioc3_driver_data *idd, - unsigned int irqs) -{ - writel(irqs & is->irq_mask, &idd->vma->sio_ir); -} - -void ioc3_disable(struct ioc3_submodule *is, - struct ioc3_driver_data *idd, unsigned int irqs) -{ - write_ireg(idd, irqs & is->irq_mask, IOC3_W_IEC); -} - -void ioc3_gpcr_set(struct ioc3_driver_data *idd, unsigned int val) -{ - unsigned long flags; - spin_lock_irqsave(&idd->gpio_lock, flags); - writel(val, &idd->vma->gpcr_s); - spin_unlock_irqrestore(&idd->gpio_lock, flags); -} - -/* Keep it simple, stupid! */ -static int find_slot(void **tab, int max) -{ - int i; - for(i=0;iethernet) { - if(ioc3_ethernet==NULL) - ioc3_ethernet=is; - else - printk(KERN_WARNING - "IOC3 Ethernet module already registered!\n"); - } - } - write_unlock_irqrestore(&ioc3_submodules_lock, flags); - - if(alloc_id == -1) { - printk(KERN_WARNING "Increase IOC3_MAX_SUBMODULES!\n"); - return -ENOMEM; - } - - is->id=alloc_id; - - /* Initialize submodule for each IOC3 */ - if (!is->probe) - return 0; - - down_read(&ioc3_devices_rwsem); - list_for_each_entry(idd, &ioc3_devices, list) { - /* set to 1 for IRQs in probe */ - idd->active[alloc_id] = 1; - idd->active[alloc_id] = !is->probe(is, idd); - } - up_read(&ioc3_devices_rwsem); - - return 0; -} - -/* Unregister an IOC3 submodule */ -void ioc3_unregister_submodule(struct ioc3_submodule *is) -{ - struct ioc3_driver_data *idd; - unsigned long flags; - - write_lock_irqsave(&ioc3_submodules_lock, flags); - if(ioc3_submodules[is->id]==is) - ioc3_submodules[is->id]=NULL; - else - printk(KERN_WARNING - "IOC3 submodule %s has wrong ID.\n",is->name); - if(ioc3_ethernet==is) - ioc3_ethernet = NULL; - write_unlock_irqrestore(&ioc3_submodules_lock, flags); - - /* Remove submodule for each IOC3 */ - down_read(&ioc3_devices_rwsem); - list_for_each_entry(idd, &ioc3_devices, list) - if(idd->active[is->id]) { - if(is->remove) - if(is->remove(is, idd)) - printk(KERN_WARNING - "%s: IOC3 submodule %s remove failed " - "for pci_dev %s.\n", - __FUNCTION__, module_name(is->owner), - pci_name(idd->pdev)); - idd->active[is->id] = 0; - if(is->irq_mask) - write_ireg(idd, is->irq_mask, IOC3_W_IEC); - } - up_read(&ioc3_devices_rwsem); -} - -/********************* - * Device management * - *********************/ - -static char * -ioc3_class_names[]={"unknown", "IP27 BaseIO", "IP30 system", "MENET 1/2/3", - "MENET 4", "CADduo", "Altix Serial"}; - -static int ioc3_class(struct ioc3_driver_data *idd) -{ - int res = IOC3_CLASS_NONE; - /* NIC-based logic */ - if(!strncmp(idd->nic_part, "030-0891-", 9)) - res = IOC3_CLASS_BASE_IP30; - if(!strncmp(idd->nic_part, "030-1155-", 9)) - res = IOC3_CLASS_CADDUO; - if(!strncmp(idd->nic_part, "030-1657-", 9)) - res = IOC3_CLASS_SERIAL; - if(!strncmp(idd->nic_part, "030-1664-", 9)) - res = IOC3_CLASS_SERIAL; - /* total random heuristics */ -#ifdef CONFIG_SGI_IP27 - if(!idd->nic_part[0]) - res = IOC3_CLASS_BASE_IP27; -#endif - /* print educational message */ - printk(KERN_INFO "IOC3 part: [%s], serial: [%s] => class %s\n", - idd->nic_part, idd->nic_serial, ioc3_class_names[res]); - return res; -} -/* Adds a new instance of an IOC3 card */ -static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) -{ - struct ioc3_driver_data *idd; - uint32_t pcmd; - int ret, id; - - /* Enable IOC3 and take ownership of it */ - if ((ret = pci_enable_device(pdev))) { - printk(KERN_WARNING - "%s: Failed to enable IOC3 device for pci_dev %s.\n", - __FUNCTION__, pci_name(pdev)); - goto out; - } - pci_set_master(pdev); - -#ifdef USE_64BIT_DMA - ret = pci_set_dma_mask(pdev, 0xffffffffffffffffULL); - if (!ret) { - ret = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL); - if (ret < 0) { - printk(KERN_WARNING "%s: Unable to obtain 64 bit DMA " - "for consistent allocations\n", - __FUNCTION__); - } - } -#endif - - /* Set up per-IOC3 data */ - idd = kmalloc(sizeof(struct ioc3_driver_data), GFP_KERNEL); - if (!idd) { - printk(KERN_WARNING - "%s: Failed to allocate IOC3 data for pci_dev %s.\n", - __FUNCTION__, pci_name(pdev)); - ret = -ENODEV; - goto out_idd; - } - memset(idd, 0, sizeof(struct ioc3_driver_data)); - spin_lock_init(&idd->ir_lock); - spin_lock_init(&idd->gpio_lock); - idd->pdev = pdev; - - /* Map all IOC3 registers. These are shared between subdevices - * so the main IOC3 module manages them. - */ - idd->pma = pci_resource_start(pdev, 0); - if (!idd->pma) { - printk(KERN_WARNING - "%s: Unable to find IOC3 resource " - "for pci_dev %s.\n", - __FUNCTION__, pci_name(pdev)); - ret = -ENODEV; - goto out_pci; - } - if (!request_region(idd->pma, IOC3_PCI_SIZE, "ioc3")) { - printk(KERN_WARNING - "%s: Unable to request IOC3 region " - "for pci_dev %s.\n", - __FUNCTION__, pci_name(pdev)); - ret = -ENODEV; - goto out_pci; - } - idd->vma = ioremap(idd->pma, IOC3_PCI_SIZE); - if (!idd->vma) { - printk(KERN_WARNING - "%s: Unable to remap IOC3 region " - "for pci_dev %s.\n", - __FUNCTION__, pci_name(pdev)); - ret = -ENODEV; - goto out_misc_region; - } - - /* Track PCI-device specific data */ - pci_set_drvdata(pdev, idd); - down_write(&ioc3_devices_rwsem); - list_add(&idd->list, &ioc3_devices); - idd->id = ioc3_counter++; - up_write(&ioc3_devices_rwsem); - - idd->gpdr_shadow = idd->vma->gpdr; - - /* Read IOC3 NIC contents */ - probe_nic(idd); - - /* Detect IOC3 class */ - idd->class = ioc3_class(idd); - - /* Initialize IOC3 */ - pci_read_config_dword(pdev, PCI_COMMAND, &pcmd); - pci_write_config_dword(pdev, PCI_COMMAND, - pcmd | PCI_COMMAND_MEMORY | - PCI_COMMAND_PARITY | PCI_COMMAND_SERR | - PCI_SCR_DROP_MODE_EN); - - write_ireg(idd, ~0, IOC3_W_IEC); - writel(~0, &idd->vma->sio_ir); - - /* Set up IRQs */ - if(idd->class == IOC3_CLASS_BASE_IP30 - || idd->class == IOC3_CLASS_BASE_IP27) { - writel(0, &idd->vma->eier); - writel(~0, &idd->vma->eisr); - - idd->dual_irq = 1; - if (!request_irq(pdev->irq, ioc3_intr_eth, SA_SHIRQ, - "ioc3-eth", (void *)idd)) { - idd->irq_eth = pdev->irq; - } else { - printk(KERN_WARNING - "%s : request_irq fails for IRQ 0x%x\n ", - __FUNCTION__, pdev->irq); - } - if (!request_irq(pdev->irq+2, ioc3_intr_io, SA_SHIRQ, - "ioc3-io", (void *)idd)) { - idd->irq_io = pdev->irq+2; - } else { - printk(KERN_WARNING - "%s : request_irq fails for IRQ 0x%x\n ", - __FUNCTION__, pdev->irq+2); - } - } else { - if (!request_irq(pdev->irq, ioc3_intr_io, SA_SHIRQ, - "ioc3", (void *)idd)) { - idd->irq_io = pdev->irq; - } else { - printk(KERN_WARNING - "%s : request_irq fails for IRQ 0x%x\n ", - __FUNCTION__, pdev->irq); - } - } - - /* Add this IOC3 to all submodules */ - read_lock(&ioc3_submodules_lock); - for(id=0;idprobe) { - idd->active[id] = 1; - idd->active[id] = !ioc3_submodules[id]->probe - (ioc3_submodules[id], idd); - } - read_unlock(&ioc3_submodules_lock); - - printk(KERN_INFO "IOC3 Master Driver loaded for %s\n", pci_name(pdev)); - - return 0; - -out_misc_region: - release_region(idd->pma, IOC3_PCI_SIZE); -out_pci: - kfree(idd); -out_idd: - pci_disable_device(pdev); -out: - return ret; -} - -/* Removes a particular instance of an IOC3 card. */ -static void ioc3_remove(struct pci_dev *pdev) -{ - int id; - struct ioc3_driver_data *idd; - - idd = pci_get_drvdata(pdev); - - /* Remove this IOC3 from all submodules */ - read_lock(&ioc3_submodules_lock); - for(id=0;idactive[id]) { - if(ioc3_submodules[id] && ioc3_submodules[id]->remove) - if(ioc3_submodules[id]->remove(ioc3_submodules[id], - idd)) - printk(KERN_WARNING - "%s: IOC3 submodule 0x%s remove failed " - "for pci_dev %s.\n", - __FUNCTION__, - module_name(ioc3_submodules[id]->owner), - pci_name(pdev)); - idd->active[id] = 0; - } - read_unlock(&ioc3_submodules_lock); - - /* Clear and disable all IRQs */ - write_ireg(idd, ~0, IOC3_W_IEC); - writel(~0, &idd->vma->sio_ir); - - /* Release resources */ - free_irq(idd->irq_io, (void *)idd); - if(idd->dual_irq) - free_irq(idd->irq_eth, (void *)idd); - iounmap(idd->vma); - release_region(idd->pma, IOC3_PCI_SIZE); - - /* Disable IOC3 and relinquish */ - pci_disable_device(pdev); - - /* Remove and free driver data */ - down_write(&ioc3_devices_rwsem); - list_del(&idd->list); - up_write(&ioc3_devices_rwsem); - kfree(idd); -} - -static struct pci_device_id ioc3_id_table[] = { - {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID}, - {0} -}; - -static struct pci_driver ioc3_driver = { - .name = "IOC3", - .id_table = ioc3_id_table, - .probe = ioc3_probe, - .remove = ioc3_remove, -}; - -MODULE_DEVICE_TABLE(pci, ioc3_id_table); - -/********************* - * Module management * - *********************/ - -/* Module load */ -static int __devinit ioc3_init(void) -{ - if (ia64_platform_is("sn2")) - return pci_register_driver(&ioc3_driver); - return 0; -} - -/* Module unload */ -static void __devexit ioc3_exit(void) -{ - pci_unregister_driver(&ioc3_driver); -} - -module_init(ioc3_init); -module_exit(ioc3_exit); - -MODULE_AUTHOR("Stanislaw Skowronek "); -MODULE_DESCRIPTION("PCI driver for SGI IOC3"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(ioc3_register_submodule); -EXPORT_SYMBOL(ioc3_unregister_submodule); -EXPORT_SYMBOL(ioc3_ack); -EXPORT_SYMBOL(ioc3_gpcr_set); -EXPORT_SYMBOL(ioc3_disable); -EXPORT_SYMBOL(ioc3_enable); diff --git a/trunk/drivers/usb/atm/usbatm.c b/trunk/drivers/usb/atm/usbatm.c index 7af1883d4bf9..9baa6296fc95 100644 --- a/trunk/drivers/usb/atm/usbatm.c +++ b/trunk/drivers/usb/atm/usbatm.c @@ -207,7 +207,7 @@ static inline void usbatm_pop(struct atm_vcc *vcc, struct sk_buff *skb) ** urbs ** ************/ -static struct urb *usbatm_pop_urb(struct usbatm_channel *channel) +static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel) { struct urb *urb; @@ -224,7 +224,7 @@ static struct urb *usbatm_pop_urb(struct usbatm_channel *channel) return urb; } -static int usbatm_submit_urb(struct urb *urb) +static inline int usbatm_submit_urb(struct urb *urb) { struct usbatm_channel *channel = urb->context; int ret; diff --git a/trunk/drivers/video/68328fb.c b/trunk/drivers/video/68328fb.c index 78488bb41aeb..3b0ddc55236b 100644 --- a/trunk/drivers/video/68328fb.c +++ b/trunk/drivers/video/68328fb.c @@ -102,7 +102,8 @@ static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); static int mc68x328fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); -static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma); +static int mc68x328fb_mmap(struct fb_info *info, struct file *file, + struct vm_area_struct *vma); static struct fb_ops mc68x328fb_ops = { .fb_check_var = mc68x328fb_check_var, @@ -397,7 +398,8 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var, * Most drivers don't need their own mmap function */ -static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int mc68x328fb_mmap(struct fb_info *info, struct file *file, + struct vm_area_struct *vma) { #ifndef MMU /* this is uClinux (no MMU) specific code */ diff --git a/trunk/drivers/video/acornfb.c b/trunk/drivers/video/acornfb.c index b058273527bb..750cebb18306 100644 --- a/trunk/drivers/video/acornfb.c +++ b/trunk/drivers/video/acornfb.c @@ -883,7 +883,7 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) * Note that we are entered with the kernel locked. */ static int -acornfb_mmap(struct fb_info *info, struct vm_area_struct *vma) +acornfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { unsigned long off, start; u32 len; diff --git a/trunk/drivers/video/amba-clcd.c b/trunk/drivers/video/amba-clcd.c index b2187175d03f..0da4083ba908 100644 --- a/trunk/drivers/video/amba-clcd.c +++ b/trunk/drivers/video/amba-clcd.c @@ -307,7 +307,7 @@ static int clcdfb_blank(int blank_mode, struct fb_info *info) return 0; } -static int clcdfb_mmap(struct fb_info *info, +static int clcdfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { struct clcd_fb *fb = to_clcd(info); diff --git a/trunk/drivers/video/amifb.c b/trunk/drivers/video/amifb.c index 3033c72dea20..2c42a812655a 100644 --- a/trunk/drivers/video/amifb.c +++ b/trunk/drivers/video/amifb.c @@ -1131,7 +1131,9 @@ static void amifb_copyarea(struct fb_info *info, const struct fb_copyarea *region); static void amifb_imageblit(struct fb_info *info, const struct fb_image *image); -static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); +static int amifb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + struct fb_info *info); /* @@ -2170,8 +2172,9 @@ static void amifb_imageblit(struct fb_info *info, const struct fb_image *image) * Amiga Frame Buffer Specific ioctls */ -static int amifb_ioctl(struct fb_info *info, - unsigned int cmd, unsigned long arg) +static int amifb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + struct fb_info *info) { union { struct fb_fix_cursorinfo fix; diff --git a/trunk/drivers/video/arcfb.c b/trunk/drivers/video/arcfb.c index df8e5667b348..89060b2db8e5 100644 --- a/trunk/drivers/video/arcfb.c +++ b/trunk/drivers/video/arcfb.c @@ -399,8 +399,9 @@ static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image) image->height); } -static int arcfb_ioctl(struct fb_info *info, - unsigned int cmd, unsigned long arg) +static int arcfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + struct fb_info *info) { void __user *argp = (void __user *)arg; struct arcfb_par *par = info->par; diff --git a/trunk/drivers/video/atafb.c b/trunk/drivers/video/atafb.c index e69ab65f7843..15ec1295bc29 100644 --- a/trunk/drivers/video/atafb.c +++ b/trunk/drivers/video/atafb.c @@ -2571,7 +2571,8 @@ atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info) } static int -atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +atafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, int con, struct fb_info *info) { switch (cmd) { #ifdef FBCMD_GET_CURRENTPAR diff --git a/trunk/drivers/video/aty/aty128fb.c b/trunk/drivers/video/aty/aty128fb.c index bfc8a93b2c73..e686185a076d 100644 --- a/trunk/drivers/video/aty/aty128fb.c +++ b/trunk/drivers/video/aty/aty128fb.c @@ -431,7 +431,8 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, static int aty128fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb); static int aty128fb_blank(int blank, struct fb_info *fb); -static int aty128fb_ioctl(struct fb_info *info, u_int cmd, unsigned long arg); +static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, struct fb_info *info); static int aty128fb_sync(struct fb_info *info); /* @@ -2107,7 +2108,8 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, /* in param: u32* backlight value: 0 to 15 */ #define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32) -static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) +static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, struct fb_info *info) { struct aty128fb_par *par = info->par; u32 value; diff --git a/trunk/drivers/video/aty/atyfb_base.c b/trunk/drivers/video/aty/atyfb_base.c index 485be386a8ff..ed81005cbdba 100644 --- a/trunk/drivers/video/aty/atyfb_base.c +++ b/trunk/drivers/video/aty/atyfb_base.c @@ -238,12 +238,13 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); static int atyfb_blank(int blank, struct fb_info *info); -static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg); +static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, struct fb_info *info); extern void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); extern void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); extern void atyfb_imageblit(struct fb_info *info, const struct fb_image *image); #ifdef __sparc__ -static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma); +static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma); #endif static int atyfb_sync(struct fb_info *info); @@ -1738,7 +1739,8 @@ struct atyclk { #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) #endif -static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) +static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; #ifdef __sparc__ @@ -1843,7 +1845,7 @@ static int atyfb_sync(struct fb_info *info) } #ifdef __sparc__ -static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { struct atyfb_par *par = (struct atyfb_par *) info->par; unsigned int size, page, map_size = 0; diff --git a/trunk/drivers/video/aty/radeon_base.c b/trunk/drivers/video/aty/radeon_base.c index c9f0c5a07e6e..156db84cb363 100644 --- a/trunk/drivers/video/aty/radeon_base.c +++ b/trunk/drivers/video/aty/radeon_base.c @@ -864,8 +864,8 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var, } -static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd, - unsigned long arg) +static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) { struct radeonfb_info *rinfo = info->par; unsigned int tmp; diff --git a/trunk/drivers/video/aty/radeon_pm.c b/trunk/drivers/video/aty/radeon_pm.c index 556895e99645..097d668c4fe5 100644 --- a/trunk/drivers/video/aty/radeon_pm.c +++ b/trunk/drivers/video/aty/radeon_pm.c @@ -2734,7 +2734,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) * BIOS does tho. Right now, all this PM stuff is pmac-only for that * reason. --BenH */ -#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) +#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF) if (_machine == _MACH_Pmac && rinfo->of_node) { if (rinfo->is_mobility && rinfo->pm_reg && rinfo->family <= CHIP_FAMILY_RV250) @@ -2778,12 +2778,12 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000); #endif } -#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) */ +#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_OF) */ } void radeonfb_pm_exit(struct radeonfb_info *rinfo) { -#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) +#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF) if (rinfo->pm_mode != radeon_pm_none) pmac_set_early_video_resume(NULL, NULL); #endif diff --git a/trunk/drivers/video/au1100fb.c b/trunk/drivers/video/au1100fb.c index 2406899f1207..a5129806172f 100644 --- a/trunk/drivers/video/au1100fb.c +++ b/trunk/drivers/video/au1100fb.c @@ -379,7 +379,7 @@ void au1100fb_fb_rotate(struct fb_info *fbi, int angle) * Map video memory in user space. We don't use the generic fb_mmap method mainly * to allow the use of the TLB streaming flag (CCA=6) */ -int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) +int au1100fb_fb_mmap(struct fb_info *fbi, struct file *file, struct vm_area_struct *vma) { struct au1100fb_device *fbdev = to_au1100fb_device(fbi); unsigned int len; diff --git a/trunk/drivers/video/bw2.c b/trunk/drivers/video/bw2.c index c029db4646f6..9248fe1fbb1a 100644 --- a/trunk/drivers/video/bw2.c +++ b/trunk/drivers/video/bw2.c @@ -35,8 +35,9 @@ static int bw2_blank(int, struct fb_info *); -static int bw2_mmap(struct fb_info *, struct vm_area_struct *); -static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long); +static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int bw2_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -168,7 +169,7 @@ static struct sbus_mmap_map bw2_mmap_map[] = { { .size = 0 } }; -static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { struct bw2_par *par = (struct bw2_par *)info->par; @@ -180,7 +181,8 @@ static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma) vma); } -static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +static int bw2_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) { struct bw2_par *par = (struct bw2_par *) info->par; diff --git a/trunk/drivers/video/cg14.c b/trunk/drivers/video/cg14.c index 63b6c79c8a0a..a56147102abb 100644 --- a/trunk/drivers/video/cg14.c +++ b/trunk/drivers/video/cg14.c @@ -31,8 +31,9 @@ static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); -static int cg14_mmap(struct fb_info *, struct vm_area_struct *); -static int cg14_ioctl(struct fb_info *, unsigned int, unsigned long); +static int cg14_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int cg14_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *); /* @@ -267,7 +268,7 @@ static int cg14_setcolreg(unsigned regno, return 0; } -static int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int cg14_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { struct cg14_par *par = (struct cg14_par *) info->par; @@ -276,7 +277,8 @@ static int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma) par->iospace, vma); } -static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +static int cg14_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) { struct cg14_par *par = (struct cg14_par *) info->par; struct cg14_regs __iomem *regs = par->regs; diff --git a/trunk/drivers/video/cg3.c b/trunk/drivers/video/cg3.c index 3de6e1b5ab2f..9fcd89608ed7 100644 --- a/trunk/drivers/video/cg3.c +++ b/trunk/drivers/video/cg3.c @@ -33,8 +33,9 @@ static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int cg3_blank(int, struct fb_info *); -static int cg3_mmap(struct fb_info *, struct vm_area_struct *); -static int cg3_ioctl(struct fb_info *, unsigned int, unsigned long); +static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int cg3_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -229,7 +230,7 @@ static struct sbus_mmap_map cg3_mmap_map[] = { { .size = 0 } }; -static int cg3_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int cg3_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { struct cg3_par *par = (struct cg3_par *)info->par; @@ -239,7 +240,8 @@ static int cg3_mmap(struct fb_info *info, struct vm_area_struct *vma) vma); } -static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +static int cg3_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) { struct cg3_par *par = (struct cg3_par *) info->par; diff --git a/trunk/drivers/video/cg6.c b/trunk/drivers/video/cg6.c index 7aab91ead681..050835e39aa3 100644 --- a/trunk/drivers/video/cg6.c +++ b/trunk/drivers/video/cg6.c @@ -36,8 +36,9 @@ static int cg6_blank(int, struct fb_info *); static void cg6_imageblit(struct fb_info *, const struct fb_image *); static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); static int cg6_sync(struct fb_info *); -static int cg6_mmap(struct fb_info *, struct vm_area_struct *); -static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long); +static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int cg6_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -523,7 +524,7 @@ static struct sbus_mmap_map cg6_mmap_map[] = { { .size = 0 } }; -static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { struct cg6_par *par = (struct cg6_par *)info->par; @@ -533,7 +534,8 @@ static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma) vma); } -static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +static int cg6_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) { struct cg6_par *par = (struct cg6_par *) info->par; diff --git a/trunk/drivers/video/controlfb.c b/trunk/drivers/video/controlfb.c index 655301a8671c..03798e9c882d 100644 --- a/trunk/drivers/video/controlfb.c +++ b/trunk/drivers/video/controlfb.c @@ -128,7 +128,7 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var, static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); static int controlfb_blank(int blank_mode, struct fb_info *info); -static int controlfb_mmap(struct fb_info *info, +static int controlfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma); static int controlfb_set_par (struct fb_info *info); static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info); @@ -280,7 +280,7 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var, * for controlfb. * Note there's no locking in here; it's done in fb_mmap() in fbmem.c. */ -static int controlfb_mmap(struct fb_info *info, +static int controlfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { unsigned long off, start; diff --git a/trunk/drivers/video/fbmem.c b/trunk/drivers/video/fbmem.c index d2dede6ed3e5..32a9b69becc5 100644 --- a/trunk/drivers/video/fbmem.c +++ b/trunk/drivers/video/fbmem.c @@ -957,7 +957,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, default: if (fb->fb_ioctl == NULL) return -EINVAL; - return fb->fb_ioctl(info, cmd, arg); + return fb->fb_ioctl(inode, file, cmd, arg, info); } } @@ -1107,7 +1107,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) default: if (fb->fb_compat_ioctl) - ret = fb->fb_compat_ioctl(info, cmd, arg); + ret = fb->fb_compat_ioctl(file, cmd, arg, info); break; } unlock_kernel(); @@ -1135,7 +1135,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) if (fb->fb_mmap) { int res; lock_kernel(); - res = fb->fb_mmap(info, vma); + res = fb->fb_mmap(info, file, vma); unlock_kernel(); return res; } diff --git a/trunk/drivers/video/ffb.c b/trunk/drivers/video/ffb.c index 9c9b21d469a1..c4870d559afc 100644 --- a/trunk/drivers/video/ffb.c +++ b/trunk/drivers/video/ffb.c @@ -37,8 +37,9 @@ static void ffb_imageblit(struct fb_info *, const struct fb_image *); static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *); static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *); static int ffb_sync(struct fb_info *); -static int ffb_mmap(struct fb_info *, struct vm_area_struct *); -static int ffb_ioctl(struct fb_info *, unsigned int, unsigned long); +static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int ffb_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *); /* @@ -838,7 +839,7 @@ static struct sbus_mmap_map ffb_mmap_map[] = { { .size = 0 } }; -static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int ffb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { struct ffb_par *par = (struct ffb_par *)info->par; @@ -847,7 +848,8 @@ static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma) 0, vma); } -static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +static int ffb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) { struct ffb_par *par = (struct ffb_par *) info->par; diff --git a/trunk/drivers/video/gbefb.c b/trunk/drivers/video/gbefb.c index 38d22729b129..d744c51807b7 100644 --- a/trunk/drivers/video/gbefb.c +++ b/trunk/drivers/video/gbefb.c @@ -979,7 +979,7 @@ static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) return 0; } -static int gbefb_mmap(struct fb_info *info, +static int gbefb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { unsigned long size = vma->vm_end - vma->vm_start; @@ -1000,6 +1000,7 @@ static int gbefb_mmap(struct fb_info *info, pgprot_fb(pgprot_val(vma->vm_page_prot)); vma->vm_flags |= VM_IO | VM_RESERVED; + vma->vm_file = file; /* look for the starting tile */ tile = &gbe_tiles.cpu[offset >> TILE_SHIFT]; diff --git a/trunk/drivers/video/geode/gx1fb_core.c b/trunk/drivers/video/geode/gx1fb_core.c index 20e69156d728..8e8da7433994 100644 --- a/trunk/drivers/video/geode/gx1fb_core.c +++ b/trunk/drivers/video/geode/gx1fb_core.c @@ -215,11 +215,11 @@ static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *d if (ret < 0) return ret; - ret = pci_request_region(dev, 0, "gx1fb (video)"); + ret = pci_request_region(dev, 1, "gx1fb (video)"); if (ret < 0) return ret; - par->vid_regs = ioremap(pci_resource_start(dev, 0), - pci_resource_len(dev, 0)); + par->vid_regs = ioremap(pci_resource_start(dev, 1), + pci_resource_len(dev, 1)); if (!par->vid_regs) return -ENOMEM; @@ -229,9 +229,12 @@ static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *d if (!par->dc_regs) return -ENOMEM; + ret = pci_request_region(dev, 0, "gx1fb (frame buffer)"); + if (ret < 0 ) + return -EBUSY; if ((fb_len = gx1_frame_buffer_size()) < 0) return -ENOMEM; - info->fix.smem_start = gx_base + 0x800000; + info->fix.smem_start = pci_resource_start(dev, 0); info->fix.smem_len = fb_len; info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); if (!info->screen_base) diff --git a/trunk/drivers/video/igafb.c b/trunk/drivers/video/igafb.c index 6b88050d21bf..e326f44f652d 100644 --- a/trunk/drivers/video/igafb.c +++ b/trunk/drivers/video/igafb.c @@ -219,7 +219,7 @@ static void iga_blank_border(struct iga_par *par) } #ifdef __sparc__ -static int igafb_mmap(struct fb_info *info, +static int igafb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { struct iga_par *par = (struct iga_par *)info->par; diff --git a/trunk/drivers/video/imsttfb.c b/trunk/drivers/video/imsttfb.c index ad416ae47596..a5d813050db5 100644 --- a/trunk/drivers/video/imsttfb.c +++ b/trunk/drivers/video/imsttfb.c @@ -1267,7 +1267,8 @@ imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor) #define FBIMSTT_GETIDXREG 0x545406 static int -imsttfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) +imsttfb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, struct fb_info *info) { struct imstt_par *par = info->par; void __user *argp = (void __user *)arg; diff --git a/trunk/drivers/video/intelfb/intelfbdrv.c b/trunk/drivers/video/intelfb/intelfbdrv.c index 6b8bd3cdf9c0..0090544842f5 100644 --- a/trunk/drivers/video/intelfb/intelfbdrv.c +++ b/trunk/drivers/video/intelfb/intelfbdrv.c @@ -157,8 +157,9 @@ static int intelfb_cursor(struct fb_info *info, static int intelfb_sync(struct fb_info *info); -static int intelfb_ioctl(struct fb_info *info, - unsigned int cmd, unsigned long arg); +static int intelfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + struct fb_info *info); static int __devinit intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -1379,7 +1380,8 @@ intelfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) /* When/if we have our own ioctls. */ static int -intelfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +intelfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) { int retval = 0; diff --git a/trunk/drivers/video/kyro/fbdev.c b/trunk/drivers/video/kyro/fbdev.c index 477ad297de4e..bcd359b6d4ff 100644 --- a/trunk/drivers/video/kyro/fbdev.c +++ b/trunk/drivers/video/kyro/fbdev.c @@ -586,8 +586,9 @@ static int __init kyrofb_setup(char *options) } #endif -static int kyrofb_ioctl(struct fb_info *info, - unsigned int cmd, unsigned long arg) +static int kyrofb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + struct fb_info *info) { overlay_create ol_create; overlay_viewport_set ol_viewport_set; diff --git a/trunk/drivers/video/leo.c b/trunk/drivers/video/leo.c index a23cfdb9d826..494287f8f8bf 100644 --- a/trunk/drivers/video/leo.c +++ b/trunk/drivers/video/leo.c @@ -32,8 +32,9 @@ static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int leo_blank(int, struct fb_info *); -static int leo_mmap(struct fb_info *, struct vm_area_struct *); -static int leo_ioctl(struct fb_info *, unsigned int, unsigned long); +static int leo_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int leo_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *); /* @@ -362,7 +363,7 @@ static struct sbus_mmap_map leo_mmap_map[] = { { .size = 0 } }; -static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { struct leo_par *par = (struct leo_par *)info->par; @@ -372,7 +373,8 @@ static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma) vma); } -static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +static int leo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) { struct leo_par *par = (struct leo_par *) info->par; diff --git a/trunk/drivers/video/matrox/matroxfb_base.c b/trunk/drivers/video/matrox/matroxfb_base.c index 4055ff6f5a81..1e74f4cca53b 100644 --- a/trunk/drivers/video/matrox/matroxfb_base.c +++ b/trunk/drivers/video/matrox/matroxfb_base.c @@ -865,8 +865,9 @@ static struct matrox_altout panellink_output = { .name = "Panellink output", }; -static int matroxfb_ioctl(struct fb_info *info, - unsigned int cmd, unsigned long arg) +static int matroxfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + struct fb_info *info) { void __user *argp = (void __user *)arg; MINFO_FROM_INFO(info); diff --git a/trunk/drivers/video/matrox/matroxfb_crtc2.c b/trunk/drivers/video/matrox/matroxfb_crtc2.c index 27eb4bb4f89f..d52d7d825c41 100644 --- a/trunk/drivers/video/matrox/matroxfb_crtc2.c +++ b/trunk/drivers/video/matrox/matroxfb_crtc2.c @@ -419,10 +419,11 @@ static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, stru return 0; } -static int matroxfb_dh_ioctl(struct fb_info *info, +static int matroxfb_dh_ioctl(struct inode* inode, + struct file* file, unsigned int cmd, - unsigned long arg) -{ + unsigned long arg, + struct fb_info* info) { #define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) MINFO_FROM(m2info->primary_dev); @@ -456,7 +457,7 @@ static int matroxfb_dh_ioctl(struct fb_info *info, case MATROXFB_GET_OUTPUT_MODE: case MATROXFB_GET_ALL_OUTPUTS: { - return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(&ACCESS_FBINFO(fbcon), cmd, arg); + return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(inode, file, cmd, arg, &ACCESS_FBINFO(fbcon)); } case MATROXFB_SET_OUTPUT_CONNECTION: { diff --git a/trunk/drivers/video/matrox/matroxfb_maven.c b/trunk/drivers/video/matrox/matroxfb_maven.c index 6019710dc298..a1f2c5e8fc88 100644 --- a/trunk/drivers/video/matrox/matroxfb_maven.c +++ b/trunk/drivers/video/matrox/matroxfb_maven.c @@ -968,7 +968,7 @@ static inline int maven_compute_timming(struct maven_data* md, return 0; } -static int maven_program_timming(struct maven_data* md, +static inline int maven_program_timming(struct maven_data* md, const struct mavenregs* m) { struct i2c_client* c = md->client; diff --git a/trunk/drivers/video/neofb.c b/trunk/drivers/video/neofb.c index 747602aa5615..e18c9f98a401 100644 --- a/trunk/drivers/video/neofb.c +++ b/trunk/drivers/video/neofb.c @@ -853,7 +853,7 @@ static int neofb_set_par(struct fb_info *info) /* If the user did not specify any display devices, then... */ if (par->PanelDispCntlReg1 == 0x00) { /* Default to internal (i.e., LCD) only. */ - par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03; + par->PanelDispCntlReg1 |= 0x02; } /* If we are using a fixed mode, then tell the chip we are. */ diff --git a/trunk/drivers/video/p9100.c b/trunk/drivers/video/p9100.c index 0d1957505359..b251e754e16c 100644 --- a/trunk/drivers/video/p9100.c +++ b/trunk/drivers/video/p9100.c @@ -31,8 +31,9 @@ static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int p9100_blank(int, struct fb_info *); -static int p9100_mmap(struct fb_info *, struct vm_area_struct *); -static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long); +static int p9100_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int p9100_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -221,7 +222,7 @@ static struct sbus_mmap_map p9100_mmap_map[] = { { 0, 0, 0 } }; -static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int p9100_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { struct p9100_par *par = (struct p9100_par *)info->par; @@ -231,8 +232,8 @@ static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma) vma); } -static int p9100_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) +static int p9100_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) { struct p9100_par *par = (struct p9100_par *) info->par; diff --git a/trunk/drivers/video/pm3fb.c b/trunk/drivers/video/pm3fb.c index 0e78ddc81583..2e11b601c488 100644 --- a/trunk/drivers/video/pm3fb.c +++ b/trunk/drivers/video/pm3fb.c @@ -657,7 +657,9 @@ static void pm3fb_set_disp(const void *par, struct display *disp, static void pm3fb_detect(void); static int pm3fb_pan_display(const struct fb_var_screeninfo *var, struct fb_info_gen *info); -static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg); +static int pm3fb_ioctl(struct inode *inode, struct file *file, + u_int cmd, u_long arg, int con, + struct fb_info *info); /* the struct that hold them together */ @@ -3436,7 +3438,9 @@ static int pm3fb_pan_display(const struct fb_var_screeninfo *var, return 0; } -static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) +static int pm3fb_ioctl(struct inode *inode, struct file *file, + u_int cmd, u_long arg, int con, + struct fb_info *info) { struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; u32 cm, i; diff --git a/trunk/drivers/video/pmag-aa-fb.c b/trunk/drivers/video/pmag-aa-fb.c index d92f352211ef..28d1fe5fe340 100644 --- a/trunk/drivers/video/pmag-aa-fb.c +++ b/trunk/drivers/video/pmag-aa-fb.c @@ -299,7 +299,8 @@ static int aafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, return -EINVAL; } -static int aafb_ioctl(struct fb_info *info, u32 cmd, unsigned long arg) +static int aafb_ioctl(struct inode *inode, struct file *file, u32 cmd, + unsigned long arg, int con, struct fb_info *info) { /* TODO: Not yet implemented */ return -ENOIOCTLCMD; diff --git a/trunk/drivers/video/pxafb.c b/trunk/drivers/video/pxafb.c index 53ad61f1038c..9fc10b9e6f57 100644 --- a/trunk/drivers/video/pxafb.c +++ b/trunk/drivers/video/pxafb.c @@ -395,7 +395,7 @@ static int pxafb_blank(int blank, struct fb_info *info) return 0; } -static int pxafb_mmap(struct fb_info *info, +static int pxafb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { struct pxafb_info *fbi = (struct pxafb_info *)info; diff --git a/trunk/drivers/video/radeonfb.c b/trunk/drivers/video/radeonfb.c index db9fb9074dbc..600318f708f2 100644 --- a/trunk/drivers/video/radeonfb.c +++ b/trunk/drivers/video/radeonfb.c @@ -1497,8 +1497,8 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var, } -static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd, - unsigned long arg) +static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) { struct radeonfb_info *rinfo = (struct radeonfb_info *) info; unsigned int tmp; diff --git a/trunk/drivers/video/sa1100fb.c b/trunk/drivers/video/sa1100fb.c index 8a893ce7040d..087e58689e4c 100644 --- a/trunk/drivers/video/sa1100fb.c +++ b/trunk/drivers/video/sa1100fb.c @@ -815,7 +815,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info) return 0; } -static int sa1100fb_mmap(struct fb_info *info, +static int sa1100fb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; diff --git a/trunk/drivers/video/sgivwfb.c b/trunk/drivers/video/sgivwfb.c index 2e6df1fcb2b9..7054660767e4 100644 --- a/trunk/drivers/video/sgivwfb.c +++ b/trunk/drivers/video/sgivwfb.c @@ -115,7 +115,7 @@ static int sgivwfb_set_par(struct fb_info *info); static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); -static int sgivwfb_mmap(struct fb_info *info, +static int sgivwfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma); static struct fb_ops sgivwfb_ops = { @@ -706,7 +706,7 @@ static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, return 0; } -static int sgivwfb_mmap(struct fb_info *info, +static int sgivwfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { unsigned long size = vma->vm_end - vma->vm_start; @@ -723,6 +723,7 @@ static int sgivwfb_mmap(struct fb_info *info, if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT, size, vma->vm_page_prot)) return -EAGAIN; + vma->vm_file = file; printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n", offset, vma->vm_start); return 0; diff --git a/trunk/drivers/video/sis/sis_main.c b/trunk/drivers/video/sis/sis_main.c index 8adf5bf91eee..dea1a46c67c4 100644 --- a/trunk/drivers/video/sis/sis_main.c +++ b/trunk/drivers/video/sis/sis_main.c @@ -1743,14 +1743,13 @@ sisfb_blank(int blank, struct fb_info *info) /* ----------- FBDev related routines for all series ---------- */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) -static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) -#else -static int sisfb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - struct fb_info *info) +static int +sisfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + int con, #endif + struct fb_info *info) { struct sis_video_info *ivideo = (struct sis_video_info *)info->par; struct sis_memreq sismemreq; @@ -1925,6 +1924,19 @@ static int sisfb_ioctl(struct inode *inode, struct file *file, return 0; } +#ifdef SIS_NEW_CONFIG_COMPAT +static long +sisfb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg, struct fb_info *info) +{ + int ret; + + lock_kernel(); + ret = sisfb_ioctl(NULL, f, cmd, arg, info); + unlock_kernel(); + return ret; +} +#endif + static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) { @@ -1995,7 +2007,7 @@ static struct fb_ops sisfb_ops = { #endif .fb_sync = fbcon_sis_sync, #ifdef SIS_NEW_CONFIG_COMPAT - .fb_compat_ioctl= sisfb_ioctl, + .fb_compat_ioctl= sisfb_compat_ioctl, #endif .fb_ioctl = sisfb_ioctl }; diff --git a/trunk/drivers/video/sis/sis_main.h b/trunk/drivers/video/sis/sis_main.h index 70b6df371b8e..445bcbba03ae 100644 --- a/trunk/drivers/video/sis/sis_main.h +++ b/trunk/drivers/video/sis/sis_main.h @@ -727,14 +727,9 @@ static int sisfb_ioctl(struct inode *inode, struct file *file, #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) -static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg); -#else static int sisfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, struct fb_info *info); -#endif static int sisfb_set_par(struct fb_info *info); static int sisfb_blank(int blank, struct fb_info *info); diff --git a/trunk/drivers/video/sstfb.c b/trunk/drivers/video/sstfb.c index 99921df35474..8a5ce210bb27 100644 --- a/trunk/drivers/video/sstfb.c +++ b/trunk/drivers/video/sstfb.c @@ -771,7 +771,8 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, return 0; } -static int sstfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) +static int sstfb_ioctl(struct inode *inode, struct file *file, + u_int cmd, u_long arg, struct fb_info *info ) { struct sstfb_par *par = info->par; struct pci_dev *sst_dev = par->dev; diff --git a/trunk/drivers/video/tcx.c b/trunk/drivers/video/tcx.c index 95b918229d9b..2b27b4474001 100644 --- a/trunk/drivers/video/tcx.c +++ b/trunk/drivers/video/tcx.c @@ -33,8 +33,9 @@ static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int tcx_blank(int, struct fb_info *); -static int tcx_mmap(struct fb_info *, struct vm_area_struct *); -static int tcx_ioctl(struct fb_info *, unsigned int, unsigned long); +static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int tcx_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); static int tcx_pan_display(struct fb_var_screeninfo *, struct fb_info *); /* @@ -301,7 +302,7 @@ static struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = { { .size = 0 } }; -static int tcx_mmap(struct fb_info *info, struct vm_area_struct *vma) +static int tcx_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { struct tcx_par *par = (struct tcx_par *)info->par; @@ -311,8 +312,8 @@ static int tcx_mmap(struct fb_info *info, struct vm_area_struct *vma) vma); } -static int tcx_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) +static int tcx_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) { struct tcx_par *par = (struct tcx_par *) info->par; diff --git a/trunk/drivers/video/vfb.c b/trunk/drivers/video/vfb.c index 53208cb58396..ffa1ad474226 100644 --- a/trunk/drivers/video/vfb.c +++ b/trunk/drivers/video/vfb.c @@ -81,7 +81,7 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); static int vfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); -static int vfb_mmap(struct fb_info *info, +static int vfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma); static struct fb_ops vfb_ops = { @@ -368,7 +368,7 @@ static int vfb_pan_display(struct fb_var_screeninfo *var, * Most drivers don't need their own mmap function */ -static int vfb_mmap(struct fb_info *info, +static int vfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { return -EINVAL; diff --git a/trunk/fs/9p/conv.c b/trunk/fs/9p/conv.c index 32a9f99154e2..55ccfa10ee9e 100644 --- a/trunk/fs/9p/conv.c +++ b/trunk/fs/9p/conv.c @@ -56,7 +56,7 @@ static inline int buf_check_overflow(struct cbuf *buf) return buf->p > buf->ep; } -static int buf_check_size(struct cbuf *buf, int len) +static inline int buf_check_size(struct cbuf *buf, int len) { if (buf->p + len > buf->ep) { if (buf->p < buf->ep) { @@ -72,7 +72,7 @@ static int buf_check_size(struct cbuf *buf, int len) return 1; } -static void *buf_alloc(struct cbuf *buf, int len) +static inline void *buf_alloc(struct cbuf *buf, int len) { void *ret = NULL; @@ -84,7 +84,7 @@ static void *buf_alloc(struct cbuf *buf, int len) return ret; } -static void buf_put_int8(struct cbuf *buf, u8 val) +static inline void buf_put_int8(struct cbuf *buf, u8 val) { if (buf_check_size(buf, 1)) { buf->p[0] = val; @@ -92,7 +92,7 @@ static void buf_put_int8(struct cbuf *buf, u8 val) } } -static void buf_put_int16(struct cbuf *buf, u16 val) +static inline void buf_put_int16(struct cbuf *buf, u16 val) { if (buf_check_size(buf, 2)) { *(__le16 *) buf->p = cpu_to_le16(val); @@ -100,7 +100,7 @@ static void buf_put_int16(struct cbuf *buf, u16 val) } } -static void buf_put_int32(struct cbuf *buf, u32 val) +static inline void buf_put_int32(struct cbuf *buf, u32 val) { if (buf_check_size(buf, 4)) { *(__le32 *)buf->p = cpu_to_le32(val); @@ -108,7 +108,7 @@ static void buf_put_int32(struct cbuf *buf, u32 val) } } -static void buf_put_int64(struct cbuf *buf, u64 val) +static inline void buf_put_int64(struct cbuf *buf, u64 val) { if (buf_check_size(buf, 8)) { *(__le64 *)buf->p = cpu_to_le64(val); @@ -116,7 +116,7 @@ static void buf_put_int64(struct cbuf *buf, u64 val) } } -static void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) +static inline void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) { if (buf_check_size(buf, slen + 2)) { buf_put_int16(buf, slen); @@ -130,7 +130,7 @@ static inline void buf_put_string(struct cbuf *buf, const char *s) buf_put_stringn(buf, s, strlen(s)); } -static u8 buf_get_int8(struct cbuf *buf) +static inline u8 buf_get_int8(struct cbuf *buf) { u8 ret = 0; @@ -142,7 +142,7 @@ static u8 buf_get_int8(struct cbuf *buf) return ret; } -static u16 buf_get_int16(struct cbuf *buf) +static inline u16 buf_get_int16(struct cbuf *buf) { u16 ret = 0; @@ -154,7 +154,7 @@ static u16 buf_get_int16(struct cbuf *buf) return ret; } -static u32 buf_get_int32(struct cbuf *buf) +static inline u32 buf_get_int32(struct cbuf *buf) { u32 ret = 0; @@ -166,7 +166,7 @@ static u32 buf_get_int32(struct cbuf *buf) return ret; } -static u64 buf_get_int64(struct cbuf *buf) +static inline u64 buf_get_int64(struct cbuf *buf) { u64 ret = 0; @@ -178,7 +178,7 @@ static u64 buf_get_int64(struct cbuf *buf) return ret; } -static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr) +static inline void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr) { vstr->len = buf_get_int16(buf); if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) { @@ -190,7 +190,7 @@ static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr) } } -static void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid) +static inline void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid) { qid->type = buf_get_int8(bufp); qid->version = buf_get_int32(bufp); @@ -254,7 +254,7 @@ static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended) * */ -static void +static inline void buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended) { stat->size = buf_get_int16(bufp); @@ -427,7 +427,7 @@ static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p) buf_put_int64(bufp, val); } -static void +static inline void v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str) { if (data) { @@ -441,7 +441,7 @@ v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str) buf_put_stringn(bufp, data, str->len); } -static int +static inline int v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count, unsigned char **pdata) { diff --git a/trunk/fs/autofs4/root.c b/trunk/fs/autofs4/root.c index 62d8d4acb8bb..e93a7ae467c9 100644 --- a/trunk/fs/autofs4/root.c +++ b/trunk/fs/autofs4/root.c @@ -195,8 +195,6 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) if (!empty) d_invalidate(dentry); - nd.dentry = dentry; - nd.mnt = mnt; nd.flags = LOOKUP_DIRECTORY; status = (dentry->d_op->d_revalidate)(dentry, &nd); diff --git a/trunk/fs/binfmt_elf.c b/trunk/fs/binfmt_elf.c index 1b117a441298..f979ebbce49c 100644 --- a/trunk/fs/binfmt_elf.c +++ b/trunk/fs/binfmt_elf.c @@ -1218,7 +1218,7 @@ static int writenote(struct memelfnote *men, struct file *file) if (!dump_seek(file, (off))) \ goto end_coredump; -static void fill_elf_header(struct elfhdr *elf, int segs) +static inline void fill_elf_header(struct elfhdr *elf, int segs) { memcpy(elf->e_ident, ELFMAG, SELFMAG); elf->e_ident[EI_CLASS] = ELF_CLASS; @@ -1243,7 +1243,7 @@ static void fill_elf_header(struct elfhdr *elf, int segs) return; } -static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset) +static inline void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset) { phdr->p_type = PT_NOTE; phdr->p_offset = offset; diff --git a/trunk/fs/binfmt_misc.c b/trunk/fs/binfmt_misc.c index 6a7b730c206b..9ccc7d8275b8 100644 --- a/trunk/fs/binfmt_misc.c +++ b/trunk/fs/binfmt_misc.c @@ -264,7 +264,7 @@ static int unquote(char *from) return p - from; } -static char * check_special_flags (char * sfs, Node * e) +static inline char * check_special_flags (char * sfs, Node * e) { char * p = sfs; int cont = 1; diff --git a/trunk/fs/bio.c b/trunk/fs/bio.c index bbc442b8c867..7b3069589951 100644 --- a/trunk/fs/bio.c +++ b/trunk/fs/bio.c @@ -123,7 +123,7 @@ static void bio_fs_destructor(struct bio *bio) bio_free(bio, fs_bio_set); } -void bio_init(struct bio *bio) +inline void bio_init(struct bio *bio) { bio->bi_next = NULL; bio->bi_bdev = NULL; @@ -253,7 +253,7 @@ inline int bio_hw_segments(request_queue_t *q, struct bio *bio) * the actual data it points to. Reference count of returned * bio will be one. */ -void __bio_clone(struct bio *bio, struct bio *bio_src) +inline void __bio_clone(struct bio *bio, struct bio *bio_src) { request_queue_t *q = bdev_get_queue(bio_src->bi_bdev); diff --git a/trunk/fs/buffer.c b/trunk/fs/buffer.c index 7cdf48a9a501..b9bb7ad6897b 100644 --- a/trunk/fs/buffer.c +++ b/trunk/fs/buffer.c @@ -1165,7 +1165,7 @@ grow_dev_page(struct block_device *bdev, sector_t block, * some of those buffers may be aliases of filesystem data. * grow_dev_page() will go BUG() if this happens. */ -static int +static inline int grow_buffers(struct block_device *bdev, sector_t block, int size) { struct page *page; @@ -1391,7 +1391,7 @@ static void bh_lru_install(struct buffer_head *bh) /* * Look up the bh in this cpu's LRU. If it's there, move it to the head. */ -static struct buffer_head * +static inline struct buffer_head * lookup_bh_lru(struct block_device *bdev, sector_t block, int size) { struct buffer_head *ret = NULL; @@ -1541,7 +1541,7 @@ EXPORT_SYMBOL(set_bh_page); /* * Called when truncating a buffer on a page completely. */ -static void discard_buffer(struct buffer_head * bh) +static inline void discard_buffer(struct buffer_head * bh) { lock_buffer(bh); clear_buffer_dirty(bh); diff --git a/trunk/fs/char_dev.c b/trunk/fs/char_dev.c index 21195c481637..3b1b1eefdbb0 100644 --- a/trunk/fs/char_dev.c +++ b/trunk/fs/char_dev.c @@ -35,7 +35,7 @@ static struct char_device_struct { unsigned int major; unsigned int baseminor; int minorct; - char name[64]; + const char *name; struct file_operations *fops; struct cdev *cdev; /* will die */ } *chrdevs[MAX_PROBE_HASH]; @@ -46,84 +46,34 @@ static inline int major_to_index(int major) return major % MAX_PROBE_HASH; } -struct chrdev_info { - int index; - struct char_device_struct *cd; -}; - -void *get_next_chrdev(void *dev) -{ - struct chrdev_info *info; - - if (dev == NULL) { - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - goto out; - info->index=0; - info->cd = chrdevs[info->index]; - if (info->cd) - goto out; - } else { - info = dev; - } - - while (info->index < ARRAY_SIZE(chrdevs)) { - if (info->cd) - info->cd = info->cd->next; - if (info->cd) - goto out; - /* - * No devices on this chain, move to the next - */ - info->index++; - info->cd = (info->index < ARRAY_SIZE(chrdevs)) ? - chrdevs[info->index] : NULL; - if (info->cd) - goto out; - } - -out: - return info; -} - -void *acquire_chrdev_list(void) -{ - down(&chrdevs_lock); - return get_next_chrdev(NULL); -} - -void release_chrdev_list(void *dev) -{ - up(&chrdevs_lock); - kfree(dev); -} - - -int count_chrdev_list(void) +/* get char device names in somewhat random order */ +int get_chrdev_list(char *page) { struct char_device_struct *cd; - int i, count; + int i, len; - count = 0; + len = sprintf(page, "Character devices:\n"); + down(&chrdevs_lock); for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) { - for (cd = chrdevs[i]; cd; cd = cd->next) - count++; + for (cd = chrdevs[i]; cd; cd = cd->next) { + /* + * if the current name, plus the 5 extra characters + * in the device line for this entry + * would run us off the page, we're done + */ + if ((len+strlen(cd->name) + 5) >= PAGE_SIZE) + goto page_full; + + + len += sprintf(page+len, "%3d %s\n", + cd->major, cd->name); + } } +page_full: + up(&chrdevs_lock); - return count; -} - -int get_chrdev_info(void *dev, int *major, char **name) -{ - struct chrdev_info *info = dev; - - if (info->cd == NULL) - return 1; - - *major = info->cd->major; - *name = info->cd->name; - return 0; + return len; } /* @@ -171,7 +121,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, cd->major = major; cd->baseminor = baseminor; cd->minorct = minorct; - strncpy(cd->name,name, 64); + cd->name = name; i = major_to_index(major); diff --git a/trunk/fs/compat.c b/trunk/fs/compat.c index 2468ac1df2f0..271b75d1597f 100644 --- a/trunk/fs/compat.c +++ b/trunk/fs/compat.c @@ -1537,7 +1537,7 @@ int compat_do_execve(char * filename, * Ooo, nasty. We need here to frob 32-bit unsigned longs to * 64-bit unsigned longs. */ -static +static inline int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, unsigned long *fdset) { @@ -1570,7 +1570,7 @@ int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, return 0; } -static +static inline void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, unsigned long *fdset) { diff --git a/trunk/fs/dcache.c b/trunk/fs/dcache.c index 86bdb93789c6..134d6775183f 100644 --- a/trunk/fs/dcache.c +++ b/trunk/fs/dcache.c @@ -94,7 +94,7 @@ static void d_free(struct dentry *dentry) * d_iput() operation if defined. * Called with dcache_lock and per dentry lock held, drops both. */ -static void dentry_iput(struct dentry * dentry) +static inline void dentry_iput(struct dentry * dentry) { struct inode *inode = dentry->d_inode; if (inode) { diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index 62b40af68cc4..b5bcf1aae0ab 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -575,7 +575,7 @@ static int exec_mmap(struct mm_struct *mm) * disturbing other processes. (Other processes might share the signal * table via the CLONE_SIGHAND option to clone().) */ -static int de_thread(struct task_struct *tsk) +static inline int de_thread(struct task_struct *tsk) { struct signal_struct *sig = tsk->signal; struct sighand_struct *newsighand, *oldsighand = tsk->sighand; @@ -780,7 +780,7 @@ static int de_thread(struct task_struct *tsk) * so that a new one can be started */ -static void flush_old_files(struct files_struct * files) +static inline void flush_old_files(struct files_struct * files) { long j = -1; struct fdtable *fdt; @@ -964,7 +964,7 @@ int prepare_binprm(struct linux_binprm *bprm) EXPORT_SYMBOL(prepare_binprm); -static int unsafe_exec(struct task_struct *p) +static inline int unsafe_exec(struct task_struct *p) { int unsafe = 0; if (p->ptrace & PT_PTRACED) { diff --git a/trunk/fs/ext2/namei.c b/trunk/fs/ext2/namei.c index ad1432a2a62e..c5513953c825 100644 --- a/trunk/fs/ext2/namei.c +++ b/trunk/fs/ext2/namei.c @@ -83,7 +83,10 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, str if (!inode) return ERR_PTR(-EACCES); } - return d_splice_alias(inode, dentry); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return NULL; } struct dentry *ext2_get_parent(struct dentry *child) diff --git a/trunk/fs/ext3/namei.c b/trunk/fs/ext3/namei.c index 8bd8ac077704..af193a304ee5 100644 --- a/trunk/fs/ext3/namei.c +++ b/trunk/fs/ext3/namei.c @@ -1005,7 +1005,10 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str if (!inode) return ERR_PTR(-EACCES); } - return d_splice_alias(inode, dentry); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return NULL; } diff --git a/trunk/fs/fcntl.c b/trunk/fs/fcntl.c index 5f96786d1c73..d0767fe58362 100644 --- a/trunk/fs/fcntl.c +++ b/trunk/fs/fcntl.c @@ -36,7 +36,7 @@ void fastcall set_close_on_exec(unsigned int fd, int flag) spin_unlock(&files->file_lock); } -static int get_close_on_exec(unsigned int fd) +static inline int get_close_on_exec(unsigned int fd) { struct files_struct *files = current->files; struct fdtable *fdt; diff --git a/trunk/fs/hugetlbfs/inode.c b/trunk/fs/hugetlbfs/inode.c index f568102da1e8..ab4c3a9d51b8 100644 --- a/trunk/fs/hugetlbfs/inode.c +++ b/trunk/fs/hugetlbfs/inode.c @@ -402,7 +402,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid, inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; info = HUGETLBFS_I(inode); - mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, NULL); + mpol_shared_policy_init(&info->policy); switch (mode & S_IFMT) { default: init_special_inode(inode, mode, dev); diff --git a/trunk/fs/isofs/namei.c b/trunk/fs/isofs/namei.c index e7ba0c30e071..e37e82b7cbf0 100644 --- a/trunk/fs/isofs/namei.c +++ b/trunk/fs/isofs/namei.c @@ -185,5 +185,8 @@ struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct n } } unlock_kernel(); - return d_splice_alias(inode, dentry); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return NULL; } diff --git a/trunk/fs/jffs2/build.c b/trunk/fs/jffs2/build.c index 70f7a896c04a..fff108bb118b 100644 --- a/trunk/fs/jffs2/build.c +++ b/trunk/fs/jffs2/build.c @@ -47,7 +47,7 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c) ic = next_inode(&i, ic, (c))) -static void jffs2_build_inode_pass1(struct jffs2_sb_info *c, +static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) { struct jffs2_full_dirent *fd; diff --git a/trunk/fs/jffs2/nodelist.c b/trunk/fs/jffs2/nodelist.c index b635e167a3fa..c79eebb8ab32 100644 --- a/trunk/fs/jffs2/nodelist.c +++ b/trunk/fs/jffs2/nodelist.c @@ -134,7 +134,7 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ /* * Allocate and initializes a new fragment. */ -static struct jffs2_node_frag * new_fragment(struct jffs2_full_dnode *fn, uint32_t ofs, uint32_t size) +static inline struct jffs2_node_frag * new_fragment(struct jffs2_full_dnode *fn, uint32_t ofs, uint32_t size) { struct jffs2_node_frag *newfrag; @@ -513,7 +513,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info * * Checks the node if we are in the checking stage. */ -static int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn) +static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn) { int ret; diff --git a/trunk/fs/lockd/xdr.c b/trunk/fs/lockd/xdr.c index 200fbda2c6d1..f01e9c0d2677 100644 --- a/trunk/fs/lockd/xdr.c +++ b/trunk/fs/lockd/xdr.c @@ -44,7 +44,7 @@ loff_t_to_s32(loff_t offset) /* * XDR functions for basic NLM types */ -static u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c) +static inline u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c) { unsigned int len; @@ -79,7 +79,7 @@ nlm_encode_cookie(u32 *p, struct nlm_cookie *c) return p; } -static u32 * +static inline u32 * nlm_decode_fh(u32 *p, struct nfs_fh *f) { unsigned int len; @@ -119,7 +119,7 @@ nlm_encode_oh(u32 *p, struct xdr_netobj *oh) return xdr_encode_netobj(p, oh); } -static u32 * +static inline u32 * nlm_decode_lock(u32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; diff --git a/trunk/fs/mbcache.c b/trunk/fs/mbcache.c index f5bbe4c97c58..0f1e4530670f 100644 --- a/trunk/fs/mbcache.c +++ b/trunk/fs/mbcache.c @@ -126,7 +126,7 @@ __mb_cache_entry_is_hashed(struct mb_cache_entry *ce) } -static void +static inline void __mb_cache_entry_unhash(struct mb_cache_entry *ce) { int n; @@ -139,7 +139,7 @@ __mb_cache_entry_unhash(struct mb_cache_entry *ce) } -static void +static inline void __mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask) { struct mb_cache *cache = ce->e_cache; @@ -158,7 +158,7 @@ __mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask) } -static void +static inline void __mb_cache_entry_release_unlock(struct mb_cache_entry *ce) { /* Wake up all processes queuing for this cache entry. */ diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index 33fb5bd34a81..1e5746eb1380 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -113,7 +113,7 @@ * POSIX.1 2.4: an empty pathname is invalid (ENOENT). * PATH_MAX includes the nul terminator --RR. */ -static int do_getname(const char __user *filename, char *page) +static inline int do_getname(const char __user *filename, char *page) { int retval; unsigned long len = PATH_MAX; @@ -396,7 +396,7 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, * short-cut DAC fails, then call permission() to do more * complete permission check. */ -static int exec_permission_lite(struct inode *inode, +static inline int exec_permission_lite(struct inode *inode, struct nameidata *nd) { umode_t mode = inode->i_mode; @@ -486,7 +486,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s static int __emul_lookup_dentry(const char *, struct nameidata *); /* SMP-safe */ -static __always_inline int +static inline int walk_init_root(const char *name, struct nameidata *nd) { read_lock(¤t->fs->lock); @@ -504,7 +504,7 @@ walk_init_root(const char *name, struct nameidata *nd) return 1; } -static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link) +static inline int __vfs_follow_link(struct nameidata *nd, const char *link) { int res = 0; char *name; @@ -544,7 +544,7 @@ struct path { struct dentry *dentry; }; -static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) +static inline int __do_follow_link(struct path *path, struct nameidata *nd) { int error; void *cookie; @@ -690,7 +690,7 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry) return 0; } -static __always_inline void follow_dotdot(struct nameidata *nd) +static inline void follow_dotdot(struct nameidata *nd) { while(1) { struct vfsmount *parent; @@ -1294,7 +1294,7 @@ static inline int check_sticky(struct inode *dir, struct inode *inode) * 10. We don't allow removal of NFS sillyrenamed files; it's handled by * nfs_async_unlink(). */ -static int may_delete(struct inode *dir,struct dentry *victim,int isdir) +static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir) { int error; @@ -2315,7 +2315,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, return error; } -static int do_rename(const char * oldname, const char * newname) +static inline int do_rename(const char * oldname, const char * newname) { int error = 0; struct dentry * old_dir, * new_dir; diff --git a/trunk/fs/ncpfs/inode.c b/trunk/fs/ncpfs/inode.c index d277a58bd128..8c8839203cd5 100644 --- a/trunk/fs/ncpfs/inode.c +++ b/trunk/fs/ncpfs/inode.c @@ -716,8 +716,10 @@ static void ncp_put_super(struct super_block *sb) fput(server->ncp_filp); kill_proc(server->m.wdog_pid, SIGTERM, 1); - kfree(server->priv.data); - kfree(server->auth.object_name); + if (server->priv.data) + ncp_kfree_s(server->priv.data, server->priv.len); + if (server->auth.object_name) + ncp_kfree_s(server->auth.object_name, server->auth.object_name_len); vfree(server->packet); sb->s_fs_info = NULL; kfree(server); @@ -956,6 +958,11 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr) return result; } +#ifdef DEBUG_NCP_MALLOC +int ncp_malloced; +int ncp_current_malloced; +#endif + static struct super_block *ncp_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { @@ -974,6 +981,10 @@ static int __init init_ncp_fs(void) int err; DPRINTK("ncpfs: init_module called\n"); +#ifdef DEBUG_NCP_MALLOC + ncp_malloced = 0; + ncp_current_malloced = 0; +#endif err = init_inodecache(); if (err) goto out1; @@ -992,6 +1003,10 @@ static void __exit exit_ncp_fs(void) DPRINTK("ncpfs: cleanup_module called\n"); unregister_filesystem(&ncp_fs_type); destroy_inodecache(); +#ifdef DEBUG_NCP_MALLOC + PRINTK("ncp_malloced: %d\n", ncp_malloced); + PRINTK("ncp_current_malloced: %d\n", ncp_current_malloced); +#endif } module_init(init_ncp_fs) diff --git a/trunk/fs/ncpfs/ioctl.c b/trunk/fs/ncpfs/ioctl.c index eb3813ad136f..d6e0c089e1b1 100644 --- a/trunk/fs/ncpfs/ioctl.c +++ b/trunk/fs/ncpfs/ioctl.c @@ -518,11 +518,10 @@ int ncp_ioctl(struct inode *inode, struct file *filp, if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN) return -ENOMEM; if (user.object_name_len) { - newname = kmalloc(user.object_name_len, GFP_USER); - if (!newname) - return -ENOMEM; + newname = ncp_kmalloc(user.object_name_len, GFP_USER); + if (!newname) return -ENOMEM; if (copy_from_user(newname, user.object_name, user.object_name_len)) { - kfree(newname); + ncp_kfree_s(newname, user.object_name_len); return -EFAULT; } } else { @@ -541,8 +540,8 @@ int ncp_ioctl(struct inode *inode, struct file *filp, server->priv.len = 0; server->priv.data = NULL; /* leave critical section */ - kfree(oldprivate); - kfree(oldname); + if (oldprivate) ncp_kfree_s(oldprivate, oldprivatelen); + if (oldname) ncp_kfree_s(oldname, oldnamelen); return 0; } case NCP_IOC_GETPRIVATEDATA: @@ -582,11 +581,10 @@ int ncp_ioctl(struct inode *inode, struct file *filp, if (user.len > NCP_PRIVATE_DATA_MAX_LEN) return -ENOMEM; if (user.len) { - new = kmalloc(user.len, GFP_USER); - if (!new) - return -ENOMEM; + new = ncp_kmalloc(user.len, GFP_USER); + if (!new) return -ENOMEM; if (copy_from_user(new, user.data, user.len)) { - kfree(new); + ncp_kfree_s(new, user.len); return -EFAULT; } } else { @@ -598,7 +596,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, server->priv.len = user.len; server->priv.data = new; /* leave critical section */ - kfree(old); + if (old) ncp_kfree_s(old, oldlen); return 0; } diff --git a/trunk/fs/nfsd/nfsxdr.c b/trunk/fs/nfsd/nfsxdr.c index e3a0797dd56b..aa7bb41b293d 100644 --- a/trunk/fs/nfsd/nfsxdr.c +++ b/trunk/fs/nfsd/nfsxdr.c @@ -37,7 +37,7 @@ static u32 nfs_ftypes[] = { /* * XDR functions for basic NFS types */ -static u32 * +static inline u32 * decode_fh(u32 *p, struct svc_fh *fhp) { fh_init(fhp, NFS_FHSIZE); @@ -151,7 +151,7 @@ decode_sattr(u32 *p, struct iattr *iap) return p; } -static u32 * +static inline u32 * encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp, struct kstat *stat) { diff --git a/trunk/fs/pipe.c b/trunk/fs/pipe.c index d722579df79a..eef0f29e86ef 100644 --- a/trunk/fs/pipe.c +++ b/trunk/fs/pipe.c @@ -50,7 +50,7 @@ void pipe_wait(struct inode * inode) mutex_lock(PIPE_MUTEX(*inode)); } -static int +static inline int pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len) { unsigned long copy; @@ -70,7 +70,7 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len) return 0; } -static int +static inline int pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len) { unsigned long copy; diff --git a/trunk/fs/proc/proc_misc.c b/trunk/fs/proc/proc_misc.c index 8f8014285a34..63bf6c00fa0c 100644 --- a/trunk/fs/proc/proc_misc.c +++ b/trunk/fs/proc/proc_misc.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -63,6 +62,7 @@ */ extern int get_hardware_list(char *); extern int get_stram_list(char *); +extern int get_chrdev_list(char *); extern int get_filesystem_list(char *); extern int get_exec_domain_list(char *); extern int get_dma_list(char *); @@ -248,154 +248,6 @@ static int cpuinfo_open(struct inode *inode, struct file *file) { return seq_open(file, &cpuinfo_op); } - -enum devinfo_states { - CHR_HDR, - CHR_LIST, - BLK_HDR, - BLK_LIST, - DEVINFO_DONE -}; - -struct devinfo_state { - void *chrdev; - void *blkdev; - unsigned int num_records; - unsigned int cur_record; - enum devinfo_states state; -}; - -static void *devinfo_start(struct seq_file *f, loff_t *pos) -{ - struct devinfo_state *info = f->private; - - if (*pos) { - if ((info) && (*pos <= info->num_records)) - return info; - return NULL; - } - info = kmalloc(sizeof(*info), GFP_KERNEL); - f->private = info; - info->chrdev = acquire_chrdev_list(); - info->blkdev = acquire_blkdev_list(); - info->state = CHR_HDR; - info->num_records = count_chrdev_list(); - info->num_records += count_blkdev_list(); - info->num_records += 2; /* Character and Block headers */ - *pos = 1; - info->cur_record = *pos; - return info; -} - -static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos) -{ - int idummy; - char *ndummy; - struct devinfo_state *info = f->private; - - switch (info->state) { - case CHR_HDR: - info->state = CHR_LIST; - (*pos)++; - /*fallthrough*/ - case CHR_LIST: - if (get_chrdev_info(info->chrdev,&idummy,&ndummy)) { - /* - * The character dev list is complete - */ - info->state = BLK_HDR; - } else { - info->chrdev = get_next_chrdev(info->chrdev); - } - (*pos)++; - break; - case BLK_HDR: - info->state = BLK_LIST; - (*pos)++; - break; - case BLK_LIST: - if (get_blkdev_info(info->blkdev,&idummy,&ndummy)) { - /* - * The block dev list is complete - */ - info->state = DEVINFO_DONE; - } else { - info->blkdev = get_next_blkdev(info->blkdev); - } - (*pos)++; - break; - case DEVINFO_DONE: - (*pos)++; - info->cur_record = *pos; - info = NULL; - break; - default: - break; - } - if (info) - info->cur_record = *pos; - return info; -} - -static void devinfo_stop(struct seq_file *f, void *v) -{ - struct devinfo_state *info = f->private; - - if (info) { - release_chrdev_list(info->chrdev); - release_blkdev_list(info->blkdev); - f->private = NULL; - kfree(info); - } -} - -static int devinfo_show(struct seq_file *f, void *arg) -{ - int major; - char *name; - struct devinfo_state *info = f->private; - - switch(info->state) { - case CHR_HDR: - seq_printf(f,"Character devices:\n"); - /* fallthrough */ - case CHR_LIST: - if (!get_chrdev_info(info->chrdev,&major,&name)) - seq_printf(f,"%3d %s\n",major,name); - break; - case BLK_HDR: - seq_printf(f,"\nBlock devices:\n"); - /* fallthrough */ - case BLK_LIST: - if (!get_blkdev_info(info->blkdev,&major,&name)) - seq_printf(f,"%3d %s\n",major,name); - break; - default: - break; - } - - return 0; -} - -static struct seq_operations devinfo_op = { - .start = devinfo_start, - .next = devinfo_next, - .stop = devinfo_stop, - .show = devinfo_show, -}; - -static int devinfo_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &devinfo_op); -} - -static struct file_operations proc_devinfo_operations = { - .open = devinfo_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - static struct file_operations proc_cpuinfo_operations = { .open = cpuinfo_open, .read = seq_read, @@ -598,6 +450,14 @@ static struct file_operations proc_stat_operations = { .release = single_release, }; +static int devices_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = get_chrdev_list(page); + len += get_blkdev_list(page+len, len); + return proc_calc_metrics(page, start, off, count, eof, len); +} + /* * /proc/interrupts */ @@ -722,6 +582,7 @@ void __init proc_misc_init(void) #ifdef CONFIG_STRAM_PROC {"stram", stram_read_proc}, #endif + {"devices", devices_read_proc}, {"filesystems", filesystems_read_proc}, {"cmdline", cmdline_read_proc}, {"locks", locks_read_proc}, @@ -737,7 +598,6 @@ void __init proc_misc_init(void) entry = create_proc_entry("kmsg", S_IRUSR, &proc_root); if (entry) entry->proc_fops = &proc_kmsg_operations; - create_seq_entry("devices", 0, &proc_devinfo_operations); create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); create_seq_entry("partitions", 0, &proc_partitions_operations); create_seq_entry("stat", 0, &proc_stat_operations); diff --git a/trunk/fs/quota_v2.c b/trunk/fs/quota_v2.c index a4ef91bb4f3b..7afcbb1b9376 100644 --- a/trunk/fs/quota_v2.c +++ b/trunk/fs/quota_v2.c @@ -35,8 +35,7 @@ static int v2_check_quota_file(struct super_block *sb, int type) size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0); if (size != sizeof(struct v2_disk_dqheader)) { - printk("quota_v2: failed read expected=%d got=%d\n", - sizeof(struct v2_disk_dqheader), size); + printk("failed read\n"); return 0; } if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] || diff --git a/trunk/fs/reiserfs/namei.c b/trunk/fs/reiserfs/namei.c index 8f8d8d01107c..3549067c42d9 100644 --- a/trunk/fs/reiserfs/namei.c +++ b/trunk/fs/reiserfs/namei.c @@ -375,7 +375,11 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, return ERR_PTR(-EIO); } - return d_splice_alias(inode, dentry); + if (inode) + return d_splice_alias(inode, dentry); + + d_add(dentry, inode); + return NULL; } /* diff --git a/trunk/fs/smbfs/Makefile b/trunk/fs/smbfs/Makefile index 6673ee82cb4c..93246b7dd6fb 100644 --- a/trunk/fs/smbfs/Makefile +++ b/trunk/fs/smbfs/Makefile @@ -13,6 +13,7 @@ smbfs-objs := proc.o dir.o cache.o sock.o inode.o file.o ioctl.o getopt.o \ EXTRA_CFLAGS += -DSMBFS_PARANOIA #EXTRA_CFLAGS += -DSMBFS_DEBUG #EXTRA_CFLAGS += -DSMBFS_DEBUG_VERBOSE +#EXTRA_CFLAGS += -DDEBUG_SMB_MALLOC #EXTRA_CFLAGS += -DDEBUG_SMB_TIMESTAMP #EXTRA_CFLAGS += -Werror diff --git a/trunk/fs/smbfs/inode.c b/trunk/fs/smbfs/inode.c index 02e3e82d465c..6ec88bf59b2d 100644 --- a/trunk/fs/smbfs/inode.c +++ b/trunk/fs/smbfs/inode.c @@ -487,11 +487,11 @@ smb_put_super(struct super_block *sb) if (server->conn_pid) kill_proc(server->conn_pid, SIGTERM, 1); - kfree(server->ops); + smb_kfree(server->ops); smb_unload_nls(server); sb->s_fs_info = NULL; smb_unlock_server(server); - kfree(server); + smb_kfree(server); } static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) @@ -519,10 +519,11 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) sb->s_op = &smb_sops; sb->s_time_gran = 100; - server = kzalloc(sizeof(struct smb_sb_info), GFP_KERNEL); + server = smb_kmalloc(sizeof(struct smb_sb_info), GFP_KERNEL); if (!server) goto out_no_server; sb->s_fs_info = server; + memset(server, 0, sizeof(struct smb_sb_info)); server->super_block = sb; server->mnt = NULL; @@ -541,8 +542,8 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) /* FIXME: move these to the smb_sb_info struct */ VERBOSE("alloc chunk = %d\n", sizeof(struct smb_ops) + sizeof(struct smb_mount_data_kernel)); - mem = kmalloc(sizeof(struct smb_ops) + - sizeof(struct smb_mount_data_kernel), GFP_KERNEL); + mem = smb_kmalloc(sizeof(struct smb_ops) + + sizeof(struct smb_mount_data_kernel), GFP_KERNEL); if (!mem) goto out_no_mem; @@ -620,12 +621,12 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) out_no_smbiod: smb_unload_nls(server); out_bad_option: - kfree(mem); + smb_kfree(mem); out_no_mem: if (!server->mnt) printk(KERN_ERR "smb_fill_super: allocation failure\n"); sb->s_fs_info = NULL; - kfree(server); + smb_kfree(server); goto out_fail; out_wrong_data: printk(KERN_ERR "smbfs: mount_data version %d is not supported\n", ver); @@ -781,6 +782,12 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr) return error; } +#ifdef DEBUG_SMB_MALLOC +int smb_malloced; +int smb_current_kmalloced; +int smb_current_vmalloced; +#endif + static struct super_block *smb_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { @@ -800,6 +807,12 @@ static int __init init_smb_fs(void) int err; DEBUG1("registering ...\n"); +#ifdef DEBUG_SMB_MALLOC + smb_malloced = 0; + smb_current_kmalloced = 0; + smb_current_vmalloced = 0; +#endif + err = init_inodecache(); if (err) goto out_inode; @@ -824,6 +837,11 @@ static void __exit exit_smb_fs(void) unregister_filesystem(&smb_fs_type); smb_destroy_request_cache(); destroy_inodecache(); +#ifdef DEBUG_SMB_MALLOC + printk(KERN_DEBUG "smb_malloced: %d\n", smb_malloced); + printk(KERN_DEBUG "smb_current_kmalloced: %d\n",smb_current_kmalloced); + printk(KERN_DEBUG "smb_current_vmalloced: %d\n",smb_current_vmalloced); +#endif } module_init(init_smb_fs) diff --git a/trunk/fs/smbfs/request.c b/trunk/fs/smbfs/request.c index c71c375863cc..a0f296d9928a 100644 --- a/trunk/fs/smbfs/request.c +++ b/trunk/fs/smbfs/request.c @@ -68,7 +68,7 @@ static struct smb_request *smb_do_alloc_request(struct smb_sb_info *server, goto out; if (bufsize > 0) { - buf = kmalloc(bufsize, GFP_NOFS); + buf = smb_kmalloc(bufsize, GFP_NOFS); if (!buf) { kmem_cache_free(req_cachep, req); return NULL; @@ -124,8 +124,9 @@ static void smb_free_request(struct smb_request *req) { atomic_dec(&req->rq_server->nr_requests); if (req->rq_buffer && !(req->rq_flags & SMB_REQ_STATIC)) - kfree(req->rq_buffer); - kfree(req->rq_trans2buffer); + smb_kfree(req->rq_buffer); + if (req->rq_trans2buffer) + smb_kfree(req->rq_trans2buffer); kmem_cache_free(req_cachep, req); } @@ -182,7 +183,8 @@ static int smb_setup_request(struct smb_request *req) req->rq_err = 0; req->rq_errno = 0; req->rq_fragment = 0; - kfree(req->rq_trans2buffer); + if (req->rq_trans2buffer) + smb_kfree(req->rq_trans2buffer); return 0; } @@ -645,9 +647,10 @@ static int smb_recv_trans2(struct smb_sb_info *server, struct smb_request *req) goto out_too_long; req->rq_trans2bufsize = buf_len; - req->rq_trans2buffer = kzalloc(buf_len, GFP_NOFS); + req->rq_trans2buffer = smb_kmalloc(buf_len, GFP_NOFS); if (!req->rq_trans2buffer) goto out_no_mem; + memset(req->rq_trans2buffer, 0, buf_len); req->rq_parm = req->rq_trans2buffer; req->rq_data = req->rq_trans2buffer + parm_tot; diff --git a/trunk/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/trunk/include/asm-arm/arch-ixp2000/ixp2000-regs.h index 2b57f91b4ebd..8cf70ff160af 100644 --- a/trunk/include/asm-arm/arch-ixp2000/ixp2000-regs.h +++ b/trunk/include/asm-arm/arch-ixp2000/ixp2000-regs.h @@ -26,8 +26,6 @@ * fc000000 da000000 16M PCI CFG0 * fd000000 d8000000 16M PCI I/O * fe[0-7]00000 8M per-platform mappings - * fe900000 80000000 1M SRAM #0 (first MB) - * fea00000 cb400000 1M SCRATCH ring get/put * feb00000 c8000000 1M MSF * fec00000 df000000 1M PCI CSRs * fed00000 de000000 1M PCI CREG @@ -93,14 +91,6 @@ #define IXP2000_MSF_VIRT_BASE 0xfeb00000 #define IXP2000_MSF_SIZE 0x00100000 -#define IXP2000_SCRATCH_RING_PHYS_BASE 0xcb400000 -#define IXP2000_SCRATCH_RING_VIRT_BASE 0xfea00000 -#define IXP2000_SCRATCH_RING_SIZE 0x00100000 - -#define IXP2000_SRAM0_PHYS_BASE 0x80000000 -#define IXP2000_SRAM0_VIRT_BASE 0xfe900000 -#define IXP2000_SRAM0_SIZE 0x00100000 - #define IXP2000_PCI_IO_PHYS_BASE 0xd8000000 #define IXP2000_PCI_IO_VIRT_BASE 0xfd000000 #define IXP2000_PCI_IO_SIZE 0x01000000 diff --git a/trunk/include/asm-arm/arch-versatile/entry-macro.S b/trunk/include/asm-arm/arch-versatile/entry-macro.S index feff771c0a0a..58f0d71759f6 100644 --- a/trunk/include/asm-arm/arch-versatile/entry-macro.S +++ b/trunk/include/asm-arm/arch-versatile/entry-macro.S @@ -8,7 +8,6 @@ * warranty of any kind, whether express or implied. */ #include -#include .macro disable_fiq .endm diff --git a/trunk/include/asm-arm/arch-versatile/platform.h b/trunk/include/asm-arm/arch-versatile/platform.h index 72ef874567d5..cbdd9fb96332 100644 --- a/trunk/include/asm-arm/arch-versatile/platform.h +++ b/trunk/include/asm-arm/arch-versatile/platform.h @@ -293,7 +293,26 @@ * VERSATILE_SYS_IC * */ -/* VIC definitions in include/asm-arm/hardware/vic.h */ +#define VIC_IRQ_STATUS 0 +#define VIC_FIQ_STATUS 0x04 +#define VIC_IRQ_RAW_STATUS 0x08 +#define VIC_INT_SELECT 0x0C /* 1 = FIQ, 0 = IRQ */ +#define VIC_IRQ_ENABLE 0x10 /* 1 = enable, 0 = disable */ +#define VIC_IRQ_ENABLE_CLEAR 0x14 +#define VIC_IRQ_SOFT 0x18 +#define VIC_IRQ_SOFT_CLEAR 0x1C +#define VIC_PROTECT 0x20 +#define VIC_VECT_ADDR 0x30 +#define VIC_DEF_VECT_ADDR 0x34 +#define VIC_VECT_ADDR0 0x100 /* 0 to 15 */ +#define VIC_VECT_CNTL0 0x200 /* 0 to 15 */ +#define VIC_ITCR 0x300 /* VIC test control register */ + +#define VIC_FIQ_RAW_STATUS 0x08 +#define VIC_FIQ_ENABLE 0x10 /* 1 = enable, 0 = disable */ +#define VIC_FIQ_ENABLE_CLEAR 0x14 +#define VIC_FIQ_SOFT 0x18 +#define VIC_FIQ_SOFT_CLEAR 0x1C #define SIC_IRQ_STATUS 0 #define SIC_IRQ_RAW_STATUS 0x04 @@ -306,6 +325,8 @@ #define SIC_INT_PIC_ENABLES 0x20 /* set interrupt pass through bits */ #define SIC_INT_PIC_ENABLEC 0x24 /* Clear interrupt pass through bits */ +#define VICVectCntl_Enable (1 << 5) + /* ------------------------------------------------------------------------ * Interrupts - bit assignment (primary) * ------------------------------------------------------------------------ diff --git a/trunk/include/asm-arm/hardware/vic.h b/trunk/include/asm-arm/hardware/vic.h deleted file mode 100644 index 81825eb54c9e..000000000000 --- a/trunk/include/asm-arm/hardware/vic.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * linux/include/asm-arm/hardware/vic.h - * - * Copyright (c) ARM Limited 2003. 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __ASM_ARM_HARDWARE_VIC_H -#define __ASM_ARM_HARDWARE_VIC_H - -#define VIC_IRQ_STATUS 0x00 -#define VIC_FIQ_STATUS 0x04 -#define VIC_RAW_STATUS 0x08 -#define VIC_INT_SELECT 0x0c /* 1 = FIQ, 0 = IRQ */ -#define VIC_INT_ENABLE 0x10 /* 1 = enable, 0 = disable */ -#define VIC_INT_ENABLE_CLEAR 0x14 -#define VIC_INT_SOFT 0x18 -#define VIC_INT_SOFT_CLEAR 0x1c -#define VIC_PROTECT 0x20 -#define VIC_VECT_ADDR 0x30 -#define VIC_DEF_VECT_ADDR 0x34 - -#define VIC_VECT_ADDR0 0x100 /* 0 to 15 */ -#define VIC_VECT_CNTL0 0x200 /* 0 to 15 */ -#define VIC_ITCR 0x300 /* VIC test control register */ - -#define VIC_VECT_CNTL_ENABLE (1 << 5) - -#ifndef __ASSEMBLY__ -void vic_init(void __iomem *base, u32 vic_sources); -#endif - -#endif diff --git a/trunk/include/asm-arm/mach/arch.h b/trunk/include/asm-arm/mach/arch.h index 2cd57b4d64d9..eb262e078c46 100644 --- a/trunk/include/asm-arm/mach/arch.h +++ b/trunk/include/asm-arm/mach/arch.h @@ -10,8 +10,6 @@ #ifndef __ASSEMBLY__ -#include - struct tag; struct meminfo; struct sys_timer; @@ -22,7 +20,7 @@ struct machine_desc { * by assembler code in head-armv.S */ unsigned int nr; /* architecture number */ - unsigned int __deprecated phys_ram; /* start of physical ram */ + unsigned int phys_ram; /* start of physical ram */ unsigned int phys_io; /* start of physical io */ unsigned int io_pg_offst; /* byte offset for io * page tabe entry */ diff --git a/trunk/include/asm-arm/page.h b/trunk/include/asm-arm/page.h index 416320d95419..4da1d532cbeb 100644 --- a/trunk/include/asm-arm/page.h +++ b/trunk/include/asm-arm/page.h @@ -170,13 +170,6 @@ extern pmd_t *top_pmd; #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) -/* - * With EABI on ARMv5 and above we must have 64-bit aligned slab pointers. - */ -#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) -#define ARCH_SLAB_MINALIGN 8 -#endif - #endif /* __KERNEL__ */ #include diff --git a/trunk/include/asm-arm/processor.h b/trunk/include/asm-arm/processor.h index 04f4d34c6317..31290694648b 100644 --- a/trunk/include/asm-arm/processor.h +++ b/trunk/include/asm-arm/processor.h @@ -49,12 +49,6 @@ struct thread_struct { #define INIT_THREAD { } -#ifdef CONFIG_MMU -#define nommu_start_thread(regs) do { } while (0) -#else -#define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data -#endif - #define start_thread(regs,pc,sp) \ ({ \ unsigned long *stack = (unsigned long *)sp; \ @@ -71,7 +65,6 @@ struct thread_struct { regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ regs->ARM_r1 = stack[1]; /* r1 (argv) */ \ regs->ARM_r0 = stack[0]; /* r0 (argc) */ \ - nommu_start_thread(regs); \ }) /* Forward declaration, a strange C thing */ diff --git a/trunk/include/asm-arm/ptrace.h b/trunk/include/asm-arm/ptrace.h index 77adb7fa169b..4377e22b7e1a 100644 --- a/trunk/include/asm-arm/ptrace.h +++ b/trunk/include/asm-arm/ptrace.h @@ -23,9 +23,6 @@ #define PTRACE_OLDSETOPTIONS 21 #define PTRACE_GET_THREAD_AREA 22 - -#define PTRACE_SET_SYSCALL 23 - /* * PSR bits */ @@ -63,11 +60,9 @@ #ifndef __ASSEMBLY__ -/* - * This struct defines the way the registers are stored on the - * stack during a system call. Note that sizeof(struct pt_regs) - * has to be a multiple of 8. - */ +/* this struct defines the way the registers are stored on the + stack during a system call. */ + struct pt_regs { long uregs[18]; }; diff --git a/trunk/include/asm-arm/stat.h b/trunk/include/asm-arm/stat.h index 42c0c13999d5..ec4e2c2e3b47 100644 --- a/trunk/include/asm-arm/stat.h +++ b/trunk/include/asm-arm/stat.h @@ -70,7 +70,14 @@ struct stat64 { long long st_size; unsigned long st_blksize; - unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ + +#if defined(__ARMEB__) + unsigned long __pad4; /* Future possible st_blocks hi bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ +#else /* Must be little */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* Future possible st_blocks hi bits */ +#endif unsigned long st_atime; unsigned long st_atime_nsec; @@ -82,6 +89,6 @@ struct stat64 { unsigned long st_ctime_nsec; unsigned long long st_ino; -}; +} __attribute__((packed)); #endif diff --git a/trunk/include/asm-arm/statfs.h b/trunk/include/asm-arm/statfs.h index a02e6a8c3d70..e81f82783b87 100644 --- a/trunk/include/asm-arm/statfs.h +++ b/trunk/include/asm-arm/statfs.h @@ -1,42 +1,6 @@ #ifndef _ASMARM_STATFS_H #define _ASMARM_STATFS_H -#ifndef __KERNEL_STRICT_NAMES -# include -typedef __kernel_fsid_t fsid_t; -#endif - -struct statfs { - __u32 f_type; - __u32 f_bsize; - __u32 f_blocks; - __u32 f_bfree; - __u32 f_bavail; - __u32 f_files; - __u32 f_ffree; - __kernel_fsid_t f_fsid; - __u32 f_namelen; - __u32 f_frsize; - __u32 f_spare[5]; -}; - -/* - * With EABI there is 4 bytes of padding added to this structure. - * Let's pack it so the padding goes away to simplify dual ABI support. - * Note that user space does NOT have to pack this structure. - */ -struct statfs64 { - __u32 f_type; - __u32 f_bsize; - __u64 f_blocks; - __u64 f_bfree; - __u64 f_bavail; - __u64 f_files; - __u64 f_ffree; - __kernel_fsid_t f_fsid; - __u32 f_namelen; - __u32 f_frsize; - __u32 f_spare[5]; -} __attribute__ ((packed,aligned(4))); +#include #endif diff --git a/trunk/include/asm-arm/unistd.h b/trunk/include/asm-arm/unistd.h index 77430d6178ae..d626e70faded 100644 --- a/trunk/include/asm-arm/unistd.h +++ b/trunk/include/asm-arm/unistd.h @@ -15,12 +15,10 @@ #include -#define __NR_OABI_SYSCALL_BASE 0x900000 - -#if defined(__thumb__) || defined(__ARM_EABI__) +#if defined(__thumb__) #define __NR_SYSCALL_BASE 0 #else -#define __NR_SYSCALL_BASE __NR_OABI_SYSCALL_BASE +#define __NR_SYSCALL_BASE 0x900000 #endif /* @@ -375,13 +373,13 @@ #define __sys1(x) __sys2(x) #ifndef __syscall -#if defined(__thumb__) || defined(__ARM_EABI__) -#define __SYS_REG(name) register long __sysreg __asm__("r7") = __NR_##name; -#define __SYS_REG_LIST(regs...) "r" (__sysreg) , ##regs -#define __syscall(name) "swi\t0" +#if defined(__thumb__) +#define __syscall(name) \ + "push {r7}\n\t" \ + "mov r7, #" __sys1(__NR_##name) "\n\t" \ + "swi 0\n\t" \ + "pop {r7}" #else -#define __SYS_REG(name) -#define __SYS_REG_LIST(regs...) regs #define __syscall(name) "swi\t" __sys1(__NR_##name) "" #endif #endif @@ -397,34 +395,33 @@ do { \ #define _syscall0(type,name) \ type name(void) { \ - __SYS_REG(name) \ register long __res_r0 __asm__("r0"); \ long __res; \ __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : __SYS_REG_LIST() ); \ + : \ + : "lr"); \ __res = __res_r0; \ __syscall_return(type,__res); \ } #define _syscall1(type,name,type1,arg1) \ type name(type1 arg1) { \ - __SYS_REG(name) \ register long __r0 __asm__("r0") = (long)arg1; \ register long __res_r0 __asm__("r0"); \ long __res; \ __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : __SYS_REG_LIST( "0" (__r0) ) ); \ + : "r" (__r0) \ + : "lr"); \ __res = __res_r0; \ __syscall_return(type,__res); \ } #define _syscall2(type,name,type1,arg1,type2,arg2) \ type name(type1 arg1,type2 arg2) { \ - __SYS_REG(name) \ register long __r0 __asm__("r0") = (long)arg1; \ register long __r1 __asm__("r1") = (long)arg2; \ register long __res_r0 __asm__("r0"); \ @@ -432,7 +429,8 @@ type name(type1 arg1,type2 arg2) { \ __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : __SYS_REG_LIST( "0" (__r0), "r" (__r1) ) ); \ + : "r" (__r0),"r" (__r1) \ + : "lr"); \ __res = __res_r0; \ __syscall_return(type,__res); \ } @@ -440,7 +438,6 @@ type name(type1 arg1,type2 arg2) { \ #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ type name(type1 arg1,type2 arg2,type3 arg3) { \ - __SYS_REG(name) \ register long __r0 __asm__("r0") = (long)arg1; \ register long __r1 __asm__("r1") = (long)arg2; \ register long __r2 __asm__("r2") = (long)arg3; \ @@ -449,7 +446,8 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \ __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) ) ); \ + : "r" (__r0),"r" (__r1),"r" (__r2) \ + : "lr"); \ __res = __res_r0; \ __syscall_return(type,__res); \ } @@ -457,7 +455,6 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ - __SYS_REG(name) \ register long __r0 __asm__("r0") = (long)arg1; \ register long __r1 __asm__("r1") = (long)arg2; \ register long __r2 __asm__("r2") = (long)arg3; \ @@ -467,7 +464,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) ); \ + : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3) \ + : "lr"); \ __res = __res_r0; \ __syscall_return(type,__res); \ } @@ -475,7 +473,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ - __SYS_REG(name) \ register long __r0 __asm__("r0") = (long)arg1; \ register long __r1 __asm__("r1") = (long)arg2; \ register long __r2 __asm__("r2") = (long)arg3; \ @@ -486,15 +483,14 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \ - "r" (__r3), "r" (__r4) ) ); \ + : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3),"r" (__r4) \ + : "lr"); \ __res = __res_r0; \ __syscall_return(type,__res); \ } #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ - __SYS_REG(name) \ register long __r0 __asm__("r0") = (long)arg1; \ register long __r1 __asm__("r1") = (long)arg2; \ register long __r2 __asm__("r2") = (long)arg3; \ @@ -506,33 +502,30 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6 __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \ - "r" (__r3), "r" (__r4), "r" (__r5) ) ); \ + : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3), "r" (__r4),"r" (__r5) \ + : "lr"); \ __res = __res_r0; \ __syscall_return(type,__res); \ } #ifdef __KERNEL__ #define __ARCH_WANT_IPC_PARSE_VERSION +#define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 +#define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE +#define __ARCH_WANT_SYS_TIME +#define __ARCH_WANT_SYS_UTIME +#define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_GETPGRP #define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE +#define __ARCH_WANT_SYS_OLD_GETRLIMIT +#define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION - -#if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) -#define __ARCH_WANT_SYS_TIME -#define __ARCH_WANT_SYS_OLDUMOUNT -#define __ARCH_WANT_SYS_ALARM -#define __ARCH_WANT_SYS_UTIME -#define __ARCH_WANT_SYS_OLD_GETRLIMIT -#define __ARCH_WANT_OLD_READDIR -#define __ARCH_WANT_SYS_SOCKETCALL -#endif #endif #ifdef __KERNEL_SYSCALLS__ diff --git a/trunk/include/asm-generic/atomic.h b/trunk/include/asm-generic/atomic.h index 42a95d9a0641..0fada8f16dc6 100644 --- a/trunk/include/asm-generic/atomic.h +++ b/trunk/include/asm-generic/atomic.h @@ -35,7 +35,7 @@ static inline void atomic_long_set(atomic_long_t *l, long i) { atomic64_t *v = (atomic64_t *)l; - atomic64_set(v, i); + atomic_set(v, i); } static inline void atomic_long_inc(atomic_long_t *l) diff --git a/trunk/include/asm-i386/bitops.h b/trunk/include/asm-i386/bitops.h index 88e6ca248cd7..fe0819fe9c64 100644 --- a/trunk/include/asm-i386/bitops.h +++ b/trunk/include/asm-i386/bitops.h @@ -247,7 +247,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long* addr) static int test_bit(int nr, const volatile void * addr); #endif -static __always_inline int constant_test_bit(int nr, const volatile unsigned long *addr) +static inline int constant_test_bit(int nr, const volatile unsigned long *addr) { return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0; } diff --git a/trunk/include/asm-i386/current.h b/trunk/include/asm-i386/current.h index 3cbbecd79016..d97328951f5f 100644 --- a/trunk/include/asm-i386/current.h +++ b/trunk/include/asm-i386/current.h @@ -5,7 +5,7 @@ struct task_struct; -static __always_inline struct task_struct * get_current(void) +static inline struct task_struct * get_current(void) { return current_thread_info()->task; } diff --git a/trunk/include/asm-i386/string.h b/trunk/include/asm-i386/string.h index bb5f88a27f7a..02c8f5d22065 100644 --- a/trunk/include/asm-i386/string.h +++ b/trunk/include/asm-i386/string.h @@ -201,7 +201,7 @@ __asm__ __volatile__( return __res; } -static __always_inline void * __memcpy(void * to, const void * from, size_t n) +static inline void * __memcpy(void * to, const void * from, size_t n) { int d0, d1, d2; __asm__ __volatile__( @@ -223,7 +223,7 @@ return (to); * This looks ugly, but the compiler can optimize it totally, * as the count is constant. */ -static __always_inline void * __constant_memcpy(void * to, const void * from, size_t n) +static inline void * __constant_memcpy(void * to, const void * from, size_t n) { long esi, edi; if (!n) return to; @@ -367,7 +367,7 @@ return s; * things 32 bits at a time even when we don't know the size of the * area at compile-time.. */ -static __always_inline void * __constant_c_memset(void * s, unsigned long c, size_t count) +static inline void * __constant_c_memset(void * s, unsigned long c, size_t count) { int d0, d1; __asm__ __volatile__( @@ -416,7 +416,7 @@ extern char *strstr(const char *cs, const char *ct); * This looks horribly ugly, but the compiler can optimize it totally, * as we by now know that both pattern and count is constant.. */ -static __always_inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count) +static inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count) { switch (count) { case 0: diff --git a/trunk/include/asm-i386/uaccess.h b/trunk/include/asm-i386/uaccess.h index 3f1337c34208..89ab7e2bc5aa 100644 --- a/trunk/include/asm-i386/uaccess.h +++ b/trunk/include/asm-i386/uaccess.h @@ -411,7 +411,7 @@ unsigned long __must_check __copy_from_user_ll(void *to, * Returns number of bytes that could not be copied. * On success, this will be zero. */ -static __always_inline unsigned long __must_check +static inline unsigned long __must_check __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) { if (__builtin_constant_p(n)) { @@ -432,7 +432,7 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) return __copy_to_user_ll(to, from, n); } -static __always_inline unsigned long __must_check +static inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n) { might_sleep(); @@ -456,7 +456,7 @@ __copy_to_user(void __user *to, const void *from, unsigned long n) * If some data could not be copied, this function will pad the copied * data to the requested size using zero bytes. */ -static __always_inline unsigned long +static inline unsigned long __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) { if (__builtin_constant_p(n)) { @@ -477,7 +477,7 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) return __copy_from_user_ll(to, from, n); } -static __always_inline unsigned long +static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) { might_sleep(); diff --git a/trunk/include/asm-ia64/sn/ioc3.h b/trunk/include/asm-ia64/sn/ioc3.h deleted file mode 100644 index 95ed6cc83cf1..000000000000 --- a/trunk/include/asm-ia64/sn/ioc3.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (C) 2005 Silicon Graphics, Inc. - */ -#ifndef IA64_SN_IOC3_H -#define IA64_SN_IOC3_H - -/* serial port register map */ -struct ioc3_serialregs { - uint32_t sscr; - uint32_t stpir; - uint32_t stcir; - uint32_t srpir; - uint32_t srcir; - uint32_t srtr; - uint32_t shadow; -}; - -/* SUPERIO uart register map */ -struct ioc3_uartregs { - char iu_lcr; - union { - char iir; /* read only */ - char fcr; /* write only */ - } u3; - union { - char ier; /* DLAB == 0 */ - char dlm; /* DLAB == 1 */ - } u2; - union { - char rbr; /* read only, DLAB == 0 */ - char thr; /* write only, DLAB == 0 */ - char dll; /* DLAB == 1 */ - } u1; - char iu_scr; - char iu_msr; - char iu_lsr; - char iu_mcr; -}; - -#define iu_rbr u1.rbr -#define iu_thr u1.thr -#define iu_dll u1.dll -#define iu_ier u2.ier -#define iu_dlm u2.dlm -#define iu_iir u3.iir -#define iu_fcr u3.fcr - -struct ioc3_sioregs { - char fill[0x170]; - struct ioc3_uartregs uartb; - struct ioc3_uartregs uarta; -}; - -/* PCI IO/mem space register map */ -struct ioc3 { - uint32_t pci_id; - uint32_t pci_scr; - uint32_t pci_rev; - uint32_t pci_lat; - uint32_t pci_addr; - uint32_t pci_err_addr_l; - uint32_t pci_err_addr_h; - - uint32_t sio_ir; - /* these registers are read-only for general kernel code. To - * modify them use the functions in ioc3.c - */ - uint32_t sio_ies; - uint32_t sio_iec; - uint32_t sio_cr; - uint32_t int_out; - uint32_t mcr; - uint32_t gpcr_s; - uint32_t gpcr_c; - uint32_t gpdr; - uint32_t gppr[9]; - char fill[0x4c]; - - /* serial port registers */ - uint32_t sbbr_h; - uint32_t sbbr_l; - - struct ioc3_serialregs port_a; - struct ioc3_serialregs port_b; - char fill1[0x1ff10]; - /* superio registers */ - struct ioc3_sioregs sregs; -}; - -/* These don't exist on the ioc3 serial card... */ -#define eier fill1[8] -#define eisr fill1[4] - -#define PCI_LAT 0xc /* Latency Timer */ -#define PCI_SCR_DROP_MODE_EN 0x00008000 /* drop pios on parity err */ -#define UARTA_BASE 0x178 -#define UARTB_BASE 0x170 - - -/* bitmasks for serial RX status byte */ -#define RXSB_OVERRUN 0x01 /* char(s) lost */ -#define RXSB_PAR_ERR 0x02 /* parity error */ -#define RXSB_FRAME_ERR 0x04 /* framing error */ -#define RXSB_BREAK 0x08 /* break character */ -#define RXSB_CTS 0x10 /* state of CTS */ -#define RXSB_DCD 0x20 /* state of DCD */ -#define RXSB_MODEM_VALID 0x40 /* DCD, CTS and OVERRUN are valid */ -#define RXSB_DATA_VALID 0x80 /* FRAME_ERR PAR_ERR & BREAK valid */ - -/* bitmasks for serial TX control byte */ -#define TXCB_INT_WHEN_DONE 0x20 /* interrupt after this byte is sent */ -#define TXCB_INVALID 0x00 /* byte is invalid */ -#define TXCB_VALID 0x40 /* byte is valid */ -#define TXCB_MCR 0x80 /* data<7:0> to modem cntrl register */ -#define TXCB_DELAY 0xc0 /* delay data<7:0> mSec */ - -/* bitmasks for SBBR_L */ -#define SBBR_L_SIZE 0x00000001 /* 0 1KB rings, 1 4KB rings */ - -/* bitmasks for SSCR_ */ -#define SSCR_RX_THRESHOLD 0x000001ff /* hiwater mark */ -#define SSCR_TX_TIMER_BUSY 0x00010000 /* TX timer in progress */ -#define SSCR_HFC_EN 0x00020000 /* h/w flow cntrl enabled */ -#define SSCR_RX_RING_DCD 0x00040000 /* postRX record on delta-DCD */ -#define SSCR_RX_RING_CTS 0x00080000 /* postRX record on delta-CTS */ -#define SSCR_HIGH_SPD 0x00100000 /* 4X speed */ -#define SSCR_DIAG 0x00200000 /* bypass clock divider */ -#define SSCR_RX_DRAIN 0x08000000 /* drain RX buffer to memory */ -#define SSCR_DMA_EN 0x10000000 /* enable ring buffer DMA */ -#define SSCR_DMA_PAUSE 0x20000000 /* pause DMA */ -#define SSCR_PAUSE_STATE 0x40000000 /* set when PAUSE takes effect*/ -#define SSCR_RESET 0x80000000 /* reset DMA channels */ - -/* all producer/comsumer pointers are the same bitfield */ -#define PROD_CONS_PTR_4K 0x00000ff8 /* for 4K buffers */ -#define PROD_CONS_PTR_1K 0x000003f8 /* for 1K buffers */ -#define PROD_CONS_PTR_OFF 3 - -/* bitmasks for SRCIR_ */ -#define SRCIR_ARM 0x80000000 /* arm RX timer */ - -/* bitmasks for SHADOW_ */ -#define SHADOW_DR 0x00000001 /* data ready */ -#define SHADOW_OE 0x00000002 /* overrun error */ -#define SHADOW_PE 0x00000004 /* parity error */ -#define SHADOW_FE 0x00000008 /* framing error */ -#define SHADOW_BI 0x00000010 /* break interrupt */ -#define SHADOW_THRE 0x00000020 /* transmit holding reg empty */ -#define SHADOW_TEMT 0x00000040 /* transmit shift reg empty */ -#define SHADOW_RFCE 0x00000080 /* char in RX fifo has error */ -#define SHADOW_DCTS 0x00010000 /* delta clear to send */ -#define SHADOW_DDCD 0x00080000 /* delta data carrier detect */ -#define SHADOW_CTS 0x00100000 /* clear to send */ -#define SHADOW_DCD 0x00800000 /* data carrier detect */ -#define SHADOW_DTR 0x01000000 /* data terminal ready */ -#define SHADOW_RTS 0x02000000 /* request to send */ -#define SHADOW_OUT1 0x04000000 /* 16550 OUT1 bit */ -#define SHADOW_OUT2 0x08000000 /* 16550 OUT2 bit */ -#define SHADOW_LOOP 0x10000000 /* loopback enabled */ - -/* bitmasks for SRTR_ */ -#define SRTR_CNT 0x00000fff /* reload value for RX timer */ -#define SRTR_CNT_VAL 0x0fff0000 /* current value of RX timer */ -#define SRTR_CNT_VAL_SHIFT 16 -#define SRTR_HZ 16000 /* SRTR clock frequency */ - -/* bitmasks for SIO_IR, SIO_IEC and SIO_IES */ -#define SIO_IR_SA_TX_MT 0x00000001 /* Serial port A TX empty */ -#define SIO_IR_SA_RX_FULL 0x00000002 /* port A RX buf full */ -#define SIO_IR_SA_RX_HIGH 0x00000004 /* port A RX hiwat */ -#define SIO_IR_SA_RX_TIMER 0x00000008 /* port A RX timeout */ -#define SIO_IR_SA_DELTA_DCD 0x00000010 /* port A delta DCD */ -#define SIO_IR_SA_DELTA_CTS 0x00000020 /* port A delta CTS */ -#define SIO_IR_SA_INT 0x00000040 /* port A pass-thru intr */ -#define SIO_IR_SA_TX_EXPLICIT 0x00000080 /* port A explicit TX thru */ -#define SIO_IR_SA_MEMERR 0x00000100 /* port A PCI error */ -#define SIO_IR_SB_TX_MT 0x00000200 -#define SIO_IR_SB_RX_FULL 0x00000400 -#define SIO_IR_SB_RX_HIGH 0x00000800 -#define SIO_IR_SB_RX_TIMER 0x00001000 -#define SIO_IR_SB_DELTA_DCD 0x00002000 -#define SIO_IR_SB_DELTA_CTS 0x00004000 -#define SIO_IR_SB_INT 0x00008000 -#define SIO_IR_SB_TX_EXPLICIT 0x00010000 -#define SIO_IR_SB_MEMERR 0x00020000 -#define SIO_IR_PP_INT 0x00040000 /* P port pass-thru intr */ -#define SIO_IR_PP_INTA 0x00080000 /* PP context A thru */ -#define SIO_IR_PP_INTB 0x00100000 /* PP context B thru */ -#define SIO_IR_PP_MEMERR 0x00200000 /* PP PCI error */ -#define SIO_IR_KBD_INT 0x00400000 /* kbd/mouse intr */ -#define SIO_IR_RT_INT 0x08000000 /* RT output pulse */ -#define SIO_IR_GEN_INT1 0x10000000 /* RT input pulse */ -#define SIO_IR_GEN_INT_SHIFT 28 - -/* per device interrupt masks */ -#define SIO_IR_SA (SIO_IR_SA_TX_MT | \ - SIO_IR_SA_RX_FULL | \ - SIO_IR_SA_RX_HIGH | \ - SIO_IR_SA_RX_TIMER | \ - SIO_IR_SA_DELTA_DCD | \ - SIO_IR_SA_DELTA_CTS | \ - SIO_IR_SA_INT | \ - SIO_IR_SA_TX_EXPLICIT | \ - SIO_IR_SA_MEMERR) - -#define SIO_IR_SB (SIO_IR_SB_TX_MT | \ - SIO_IR_SB_RX_FULL | \ - SIO_IR_SB_RX_HIGH | \ - SIO_IR_SB_RX_TIMER | \ - SIO_IR_SB_DELTA_DCD | \ - SIO_IR_SB_DELTA_CTS | \ - SIO_IR_SB_INT | \ - SIO_IR_SB_TX_EXPLICIT | \ - SIO_IR_SB_MEMERR) - -#define SIO_IR_PP (SIO_IR_PP_INT | SIO_IR_PP_INTA | \ - SIO_IR_PP_INTB | SIO_IR_PP_MEMERR) -#define SIO_IR_RT (SIO_IR_RT_INT | SIO_IR_GEN_INT1) - -/* bitmasks for SIO_CR */ -#define SIO_CR_CMD_PULSE_SHIFT 15 -#define SIO_CR_SER_A_BASE_SHIFT 1 -#define SIO_CR_SER_B_BASE_SHIFT 8 -#define SIO_CR_ARB_DIAG 0x00380000 /* cur !enet PCI requet (ro) */ -#define SIO_CR_ARB_DIAG_TXA 0x00000000 -#define SIO_CR_ARB_DIAG_RXA 0x00080000 -#define SIO_CR_ARB_DIAG_TXB 0x00100000 -#define SIO_CR_ARB_DIAG_RXB 0x00180000 -#define SIO_CR_ARB_DIAG_PP 0x00200000 -#define SIO_CR_ARB_DIAG_IDLE 0x00400000 /* 0 -> active request (ro) */ - -/* defs for some of the generic I/O pins */ -#define GPCR_PHY_RESET 0x20 /* pin is output to PHY reset */ -#define GPCR_UARTB_MODESEL 0x40 /* pin is output to port B mode sel */ -#define GPCR_UARTA_MODESEL 0x80 /* pin is output to port A mode sel */ - -#define GPPR_PHY_RESET_PIN 5 /* GIO pin controlling phy reset */ -#define GPPR_UARTB_MODESEL_PIN 6 /* GIO pin cntrling uartb modeselect */ -#define GPPR_UARTA_MODESEL_PIN 7 /* GIO pin cntrling uarta modeselect */ - -#endif /* IA64_SN_IOC3_H */ diff --git a/trunk/include/asm-powerpc/kexec.h b/trunk/include/asm-powerpc/kexec.h index 640a6459f2f4..fffdf690b840 100644 --- a/trunk/include/asm-powerpc/kexec.h +++ b/trunk/include/asm-powerpc/kexec.h @@ -31,80 +31,12 @@ #define KEXEC_ARCH KEXEC_ARCH_PPC #endif -#ifdef CONFIG_KEXEC - -#ifdef __powerpc64__ -/* - * This function is responsible for capturing register states if coming - * via panic or invoking dump using sysrq-trigger. - */ -static inline void crash_setup_regs(struct pt_regs *newregs, - struct pt_regs *oldregs) -{ - if (oldregs) - memcpy(newregs, oldregs, sizeof(*newregs)); - else { - /* FIXME Merge this with xmon_save_regs ?? */ - unsigned long tmp1, tmp2; - __asm__ __volatile__ ( - "std 0,0(%2)\n" - "std 1,8(%2)\n" - "std 2,16(%2)\n" - "std 3,24(%2)\n" - "std 4,32(%2)\n" - "std 5,40(%2)\n" - "std 6,48(%2)\n" - "std 7,56(%2)\n" - "std 8,64(%2)\n" - "std 9,72(%2)\n" - "std 10,80(%2)\n" - "std 11,88(%2)\n" - "std 12,96(%2)\n" - "std 13,104(%2)\n" - "std 14,112(%2)\n" - "std 15,120(%2)\n" - "std 16,128(%2)\n" - "std 17,136(%2)\n" - "std 18,144(%2)\n" - "std 19,152(%2)\n" - "std 20,160(%2)\n" - "std 21,168(%2)\n" - "std 22,176(%2)\n" - "std 23,184(%2)\n" - "std 24,192(%2)\n" - "std 25,200(%2)\n" - "std 26,208(%2)\n" - "std 27,216(%2)\n" - "std 28,224(%2)\n" - "std 29,232(%2)\n" - "std 30,240(%2)\n" - "std 31,248(%2)\n" - "mfmsr %0\n" - "std %0, 264(%2)\n" - "mfctr %0\n" - "std %0, 280(%2)\n" - "mflr %0\n" - "std %0, 288(%2)\n" - "bl 1f\n" - "1: mflr %1\n" - "std %1, 256(%2)\n" - "mtlr %0\n" - "mfxer %0\n" - "std %0, 296(%2)\n" - : "=&r" (tmp1), "=&r" (tmp2) - : "b" (newregs)); - } -} -#else -/* - * Provide a dummy definition to avoid build failures. Will remain - * empty till crash dump support is enabled. - */ -static inline void crash_setup_regs(struct pt_regs *newregs, - struct pt_regs *oldregs) { } -#endif /* !__powerpc64 __ */ +#define HAVE_ARCH_COPY_OLDMEM_PAGE #ifndef __ASSEMBLY__ + +#ifdef CONFIG_KEXEC + #define MAX_NOTE_BYTES 1024 #ifdef __powerpc64__ @@ -121,7 +53,14 @@ extern void default_machine_kexec(struct kimage *image); extern int default_machine_kexec_prepare(struct kimage *image); extern void default_machine_crash_shutdown(struct pt_regs *regs); +#endif /* !CONFIG_KEXEC */ + +/* + * Provide a dummy definition to avoid build failures. Will remain + * empty till crash dump support is enabled. + */ +static inline void crash_setup_regs(struct pt_regs *newregs, + struct pt_regs *oldregs) { } #endif /* ! __ASSEMBLY__ */ -#endif /* CONFIG_KEXEC */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_KEXEC_H */ diff --git a/trunk/include/asm-ppc/prom.h b/trunk/include/asm-ppc/prom.h index 6d431d6fb022..eb317a0806e4 100644 --- a/trunk/include/asm-ppc/prom.h +++ b/trunk/include/asm-ppc/prom.h @@ -167,14 +167,6 @@ extern int of_address_to_resource(struct device_node *dev, int index, extern int of_pci_address_to_resource(struct device_node *dev, int bar, struct resource *r); -#ifndef CONFIG_PPC_OF -/* - * Fallback definitions for builds where we don't have prom.c included. - */ -#define machine_is_compatible(x) 0 -#define of_find_compatible_node(f, t, c) NULL -#define get_property(p, n, l) NULL -#endif #endif /* _PPC_PROM_H */ #endif /* __KERNEL__ */ diff --git a/trunk/include/asm-s390/s390_rdev.h b/trunk/include/asm-s390/s390_rdev.h index 6fa20442a48c..3ad78f2b9c48 100644 --- a/trunk/include/asm-s390/s390_rdev.h +++ b/trunk/include/asm-s390/s390_rdev.h @@ -2,7 +2,7 @@ * include/asm-s390/ccwdev.h * * Copyright (C) 2002,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Cornelia Huck + * Author(s): Cornelia Huck * Carsten Otte * * Interface for s390 root device diff --git a/trunk/include/asm-s390/sigcontext.h b/trunk/include/asm-s390/sigcontext.h index aeb6e0b13329..803545351dd8 100644 --- a/trunk/include/asm-s390/sigcontext.h +++ b/trunk/include/asm-s390/sigcontext.h @@ -8,8 +8,6 @@ #ifndef _ASM_S390_SIGCONTEXT_H #define _ASM_S390_SIGCONTEXT_H -#include - #define __NUM_GPRS 16 #define __NUM_FPRS 16 #define __NUM_ACRS 16 diff --git a/trunk/include/asm-s390/system.h b/trunk/include/asm-s390/system.h index b2e65e8bf812..c7c3a9ad593f 100644 --- a/trunk/include/asm-s390/system.h +++ b/trunk/include/asm-s390/system.h @@ -115,14 +115,13 @@ static inline void sched_cacheflush(void) } #ifdef CONFIG_VIRT_CPU_ACCOUNTING -extern void account_vtime(struct task_struct *); -extern void account_tick_vtime(struct task_struct *); +extern void account_user_vtime(struct task_struct *); extern void account_system_vtime(struct task_struct *); #endif #define finish_arch_switch(prev) do { \ set_fs(current->thread.mm_segment); \ - account_vtime(prev); \ + account_system_vtime(prev); \ } while (0) #define nop() __asm__ __volatile__ ("nop") diff --git a/trunk/include/asm-x86_64/fixmap.h b/trunk/include/asm-x86_64/fixmap.h index 7b286bd21d1d..a582cfcf2231 100644 --- a/trunk/include/asm-x86_64/fixmap.h +++ b/trunk/include/asm-x86_64/fixmap.h @@ -76,7 +76,7 @@ extern void __this_fixmap_does_not_exist(void); * directly without translation, we catch the bug with a NULL-deference * kernel oops. Illegal ranges of incoming indices are caught too. */ -static __always_inline unsigned long fix_to_virt(const unsigned int idx) +static inline unsigned long fix_to_virt(const unsigned int idx) { /* * this branch gets completely eliminated after inlining, diff --git a/trunk/include/asm-x86_64/uaccess.h b/trunk/include/asm-x86_64/uaccess.h index bddffcb591b8..2892c4b7a28b 100644 --- a/trunk/include/asm-x86_64/uaccess.h +++ b/trunk/include/asm-x86_64/uaccess.h @@ -244,7 +244,7 @@ extern unsigned long copy_to_user(void __user *to, const void *from, unsigned le extern unsigned long copy_from_user(void *to, const void __user *from, unsigned len); extern unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len); -static __always_inline int __copy_from_user(void *dst, const void __user *src, unsigned size) +static inline int __copy_from_user(void *dst, const void __user *src, unsigned size) { int ret = 0; if (!__builtin_constant_p(size)) @@ -273,7 +273,7 @@ static __always_inline int __copy_from_user(void *dst, const void __user *src, u } } -static __always_inline int __copy_to_user(void __user *dst, const void *src, unsigned size) +static inline int __copy_to_user(void __user *dst, const void *src, unsigned size) { int ret = 0; if (!__builtin_constant_p(size)) @@ -305,7 +305,7 @@ static __always_inline int __copy_to_user(void __user *dst, const void *src, uns } -static __always_inline int __copy_in_user(void __user *dst, const void __user *src, unsigned size) +static inline int __copy_in_user(void __user *dst, const void __user *src, unsigned size) { int ret = 0; if (!__builtin_constant_p(size)) diff --git a/trunk/include/linux/compiler-gcc3.h b/trunk/include/linux/compiler-gcc3.h index 1698b845761f..4209082ee934 100644 --- a/trunk/include/linux/compiler-gcc3.h +++ b/trunk/include/linux/compiler-gcc3.h @@ -13,4 +13,3 @@ #define __must_check __attribute__((warn_unused_result)) #endif -#define __always_inline inline __attribute__((always_inline)) diff --git a/trunk/include/linux/compiler-gcc4.h b/trunk/include/linux/compiler-gcc4.h index 6f5cc6f0e7a6..e913e9beaf69 100644 --- a/trunk/include/linux/compiler-gcc4.h +++ b/trunk/include/linux/compiler-gcc4.h @@ -3,16 +3,7 @@ /* These definitions are for GCC v4.x. */ #include -#ifdef CONFIG_FORCED_INLINING -# undef inline -# undef __inline__ -# undef __inline -# define inline inline __attribute__((always_inline)) -# define __inline__ __inline__ __attribute__((always_inline)) -# define __inline __inline __attribute__((always_inline)) -#endif - #define __attribute_used__ __attribute__((__used__)) #define __must_check __attribute__((warn_unused_result)) #define __compiler_offsetof(a,b) __builtin_offsetof(a,b) -#define __always_inline inline __attribute__((always_inline)) + diff --git a/trunk/include/linux/cpuset.h b/trunk/include/linux/cpuset.h index 3bc606927116..c472f972bd6d 100644 --- a/trunk/include/linux/cpuset.h +++ b/trunk/include/linux/cpuset.h @@ -48,9 +48,6 @@ extern void __cpuset_memory_pressure_bump(void); extern struct file_operations proc_cpuset_operations; extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer); -extern void cpuset_lock(void); -extern void cpuset_unlock(void); - #else /* !CONFIG_CPUSETS */ static inline int cpuset_init_early(void) { return 0; } @@ -96,9 +93,6 @@ static inline char *cpuset_task_status_allowed(struct task_struct *task, return buffer; } -static inline void cpuset_lock(void) {} -static inline void cpuset_unlock(void) {} - #endif /* !CONFIG_CPUSETS */ #endif /* _LINUX_CPUSET_H */ diff --git a/trunk/include/linux/fb.h b/trunk/include/linux/fb.h index 2cb19e6503aa..a973be2cfe61 100644 --- a/trunk/include/linux/fb.h +++ b/trunk/include/linux/fb.h @@ -608,15 +608,15 @@ struct fb_ops { int (*fb_sync)(struct fb_info *info); /* perform fb specific ioctl (optional) */ - int (*fb_ioctl)(struct fb_info *info, unsigned int cmd, - unsigned long arg); + int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info); /* Handle 32bit compat ioctl (optional) */ - int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd, - unsigned long arg); + long (*fb_compat_ioctl)(struct file *f, unsigned cmd, unsigned long arg, + struct fb_info *info); /* perform fb specific mmap */ - int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma); + int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma); /* save current hardware state */ void (*fb_save_state)(struct fb_info *info); diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 552cedfa6064..d1e370d25f7b 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -1383,12 +1383,6 @@ extern int register_chrdev(unsigned int, const char *, extern int unregister_chrdev(unsigned int, const char *); extern void unregister_chrdev_region(dev_t, unsigned); extern int chrdev_open(struct inode *, struct file *); -extern int get_chrdev_list(char *); -extern void *acquire_chrdev_list(void); -extern int count_chrdev_list(void); -extern void *get_next_chrdev(void *); -extern int get_chrdev_info(void *, int *, char **); -extern void release_chrdev_list(void *); /* fs/block_dev.c */ #define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ @@ -1397,11 +1391,6 @@ extern const char *bdevname(struct block_device *bdev, char *buffer); extern struct block_device *lookup_bdev(const char *); extern struct block_device *open_bdev_excl(const char *, int, void *); extern void close_bdev_excl(struct block_device *); -extern void *acquire_blkdev_list(void); -extern int count_blkdev_list(void); -extern void *get_next_blkdev(void *); -extern int get_blkdev_info(void *, int *, char **); -extern void release_blkdev_list(void *); extern void init_special_inode(struct inode *, umode_t, dev_t); diff --git a/trunk/include/linux/hardirq.h b/trunk/include/linux/hardirq.h index eab537091f2a..71d2b8a723b9 100644 --- a/trunk/include/linux/hardirq.h +++ b/trunk/include/linux/hardirq.h @@ -93,6 +93,10 @@ extern void synchronize_irq(unsigned int irq); struct task_struct; #ifndef CONFIG_VIRT_CPU_ACCOUNTING +static inline void account_user_vtime(struct task_struct *tsk) +{ +} + static inline void account_system_vtime(struct task_struct *tsk) { } diff --git a/trunk/include/linux/ioc3.h b/trunk/include/linux/ioc3.h deleted file mode 100644 index e7906a72a4f1..000000000000 --- a/trunk/include/linux/ioc3.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (c) 2005 Stanislaw Skowronek - */ - -#ifndef _LINUX_IOC3_H -#define _LINUX_IOC3_H - -#include - -#define IOC3_MAX_SUBMODULES 32 - -#define IOC3_CLASS_NONE 0 -#define IOC3_CLASS_BASE_IP27 1 -#define IOC3_CLASS_BASE_IP30 2 -#define IOC3_CLASS_MENET_123 3 -#define IOC3_CLASS_MENET_4 4 -#define IOC3_CLASS_CADDUO 5 -#define IOC3_CLASS_SERIAL 6 - -/* One of these per IOC3 */ -struct ioc3_driver_data { - struct list_head list; - int id; /* IOC3 sequence number */ - /* PCI mapping */ - unsigned long pma; /* physical address */ - struct __iomem ioc3 *vma; /* pointer to registers */ - struct pci_dev *pdev; /* PCI device */ - /* IRQ stuff */ - int dual_irq; /* set if separate IRQs are used */ - int irq_io, irq_eth; /* IRQ numbers */ - /* GPIO magic */ - spinlock_t gpio_lock; - unsigned int gpdr_shadow; - /* NIC identifiers */ - char nic_part[32]; - char nic_serial[16]; - char nic_mac[6]; - /* submodule set */ - int class; - void *data[IOC3_MAX_SUBMODULES]; /* for submodule use */ - int active[IOC3_MAX_SUBMODULES]; /* set if probe succeeds */ - /* is_ir_lock must be held while - * modifying sio_ie values, so - * we can be sure that sio_ie is - * not changing when we read it - * along with sio_ir. - */ - spinlock_t ir_lock; /* SIO_IE[SC] mod lock */ -}; - -/* One per submodule */ -struct ioc3_submodule { - char *name; /* descriptive submodule name */ - struct module *owner; /* owning kernel module */ - int ethernet; /* set for ethernet drivers */ - int (*probe) (struct ioc3_submodule *, struct ioc3_driver_data *); - int (*remove) (struct ioc3_submodule *, struct ioc3_driver_data *); - int id; /* assigned by IOC3, index for the "data" array */ - /* IRQ stuff */ - unsigned int irq_mask; /* IOC3 IRQ mask, leave clear for Ethernet */ - int reset_mask; /* non-zero if you want the ioc3.c module to reset interrupts */ - int (*intr) (struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int, struct pt_regs *); - /* private submodule data */ - void *data; /* assigned by submodule */ -}; - -/********************************** - * Functions needed by submodules * - **********************************/ - -#define IOC3_W_IES 0 -#define IOC3_W_IEC 1 - -/* registers a submodule for all existing and future IOC3 chips */ -extern int ioc3_register_submodule(struct ioc3_submodule *); -/* unregisters a submodule */ -extern void ioc3_unregister_submodule(struct ioc3_submodule *); -/* enables IRQs indicated by irq_mask for a specified IOC3 chip */ -extern void ioc3_enable(struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int); -/* ackowledges specified IRQs */ -extern void ioc3_ack(struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int); -/* disables IRQs indicated by irq_mask for a specified IOC3 chip */ -extern void ioc3_disable(struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int); -/* atomically sets GPCR bits */ -extern void ioc3_gpcr_set(struct ioc3_driver_data *, unsigned int); -/* general ireg writer */ -extern void ioc3_write_ireg(struct ioc3_driver_data *idd, uint32_t value, int reg); - -#endif diff --git a/trunk/include/linux/mempolicy.h b/trunk/include/linux/mempolicy.h index d6a53ed6ab6c..c7ac77e873b3 100644 --- a/trunk/include/linux/mempolicy.h +++ b/trunk/include/linux/mempolicy.h @@ -132,8 +132,12 @@ struct shared_policy { spinlock_t lock; }; -void mpol_shared_policy_init(struct shared_policy *info, int policy, - nodemask_t *nodes); +static inline void mpol_shared_policy_init(struct shared_policy *info) +{ + info->root = RB_ROOT; + spin_lock_init(&info->lock); +} + int mpol_set_shared_policy(struct shared_policy *info, struct vm_area_struct *vma, struct mempolicy *new); @@ -207,8 +211,7 @@ static inline int mpol_set_shared_policy(struct shared_policy *info, return -EINVAL; } -static inline void mpol_shared_policy_init(struct shared_policy *info, - int policy, nodemask_t *nodes) +static inline void mpol_shared_policy_init(struct shared_policy *info) { } diff --git a/trunk/include/linux/mm.h b/trunk/include/linux/mm.h index 85854b867463..c643016499a1 100644 --- a/trunk/include/linux/mm.h +++ b/trunk/include/linux/mm.h @@ -512,7 +512,7 @@ static inline void set_page_links(struct page *page, unsigned long zone, extern struct page *mem_map; #endif -static __always_inline void *lowmem_page_address(struct page *page) +static inline void *lowmem_page_address(struct page *page) { return __va(page_to_pfn(page) << PAGE_SHIFT); } diff --git a/trunk/include/linux/ncp_fs.h b/trunk/include/linux/ncp_fs.h index e01342568530..7297e4372c0f 100644 --- a/trunk/include/linux/ncp_fs.h +++ b/trunk/include/linux/ncp_fs.h @@ -201,6 +201,34 @@ static inline struct ncp_inode_info *NCP_FINFO(struct inode *inode) return container_of(inode, struct ncp_inode_info, vfs_inode); } +#ifdef DEBUG_NCP_MALLOC + +#include + +extern int ncp_malloced; +extern int ncp_current_malloced; + +static inline void * + ncp_kmalloc(unsigned int size, int priority) +{ + ncp_malloced += 1; + ncp_current_malloced += 1; + return kmalloc(size, priority); +} + +static inline void ncp_kfree_s(void *obj, int size) +{ + ncp_current_malloced -= 1; + kfree(obj); +} + +#else /* DEBUG_NCP_MALLOC */ + +#define ncp_kmalloc(s,p) kmalloc(s,p) +#define ncp_kfree_s(o,s) kfree(o) + +#endif /* DEBUG_NCP_MALLOC */ + /* linux/fs/ncpfs/inode.c */ int ncp_notify_change(struct dentry *, struct iattr *); struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *); diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 2df1a1a2fee5..a72e17135421 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -160,7 +160,6 @@ extern unsigned long nr_iowait(void); #define SCHED_NORMAL 0 #define SCHED_FIFO 1 #define SCHED_RR 2 -#define SCHED_BATCH 3 struct sched_param { int sched_priority; @@ -471,9 +470,9 @@ struct signal_struct { /* * Priority of a process goes from 0..MAX_PRIO-1, valid RT - * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH - * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority - * values are inverted: lower p->prio value means higher priority. + * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL tasks are + * in the range MAX_RT_PRIO..MAX_PRIO-1. Priority values + * are inverted: lower p->prio value means higher priority. * * The MAX_USER_RT_PRIO value allows the actual maximum * RT priority to be separate from the value exported to diff --git a/trunk/include/linux/serial_core.h b/trunk/include/linux/serial_core.h index ec351005bf9d..a8187c3c8a7b 100644 --- a/trunk/include/linux/serial_core.h +++ b/trunk/include/linux/serial_core.h @@ -136,7 +136,6 @@ #include #include #include -#include struct uart_port; struct uart_info; @@ -285,7 +284,7 @@ struct uart_state { struct uart_info *info; struct uart_port *port; - struct mutex mutex; + struct semaphore sem; }; #define UART_XMIT_SIZE PAGE_SIZE diff --git a/trunk/include/linux/shmem_fs.h b/trunk/include/linux/shmem_fs.h index c057f0b32318..c3e598276e78 100644 --- a/trunk/include/linux/shmem_fs.h +++ b/trunk/include/linux/shmem_fs.h @@ -26,8 +26,6 @@ struct shmem_sb_info { unsigned long free_blocks; /* How many are left for allocation */ unsigned long max_inodes; /* How many inodes are allowed */ unsigned long free_inodes; /* How many are left for allocation */ - int policy; /* Default NUMA memory alloc policy */ - nodemask_t policy_nodes; /* nodemask for preferred and bind */ spinlock_t stat_lock; }; diff --git a/trunk/include/linux/smb_fs.h b/trunk/include/linux/smb_fs.h index 621a3d3662f3..c4153120ade6 100644 --- a/trunk/include/linux/smb_fs.h +++ b/trunk/include/linux/smb_fs.h @@ -58,6 +58,53 @@ static inline struct smb_inode_info *SMB_I(struct inode *inode) /* where to find the base of the SMB packet proper */ #define smb_base(buf) ((u8 *)(((u8 *)(buf))+4)) +#ifdef DEBUG_SMB_MALLOC + +#include + +extern int smb_malloced; +extern int smb_current_vmalloced; +extern int smb_current_kmalloced; + +static inline void * +smb_vmalloc(unsigned int size) +{ + smb_malloced += 1; + smb_current_vmalloced += 1; + return vmalloc(size); +} + +static inline void +smb_vfree(void *obj) +{ + smb_current_vmalloced -= 1; + vfree(obj); +} + +static inline void * +smb_kmalloc(size_t size, int flags) +{ + smb_malloced += 1; + smb_current_kmalloced += 1; + return kmalloc(size, flags); +} + +static inline void +smb_kfree(void *obj) +{ + smb_current_kmalloced -= 1; + kfree(obj); +} + +#else /* DEBUG_SMB_MALLOC */ + +#define smb_kmalloc(s,p) kmalloc(s,p) +#define smb_kfree(o) kfree(o) +#define smb_vmalloc(s) vmalloc(s) +#define smb_vfree(o) vfree(o) + +#endif /* DEBUG_SMB_MALLOC */ + /* * Flags for the in-memory inode */ diff --git a/trunk/include/linux/swap.h b/trunk/include/linux/swap.h index e92054d6530b..389d1c382e20 100644 --- a/trunk/include/linux/swap.h +++ b/trunk/include/linux/swap.h @@ -180,11 +180,6 @@ extern int isolate_lru_page(struct page *p); extern int putback_lru_pages(struct list_head *l); extern int migrate_pages(struct list_head *l, struct list_head *t, struct list_head *moved, struct list_head *failed); -#else -static inline int isolate_lru_page(struct page *p) { return -ENOSYS; } -static inline int putback_lru_pages(struct list_head *l) { return 0; } -static inline int migrate_pages(struct list_head *l, struct list_head *t, - struct list_head *moved, struct list_head *failed) { return -ENOSYS; } #endif #ifdef CONFIG_MMU diff --git a/trunk/init/main.c b/trunk/init/main.c index 7c79da57d3a2..e092b1979a90 100644 --- a/trunk/init/main.c +++ b/trunk/init/main.c @@ -54,18 +54,20 @@ #include #include +/* + * This is one of the first .c files built. Error out early + * if we have compiler trouble.. + */ + #ifdef CONFIG_X86_LOCAL_APIC #include #endif /* - * This is one of the first .c files built. Error out early if we have compiler - * trouble. - * - * Versions of gcc older than that listed below may actually compile and link - * okay, but the end product can have subtle run time bugs. To avoid associated - * bogus bug reports, we flatly refuse to compile with a gcc that is known to be - * too old from the very beginning. + * Versions of gcc older than that listed below may actually compile + * and link okay, but the end product can have subtle run time bugs. + * To avoid associated bogus bug reports, we flatly refuse to compile + * with a gcc that is known to be too old from the very beginning. */ #if (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 2) #error Sorry, your GCC is too old. It builds incorrect kernels. diff --git a/trunk/kernel/cpuset.c b/trunk/kernel/cpuset.c index fe2f71f92ae0..2a75e44e1a41 100644 --- a/trunk/kernel/cpuset.c +++ b/trunk/kernel/cpuset.c @@ -1554,7 +1554,7 @@ struct ctr_struct { * when reading out p->cpuset, as we don't really care if it changes * on the next cycle, and we are not going to try to dereference it. */ -static int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs) +static inline int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs) { int n = 0; struct task_struct *g, *p; @@ -2149,33 +2149,6 @@ int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) return allowed; } -/** - * cpuset_lock - lock out any changes to cpuset structures - * - * The out of memory (oom) code needs to lock down cpusets - * from being changed while it scans the tasklist looking for a - * task in an overlapping cpuset. Expose callback_sem via this - * cpuset_lock() routine, so the oom code can lock it, before - * locking the task list. The tasklist_lock is a spinlock, so - * must be taken inside callback_sem. - */ - -void cpuset_lock(void) -{ - down(&callback_sem); -} - -/** - * cpuset_unlock - release lock on cpuset changes - * - * Undo the lock taken in a previous cpuset_lock() call. - */ - -void cpuset_unlock(void) -{ - up(&callback_sem); -} - /** * cpuset_excl_nodes_overlap - Do we overlap @p's mem_exclusive ancestors? * @p: pointer to task_struct of some other task. @@ -2185,7 +2158,7 @@ void cpuset_unlock(void) * determine if task @p's memory usage might impact the memory * available to the current task. * - * Call while holding callback_sem. + * Acquires callback_sem - not suitable for calling from a fast path. **/ int cpuset_excl_nodes_overlap(const struct task_struct *p) @@ -2193,6 +2166,8 @@ int cpuset_excl_nodes_overlap(const struct task_struct *p) const struct cpuset *cs1, *cs2; /* my and p's cpuset ancestors */ int overlap = 0; /* do cpusets overlap? */ + down(&callback_sem); + task_lock(current); if (current->flags & PF_EXITING) { task_unlock(current); @@ -2211,6 +2186,8 @@ int cpuset_excl_nodes_overlap(const struct task_struct *p) overlap = nodes_intersects(cs1->mems_allowed, cs2->mems_allowed); done: + up(&callback_sem); + return overlap; } diff --git a/trunk/kernel/exit.c b/trunk/kernel/exit.c index 93cee3671332..f8e609ff1893 100644 --- a/trunk/kernel/exit.c +++ b/trunk/kernel/exit.c @@ -193,7 +193,7 @@ int is_orphaned_pgrp(int pgrp) return retval; } -static int has_stopped_jobs(int pgrp) +static inline int has_stopped_jobs(int pgrp) { int retval = 0; struct task_struct *p; @@ -230,7 +230,7 @@ static int has_stopped_jobs(int pgrp) * * NOTE that reparent_to_init() gives the caller full capabilities. */ -static void reparent_to_init(void) +static inline void reparent_to_init(void) { write_lock_irq(&tasklist_lock); @@ -244,9 +244,7 @@ static void reparent_to_init(void) /* Set the exit signal to SIGCHLD so we signal init on exit */ current->exit_signal = SIGCHLD; - if ((current->policy == SCHED_NORMAL || - current->policy == SCHED_BATCH) - && (task_nice(current) < 0)) + if ((current->policy == SCHED_NORMAL) && (task_nice(current) < 0)) set_user_nice(current, 0); /* cpus_allowed? */ /* rt_priority? */ @@ -369,7 +367,7 @@ void daemonize(const char *name, ...) EXPORT_SYMBOL(daemonize); -static void close_files(struct files_struct * files) +static inline void close_files(struct files_struct * files) { int i, j; struct fdtable *fdt; @@ -543,7 +541,7 @@ static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_re p->real_parent = reaper; } -static void reparent_thread(task_t *p, task_t *father, int traced) +static inline void reparent_thread(task_t *p, task_t *father, int traced) { /* We don't want people slaying init. */ if (p->exit_signal != -1) @@ -607,7 +605,7 @@ static void reparent_thread(task_t *p, task_t *father, int traced) * group, and if no such member exists, give it to * the global child reaper process (ie "init") */ -static void forget_original_parent(struct task_struct * father, +static inline void forget_original_parent(struct task_struct * father, struct list_head *to_release) { struct task_struct *p, *reaper = father; diff --git a/trunk/kernel/posix-timers.c b/trunk/kernel/posix-timers.c index 197208b3aa2a..9e66e614862a 100644 --- a/trunk/kernel/posix-timers.c +++ b/trunk/kernel/posix-timers.c @@ -192,7 +192,7 @@ static inline int common_clock_set(const clockid_t which_clock, return do_sys_settimeofday(tp, NULL); } -static int common_timer_create(struct k_itimer *new_timer) +static inline int common_timer_create(struct k_itimer *new_timer) { hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock); new_timer->it.real.timer.data = new_timer; @@ -361,7 +361,7 @@ static int posix_timer_fn(void *data) return ret; } -static struct task_struct * good_sigevent(sigevent_t * event) +static inline struct task_struct * good_sigevent(sigevent_t * event) { struct task_struct *rtn = current->group_leader; @@ -687,7 +687,7 @@ sys_timer_getoverrun(timer_t timer_id) /* Set a POSIX.1b interval timer. */ /* timr->it_lock is taken. */ -static int +static inline int common_timer_set(struct k_itimer *timr, int flags, struct itimerspec *new_setting, struct itimerspec *old_setting) { @@ -829,7 +829,7 @@ sys_timer_delete(timer_t timer_id) /* * return timer owned by the process, used by exit_itimers */ -static void itimer_delete(struct k_itimer *timer) +static inline void itimer_delete(struct k_itimer *timer) { unsigned long flags; diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index 788ecce1e0e4..c9dec2aa1976 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -521,7 +521,7 @@ static inline void sched_info_dequeued(task_t *t) * long it was waiting to run. We also note when it began so that we * can keep stats on how long its timeslice is. */ -static void sched_info_arrive(task_t *t) +static inline void sched_info_arrive(task_t *t) { unsigned long now = jiffies, diff = 0; struct runqueue *rq = task_rq(t); @@ -748,14 +748,10 @@ static int recalc_task_prio(task_t *p, unsigned long long now) unsigned long long __sleep_time = now - p->timestamp; unsigned long sleep_time; - if (unlikely(p->policy == SCHED_BATCH)) - sleep_time = 0; - else { - if (__sleep_time > NS_MAX_SLEEP_AVG) - sleep_time = NS_MAX_SLEEP_AVG; - else - sleep_time = (unsigned long)__sleep_time; - } + if (__sleep_time > NS_MAX_SLEEP_AVG) + sleep_time = NS_MAX_SLEEP_AVG; + else + sleep_time = (unsigned long)__sleep_time; if (likely(sleep_time > 0)) { /* @@ -1007,7 +1003,7 @@ void kick_process(task_t *p) * We want to under-estimate the load of migration sources, to * balance conservatively. */ -static unsigned long __source_load(int cpu, int type, enum idle_type idle) +static inline unsigned long __source_load(int cpu, int type, enum idle_type idle) { runqueue_t *rq = cpu_rq(cpu); unsigned long running = rq->nr_running; @@ -1870,7 +1866,7 @@ void sched_exec(void) * pull_task - move a task from a remote runqueue to the local runqueue. * Both runqueues must be locked. */ -static +static inline void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p, runqueue_t *this_rq, prio_array_t *this_array, int this_cpu) { @@ -1892,7 +1888,7 @@ void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p, /* * can_migrate_task - may task p from runqueue rq be migrated to this_cpu? */ -static +static inline int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu, struct sched_domain *sd, enum idle_type idle, int *all_pinned) @@ -2378,7 +2374,7 @@ static int load_balance_newidle(int this_cpu, runqueue_t *this_rq, * idle_balance is called by schedule() if this_cpu is about to become * idle. Attempts to pull tasks from other CPUs. */ -static void idle_balance(int this_cpu, runqueue_t *this_rq) +static inline void idle_balance(int this_cpu, runqueue_t *this_rq) { struct sched_domain *sd; @@ -2762,7 +2758,7 @@ static inline void wakeup_busy_runqueue(runqueue_t *rq) resched_task(rq->idle); } -static void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq) +static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq) { struct sched_domain *tmp, *sd = NULL; cpumask_t sibling_map; @@ -2816,7 +2812,7 @@ static inline unsigned long smt_slice(task_t *p, struct sched_domain *sd) return p->time_slice * (100 - sd->per_cpu_gain) / 100; } -static int dependent_sleeper(int this_cpu, runqueue_t *this_rq) +static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq) { struct sched_domain *tmp, *sd = NULL; cpumask_t sibling_map; @@ -3564,7 +3560,7 @@ void set_user_nice(task_t *p, long nice) * The RT priorities are set via sched_setscheduler(), but we still * allow the 'normal' nice value to be set - but as expected * it wont have any effect on scheduling until the task is - * not SCHED_NORMAL/SCHED_BATCH: + * not SCHED_NORMAL: */ if (rt_task(p)) { p->static_prio = NICE_TO_PRIO(nice); @@ -3710,16 +3706,10 @@ static void __setscheduler(struct task_struct *p, int policy, int prio) BUG_ON(p->array); p->policy = policy; p->rt_priority = prio; - if (policy != SCHED_NORMAL && policy != SCHED_BATCH) { + if (policy != SCHED_NORMAL) p->prio = MAX_RT_PRIO-1 - p->rt_priority; - } else { + else p->prio = p->static_prio; - /* - * SCHED_BATCH tasks are treated as perpetual CPU hogs: - */ - if (policy == SCHED_BATCH) - p->sleep_avg = 0; - } } /** @@ -3743,35 +3733,29 @@ int sched_setscheduler(struct task_struct *p, int policy, if (policy < 0) policy = oldpolicy = p->policy; else if (policy != SCHED_FIFO && policy != SCHED_RR && - policy != SCHED_NORMAL && policy != SCHED_BATCH) - return -EINVAL; + policy != SCHED_NORMAL) + return -EINVAL; /* * Valid priorities for SCHED_FIFO and SCHED_RR are - * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and - * SCHED_BATCH is 0. + * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL is 0. */ if (param->sched_priority < 0 || (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) || (!p->mm && param->sched_priority > MAX_RT_PRIO-1)) return -EINVAL; - if ((policy == SCHED_NORMAL || policy == SCHED_BATCH) - != (param->sched_priority == 0)) + if ((policy == SCHED_NORMAL) != (param->sched_priority == 0)) return -EINVAL; /* * Allow unprivileged RT tasks to decrease priority: */ if (!capable(CAP_SYS_NICE)) { - /* - * can't change policy, except between SCHED_NORMAL - * and SCHED_BATCH: - */ - if (((policy != SCHED_NORMAL && p->policy != SCHED_BATCH) && - (policy != SCHED_BATCH && p->policy != SCHED_NORMAL)) && - !p->signal->rlim[RLIMIT_RTPRIO].rlim_cur) + /* can't change policy */ + if (policy != p->policy && + !p->signal->rlim[RLIMIT_RTPRIO].rlim_cur) return -EPERM; /* can't increase priority */ - if ((policy != SCHED_NORMAL && policy != SCHED_BATCH) && + if (policy != SCHED_NORMAL && param->sched_priority > p->rt_priority && param->sched_priority > p->signal->rlim[RLIMIT_RTPRIO].rlim_cur) @@ -4249,7 +4233,6 @@ asmlinkage long sys_sched_get_priority_max(int policy) ret = MAX_USER_RT_PRIO-1; break; case SCHED_NORMAL: - case SCHED_BATCH: ret = 0; break; } @@ -4273,7 +4256,6 @@ asmlinkage long sys_sched_get_priority_min(int policy) ret = 1; break; case SCHED_NORMAL: - case SCHED_BATCH: ret = 0; } return ret; @@ -6008,7 +5990,7 @@ static void arch_destroy_sched_domains(const cpumask_t *cpu_map) * Detach sched domains from a group of cpus specified in cpu_map * These cpus will now be attached to the NULL domain */ -static void detach_destroy_domains(const cpumask_t *cpu_map) +static inline void detach_destroy_domains(const cpumask_t *cpu_map) { int i; diff --git a/trunk/kernel/signal.c b/trunk/kernel/signal.c index 5dafbd36d62e..1da2e74beb97 100644 --- a/trunk/kernel/signal.c +++ b/trunk/kernel/signal.c @@ -476,7 +476,7 @@ unblock_all_signals(void) spin_unlock_irqrestore(¤t->sighand->siglock, flags); } -static int collect_signal(int sig, struct sigpending *list, siginfo_t *info) +static inline int collect_signal(int sig, struct sigpending *list, siginfo_t *info) { struct sigqueue *q, *first = NULL; int still_pending = 0; @@ -1881,7 +1881,7 @@ do_signal_stop(int signr) * We return zero if we still hold the siglock and should look * for another signal without checking group_stop_count again. */ -static int handle_group_stop(void) +static inline int handle_group_stop(void) { int stop_count; diff --git a/trunk/kernel/sysctl.c b/trunk/kernel/sysctl.c index f5d69b6e29f5..62d4d9566876 100644 --- a/trunk/kernel/sysctl.c +++ b/trunk/kernel/sysctl.c @@ -648,7 +648,7 @@ static ctl_table kern_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, -#if defined(CONFIG_S390) && defined(CONFIG_SMP) +#if defined(CONFIG_S390) { .ctl_name = KERN_SPIN_RETRY, .procname = "spin_retry", diff --git a/trunk/kernel/workqueue.c b/trunk/kernel/workqueue.c index b052e2c4c710..82c4fa70595c 100644 --- a/trunk/kernel/workqueue.c +++ b/trunk/kernel/workqueue.c @@ -147,7 +147,7 @@ int fastcall queue_delayed_work(struct workqueue_struct *wq, return ret; } -static void run_workqueue(struct cpu_workqueue_struct *cwq) +static inline void run_workqueue(struct cpu_workqueue_struct *cwq) { unsigned long flags; diff --git a/trunk/lib/Kconfig.debug b/trunk/lib/Kconfig.debug index a314e663d517..a609235a517f 100644 --- a/trunk/lib/Kconfig.debug +++ b/trunk/lib/Kconfig.debug @@ -195,20 +195,6 @@ config FRAME_POINTER some architectures or if you use external debuggers. If you don't debug the kernel, you can say N. -config FORCED_INLINING - bool "Force gcc to inline functions marked 'inline'" - depends on DEBUG_KERNEL - default y - help - This option determines if the kernel forces gcc to inline the functions - developers have marked 'inline'. Doing so takes away freedom from gcc to - do what it thinks is best, which is desirable for the gcc 3.x series of - compilers. The gcc 4.x series have a rewritten inlining algorithm and - disabling this option will generate a smaller kernel there. Hopefully - this algorithm is so good that allowing gcc4 to make the decision can - become the default in the future, until then this option is there to - test gcc for this. - config RCU_TORTURE_TEST tristate "torture tests for RCU" depends on DEBUG_KERNEL diff --git a/trunk/mm/mempolicy.c b/trunk/mm/mempolicy.c index 3171f884d245..b62cab575a84 100644 --- a/trunk/mm/mempolicy.c +++ b/trunk/mm/mempolicy.c @@ -1359,30 +1359,6 @@ static int shared_policy_replace(struct shared_policy *sp, unsigned long start, return 0; } -void mpol_shared_policy_init(struct shared_policy *info, int policy, - nodemask_t *policy_nodes) -{ - info->root = RB_ROOT; - spin_lock_init(&info->lock); - - if (policy != MPOL_DEFAULT) { - struct mempolicy *newpol; - - /* Falls back to MPOL_DEFAULT on any error */ - newpol = mpol_new(policy, policy_nodes); - if (!IS_ERR(newpol)) { - /* Create pseudo-vma that contains just the policy */ - struct vm_area_struct pvma; - - memset(&pvma, 0, sizeof(struct vm_area_struct)); - /* Policy covers entire file */ - pvma.vm_end = TASK_SIZE; - mpol_set_shared_policy(info, &pvma, newpol); - mpol_free(newpol); - } - } -} - int mpol_set_shared_policy(struct shared_policy *info, struct vm_area_struct *vma, struct mempolicy *npol) { diff --git a/trunk/mm/oom_kill.c b/trunk/mm/oom_kill.c index 14bd4ec79597..4748b906aff2 100644 --- a/trunk/mm/oom_kill.c +++ b/trunk/mm/oom_kill.c @@ -274,7 +274,6 @@ void out_of_memory(gfp_t gfp_mask, int order) show_mem(); } - cpuset_lock(); read_lock(&tasklist_lock); retry: p = select_bad_process(); @@ -285,7 +284,6 @@ void out_of_memory(gfp_t gfp_mask, int order) /* Found nothing?!?! Either we hang forever, or we panic. */ if (!p) { read_unlock(&tasklist_lock); - cpuset_unlock(); panic("Out of memory and no killable processes...\n"); } @@ -295,7 +293,6 @@ void out_of_memory(gfp_t gfp_mask, int order) out: read_unlock(&tasklist_lock); - cpuset_unlock(); if (mm) mmput(mm); diff --git a/trunk/mm/shmem.c b/trunk/mm/shmem.c index ce501bce1c2e..343b3c0937e5 100644 --- a/trunk/mm/shmem.c +++ b/trunk/mm/shmem.c @@ -1316,8 +1316,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) case S_IFREG: inode->i_op = &shmem_inode_operations; inode->i_fop = &shmem_file_operations; - mpol_shared_policy_init(&info->policy, sbinfo->policy, - &sbinfo->policy_nodes); + mpol_shared_policy_init(&info->policy); break; case S_IFDIR: inode->i_nlink++; @@ -1331,8 +1330,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) * Must not load anything in the rbtree, * mpol_free_shared_policy will not be called. */ - mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, - NULL); + mpol_shared_policy_init(&info->policy); break; } } else if (sbinfo->max_inodes) { @@ -1845,9 +1843,7 @@ static struct inode_operations shmem_symlink_inode_operations = { .put_link = shmem_put_link, }; -static int shmem_parse_options(char *options, int *mode, uid_t *uid, - gid_t *gid, unsigned long *blocks, unsigned long *inodes, - int *policy, nodemask_t *policy_nodes) +static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long *blocks, unsigned long *inodes) { char *this_char, *value, *rest; @@ -1901,19 +1897,6 @@ static int shmem_parse_options(char *options, int *mode, uid_t *uid, *gid = simple_strtoul(value,&rest,0); if (*rest) goto bad_val; - } else if (!strcmp(this_char,"mpol")) { - if (!strcmp(value,"default")) - *policy = MPOL_DEFAULT; - else if (!strcmp(value,"preferred")) - *policy = MPOL_PREFERRED; - else if (!strcmp(value,"bind")) - *policy = MPOL_BIND; - else if (!strcmp(value,"interleave")) - *policy = MPOL_INTERLEAVE; - else - goto bad_val; - } else if (!strcmp(this_char,"mpol_nodelist")) { - nodelist_parse(value, *policy_nodes); } else { printk(KERN_ERR "tmpfs: Bad mount option %s\n", this_char); @@ -1934,14 +1917,12 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data) struct shmem_sb_info *sbinfo = SHMEM_SB(sb); unsigned long max_blocks = sbinfo->max_blocks; unsigned long max_inodes = sbinfo->max_inodes; - int policy = sbinfo->policy; - nodemask_t policy_nodes = sbinfo->policy_nodes; unsigned long blocks; unsigned long inodes; int error = -EINVAL; - if (shmem_parse_options(data, NULL, NULL, NULL, &max_blocks, - &max_inodes, &policy, &policy_nodes)) + if (shmem_parse_options(data, NULL, NULL, NULL, + &max_blocks, &max_inodes)) return error; spin_lock(&sbinfo->stat_lock); @@ -1967,8 +1948,6 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data) sbinfo->free_blocks = max_blocks - blocks; sbinfo->max_inodes = max_inodes; sbinfo->free_inodes = max_inodes - inodes; - sbinfo->policy = policy; - sbinfo->policy_nodes = policy_nodes; out: spin_unlock(&sbinfo->stat_lock); return error; @@ -1993,8 +1972,6 @@ static int shmem_fill_super(struct super_block *sb, struct shmem_sb_info *sbinfo; unsigned long blocks = 0; unsigned long inodes = 0; - int policy = MPOL_DEFAULT; - nodemask_t policy_nodes = node_online_map; #ifdef CONFIG_TMPFS /* @@ -2007,8 +1984,8 @@ static int shmem_fill_super(struct super_block *sb, inodes = totalram_pages - totalhigh_pages; if (inodes > blocks) inodes = blocks; - if (shmem_parse_options(data, &mode, &uid, &gid, &blocks, - &inodes, &policy, &policy_nodes)) + if (shmem_parse_options(data, &mode, &uid, &gid, + &blocks, &inodes)) return -EINVAL; } #else @@ -2026,8 +2003,6 @@ static int shmem_fill_super(struct super_block *sb, sbinfo->free_blocks = blocks; sbinfo->max_inodes = inodes; sbinfo->free_inodes = inodes; - sbinfo->policy = policy; - sbinfo->policy_nodes = policy_nodes; sb->s_fs_info = sbinfo; sb->s_maxbytes = SHMEM_MAX_BYTES; diff --git a/trunk/net/ieee80211/ieee80211_module.c b/trunk/net/ieee80211/ieee80211_module.c index 90d18b72da3d..321287bc887f 100644 --- a/trunk/net/ieee80211/ieee80211_module.c +++ b/trunk/net/ieee80211/ieee80211_module.c @@ -62,7 +62,7 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_AUTHOR(DRV_COPYRIGHT); MODULE_LICENSE("GPL"); -static int ieee80211_networks_allocate(struct ieee80211_device *ieee) +static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee) { if (ieee->networks) return 0; @@ -90,7 +90,7 @@ static inline void ieee80211_networks_free(struct ieee80211_device *ieee) ieee->networks = NULL; } -static void ieee80211_networks_initialize(struct ieee80211_device *ieee) +static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee) { int i; diff --git a/trunk/net/ieee80211/ieee80211_rx.c b/trunk/net/ieee80211/ieee80211_rx.c index 7a121802faa9..5e3380388046 100644 --- a/trunk/net/ieee80211/ieee80211_rx.c +++ b/trunk/net/ieee80211/ieee80211_rx.c @@ -35,7 +35,7 @@ #include -static void ieee80211_monitor_rx(struct ieee80211_device *ieee, +static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats) { @@ -165,7 +165,7 @@ static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, * Responsible for handling management control frames * * Called by ieee80211_rx */ -static int +static inline int ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats, u16 type, u16 stype) @@ -266,7 +266,7 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee, } /* Called only as a tasklet (software IRQ), by ieee80211_rx */ -static int +static inline int ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_crypt_data *crypt) { @@ -297,7 +297,7 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, } /* Called only as a tasklet (software IRQ), by ieee80211_rx */ -static int +static inline int ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *skb, int keyidx, struct ieee80211_crypt_data *crypt) @@ -1156,7 +1156,7 @@ static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct iee /***************************************************/ -static int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response +static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response *beacon, struct ieee80211_network *network, struct ieee80211_rx_stats *stats) @@ -1235,7 +1235,7 @@ static inline int is_same_network(struct ieee80211_network *src, !memcmp(src->ssid, dst->ssid, src->ssid_len)); } -static void update_network(struct ieee80211_network *dst, +static inline void update_network(struct ieee80211_network *dst, struct ieee80211_network *src) { int qos_active; @@ -1294,7 +1294,7 @@ static inline int is_beacon(int fc) return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON); } -static void ieee80211_process_probe_response(struct ieee80211_device +static inline void ieee80211_process_probe_response(struct ieee80211_device *ieee, struct ieee80211_probe_response *beacon, struct ieee80211_rx_stats diff --git a/trunk/net/ieee80211/ieee80211_tx.c b/trunk/net/ieee80211/ieee80211_tx.c index 8fdd943ebe8e..e5b33c8d5dbc 100644 --- a/trunk/net/ieee80211/ieee80211_tx.c +++ b/trunk/net/ieee80211/ieee80211_tx.c @@ -127,7 +127,7 @@ payload of each frame is reduced to 492 bytes. static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; -static int ieee80211_copy_snap(u8 * data, u16 h_proto) +static inline int ieee80211_copy_snap(u8 * data, u16 h_proto) { struct ieee80211_snap_hdr *snap; u8 *oui; @@ -150,7 +150,7 @@ static int ieee80211_copy_snap(u8 * data, u16 h_proto) return SNAP_SIZE + sizeof(u16); } -static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, +static inline int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, struct sk_buff *frag, int hdr_len) { struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx]; diff --git a/trunk/net/ieee80211/ieee80211_wx.c b/trunk/net/ieee80211/ieee80211_wx.c index 23e1630f50b7..406d5b964905 100644 --- a/trunk/net/ieee80211/ieee80211_wx.c +++ b/trunk/net/ieee80211/ieee80211_wx.c @@ -42,7 +42,7 @@ static const char *ieee80211_modes[] = { }; #define MAX_CUSTOM_LEN 64 -static char *ipw2100_translate_scan(struct ieee80211_device *ieee, +static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee, char *start, char *stop, struct ieee80211_network *network) { diff --git a/trunk/net/ipv4/fib_frontend.c b/trunk/net/ipv4/fib_frontend.c index 4e3d3811dea2..5b25fc0d980c 100644 --- a/trunk/net/ipv4/fib_frontend.c +++ b/trunk/net/ipv4/fib_frontend.c @@ -289,13 +289,13 @@ static int inet_check_attr(struct rtmsg *r, struct rtattr **rta) { int i; - for (i=1; i<=RTA_MAX; i++, rta++) { - struct rtattr *attr = *rta; + for (i=1; i<=RTA_MAX; i++) { + struct rtattr *attr = rta[i-1]; if (attr) { if (RTA_PAYLOAD(attr) < 4) return -EINVAL; if (i != RTA_MULTIPATH && i != RTA_METRICS) - *rta = (struct rtattr*)RTA_DATA(attr); + rta[i-1] = (struct rtattr*)RTA_DATA(attr); } } return 0; diff --git a/trunk/net/netfilter/nfnetlink.c b/trunk/net/netfilter/nfnetlink.c index f6063e8f0050..95fdf04f1d88 100644 --- a/trunk/net/netfilter/nfnetlink.c +++ b/trunk/net/netfilter/nfnetlink.c @@ -212,7 +212,7 @@ int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags) } /* Process one complete nfnetlink message. */ -static int nfnetlink_rcv_msg(struct sk_buff *skb, +static inline int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) { struct nfnl_callback *nc; diff --git a/trunk/security/selinux/hooks.c b/trunk/security/selinux/hooks.c index b9f8d9731c3d..6647204e4636 100644 --- a/trunk/security/selinux/hooks.c +++ b/trunk/security/selinux/hooks.c @@ -1019,7 +1019,7 @@ static inline int dentry_has_perm(struct task_struct *tsk, has the same SID as the process. If av is zero, then access to the file is not checked, e.g. for cases where only the descriptor is affected like seek. */ -static int file_has_perm(struct task_struct *tsk, +static inline int file_has_perm(struct task_struct *tsk, struct file *file, u32 av) { diff --git a/trunk/sound/oss/esssolo1.c b/trunk/sound/oss/esssolo1.c index 849b59f67ef5..a4ecab2f0522 100644 --- a/trunk/sound/oss/esssolo1.c +++ b/trunk/sound/oss/esssolo1.c @@ -515,7 +515,7 @@ static inline int prog_dmabuf_adc(struct solo1_state *s) return 0; } -static int prog_dmabuf_dac(struct solo1_state *s) +static inline int prog_dmabuf_dac(struct solo1_state *s) { unsigned long va; int c; diff --git a/trunk/sound/pci/es1968.c b/trunk/sound/pci/es1968.c index 3747a436f0cd..9ffb600321cb 100644 --- a/trunk/sound/pci/es1968.c +++ b/trunk/sound/pci/es1968.c @@ -727,7 +727,7 @@ static void __apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 dat apu_data_set(chip, data); } -static void apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data) +static inline void apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data) { unsigned long flags; spin_lock_irqsave(&chip->reg_lock, flags); @@ -743,7 +743,7 @@ static u16 __apu_get_register(struct es1968 *chip, u16 channel, u8 reg) return __maestro_read(chip, IDR0_DATA_PORT); } -static u16 apu_get_register(struct es1968 *chip, u16 channel, u8 reg) +static inline u16 apu_get_register(struct es1968 *chip, u16 channel, u8 reg) { unsigned long flags; u16 v;