diff options
| author | Greg Kroah-Hartman <greg@kroah.com> | 2003-09-04 19:49:13 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <greg@kroah.com> | 2003-09-04 19:49:13 -0700 |
| commit | 24467ec6c2fa857c332d4bfdd2c92f2507d16a86 (patch) | |
| tree | e9b561d5c7fb0b1dd7af2b4c6ec778b82002ae11 | |
| parent | 7c9481c3d31dab43cf053ebeab556264e608b4ae (diff) | |
| parent | 863003968458edf00e2ebdad49f68040203d886d (diff) | |
Merge kroah.com:/home/linux/BK/bleed-2.5
into kroah.com:/home/linux/BK/gregkh-2.6
462 files changed, 11106 insertions, 9816 deletions
diff --git a/Documentation/DocBook/scsidrivers.tmpl b/Documentation/DocBook/scsidrivers.tmpl index 1dbafa7c2bd9..81e1561caf14 100644 --- a/Documentation/DocBook/scsidrivers.tmpl +++ b/Documentation/DocBook/scsidrivers.tmpl @@ -16,20 +16,40 @@ </affiliation> </author> </authorgroup> - <pubdate>2002-04-27</pubdate> + <pubdate>2003-08-11</pubdate> <copyright> <year>2002</year> + <year>2003</year> <holder>Douglas Gilbert</holder> </copyright> + <legalnotice> <para> - Permission is granted to copy, distribute and/or modify this - document under the terms of the GNU Free Documentation License, - Version 1.1 or any later version published by the Free Software - Foundation; with no Invariant Sections, with no Front-Cover Texts, - and with no Back-Cover Texts. A copy of the license is included - in the section entitled "GNU Free Documentation License". + This documentation 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. + </para> + + <para> + 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. + </para> + + <para> + 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 + </para> + + <para> + For more details see the file COPYING in the source + distribution of Linux. </para> </legalnotice> diff --git a/Documentation/kmod.txt b/Documentation/kmod.txt deleted file mode 100644 index be1a9a5183ee..000000000000 --- a/Documentation/kmod.txt +++ /dev/null @@ -1,68 +0,0 @@ -Kmod: The Kernel Module Loader -Kirk Petersen - -Kmod is a simple replacement for kerneld. It consists of a -request_module() replacement and a kernel thread called kmod. When the -kernel requests a module, the kmod wakes up and execve()s modprobe, -passing it the name that was requested. - -If you have the /proc filesystem mounted, you can set the path of -modprobe (where the kernel looks for it) by doing: - - echo "/sbin/modprobe" > /proc/sys/kernel/modprobe - -To periodically unload unused modules, put something like the following -in root's crontab entry: - - 0-59/5 * * * * /sbin/rmmod -a - -Kmod only loads modules. Kerneld could do more (although -nothing in the standard kernel used its other features). If you -require features such as request_route, we suggest that you take -a similar approach. A simple request_route function could be called, -and a kroute kernel thread could be sent off to do the work. But -we should probably keep this to a minimum. - -Kerneld also had a mechanism for storing device driver settings. This -can easily be done with modprobe. When a module is unloaded, modprobe -could look at a per-driver-configurable location (/proc/sys/drivers/blah) -for device driver settings and save them to a file. When a module -is loaded, simply cat that file back to that location in the proc -filesystem. Or perhaps a script could be a setting in /etc/modules.conf. -There are many user-land methods that will work (I prefer using /proc, -myself). - -If kerneld worked, why replace it? - -- kerneld used SysV IPC, which can now be made into a module. Besides, - SysV IPC is ugly and should therefore be avoided (well, certainly for - kernel level stuff) - -- both kmod and kerneld end up doing the same thing (calling modprobe), - so why not skip the middle man? - -- removing kerneld related stuff from ipc/msg.c made it 40% smaller - -- kmod reports errors through the normal kernel mechanisms, which avoids - the chicken and egg problem of kerneld and modular Unix domain sockets - - -Keith Owens <kaos@ocs.com.au> December 1999 - -The combination of kmod and modprobe can loop, especially if modprobe uses a -system call that requires a module. If modules.dep does not exist and modprobe -was started with the -s option (kmod does this), modprobe tries to syslog() a -message. syslog() needs Unix sockets, if Unix sockets are modular then kmod -runs "modprobe -s net-pf-1". This runs a second copy of modprobe which -complains that modules.dep does not exist, tries to use syslog() and starts yet -another copy of modprobe. This is not the only possible kmod/modprobe loop, -just the most common. - -To detect loops caused by "modprobe needs a service which is in a module", kmod -limits the number of concurrent kmod issued modprobes. See MAX_KMOD_CONCURRENT -in kernel/kmod.c. When this limit is exceeded, the kernel issues message "kmod: -runaway modprobe loop assumed and stopped". - -Note for users building a heavily modularised system. It is a good idea to -create modules.dep after installing the modules and before booting a kernel for -the first time. "depmod -ae m.n.p" where m.n.p is the new kernel version. diff --git a/MAINTAINERS b/MAINTAINERS index 76557f42ec2e..d9d91b3b4eca 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1088,7 +1088,7 @@ S: Maintained KERNEL JANITORS P: Several -L: kernel-janitor-discuss@lists.sf.net +L: kernel-janitors@osdl.org W: http://www.kerneljanitors.org/ W: http://sf.net/projects/kernel-janitor/ W: http://developer.osdl.org/rddunlap/kj-patches/ diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 7ae52271f680..c2181d7de0a7 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -30,12 +30,6 @@ endif check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi) comma = , -# Select CPU dependent flags. Note that order of declaration is important; -# the options further down the list override previous items. -# -apcs-$(CONFIG_CPU_32) :=-mapcs-32 -apcs-$(CONFIG_CPU_26) :=-mapcs-26 -mcpu=arm3 - # This selects which instruction set is used. # Note that GCC does not numerically define an architecture version # macro, but instead defines a whole series of macros which makes @@ -55,37 +49,21 @@ tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 tune-$(CONFIG_CPU_XSCALE) :=$(call check_gcc,-mtune=xscale,-mtune=strongarm110) -# Force -mno-fpu to be passed to the assembler. Some versions of gcc don't -# do this with -msoft-float -CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm -CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm -AFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -msoft-float -Wa,-mno-fpu +CFLAGS_BOOT :=-mapcs-32 $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm +CFLAGS +=-mapcs-32 $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm +AFLAGS +=-mapcs-32 $(arch-y) $(tune-y) -msoft-float -Wa,-mno-fpu #Default value DATAADDR := . -ifeq ($(CONFIG_CPU_26),y) -PROCESSOR := armo -head-y := arch/arm/mach-arc/head.o arch/arm/kernel/init_task.o -LDFLAGS_BLOB += --oformat elf26-littlearm - ifeq ($(CONFIG_ROM_KERNEL),y) - DATAADDR := 0x02080000 - textaddr-y := 0x03800000 - else - textaddr-y := 0x02080000 - endif -endif - -ifeq ($(CONFIG_CPU_32),y) PROCESSOR := armv head-y := arch/arm/kernel/head.o arch/arm/kernel/init_task.o - ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) - LDFLAGS_BLOB += --oformat elf32-bigarm - else - LDFLAGS_BLOB += --oformat elf32-littlearm - endif -textaddr-y := 0xC0008000 +ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) + LDFLAGS_BLOB += --oformat elf32-bigarm +else + LDFLAGS_BLOB += --oformat elf32-littlearm endif +textaddr-y := 0xC0008000 machine-$(CONFIG_ARCH_ARCA5K) := arc machine-$(CONFIG_ARCH_RPC) := rpc @@ -160,16 +138,10 @@ include/asm-arm/.arch: $(wildcard include/config/arch/*.h) @ln -sf arch-$(INCDIR) include/asm-arm/arch @touch $@ -include/asm-arm/.proc: $(wildcard include/config/cpu/32.h) $(wildcard include/config/cpu/26.h) - @echo ' Making asm-arm/proc -> asm-arm/proc-$(PROCESSOR) symlink' - @rm -f include/asm-arm/proc - @ln -sf proc-$(PROCESSOR) include/asm-arm/proc - @touch $@ - prepare: maketools .PHONY: maketools FORCE -maketools: include/asm-arm/.arch include/asm-arm/.proc \ +maketools: include/asm-arm/.arch \ include/asm-arm/constants.h include/linux/version.h FORCE $(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h @@ -185,7 +157,6 @@ zinstall install: vmlinux MRPROPER_FILES += \ include/asm-arm/arch include/asm-arm/.arch \ - include/asm-arm/proc include/asm-arm/.proc \ include/asm-arm/constants.h* \ include/asm-arm/mach-types.h @@ -217,7 +188,7 @@ zi:; $(Q)$(MAKE) $(build)=$(boot) zinstall ) arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ - include/asm-arm/.arch include/asm-arm/.proc \ + include/asm-arm/.arch \ include/config/MARKER include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 53c7a6c717d8..1cf609a45cbb 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -2,13 +2,11 @@ # Makefile for the linux kernel. # -ENTRY_OBJ = entry-$(PROCESSOR).o - AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) # Object file lists. -obj-y := arch.o compat.o dma.o $(ENTRY_OBJ) entry-common.o irq.o \ +obj-y := arch.o compat.o dma.o entry-armv.o entry-common.o irq.o \ process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \ time.o traps.o @@ -34,6 +32,5 @@ extra-y := $(head-y) init_task.o vmlinux.lds.s # Spell out some dependencies that `make dep' doesn't spot $(obj)/entry-armv.o: $(obj)/entry-header.S include/asm-arm/constants.h -$(obj)/entry-armo.o: $(obj)/entry-header.S include/asm-arm/constants.h $(obj)/entry-common.o: $(obj)/entry-header.S include/asm-arm/constants.h \ $(obj)/calls.S diff --git a/arch/arm/kernel/entry-armo.S b/arch/arm/kernel/entry-armo.S deleted file mode 100644 index f081ad9af786..000000000000 --- a/arch/arm/kernel/entry-armo.S +++ /dev/null @@ -1,633 +0,0 @@ -/* - * linux/arch/arm/kernel/entry-armo.S - * - * Copyright (C) 1995,1996,1997,1998 Russell King. - * - * 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. - * - * Low-level vector interface routines - * - * Design issues: - * - We have several modes that each vector can be called from, - * each with its own set of registers. On entry to any vector, - * we *must* save the registers used in *that* mode. - * - * - This code must be as fast as possible. - * - * There are a few restrictions on the vectors: - * - the SWI vector cannot be called from *any* non-user mode - * - * - the FP emulator is *never* called from *any* non-user mode undefined - * instruction. - * - * Ok, so this file may be a mess, but its as efficient as possible while - * adhering to the above criteria. - */ -#include <linux/config.h> -#include <linux/init.h> -#include "entry-header.S" - - .text - -#ifdef IOC_BASE -/* IOC / IOMD based hardware */ - .equ ioc_base_high, IOC_BASE & 0xff000000 - .equ ioc_base_low, IOC_BASE & 0x00ff0000 - .macro disable_fiq - mov r12, #ioc_base_high - .if ioc_base_low - orr r12, r12, #ioc_base_low - .endif - strb r12, [r12, #0x38] @ Disable FIQ register - .endm - - .macro get_irqnr_and_base, irqnr, base - mov r4, #ioc_base_high @ point at IOC - .if ioc_base_low - orr r4, r4, #ioc_base_low - .endif - ldrb \irqnr, [r4, #0x24] @ get high priority first - adr \base, irq_prio_h - teq \irqnr, #0 - ldreqb \irqnr, [r4, #0x14] @ get low priority - adreq \base, irq_prio_l - .endm - -/* - * Interrupt table (incorporates priority) - */ - .macro irq_prio_table -irq_prio_l: .byte 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 - .byte 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 - .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 - .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 - .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3 - .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3 - .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 - .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 -irq_prio_h: .byte 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .endm -#else -#error Unknown architecture -#endif - -/*============================================================================= - * For entry-common.S - */ - -#if 0 -/* - * Uncomment these if you wish to get more debugging into about data aborts. - */ -#define FAULT_CODE_LDRSTRPOST 0x80 -#define FAULT_CODE_LDRSTRPRE 0x40 -#define FAULT_CODE_LDRSTRREG 0x20 -#define FAULT_CODE_LDMSTM 0x10 -#define FAULT_CODE_LDCSTC 0x08 -#endif -#define FAULT_CODE_PREFETCH 0x04 -#define FAULT_CODE_WRITE 0x02 -#define FAULT_CODE_FORCECOW 0x01 - -#define SVC_SAVE_ALL \ - str sp, [sp, #-16]! ;\ - str lr, [sp, #8] ;\ - str lr, [sp, #4] ;\ - stmfd sp!, {r0 - r12} ;\ - mov r0, #-1 ;\ - str r0, [sp, #S_OLD_R0] ;\ - zero_fp - -#define SVC_IRQ_SAVE_ALL \ - str sp, [sp, #-16]! ;\ - str lr, [sp, #4] ;\ - ldr lr, .LCirq ;\ - ldr lr, [lr] ;\ - str lr, [sp, #8] ;\ - stmfd sp!, {r0 - r12} ;\ - mov r0, #-1 ;\ - str r0, [sp, #S_OLD_R0] ;\ - zero_fp - -#define SVC_RESTORE_ALL \ - ldmfd sp, {r0 - pc}^ - -/*============================================================================= - * Undefined FIQs - *----------------------------------------------------------------------------- - */ -_unexp_fiq: ldr sp, .LCfiq - mov r12, #IOC_BASE - strb r12, [r12, #0x38] @ Disable FIQ register - teqp pc, #0x0c000003 - mov r0, r0 - stmfd sp!, {r0 - r3, ip, lr} - adr r0, Lfiqmsg - bl printk - ldmfd sp!, {r0 - r3, ip, lr} - teqp pc, #0x0c000001 - mov r0, r0 - movs pc, lr - -Lfiqmsg: .ascii "*** Unexpected FIQ\n\0" - .align - -.LCfiq: .word __temp_fiq -.LCirq: .word __temp_irq - -/*============================================================================= - * Undefined instruction handler - *----------------------------------------------------------------------------- - * Handles floating point instructions - */ -vector_undefinstr: - tst lr,#3 - bne __und_svc - save_user_regs - zero_fp - teqp pc, #PSR_I_BIT | MODE_SVC -.Lbug_undef: - ldr r4, .LC2 - ldr pc, [r4] @ Call FP module USR entry point - - .globl fpundefinstr -fpundefinstr: @ Called by FP module on undefined instr - mov r0, lr - mov r1, sp - teqp pc, #MODE_SVC - bl do_undefinstr - b ret_from_exception @ Normal FP exit - -__und_svc: SVC_SAVE_ALL @ Non-user mode - mask_pc r0, lr - and r2, lr, #3 - sub r0, r0, #4 - mov r1, sp - bl do_undefinstr - SVC_RESTORE_ALL - -#if defined CONFIG_FPE_NWFPE || defined CONFIG_FPE_FASTFPE - /* The FPE is always present */ - .equ fpe_not_present, 0 -#else -/* We get here if an undefined instruction happens and the floating - * point emulator is not present. If the offending instruction was - * a WFS, we just perform a normal return as if we had emulated the - * operation. This is a hack to allow some basic userland binaries - * to run so that the emulator module proper can be loaded. --philb - */ -fpe_not_present: - adr r10, wfs_mask_data - ldmia r10, {r4, r5, r6, r7, r8} - ldr r10, [sp, #S_PC] @ Load PC - sub r10, r10, #4 - mask_pc r10, r10 - ldrt r10, [r10] @ get instruction - and r5, r10, r5 - teq r5, r4 @ Is it WFS? - beq ret_from_exception - and r5, r10, r8 - teq r5, r6 @ Is it LDF/STF on sp or fp? - teqne r5, r7 - bne fpundefinstr - tst r10, #0x00200000 @ Does it have WB - beq ret_from_exception - and r4, r10, #255 @ get offset - and r6, r10, #0x000f0000 - tst r10, #0x00800000 @ +/- - ldr r5, [sp, r6, lsr #14] @ Load reg - rsbeq r4, r4, #0 - add r5, r5, r4, lsl #2 - str r5, [sp, r6, lsr #14] @ Save reg - b ret_from_exception - -wfs_mask_data: .word 0x0e200110 @ WFS/RFS - .word 0x0fef0fff - .word 0x0d0d0100 @ LDF [sp]/STF [sp] - .word 0x0d0b0100 @ LDF [fp]/STF [fp] - .word 0x0f0f0f00 -#endif - -.LC2: .word fp_enter - -/*============================================================================= - * Prefetch abort handler - *----------------------------------------------------------------------------- - */ - -vector_prefetch: - sub lr, lr, #4 - tst lr, #3 - bne __pabt_invalid - save_user_regs - teqp pc, #0x00000003 @ NOT a problem - doesn't change mode - mask_pc r0, lr @ Address of abort - mov r1, sp @ Tasks registers - bl do_PrefetchAbort - teq r0, #0 @ If non-zero, we believe this abort.. - bne ret_from_exception -#ifdef DEBUG_UNDEF - adr r0, t - bl printk -#endif - ldr lr, [sp,#S_PC] @ program to test this on. I think its - b .Lbug_undef @ broken at the moment though!) - -__pabt_invalid: SVC_SAVE_ALL - mov r0, sp @ Prefetch aborts are definitely *not* - mov r1, #BAD_PREFETCH @ allowed in non-user modes. We cant - and r2, lr, #3 @ recover from this problem. - b bad_mode - -#ifdef DEBUG_UNDEF -t: .ascii "*** undef ***\r\n\0" - .align -#endif - -/*============================================================================= - * Address exception handler - *----------------------------------------------------------------------------- - * These aren't too critical. - * (they're not supposed to happen). - * In order to debug the reason for address exceptions in non-user modes, - * we have to obtain all the registers so that we can see what's going on. - */ - -vector_addrexcptn: - sub lr, lr, #8 - tst lr, #3 - bne Laddrexcptn_not_user - save_user_regs - teq pc, #0x00000003 - mask_pc r0, lr @ Point to instruction - mov r1, sp @ Point to registers - mov r2, #0x400 - mov lr, pc - bl do_excpt - b ret_from_exception - -Laddrexcptn_not_user: - SVC_SAVE_ALL - and r2, lr, #3 - teq r2, #3 - bne Laddrexcptn_illegal_mode - teqp pc, #0x00000003 @ NOT a problem - doesn't change mode - mask_pc r0, lr - mov r1, sp - orr r2, r2, #0x400 - bl do_excpt - ldmia sp, {r0 - lr} @ I cant remember the reason I changed this... - add sp, sp, #15*4 - movs pc, lr - -Laddrexcptn_illegal_mode: - mov r0, sp - str lr, [sp, #-4]! - orr r1, r2, #0x0c000000 - teqp r1, #0 @ change into mode (wont be user mode) - mov r0, r0 - mov r1, r8 @ Any register from r8 - r14 can be banked - mov r2, r9 - mov r3, r10 - mov r4, r11 - mov r5, r12 - mov r6, r13 - mov r7, r14 - teqp pc, #0x04000003 @ back to svc - mov r0, r0 - stmfd sp!, {r1-r7} - ldmia r0, {r0-r7} - stmfd sp!, {r0-r7} - mov r0, sp - mov r1, #BAD_ADDREXCPTN - b bad_mode - -/*============================================================================= - * Interrupt (IRQ) handler - *----------------------------------------------------------------------------- - * Note: if in user mode, then *no* kernel routine is running, so do not have - * to save svc lr - * (r13 points to irq temp save area) - */ - -vector_IRQ: ldr r13, .LCirq @ I will leave this one in just in case... - sub lr, lr, #4 - str lr, [r13] - tst lr, #3 - bne __irq_svc - teqp pc, #0x08000003 - mov r0, r0 - ldr lr, .LCirq - ldr lr, [lr] - save_user_regs - -1: get_irqnr_and_base r6, r5 - teq r6, #0 - ldrneb r0, [r5, r6] @ get IRQ number - movne r1, sp - @ - @ routine called with r0 = irq number, r1 = struct pt_regs * - @ - adr lr, 1b - orr lr, lr, #0x08000003 @ Force SVC - bne asm_do_IRQ - - mov why, #0 - get_current_task r5 - b ret_to_user - - irq_prio_table - -__irq_svc: teqp pc, #0x08000003 - mov r0, r0 - SVC_IRQ_SAVE_ALL - and r2, lr, #3 - teq r2, #3 - bne __irq_invalid -1: get_irqnr_and_base r6, r5 - teq r6, #0 - ldrneb r0, [r5, r6] @ get IRQ number - movne r1, sp - @ - @ routine called with r0 = irq number, r1 = struct pt_regs * - @ - adr lr, 1b - orr lr, lr, #0x08000003 @ Force SVC - bne asm_do_IRQ @ Returns to 1b - SVC_RESTORE_ALL - -__irq_invalid: mov r0, sp - mov r1, #BAD_IRQ - b bad_mode - -/*============================================================================= - * Data abort handler code - *----------------------------------------------------------------------------- - * - * This handles both exceptions from user and SVC modes, computes the address - * range of the problem, and does any correction that is required. It then - * calls the kernel data abort routine. - * - * This is where I wish that the ARM would tell you which address aborted. - */ - -vector_data: sub lr, lr, #8 @ Correct lr - tst lr, #3 - bne Ldata_not_user - save_user_regs - teqp pc, #0x00000003 @ NOT a problem - doesn't change mode - mask_pc r0, lr - bl Ldata_do - b ret_from_exception - -Ldata_not_user: - SVC_SAVE_ALL - and r2, lr, #3 - teq r2, #3 - bne Ldata_illegal_mode - tst lr, #0x08000000 - teqeqp pc, #0x00000003 @ NOT a problem - doesn't change mode - mask_pc r0, lr - bl Ldata_do - SVC_RESTORE_ALL - -Ldata_illegal_mode: - mov r0, sp - mov r1, #BAD_DATA - b bad_mode - -Ldata_do: mov r3, sp - ldr r4, [r0] @ Get instruction - mov r2, #0 - tst r4, #1 << 20 @ Check to see if it is a write instruction - orreq r2, r2, #FAULT_CODE_WRITE @ Indicate write instruction - mov r1, r4, lsr #22 @ Now branch to the relevant processing routine - and r1, r1, #15 << 2 - add pc, pc, r1 - movs pc, lr - b Ldata_unknown - b Ldata_unknown - b Ldata_unknown - b Ldata_unknown - b Ldata_ldrstr_post @ ldr rd, [rn], #m - b Ldata_ldrstr_numindex @ ldr rd, [rn, #m] @ RegVal - b Ldata_ldrstr_post @ ldr rd, [rn], rm - b Ldata_ldrstr_regindex @ ldr rd, [rn, rm] - b Ldata_ldmstm @ ldm*a rn, <rlist> - b Ldata_ldmstm @ ldm*b rn, <rlist> - b Ldata_unknown - b Ldata_unknown - b Ldata_ldrstr_post @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m - b Ldata_ldcstc_pre @ ldc rd, [rn, #m] - b Ldata_unknown -Ldata_unknown: @ Part of jumptable - mov r0, r1 - mov r1, r4 - mov r2, r3 - b baddataabort - -Ldata_ldrstr_post: - mov r0, r4, lsr #14 @ Get Rn - and r0, r0, #15 << 2 @ Mask out reg. - teq r0, #15 << 2 - ldr r0, [r3, r0] @ Get register - biceq r0, r0, #PCMASK - mov r1, r0 -#ifdef FAULT_CODE_LDRSTRPOST - orr r2, r2, #FAULT_CODE_LDRSTRPOST -#endif - b do_DataAbort - -Ldata_ldrstr_numindex: - mov r0, r4, lsr #14 @ Get Rn - and r0, r0, #15 << 2 @ Mask out reg. - teq r0, #15 << 2 - ldr r0, [r3, r0] @ Get register - mov r1, r4, lsl #20 - biceq r0, r0, #PCMASK - tst r4, #1 << 23 - addne r0, r0, r1, lsr #20 - subeq r0, r0, r1, lsr #20 - mov r1, r0 -#ifdef FAULT_CODE_LDRSTRPRE - orr r2, r2, #FAULT_CODE_LDRSTRPRE -#endif - b do_DataAbort - -Ldata_ldrstr_regindex: - mov r0, r4, lsr #14 @ Get Rn - and r0, r0, #15 << 2 @ Mask out reg. - teq r0, #15 << 2 - ldr r0, [r3, r0] @ Get register - and r7, r4, #15 - biceq r0, r0, #PCMASK - teq r7, #15 @ Check for PC - ldr r7, [r3, r7, lsl #2] @ Get Rm - and r8, r4, #0x60 @ Get shift types - biceq r7, r7, #PCMASK - mov r9, r4, lsr #7 @ Get shift amount - and r9, r9, #31 - teq r8, #0 - moveq r7, r7, lsl r9 - teq r8, #0x20 @ LSR shift - moveq r7, r7, lsr r9 - teq r8, #0x40 @ ASR shift - moveq r7, r7, asr r9 - teq r8, #0x60 @ ROR shift - moveq r7, r7, ror r9 - tst r4, #1 << 23 - addne r0, r0, r7 - subeq r0, r0, r7 @ Apply correction - mov r1, r0 -#ifdef FAULT_CODE_LDRSTRREG - orr r2, r2, #FAULT_CODE_LDRSTRREG -#endif - b do_DataAbort - -Ldata_ldmstm: - mov r7, #0x11 - orr r7, r7, r7, lsl #8 - and r0, r4, r7 - and r1, r4, r7, lsl #1 - add r0, r0, r1, lsr #1 - and r1, r4, r7, lsl #2 - add r0, r0, r1, lsr #2 - and r1, r4, r7, lsl #3 - add r0, r0, r1, lsr #3 - add r0, r0, r0, lsr #8 - add r0, r0, r0, lsr #4 - and r7, r0, #15 @ r7 = no. of registers to transfer. - mov r5, r4, lsr #14 @ Get Rn - and r5, r5, #15 << 2 - ldr r0, [r3, r5] @ Get reg - eor r6, r4, r4, lsl #2 - tst r6, #1 << 23 @ Check inc/dec ^ writeback - rsbeq r7, r7, #0 - add r7, r0, r7, lsl #2 @ Do correction (signed) - subne r1, r7, #1 - subeq r1, r0, #1 - moveq r0, r7 - tst r4, #1 << 21 @ Check writeback - strne r7, [r3, r5] - eor r6, r4, r4, lsl #1 - tst r6, #1 << 24 @ Check Pre/Post ^ inc/dec - addeq r0, r0, #4 - addeq r1, r1, #4 - teq r5, #15*4 @ CHECK FOR PC - biceq r1, r1, #PCMASK - biceq r0, r0, #PCMASK -#ifdef FAULT_CODE_LDMSTM - orr r2, r2, #FAULT_CODE_LDMSTM -#endif - b do_DataAbort - -Ldata_ldcstc_pre: - mov r0, r4, lsr #14 @ Get Rn - and r0, r0, #15 << 2 @ Mask out reg. - teq r0, #15 << 2 - ldr r0, [r3, r0] @ Get register - mov r1, r4, lsl #24 @ Get offset - biceq r0, r0, #PCMASK - tst r4, #1 << 23 - addne r0, r0, r1, lsr #24 - subeq r0, r0, r1, lsr #24 - mov r1, r0 -#ifdef FAULT_CODE_LDCSTC - orr r2, r2, #FAULT_CODE_LDCSTC -#endif - b do_DataAbort - - -/* - * This is the return code to user mode for abort handlers - */ -ENTRY(ret_from_exception) - get_current_task tsk - mov why, #0 - b ret_to_user - - .data -ENTRY(fp_enter) - .word fpe_not_present - .text -/* - * Register switch for older 26-bit only ARMs - */ -ENTRY(__switch_to) - stmfd sp!, {r4 - sl, fp, lr} @ Store most regs on stack - str sp, [r0, #TSS_SAVE] @ Save sp_SVC - ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC - ldmfd sp!, {r4 - sl, fp, pc}^ @ Load all regs saved previously - -/* - *============================================================================= - * Low-level interface code - *----------------------------------------------------------------------------- - * Trap initialisation - *----------------------------------------------------------------------------- - * - * Note - FIQ code has changed. The default is a couple of words in 0x1c, 0x20 - * that call _unexp_fiq. Nowever, we now copy the FIQ routine to 0x1c (removes - * some excess cycles). - * - * What we need to put into 0-0x1c are branches to branch to the kernel. - */ - - __INIT - -.Ljump_addresses: - swi SYS_ERROR0 - .word vector_undefinstr - 12 - .word vector_swi - 16 - .word vector_prefetch - 20 - .word vector_data - 24 - .word vector_addrexcptn - 28 - .word vector_IRQ - 32 - .word _unexp_fiq - 36 - b . + 8 -/* - * initialise the trap system - */ -ENTRY(__trap_init) - stmfd sp!, {r4 - r7, lr} - adr r1, .Ljump_addresses - ldmia r1, {r1 - r7, ip, lr} - orr r2, lr, r2, lsr #2 - orr r3, lr, r3, lsr #2 - orr r4, lr, r4, lsr #2 - orr r5, lr, r5, lsr #2 - orr r6, lr, r6, lsr #2 - orr r7, lr, r7, lsr #2 - orr ip, lr, ip, lsr #2 - mov r0, #0 - stmia r0, {r1 - r7, ip} - ldmfd sp!, {r4 - r7, pc}^ - - .bss -__temp_irq: .space 4 @ saved lr_irq -__temp_fiq: .space 128 diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index dfb295004ea1..0a5c2ea51b99 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -15,10 +15,12 @@ */ #include <linux/config.h> #include <linux/init.h> -#include "entry-header.S" + #include <asm/thread_info.h> #include <asm/glue.h> +#include <asm/ptrace.h> +#include "entry-header.S" #ifdef IOC_BASE /* IOC / IOMD based hardware */ diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 11cc623c3726..dc43ce1eaebd 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -8,8 +8,11 @@ * published by the Free Software Foundation. */ #include <linux/config.h> -#include "entry-header.S" + #include <asm/thread_info.h> +#include <asm/ptrace.h> + +#include "entry-header.S" /* * We rely on the fact that R0 is at the bottom of the stack (due to diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 04a32ea49695..4b233763aa0c 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -16,6 +16,7 @@ #include <asm/assembler.h> #include <asm/mach-types.h> #include <asm/procinfo.h> +#include <asm/ptrace.h> #include <asm/mach/arch.h> /* diff --git a/arch/arm/mach-l7200/core.c b/arch/arm/mach-l7200/core.c index 419e6ce52fe2..2570c1f0943f 100644 --- a/arch/arm/mach-l7200/core.c +++ b/arch/arm/mach-l7200/core.c @@ -11,7 +11,6 @@ #include <asm/hardware.h> #include <asm/page.h> -#include <asm/proc/domain.h> #include <asm/mach/map.h> #include <asm/arch/hardware.h> diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c index 8c1538aaacd0..e705c3cc5b8f 100644 --- a/arch/arm/mach-rpc/riscpc.c +++ b/arch/arm/mach-rpc/riscpc.c @@ -21,7 +21,7 @@ #include <asm/mach-types.h> #include <asm/hardware.h> #include <asm/page.h> -#include <asm/proc/domain.h> +#include <asm/domain.h> #include <asm/setup.h> #include <asm/mach/map.h> diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 747343d21eb7..321b0242e523 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -4,21 +4,13 @@ # Object file lists. -obj-y := init.o extable.o fault-common.o -obj-m := -obj-n := -obj- := -ifeq ($(CONFIG_CPU_32),y) -obj-y += consistent.o fault-armv.o ioremap.o mm-armv.o +obj-y := consistent.o extable.o fault-armv.o fault-common.o \ + init.o ioremap.o mm-armv.o obj-$(CONFIG_MODULES) += proc-syms.o -endif obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o obj-$(CONFIG_DISCONTIGMEM) += discontig.o -# Select the processor-specific files -p-$(CONFIG_CPU_26) += proc-arm2_3.o - # ARMv3 p-$(CONFIG_CPU_ARM610) += proc-arm6_7.o tlb-v3.o cache-v3.o copypage-v3.o p-$(CONFIG_CPU_ARM710) += proc-arm6_7.o tlb-v3.o cache-v3.o copypage-v3.o diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index dd12fb4d8b0a..fe4dacb950e7 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -34,8 +34,8 @@ struct cachepolicy { }; static struct cachepolicy cache_policies[] __initdata = { - { "uncached", CR1_W|CR1_C, PMD_SECT_UNCACHED }, - { "buffered", CR1_C, PMD_SECT_BUFFERED }, + { "uncached", CR_W|CR_C, PMD_SECT_UNCACHED }, + { "buffered", CR_C, PMD_SECT_BUFFERED }, { "writethrough", 0, PMD_SECT_WT }, #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH { "writeback", 0, PMD_SECT_WB }, @@ -102,8 +102,8 @@ __early_param("ecc=", early_ecc); static int __init noalign_setup(char *__unused) { - cr_alignment &= ~CR1_A; - cr_no_alignment &= ~CR1_A; + cr_alignment &= ~CR_A; + cr_no_alignment &= ~CR_A; set_cr(cr_alignment); return 1; } diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index 31bca78f8768..1712b9682de9 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -30,6 +30,7 @@ #include <asm/assembler.h> #include <asm/constants.h> #include <asm/procinfo.h> +#include <asm/ptrace.h> #include <asm/hardware.h> /* diff --git a/arch/arm/mm/proc-arm2_3.S b/arch/arm/mm/proc-arm2_3.S deleted file mode 100644 index 860a95fb21f3..000000000000 --- a/arch/arm/mm/proc-arm2_3.S +++ /dev/null @@ -1,360 +0,0 @@ -/* - * linux/arch/arm/mm/proc-arm2,3.S - * - * Copyright (C) 1997-1999 Russell King - * - * 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. - * - * MMU functions for ARM2,3 - * - * These are the low level assembler for performing cache - * and memory functions on ARM2, ARM250 and ARM3 processors. - */ -#include <linux/linkage.h> -#include <linux/init.h> -#include <asm/assembler.h> -#include <asm/constants.h> -#include <asm/procinfo.h> - -/* - * MEMC workhorse code. It's both a horse which things it's a pig. - */ -/* - * Function: cpu_memc_update_entry(pgd_t *pgd, unsigned long phys_pte, unsigned long addr) - * Params : pgd Page tables/MEMC mapping - * : phys_pte physical address, or PTE - * : addr virtual address - */ -ENTRY(cpu_memc_update_entry) - tst r1, #PAGE_PRESENT @ is the page present - orreq r1, r1, #PAGE_OLD | PAGE_CLEAN - moveq r2, #0x01f00000 - mov r3, r1, lsr #13 @ convert to physical page nr - and r3, r3, #0x3fc - adr ip, memc_phys_table_32 - ldr r3, [ip, r3] - tst r1, #PAGE_OLD | PAGE_NOT_USER - biceq r3, r3, #0x200 - tsteq r1, #PAGE_READONLY | PAGE_CLEAN - biceq r3, r3, #0x300 - mov r2, r2, lsr #15 @ virtual -> nr - orr r3, r3, r2, lsl #15 - and r2, r2, #0x300 - orr r3, r3, r2, lsl #2 - and r2, r3, #255 - sub r0, r0, #256 * 4 - str r3, [r0, r2, lsl #2] - strb r3, [r3] - movs pc, lr -/* - * Params : r0 = preserved - * : r1 = memc table base (preserved) - * : r2 = page table entry - * : r3 = preserved - * : r4 = unused - * : r5 = memc physical address translation table - * : ip = virtual address (preserved) - */ -update_pte: - mov r4, r2, lsr #13 - and r4, r4, #0x3fc - ldr r4, [r5, r4] @ covert to MEMC page - - tst r2, #PAGE_OLD | PAGE_NOT_USER @ check for MEMC read - biceq r4, r4, #0x200 - tsteq r2, #PAGE_READONLY | PAGE_CLEAN @ check for MEMC write - biceq r4, r4, #0x300 - - orr r4, r4, ip - and r2, ip, #0x01800000 - orr r4, r4, r2, lsr #13 - - and r2, r4, #255 - str r4, [r1, r2, lsl #2] - movs pc, lr - -/* - * Params : r0 = preserved - * : r1 = memc table base (preserved) - * : r2 = page table base - * : r3 = preserved - * : r4 = unused - * : r5 = memc physical address translation table - * : ip = virtual address (updated) - */ -update_pte_table: - stmfd sp!, {r0, lr} - bic r0, r2, #3 -1: ldr r2, [r0], #4 @ get entry - tst r2, #PAGE_PRESENT @ page present - blne update_pte @ process pte - add ip, ip, #32768 @ increment virt addr - ldr r2, [r0], #4 @ get entry - tst r2, #PAGE_PRESENT @ page present - blne update_pte @ process pte - add ip, ip, #32768 @ increment virt addr - ldr r2, [r0], #4 @ get entry - tst r2, #PAGE_PRESENT @ page present - blne update_pte @ process pte - add ip, ip, #32768 @ increment virt addr - ldr r2, [r0], #4 @ get entry - tst r2, #PAGE_PRESENT @ page present - blne update_pte @ process pte - add ip, ip, #32768 @ increment virt addr - tst ip, #32768 * 31 @ finished? - bne 1b - ldmfd sp!, {r0, pc}^ - -/* - * Function: cpu_memc_update_all(pgd_t *pgd) - * Params : pgd Page tables/MEMC mapping - * Notes : this is optimised for 32k pages - */ -ENTRY(cpu_memc_update_all) - stmfd sp!, {r4, r5, lr} - bl clear_tables - sub r1, r0, #256 * 4 @ start of MEMC tables - adr r5, memc_phys_table_32 @ Convert to logical page number - mov ip, #0 @ virtual address -1: ldmia r0!, {r2, r3} - tst r2, #PAGE_PRESENT - addeq ip, ip, #1048576 - blne update_pte_table - mov r2, r3 - tst r2, #PAGE_PRESENT - addeq ip, ip, #1048576 - blne update_pte_table - teq ip, #32 * 1048576 - bne 1b - ldmfd sp!, {r4, r5, pc}^ - -/* - * Build the table to map from physical page number to memc page number - */ - .type memc_phys_table_32, #object -memc_phys_table_32: - .irp b7, 0x00, 0x80 - .irp b6, 0x00, 0x02 - .irp b5, 0x00, 0x04 - .irp b4, 0x00, 0x01 - - .irp b3, 0x00, 0x40 - .irp b2, 0x00, 0x20 - .irp b1, 0x00, 0x10 - .irp b0, 0x00, 0x08 - .long 0x03800300 + \b7 + \b6 + \b5 + \b4 + \b3 + \b2 + \b1 + \b0 - .endr - .endr - .endr - .endr - - .endr - .endr - .endr - .endr - .size memc_phys_table_32, . - memc_phys_table_32 - -/* - * helper for cpu_memc_update_all, this clears out all - * mappings, setting them close to the top of memory, - * and inaccessible (0x01f00000). - * Params : r0 = page table pointer - */ -clear_tables: ldr r1, _arm3_switch_mm - 4 - ldr r2, [r1] - sub r1, r0, #256 * 4 @ start of MEMC tables - add r2, r1, r2, lsl #2 @ end of tables - mov r3, #0x03f00000 @ Default mapping (null mapping) - orr r3, r3, #0x00000f00 - orr r4, r3, #1 - orr r5, r3, #2 - orr ip, r3, #3 -1: stmia r1!, {r3, r4, r5, ip} - add r3, r3, #4 - add r4, r4, #4 - add r5, r5, #4 - add ip, ip, #4 - stmia r1!, {r3, r4, r5, ip} - add r3, r3, #4 - add r4, r4, #4 - add r5, r5, #4 - add ip, ip, #4 - teq r1, r2 - bne 1b - mov pc, lr - -/* - * Function: *_switch_mm(pgd_t *pgd) - * Params : pgd New page tables/MEMC mapping - * Purpose : update MEMC hardware with new mapping - */ - .word page_nr -_arm3_switch_mm: - mcr p15, 0, r1, c1, c0, 0 @ flush cache -_arm2_switch_mm: - stmfd sp!, {lr} - ldr r1, _arm3_switch_mm - 4 - ldr r2, [r1] - sub r0, r0, #256 * 4 @ start of MEMC tables - add r1, r0, r2, lsl #2 @ end of tables -1: ldmia r0!, {r2, r3, ip, lr} - strb r2, [r2] - strb r3, [r3] - strb ip, [ip] - strb lr, [lr] - ldmia r0!, {r2, r3, ip, lr} - strb r2, [r2] - strb r3, [r3] - strb ip, [ip] - strb lr, [lr] - teq r0, r1 - bne 1b - ldmfd sp!, {pc}^ - -/* - * Function: *_proc_init (void) - * Purpose : Initialise the cache control registers - */ -_arm3_proc_init: - mov r0, #0x001f0000 - orr r0, r0, #0x0000ff00 - orr r0, r0, #0x000000ff - mcr p15, 0, r0, c3, c0 @ ARM3 Cacheable - mcr p15, 0, r0, c4, c0 @ ARM3 Updateable - mov r0, #0 - mcr p15, 0, r0, c5, c0 @ ARM3 Disruptive - mcr p15, 0, r0, c1, c0 @ ARM3 Flush - mov r0, #3 - mcr p15, 0, r0, c2, c0 @ ARM3 Control -_arm2_proc_init: - movs pc, lr - -/* - * Function: *_proc_fin (void) - * Purpose : Finalise processor (disable caches) - */ -_arm3_proc_fin: mov r0, #2 - mcr p15, 0, r0, c2, c0 -_arm2_proc_fin: orrs pc, lr, #PSR_I_BIT|PSR_F_BIT - -/* - * Function: *_xchg_1 (int new, volatile void *ptr) - * Params : new New value to store at... - * : ptr pointer to byte-wide location - * Purpose : Performs an exchange operation - * Returns : Original byte data at 'ptr' - */ -_arm2_xchg_1: mov r2, pc - orr r2, r2, #PSR_I_BIT - teqp r2, #0 - ldrb r2, [r1] - strb r0, [r1] - mov r0, r2 - movs pc, lr - -_arm3_xchg_1: swpb r0, r0, [r1] - movs pc, lr - -/* - * Function: *_xchg_4 (int new, volatile void *ptr) - * Params : new New value to store at... - * : ptr pointer to word-wide location - * Purpose : Performs an exchange operation - * Returns : Original word data at 'ptr' - */ -_arm2_xchg_4: mov r2, pc - orr r2, r2, #PSR_I_BIT - teqp r2, #0 - ldr r2, [r1] - str r0, [r1] - mov r0, r2 - movs pc, lr - -_arm3_xchg_4: swp r0, r0, [r1] - movs pc, lr - -cpu_arm2_name: - .asciz "ARM 2" -cpu_arm250_name: - .asciz "ARM 250" -cpu_arm3_name: - .asciz "ARM 3" - - __INIT -/* - * Purpose : Function pointers used to access above functions - all calls - * come through these - */ - .globl arm2_processor_functions -arm2_processor_functions: - .word _arm2_proc_init - .word _arm2_proc_fin - .word _arm2_switch_mm - .word _arm2_xchg_1 - .word _arm2_xchg_4 - - .globl arm250_processor_functions -arm250_processor_functions: - .word _arm2_proc_init - .word _arm2_proc_fin - .word _arm2_switch_mm - .word _arm3_xchg_1 - .word _arm3_xchg_4 - - .globl arm3_processor_functions -arm3_processor_functions: - .word _arm3_proc_init - .word _arm3_proc_fin - .word _arm3_switch_mm - .word _arm3_xchg_1 - .word _arm3_xchg_4 - -arm2_arch_name: .asciz "armv1" -arm3_arch_name: .asciz "armv2" -arm2_elf_name: .asciz "v1" -arm3_elf_name: .asciz "v2" - .align - - .section ".proc.info", #alloc, #execinstr - - .long 0x41560200 - .long 0xfffffff0 - .long 0 - mov pc, lr - .long arm2_arch_name - .long arm2_elf_name - .long 0 - .long cpu_arm2_name - .long arm2_processor_functions - .long 0 - .long 0 - .long 0 - - .long 0x41560250 - .long 0xfffffff0 - .long 0 - mov pc, lr - .long arm3_arch_name - .long arm3_elf_name - .long 0 - .long cpu_arm250_name - .long arm250_processor_functions - .long 0 - .long 0 - .long 0 - - .long 0x41560300 - .long 0xfffffff0 - .long 0 - mov pc, lr - .long arm3_arch_name - .long arm3_elf_name - .long 0 - .long cpu_arm3_name - .long arm3_processor_functions - .long 0 - .long 0 - .long 0 - diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S index 30997a078052..4a679dc0e965 100644 --- a/arch/arm/mm/proc-arm6_7.S +++ b/arch/arm/mm/proc-arm6_7.S @@ -15,6 +15,7 @@ #include <asm/assembler.h> #include <asm/constants.h> #include <asm/procinfo.h> +#include <asm/ptrace.h> ENTRY(cpu_arm6_dcache_clean_area) ENTRY(cpu_arm7_dcache_clean_area) diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S index fa6f22d1c169..b334b5eadd55 100644 --- a/arch/arm/mm/proc-arm720.S +++ b/arch/arm/mm/proc-arm720.S @@ -35,6 +35,7 @@ #include <asm/assembler.h> #include <asm/constants.h> #include <asm/procinfo.h> +#include <asm/ptrace.h> #include <asm/hardware.h> /* diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index 678cb15acfda..b9100180f670 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -31,6 +31,7 @@ #include <asm/procinfo.h> #include <asm/hardware.h> #include <asm/page.h> +#include <asm/ptrace.h> #include "proc-macros.S" /* diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index c547a7b0b4f1..3e9c98425751 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S @@ -32,6 +32,7 @@ #include <asm/procinfo.h> #include <asm/hardware.h> #include <asm/page.h> +#include <asm/ptrace.h> #include "proc-macros.S" /* diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index a445460fca44..7b5dee0f540b 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -31,6 +31,7 @@ #include <asm/procinfo.h> #include <asm/hardware.h> #include <asm/page.h> +#include <asm/ptrace.h> #include "proc-macros.S" /* diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index 50ae23f081e1..73d4fc433b38 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S @@ -18,7 +18,8 @@ #include <asm/constants.h> #include <asm/procinfo.h> #include <asm/hardware.h> -#include <asm/proc/pgtable.h> +#include <asm/pgtable.h> +#include <asm/ptrace.h> /* * the cache line size of the I and D cache diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S index 28c8425afaf7..7feb2663658a 100644 --- a/arch/arm/mm/proc-sa1100.S +++ b/arch/arm/mm/proc-sa1100.S @@ -23,7 +23,8 @@ #include <asm/constants.h> #include <asm/procinfo.h> #include <asm/hardware.h> -#include <asm/proc/pgtable.h> +#include <asm/pgtable.h> +#include <asm/ptrace.h> /* * the cache line size of the I and D cache diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 1c8027a6ea2c..44c41098c85b 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -25,8 +25,9 @@ #include <asm/assembler.h> #include <asm/procinfo.h> #include <asm/hardware.h> -#include <asm/proc/pgtable.h> +#include <asm/pgtable.h> #include <asm/page.h> +#include <asm/ptrace.h> #include "proc-macros.S" /* diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index fa32ee149abc..928c42588f10 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -419,6 +419,9 @@ config HPET_TIMER Choose N to continue using the legacy 8254 timer. +config HPET_EMULATE_RTC + def_bool HPET_TIMER && RTC=y + config SMP bool "Symmetric multi-processing support" ---help--- diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 94ff91ebe2e0..6651e1941eaa 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -2080,4 +2080,4 @@ MODULE_PARM_DESC(idle_period, MODULE_PARM(smp, "i"); MODULE_PARM_DESC(smp, "Set this to enable APM use on an SMP platform. Use with caution on older systems"); - +MODULE_ALIAS_MISCDEV(APM_MINOR_DEV); diff --git a/arch/i386/kernel/cpu/mcheck/non-fatal.c b/arch/i386/kernel/cpu/mcheck/non-fatal.c index f657dc87ccbc..099f9d2efe13 100644 --- a/arch/i386/kernel/cpu/mcheck/non-fatal.c +++ b/arch/i386/kernel/cpu/mcheck/non-fatal.c @@ -1,5 +1,5 @@ /* - * P4 specific Machine Check Exception Reporting + * Non Fatal Machine Check Exception Reporting */ #include <linux/init.h> diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c index 7c0d0e7407a0..3ea82f9731f4 100644 --- a/arch/i386/kernel/time_hpet.c +++ b/arch/i386/kernel/time_hpet.c @@ -187,7 +187,6 @@ __setup("hpet=", hpet_setup); #include <linux/rtc.h> extern irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs); -extern void get_rtc_time(struct rtc_time *rtc_tm); #define DEFAULT_RTC_INT_FREQ 64 #define RTC_NUM_INTS 1 @@ -354,7 +353,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) hpet_rtc_timer_reinit(); if (UIE_on | AIE_on) { - get_rtc_time(&curr_time); + rtc_get_rtc_time(&curr_time); } if (UIE_on) { if (curr_time.tm_sec != prev_update_sec) { diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c index 9e8ff72c542f..8db66f34640f 100644 --- a/arch/i386/pci/pcbios.c +++ b/arch/i386/pci/pcbios.c @@ -430,7 +430,8 @@ struct irq_routing_table * __devinit pcibios_get_irq_routing_table(void) "xor %%ah, %%ah\n" "1:" : "=a" (ret), - "=b" (map) + "=b" (map), + "+m" (opt) : "0" (PCIBIOS_GET_ROUTING_OPTIONS), "1" (0), "D" ((long) &opt), diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 22d91c235e70..7e5aa4fa045c 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -66,6 +66,9 @@ config 6xx config 40x bool "40x" +config 44x + bool "44x" + config POWER3 bool "POWER3" @@ -74,6 +77,11 @@ config 8xx endchoice +config PTE_64BIT + bool + depends on 44x + default y + source arch/ppc/platforms/4xx/Kconfig config 8260 @@ -766,8 +774,8 @@ config MCA RS/6000 machines are currently not supported by Linux. config PCI - bool "PCI support" if 4xx || 8260 - default y if !4xx && !8260 && !8xx && !APUS + bool "PCI support" if 40x || 8260 + default y if !40x && !8260 && !8xx && !APUS default PCI_PERMEDIA if !4xx && !8260 && !8xx && APUS default PCI_QSPAN if !4xx && !8260 && 8xx help @@ -1143,6 +1151,7 @@ config BOOT_LOAD_BOOL config BOOT_LOAD hex "Link/load address for booting" if BOOT_LOAD_BOOL default "0x00400000" if 40x || 8xx || 8260 + default "0x01000000" if 44x default "0x00800000" config PIN_TLB diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index 5db110d1c75b..52d06170c376 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -29,7 +29,7 @@ CFLAGS += $(cflags-y) head-y := arch/ppc/kernel/head.o head-$(CONFIG_8xx) := arch/ppc/kernel/head_8xx.o head-$(CONFIG_4xx) := arch/ppc/kernel/head_4xx.o -head-$(CONFIG_440) := arch/ppc/kernel/head_44x.o +head-$(CONFIG_44x) := arch/ppc/kernel/head_44x.o head-$(CONFIG_6xx) += arch/ppc/kernel/idle_6xx.o diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile index 28231b85cfdb..3ead7056e3a7 100644 --- a/arch/ppc/boot/simple/Makefile +++ b/arch/ppc/boot/simple/Makefile @@ -48,11 +48,16 @@ zimageinitrd-$(CONFIG_IBM_OPENBIOS) := zImage.initrd-TREE zimage-$(CONFIG_EBONY) := zImage-TREE zimageinitrd-$(CONFIG_EBONY) := zImage.initrd-TREE - extra.o-$(CONFIG_EBONY) := direct.o end-$(CONFIG_EBONY) := ebony entrypoint-$(CONFIG_EBONY) := 0x01000000 tftpimage-$(CONFIG_EBONY) := /tftpboot/zImage.$(end-y) + zimage-$(CONFIG_OCOTEA) := zImage-TREE +zimageinitrd-$(CONFIG_OCOTEA) := zImage.initrd-TREE + end-$(CONFIG_OCOTEA) := ocotea + entrypoint-$(CONFIG_OCOTEA) := 0x01000000 + tftpimage-$(CONFIG_OCOTEA) := /tftpboot/zImage.$(end-y) + extra.o-$(CONFIG_EV64260) := direct.o misc-ev64260.o tftpimage-$(CONFIG_EV64260) := /tftpboot/zImage.ev64260 diff --git a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c index c14e633386ea..6597200b829d 100644 --- a/arch/ppc/boot/simple/misc.c +++ b/arch/ppc/boot/simple/misc.c @@ -25,6 +25,9 @@ #include <asm/processor.h> #include <asm/mmu.h> #include <asm/bootinfo.h> +#ifdef CONFIG_44x +#include <asm/ibm4xx.h> +#endif #include "nonstdio.h" #include "zlib.h" @@ -80,6 +83,16 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) serial_fixups(); com_port = serial_init(0, NULL); +#ifdef CONFIG_44x + /* Reset MAL */ + mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR); + /* Wait for reset */ + while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; + /* Reset EMAC */ + *(volatile unsigned long *)PPC44x_EMAC0_MR0 = 0x20000000; + __asm__ __volatile__("eieio"); +#endif + #if defined(CONFIG_LOPEC) || defined(CONFIG_PAL4) /* * Call get_mem_size(), which is memory controller dependent, diff --git a/arch/ppc/configs/ebony_defconfig b/arch/ppc/configs/ebony_defconfig new file mode 100644 index 000000000000..b466152a06d5 --- /dev/null +++ b/arch/ppc/configs/ebony_defconfig @@ -0,0 +1,560 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MMU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_HAVE_DEC_LOCK=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODULE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# Platform support +# +CONFIG_PPC=y +CONFIG_PPC32=y +# CONFIG_6xx is not set +# CONFIG_40x is not set +CONFIG_44x=y +# CONFIG_POWER3 is not set +# CONFIG_8xx is not set +CONFIG_PTE_64BIT=y +CONFIG_4xx=y + +# +# IBM 4xx options +# +CONFIG_EBONY=y +# CONFIG_OCOTEA is not set +CONFIG_440GP=y +CONFIG_440=y +CONFIG_PIN_TLB=y +CONFIG_BOOKE=y +CONFIG_IBM_OCP=y +# CONFIG_PM is not set +CONFIG_NOT_COHERENT_CACHE=y +# CONFIG_SMP is not set +# CONFIG_PREEMPT is not set +# CONFIG_MATH_EMULATION is not set +# CONFIG_CPU_FREQ is not set + +# +# General setup +# +# CONFIG_HIGHMEM is not set +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PC_KEYBOARD is not set +CONFIG_KERNEL_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PCI_LEGACY_PROC is not set +# CONFIG_PCI_NAMES is not set +# CONFIG_HOTPLUG is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="ip=on" + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x01000000 + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_LBD=y + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +# CONFIG_NET_ETHERNET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Macintosh device drivers +# + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Library routines +# +CONFIG_CRC32=y + +# +# Kernel hacking +# +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_KGDB is not set +# CONFIG_XMON is not set +CONFIG_BDI_SWITCH=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_SERIAL_TEXT_DEBUG is not set +CONFIG_OCP=y + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set diff --git a/arch/ppc/configs/ocotea_defconfig b/arch/ppc/configs/ocotea_defconfig new file mode 100644 index 000000000000..0f398257ef7b --- /dev/null +++ b/arch/ppc/configs/ocotea_defconfig @@ -0,0 +1,574 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MMU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_HAVE_DEC_LOCK=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# Platform support +# +CONFIG_PPC=y +CONFIG_PPC32=y +# CONFIG_6xx is not set +# CONFIG_40x is not set +CONFIG_44x=y +# CONFIG_POWER3 is not set +# CONFIG_8xx is not set +CONFIG_PTE_64BIT=y +CONFIG_4xx=y + +# +# IBM 4xx options +# +# CONFIG_EBONY is not set +CONFIG_OCOTEA=y +CONFIG_440GX=y +CONFIG_440A=y +CONFIG_PIN_TLB=y +CONFIG_BOOKE=y +CONFIG_IBM_OCP=y +CONFIG_IBM_EMAC4=y +# CONFIG_PM is not set +CONFIG_NOT_COHERENT_CACHE=y +# CONFIG_SMP is not set +# CONFIG_PREEMPT is not set +# CONFIG_MATH_EMULATION is not set +# CONFIG_CPU_FREQ is not set + +# +# General setup +# +# CONFIG_HIGHMEM is not set +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PC_KEYBOARD is not set +CONFIG_KERNEL_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PCI_LEGACY_PROC is not set +# CONFIG_PCI_NAMES is not set +# CONFIG_HOTPLUG is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="ip=on console=ttyS0,115200" + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x01000000 + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_OAKNET is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Macintosh device drivers +# + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Library routines +# +CONFIG_CRC32=y + +# +# Kernel hacking +# +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_KGDB is not set +# CONFIG_XMON is not set +CONFIG_BDI_SWITCH=y +CONFIG_DEBUG_INFO=y +# CONFIG_SERIAL_TEXT_DEBUG is not set +CONFIG_OCP=y + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index a00393bbdf33..77760d6fafd7 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -12,6 +12,7 @@ endif # Start off with 'head.o', change as needed. extra-y := head.o extra-$(CONFIG_40x) := head_4xx.o +extra-$(CONFIG_44x) := head_44x.o extra-$(CONFIG_8xx) := head_8xx.o extra-$(CONFIG_6xx) += idle_6xx.o extra-y += vmlinux.lds.s diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c index 2d67a182b106..71c2c441a14f 100644 --- a/arch/ppc/kernel/cputable.c +++ b/arch/ppc/kernel/cputable.c @@ -433,7 +433,7 @@ struct cpu_spec cpu_specs[] = { }, #endif /* CONFIG_40x */ -#ifdef CONFIG_440 +#ifdef CONFIG_44x { /* 440GP Rev. B */ 0xf0000fff, 0x40000440, "440GP Rev. B", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, @@ -448,7 +448,14 @@ struct cpu_spec cpu_specs[] = { 32, 32, 0, /*__setup_cpu_440 */ }, -#endif /* CONFIG_440 */ + { /* 440GX Rev. A */ + 0xf0000fff, 0x50000850, "440GX Rev. A", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + 32, 32, + 0, /*__setup_cpu_440 */ + }, +#endif /* CONFIG_44x */ #if !CLASSIC_PPC { /* default match */ 0x00000000, 0x00000000, "(generic PPC)", diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S new file mode 100644 index 000000000000..125f131a3c30 --- /dev/null +++ b/arch/ppc/kernel/head_44x.S @@ -0,0 +1,1056 @@ +/* + * arch/ppc/kernel/head_44x.S + * + * Kernel execution entry point code. + * + * Matt Porter <mporter@mvista.com> + * + * Copyright 2002-2003 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 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/config.h> +#include <asm/processor.h> +#include <asm/page.h> +#include <asm/mmu.h> +#include <asm/pgtable.h> +#include <asm/ibm4xx.h> +#include <asm/ibm44x.h> +#include <asm/cputable.h> +#include <asm/thread_info.h> +#include <asm/ppc_asm.h> +#include <asm/offsets.h> + +/* + * Macros + */ + +#define SET_IVOR(vector_number, vector_label) \ + li r26,vector_label@l; \ + mtspr SPRN_IVOR##vector_number,r26; \ + sync + +/* As with the other PowerPC ports, it is expected that when code + * execution begins here, the following registers contain valid, yet + * optional, information: + * + * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.) + * r4 - Starting address of the init RAM disk + * r5 - Ending address of the init RAM disk + * r6 - Start of kernel command line string (e.g. "mem=128") + * r7 - End of kernel command line string + * + */ + .text +_GLOBAL(_stext) +_GLOBAL(_start) + /* + * Reserve a word at a fixed location to store the address + * of abatron_pteptrs + */ + nop +/* + * Save parameters we are passed + */ + mr r31,r3 + mr r30,r4 + mr r29,r5 + mr r28,r6 + mr r27,r7 + li r24,0 /* CPU number */ + +/* + * Set up the initial MMU state + * + * We are still executing code at the virtual address + * mappings set by the firmware for the base of RAM. + * + * We first invalidate all TLB entries but the one + * we are running from. We then load the KERNELBASE + * mappings so we can begin to use kernel addresses + * natively and so the interrupt vector locations are + * permanently pinned (necessary since Book E + * implementations always have translation enabled). + * + * TODO: Use the known TLB entry we are running from to + * determine which physical region we are located + * in. This can be used to determine where in RAM + * (on a shared CPU system) or PCI memory space + * (on a DRAMless system) we are located. + * For now, we assume a perfect world which means + * we are located at the base of DRAM (physical 0). + */ + +/* + * Search TLB for entry that we are currently using. + * Invalidate all entries but the one we are using. + */ + /* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */ + mfspr r3,SPRN_MMUCR /* Get MMUCR */ + lis r4,PPC44x_MMUCR_STS@h + ori r4,r4,PPC44x_MMUCR_TID@l /* Create mask */ + andc r3,r3,r4 /* Clear out TID/STS bits */ + mfspr r4,SPRN_PID /* Get PID */ + or r3,r3,r4 /* Set TID bits */ + mfmsr r5 /* Get MSR */ + andi. r5,r5,MSR_IS@l /* TS=1? */ + beq wmmucr /* If not, leave STS=0 */ + oris r3,r3,PPC44x_MMUCR_STS@h /* Set STS=1 */ +wmmucr: mtspr SPRN_MMUCR,r3 /* Put MMUCR */ + sync + + bl invstr /* Find our address */ +invstr: mflr r5 /* Make it accessible */ + tlbsx r23,0,r5 /* Find entry we are in */ + li r4,0 /* Start at TLB entry 0 */ + li r3,0 /* Set PAGEID inval value */ +1: cmpw r23,r4 /* Is this our entry? */ + beq skpinv /* If so, skip the inval */ + tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */ +skpinv: addi r4,r4,1 /* Increment */ + cmpwi r4,64 /* Are we done? */ + bne 1b /* If not, repeat */ + isync /* If so, context change */ + +/* + * Configure and load pinned entries into TLB slots 62 and 63. + */ + + lis r3,KERNELBASE@h /* Load the kernel virtual address */ + ori r3,r3,KERNELBASE@l + + /* Kernel is at the base of RAM */ + li r4, 0 /* Load the kernel physical address */ + + /* Load the kernel PID = 0 */ + li r0,0 + mtspr SPRN_PID,r0 + sync + + /* Load the kernel TID = 0 */ + mfspr r5,SPRN_MMUCR + lis r6, PPC44x_MMUCR_TID@h + ori r6,r6,PPC44x_MMUCR_TID@l + andc r5,r5,r6 + mtspr SPRN_MMUCR,r5 + sync + + /* pageid fields */ + clrrwi r3,r3,10 /* Mask off the effective page number */ + ori r3,r3,(PPC44x_TLB_VALID | PPC44x_TLB_PAGESZ(PPC44x_PAGESZ_256M)) + + /* xlat fields */ + clrrwi r4,r4,10 /* Mask off the real page number */ + /* ERPN is 0 for first 4GB page */ + + /* attrib fields */ + /* Added guarded bit to protect against speculative loads/stores */ + li r5,0 + ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G) + + li r0,62 /* TLB slot 62 */ + + tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ + tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ + tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */ + + /* Force context change */ + mfmsr r0 + mtspr SRR1, r0 + lis r0,3f@h + ori r0,r0,3f@l + mtspr SRR0,r0 + sync + rfi + + /* If necessary, invalidate original entry we used */ +3: cmpwi r23,62 + beq 4f + li r6,0 + tlbwe r6,r23,PPC44x_TLB_PAGEID + sync + +4: ori r3,r3,PPC44x_TLB_TS /* TS = 1 */ + + li r0,63 /* TLB slot 63 */ + + tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ + tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ + tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */ + +#ifdef CONFIG_SERIAL_TEXT_DEBUG + /* + * Add temporary UART mapping for early debug. This + * mapping must be identical to that used by the early + * bootloader code since the same asm/serial.h parameters + * are used for polled operation. + */ + /* pageid fields */ + lis r3,0xe000 + ori r3,r3,(PPC44x_TLB_VALID | PPC44x_TLB_PAGESZ(PPC44x_PAGESZ_256M)) + + /* xlat fields */ + lis r4,0x4000 /* RPN is 0x40000000 */ + ori r4,r4,0x0001 /* ERPN is 1 for second 4GB page */ + + /* attrib fields */ + li r5,0 + ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G) + + li r0,60 /* TLB slot 60 */ + + tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ + tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ + tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */ + + ori r3,r3,PPC44x_TLB_TS /* Translation state 1 */ + + li r0,61 /* TLB slot 61 */ + + tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ + tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ + tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */ +#endif /* CONFIG_SERIAL_TEXT_DEBUG */ + + /* Force context change */ + isync + + /* Establish the interrupt vector offsets */ + SET_IVOR(0, CriticalInput); + SET_IVOR(1, MachineCheck); + SET_IVOR(2, DataStorage); + SET_IVOR(3, InstructionStorage); + SET_IVOR(4, ExternalInput); + SET_IVOR(5, Alignment); + SET_IVOR(6, Program); + SET_IVOR(7, FloatingPointUnavailable); + SET_IVOR(8, SystemCall); + SET_IVOR(9, AuxillaryProcessorUnavailable); + SET_IVOR(10, Decrementer); + SET_IVOR(11, FixedIntervalTimer); + SET_IVOR(12, WatchdogTimer); + SET_IVOR(13, DataTLBError); + SET_IVOR(14, InstructionTLBError); + SET_IVOR(15, Debug); + + /* Establish the interrupt vector base */ + lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */ + mtspr SPRN_IVPR,r4 + + /* + * This is where the main kernel code starts. + */ + + /* ptr to current */ + lis r2,init_task@h + ori r2,r2,init_task@l + + /* ptr to current thread */ + addi r4,r2,THREAD /* init task's THREAD */ + mtspr SPRG3,r4 + + /* stack */ + lis r1,init_thread_union@h + ori r1,r1,init_thread_union@l + li r0,0 + stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1) + + bl early_init + +/* + * Decide what sort of machine this is and initialize the MMU. + */ + mr r3,r31 + mr r4,r30 + mr r5,r29 + mr r6,r28 + mr r7,r27 + bl machine_init + bl MMU_init + + /* Setup PTE pointers for the Abatron bdiGDB */ + lis r6, swapper_pg_dir@h + ori r6, r6, swapper_pg_dir@l + lis r5, abatron_pteptrs@h + ori r5, r5, abatron_pteptrs@l + lis r4, KERNELBASE@h + ori r4, r4, KERNELBASE@l + stw r5, 0(r4) /* Save abatron_pteptrs at a fixed location */ + stw r6, 0(r5) + + /* Let's move on */ + lis r4,start_kernel@h + ori r4,r4,start_kernel@l + lis r3,MSR_KERNEL@h + ori r3,r3,MSR_KERNEL@l + mtspr SRR0,r4 + mtspr SRR1,r3 + rfi /* change context and jump to start_kernel */ + +/* + * Interrupt vector entry code + * + * The Book E MMUs are always on so we don't need to handle + * interrupts in real mode as with previous PPC processors. In + * this case we handle interrupts in the kernel virtual address + * space. + * + * Interrupt vectors are dynamically placed relative to the + * interrupt prefix as determined by the address of interrupt_base. + * The interrupt vectors offsets are programmed using the labels + * for each interrupt vector entry. + * + * Interrupt vectors must be aligned on a 16 byte boundary. + * We align on a 32 byte cache line boundary for good measure. + */ + +#define NORMAL_EXCEPTION_PROLOG \ + mtspr SPRN_SPRG0,r10; /* save two registers to work with */\ + mtspr SPRN_SPRG1,r11; \ + mtspr SPRN_SPRG2,r1; \ + mfcr r10; /* save CR in r10 for now */\ + mfspr r11,SPRN_SRR1; /* check whether user or kernel */\ + andi. r11,r11,MSR_PR; \ + beq 1f; \ + mfspr r1,SPRG3; /* if from user, start at top of */\ + lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ + addi r1,r1,THREAD_SIZE; \ +1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ + tophys(r11,r1); \ + stw r10,_CCR(r11); /* save various registers */\ + stw r12,GPR12(r11); \ + stw r9,GPR9(r11); \ + mfspr r10,SPRG0; \ + stw r10,GPR10(r11); \ + mfspr r12,SPRG1; \ + stw r12,GPR11(r11); \ + mflr r10; \ + stw r10,_LINK(r11); \ + mfspr r10,SPRG2; \ + mfspr r12,SRR0; \ + stw r10,GPR1(r11); \ + mfspr r9,SRR1; \ + stw r10,0(r11); \ + rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ + stw r0,GPR0(r11); \ + SAVE_4GPRS(3, r11); \ + SAVE_2GPRS(7, r11) + +/* + * Exception prolog for critical exceptions. This is a little different + * from the normal exception prolog above since a critical exception + * can potentially occur at any point during normal exception processing. + * Thus we cannot use the same SPRG registers as the normal prolog above. + * Instead we use a couple of words of memory at low physical addresses. + * This is OK since we don't support SMP on these processors. + */ +/* XXX but we don't have RAM mapped at 0 in space 0 -- paulus. */ +#define CRITICAL_EXCEPTION_PROLOG \ + stw r10,crit_r10@l(0); /* save two registers to work with */\ + stw r11,crit_r11@l(0); \ + mfspr r10,SPRG0; \ + stw r10,crit_sprg0@l(0); \ + mfspr r10,SPRG1; \ + stw r10,crit_sprg1@l(0); \ + mfspr r10,SPRG4R; \ + stw r10,crit_sprg4@l(0); \ + mfspr r10,SPRG5R; \ + stw r10,crit_sprg5@l(0); \ + mfspr r10,SPRG6R; \ + stw r10,crit_sprg6@l(0); \ + mfspr r10,SPRG7R; \ + stw r10,crit_sprg7@l(0); \ + mfspr r10,SPRN_PID; \ + stw r10,crit_pid@l(0); \ + mfspr r10,SRR0; \ + stw r10,crit_srr0@l(0); \ + mfspr r10,SRR1; \ + stw r10,crit_srr1@l(0); \ + mfcr r10; /* save CR in r10 for now */\ + mfspr r11,SPRN_CSRR1; /* check whether user or kernel */\ + andi. r11,r11,MSR_PR; \ + lis r11,critical_stack_top@h; \ + ori r11,r11,critical_stack_top@l; \ + beq 1f; \ + /* COMING FROM USER MODE */ \ + mfspr r11,SPRG3; /* if from user, start at top of */\ + lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ + addi r11,r11,THREAD_SIZE; \ +1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\ + tophys(r11,r11); \ + stw r10,_CCR(r11); /* save various registers */\ + stw r12,GPR12(r11); \ + stw r9,GPR9(r11); \ + mflr r10; \ + stw r10,_LINK(r11); \ + mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ + stw r12,_DEAR(r11); /* since they may have had stuff */\ + mfspr r9,SPRN_ESR; /* in them at the point where the */\ + stw r9,_ESR(r11); /* exception was taken */\ + mfspr r12,CSRR0; \ + stw r1,GPR1(r11); \ + mfspr r9,CSRR1; \ + stw r1,0(r11); \ + tovirt(r1,r11); \ + rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ + stw r0,GPR0(r11); \ + SAVE_4GPRS(3, r11); \ + SAVE_2GPRS(7, r11) + +/* + * Exception vectors. + */ +#define START_EXCEPTION(label) \ + .align 5; \ +label: + +#define FINISH_EXCEPTION(func) \ + bl transfer_to_handler_full; \ + .long func; \ + .long ret_from_except_full + +#define EXCEPTION(n, label, hdlr, xfer) \ + START_EXCEPTION(label); \ + NORMAL_EXCEPTION_PROLOG; \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + xfer(n, hdlr) + +#define CRITICAL_EXCEPTION(n, label, hdlr) \ + START_EXCEPTION(label); \ + CRITICAL_EXCEPTION_PROLOG; \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ + NOCOPY, transfer_to_handler_full, \ + ret_from_except_full) + +#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \ + li r10,trap; \ + stw r10,TRAP(r11); \ + lis r10,msr@h; \ + ori r10,r10,msr@l; \ + copyee(r10, r9); \ + bl tfer; \ + .long hdlr; \ + .long ret + +#define COPY_EE(d, s) rlwimi d,s,0,16,16 +#define NOCOPY(d, s) + +#define EXC_XFER_STD(n, hdlr) \ + EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \ + ret_from_except_full) + +#define EXC_XFER_LITE(n, hdlr) \ + EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \ + ret_from_except) + +#define EXC_XFER_EE(n, hdlr) \ + EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \ + ret_from_except_full) + +#define EXC_XFER_EE_LITE(n, hdlr) \ + EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \ + ret_from_except) + +interrupt_base: + /* Critical Input Interrupt */ + CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException) + + /* Machine Check Interrupt */ + CRITICAL_EXCEPTION(0x0200, MachineCheck, MachineCheckException) + + /* Data Storage Interrupt */ + START_EXCEPTION(DataStorage) + mtspr SPRG0, r10 /* Save some working registers */ + mtspr SPRG1, r11 + mtspr SPRG4W, r12 + mtspr SPRG5W, r13 + mtspr SPRG6W, r14 + mfcr r11 + mtspr SPRG7W, r11 + + /* + * Check if it was a store fault, if not then bail + * because a user tried to access a kernel or + * read-protected page. Otherwise, get the + * offending address and handle it. + */ + mfspr r10, SPRN_ESR + andis. r10, r10, ESR_ST@h + beq 2f + + mfspr r10, SPRN_DEAR /* Get faulting address */ + + /* If we are faulting a kernel address, we have to use the + * kernel page tables. + */ + andis. r11, r10, 0x8000 + beq 3f + lis r11, swapper_pg_dir@h + ori r11, r11, swapper_pg_dir@l + + mfspr r12,SPRN_MMUCR /* Set TID to 0 */ + li r13,PPC44x_MMUCR_TID@l + andc r12,r12,r13 + mtspr SPRN_MMUCR,r12 + + b 4f + + /* Get the PGD for the current thread */ +3: + mfspr r11,SPRG3 + lwz r11,PGDIR(r11) + + /* Load MMUCR with our PID and STS=<current TS> */ + mfspr r12,SPRN_MMUCR /* Get MMUCR */ + lis r13,PPC44x_MMUCR_STS@h + ori r13,r13,PPC44x_MMUCR_TID@l /* Create mask */ + andc r12,r12,r13 /* Clear out TID/STS bits */ + mfspr r13,SPRN_PID /* Get PID */ + or r12,r12,r13 /* Set TID bits */ + mfspr r14,SPRN_SRR1 /* Get SRR1 */ + andi. r14,r14,MSR_IS@l /* TS=1? */ + beq 4f /* If not, leave STS=0 */ + oris r12,r12,PPC44x_MMUCR_STS@h /* Set STS=1 */ + mtspr SPRN_MMUCR,r12 +4: + rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ + lwzx r11, r12, r11 /* Get pgd/pmd entry */ + rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ + beq 2f /* Bail if no table */ + + rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ + lwz r11, 4(r12) /* Get pte entry */ + + andi. r13, r11, _PAGE_RW /* Is it writeable? */ + beq 2f /* Bail if not */ + + /* Update 'changed'. + */ + ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE + stw r11, 4(r12) /* Update Linux page table */ + + /* FIXME: Staticly setting some permissions */ + li r13, 0x003f /* Set UX,UW,UR,SX,SW,SR */ + andi. r11,r11,0xffff /* Clear MS 16 bits */ + /* FIXME: Force attributes */ + ori r11,r11, 0x0100 /* Set G */ + /* FIXME: Already set in PTE */ + rlwimi r11,r13,0,26,31 /* Insert static perms */ + + lis r13,0xffff + ori r13,r13,0x0fff /* Set U0-U3 mask */ + and r11,r11,r13 /* Clear U0-U3 */ + + /* find the TLB index that caused the fault. It has to be here. */ + tlbsx r14, 0, r10 + + tlbwe r11, r14, PPC44x_TLB_ATTRIB /* Write ATTRIB */ + + /* Done...restore registers and get out of here. + */ + mfspr r11, SPRG7R + mtcr r11 + mfspr r14, SPRG6R + mfspr r13, SPRG5R + mfspr r12, SPRG4R + + mfspr r11, SPRG1 + mfspr r10, SPRG0 + rfi /* Force context change */ + +2: + /* + * The bailout. Restore registers to pre-exception conditions + * and call the heavyweights to help us out. + */ + mfspr r11, SPRG7R + mtcr r11 + mfspr r14, SPRG6R + mfspr r13, SPRG5R + mfspr r12, SPRG4R + + mfspr r11, SPRG1 + mfspr r10, SPRG0 + b data_access + + /* Instruction Storage Interrupt */ + START_EXCEPTION(InstructionStorage) + NORMAL_EXCEPTION_PROLOG + mr r4,r12 /* Pass SRR0 as arg2 */ + li r5,0 /* Pass zero as arg3 */ + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_EE_LITE(0x0400, do_page_fault) + + /* External Input Interrupt */ + EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE) + + /* Alignment Interrupt */ + START_EXCEPTION(Alignment) + NORMAL_EXCEPTION_PROLOG + mfspr r4,SPRN_DEAR /* Grab the DEAR and save it */ + stw r4,_DEAR(r11) + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_EE(0x0600, AlignmentException) + + /* Program Interrupt */ + START_EXCEPTION(Program) + NORMAL_EXCEPTION_PROLOG + mfspr r4,SPRN_ESR /* Grab the ESR and save it */ + stw r4,_ESR(r11) + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_EE(0x700, ProgramCheckException) + + /* Floating Point Unavailable Interrupt */ + EXCEPTION(0x2010, FloatingPointUnavailable, UnknownException, EXC_XFER_EE) + + /* System Call Interrupt */ + START_EXCEPTION(SystemCall) + NORMAL_EXCEPTION_PROLOG + EXC_XFER_EE_LITE(0x0c00, DoSyscall) + + /* Auxillary Processor Unavailable Interrupt */ + EXCEPTION(0x2020, AuxillaryProcessorUnavailable, UnknownException, EXC_XFER_EE) + + /* Decrementer Interrupt */ + START_EXCEPTION(Decrementer) + NORMAL_EXCEPTION_PROLOG + lis r0,TSR_DIS@h /* Setup the DEC interrupt mask */ + mtspr SPRN_TSR,r0 /* Clear the DEC interrupt */ + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_LITE(0x1000, timer_interrupt) + + /* Fixed Internal Timer Interrupt */ + /* TODO: Add FIT support */ + EXCEPTION(0x1010, FixedIntervalTimer, UnknownException, EXC_XFER_EE) + + /* Watchdog Timer Interrupt */ + /* TODO: Add watchdog support */ + CRITICAL_EXCEPTION(0x1020, WatchdogTimer, UnknownException) + + /* Data TLB Error Interrupt */ + START_EXCEPTION(DataTLBError) + mtspr SPRG0, r10 /* Save some working registers */ + mtspr SPRG1, r11 + mtspr SPRG4W, r12 + mtspr SPRG5W, r13 + mtspr SPRG6W, r14 + mfcr r11 + mtspr SPRG7W, r11 + mfspr r10, SPRN_DEAR /* Get faulting address */ + + /* If we are faulting a kernel address, we have to use the + * kernel page tables. + */ + andis. r11, r10, 0x8000 + beq 3f + lis r11, swapper_pg_dir@h + ori r11, r11, swapper_pg_dir@l + + mfspr r12,SPRN_MMUCR /* Set TID to 0 */ + li r13,PPC44x_MMUCR_TID@l + andc r12,r12,r13 + mtspr SPRN_MMUCR,r12 + + b 4f + + /* Get the PGD for the current thread */ +3: + mfspr r11,SPRG3 + lwz r11,PGDIR(r11) + + /* Load PID into MMUCR TID */ + li r13,PPC44x_MMUCR_TID@l /* Create mask */ + andc r12,r12,r13 /* Clear out TID/STS bits */ + mfspr r13,SPRN_PID /* Get PID */ + or r12,r12,r13 + mtspr SPRN_MMUCR,r12 +4: + rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ + lwzx r11, r12, r11 /* Get pgd/pmd entry */ + rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ + beq 2f /* Bail if no table */ + + rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ + lwz r11, 4(r12) /* Get pte entry */ + andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ + beq 2f /* Bail if not present */ + + ori r11, r11, _PAGE_ACCESSED + stw r11, 4(r12) + + /* Jump to common tlb load */ + b finish_tlb_load + +2: + /* The bailout. Restore registers to pre-exception conditions + * and call the heavyweights to help us out. + */ + mfspr r11, SPRG7R + mtcr r11 + mfspr r14, SPRG6R + mfspr r13, SPRG5R + mfspr r12, SPRG4R + mfspr r11, SPRG1 + mfspr r10, SPRG0 + b data_access + + /* Instruction TLB Error Interrupt */ + /* + * Nearly the same as above, except we get our + * information from different registers and bailout + * to a different point. + */ + START_EXCEPTION(InstructionTLBError) + mtspr SPRG0, r10 /* Save some working registers */ + mtspr SPRG1, r11 + mtspr SPRG4W, r12 + mtspr SPRG5W, r13 + mtspr SPRG6W, r14 + mfcr r11 + mtspr SPRG7W, r11 + mfspr r10, SRR0 /* Get faulting address */ + + /* If we are faulting a kernel address, we have to use the + * kernel page tables. + */ + andis. r11, r10, 0x8000 + beq 3f + lis r11, swapper_pg_dir@h + ori r11, r11, swapper_pg_dir@l + + mfspr r12,SPRN_MMUCR /* Set TID to 0 */ + li r13,PPC44x_MMUCR_TID@l + andc r12,r12,r13 + mtspr SPRN_MMUCR,r12 + + b 4f + + /* Get the PGD for the current thread */ +3: + mfspr r11,SPRG3 + lwz r11,PGDIR(r11) + + /* Load PID into MMUCR TID */ + li r13,PPC44x_MMUCR_TID@l /* Create mask */ + andc r12,r13,r13 /* Clear out TID/STS bits */ + mfspr r13,SPRN_PID /* Get PID */ + or r12,r12,r13 + mtspr SPRN_MMUCR,r12 + +4: + rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ + lwzx r11, r12, r11 /* Get pgd/pmd entry */ + rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ + beq 2f /* Bail if no table */ + + rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ + lwz r11, 4(r12) /* Get pte entry */ + andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ + beq 2f /* Bail if not present */ + + ori r11, r11, _PAGE_ACCESSED + stw r11, 4(r12) + + /* Jump to common TLB load point */ + b finish_tlb_load + +2: + /* The bailout. Restore registers to pre-exception conditions + * and call the heavyweights to help us out. + */ + mfspr r11, SPRG7R + mtcr r11 + mfspr r14, SPRG6R + mfspr r13, SPRG5R + mfspr r12, SPRG4R + mfspr r11, SPRG1 + mfspr r10, SPRG0 + b InstructionStorage + +/* Check for a single step debug exception while in an exception + * handler before state has been saved. This is to catch the case + * where an instruction that we are trying to single step causes + * an exception (eg ITLB/DTLB miss) and thus the first instruction of + * the exception handler generates a single step debug exception. + * + * If we get a debug trap on the first instruction of an exception handler, + * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is + * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR). + * The exception handler was handling a non-critical interrupt, so it will + * save (and later restore) the MSR via SPRN_SRR1, which will still have + * the MSR_DE bit set. + */ + /* Debug Interrupt */ + CRITICAL_EXCEPTION(0x2000, Debug, DebugException) +#if 0 + START_EXCEPTION(Debug) + /* This first instruction was already executed by the exception + * handler and must be the first instruction of every exception + * handler. + */ + mtspr SPRN_SPRG0,r10 /* Save some working registers... */ + mtspr SPRN_SPRG1,r11 + mtspr SPRN_SPRG4W,r12 + mfcr r10 /* ..and the cr because we change it */ + + mfspr r11,SPRN_CSRR1 /* MSR at the time of fault */ + andi. r11,r11,MSR_PR + bne+ 2f /* trapped from problem state */ + + mfspr r11,SPRN_CSRR0 /* Faulting instruction address */ + lis r12, KERNELBASE@h + ori r12, r12, KERNELBASE@l + cmplw r11,r12 + blt+ 2f /* addr below exception vectors */ + + lis r12, Debug@h + ori r12, r12, Debug@l + cmplw r11,r12 + bgt+ 2f /* addr above TLB exception vectors */ + + lis r11,DBSR_IC@h /* Remove the trap status */ + mtspr SPRN_DBSR,r11 + + mfspr r11,SPRN_CSRR1 + rlwinm r11,r11,0,23,21 /* clear MSR_DE */ + mtspr SPRN_CSRR1, r11 /* restore MSR at rcfi without DE */ + + mtcrf 0xff,r10 /* restore registers */ + mfspr r12,SPRN_SPRG4R + mfspr r11,SPRN_SPRG1 + mfspr r10,SPRN_SPRG0 + + sync + rfci /* return to the exception handler */ + b . /* prevent prefetch past rfci */ + +2: + mtcrf 0xff,r10 /* restore registers */ + mfspr r12,SPRN_SPRG4R + mfspr r11,SPRN_SPRG1 + mfspr r10,SPRN_SPRG0 + + CRIT_EXCEPTION_PROLOG + addi r3,r1,STACK_FRAME_OVERHEAD + li r7,CRIT_EXC; + li r9,MSR_KERNEL + FINISH_EXCEPTION(DebugException) +#endif + +/* + * Local functions + */ + /* + * Data TLB exceptions will bail out to this point + * if they can't resolve the lightweight TLB fault. + */ +data_access: + NORMAL_EXCEPTION_PROLOG + mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */ + stw r5,_ESR(r11) + mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */ + stw r4,_DEAR(r11) + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_EE_LITE(0x0300, do_page_fault) + +/* + + * Both the instruction and data TLB miss get to this + * point to load the TLB. + * r10 - EA of fault + * r11 - available to use + * r12 - Pointer to the 64-bit PTE + * r13 - available to use + * r14 - available to use + * MMUCR - loaded with proper value when we get here + * Upon exit, we reload everything and RFI. + */ +finish_tlb_load: + /* + * We set execute, because we don't have the granularity to + * properly set this at the page level (Linux problem). + * If shared is set, we cause a zero PID->TID load. + * Many of these bits are software only. Bits we don't set + * here we (properly should) assume have the appropriate value. + */ + + /* Load the next available TLB index */ + lis r13, tlb_44x_index@h + ori r13, r13, tlb_44x_index@l + lwz r14, 0(r13) + /* Load the TLB high watermark */ + lis r13, tlb_44x_hwater@h + ori r13, r13, tlb_44x_hwater@l + lwz r11, 0(r13) + + + /* Increment, rollover, and store TLB index */ + addi r14, r14, 1 + cmpw 0, r14, r11 /* reserve entries 62-63 for kernel */ + ble 7f + li r14, 0 +7: + /* Load the next available TLB index */ + lis r13, tlb_44x_index@h + ori r13, r13, tlb_44x_index@l + stw r14, 0(r13) + +6: + lwz r13, 0(r12) /* Get MS word of PTE */ + lwz r11, 4(r12) /* Get LS word of PTE */ + rlwimi r13, r11, 0, 0 , 19 /* Insert RPN */ + tlbwe r13, r14, PPC44x_TLB_XLAT /* Write XLAT */ + + /* + * Create PAGEID. This is the faulting address plus + * a set of static bits. The static bits are page + * size and valid. Bits 20 and 21 should be zero + * for a page size of 4KB. + */ + li r12, 0x0210 /* Set size and valid */ + mfspr r13, SPRN_SRR1 /* Get SRR1 */ + andi. r13, r13, MSR_IS@l + beq 7f + ori r12, r12, PPC44x_TLB_TS@l /* Set TS=1 */ +7: rlwimi r10, r12, 0, 20, 31 /* Insert statics */ + tlbwe r10, r14, PPC44x_TLB_PAGEID /* Write PAGEID */ + + /* FIXME: Staticly setting some permissions */ + li r13, 0x002d /* Set UX,UR,SX,SR */ + andi. r11, r11, 0xffff /* Clear MS 16 bits */ + andi. r12, r11, 0x0002 /* _PAGE_HWWRITE? */ + beq 8f + ori r13, r13, 0x0002 /* Set SW */ + /* FIXME: Force attributes */ +8: ori r11, r11, 0x0100 /* Set G */ + /* FIXME: Already set in PTE */ + rlwimi r11, r13, 0, 26, 31 /* Insert static perms */ + + lis r13,0xffff + ori r13,r13,0x0fff /* Set U0-U3 mask */ + and r11,r11,r13 /* Clear U0-U3 */ + tlbwe r11, r14, PPC44x_TLB_ATTRIB /* Write ATTRIB */ + + /* Done...restore registers and get out of here. + */ + mfspr r11, SPRG7R + mtcr r11 + mfspr r14, SPRG6R + mfspr r13, SPRG5R + mfspr r12, SPRG4R + mfspr r11, SPRG1 + mfspr r10, SPRG0 + rfi /* Force context change */ + +/* + * Global functions + */ + +/* + * extern void giveup_altivec(struct task_struct *prev) + * + * The 44x core does not have an AltiVec unit. + */ +_GLOBAL(giveup_altivec) + blr + +/* + * extern void giveup_fpu(struct task_struct *prev) + * + * The 44x core does not have an FPU. + */ +_GLOBAL(giveup_fpu) + blr + +/* + * extern void abort(void) + * + * At present, this routine just applies a system reset. + */ +_GLOBAL(abort) + mfspr r13,SPRN_DBCR0 + oris r13,r13,DBCR_RST(DBCR_RST_SYSTEM)@h + mtspr SPRN_DBCR0,r13 + +_GLOBAL(set_context) + +#ifdef CONFIG_BDI_SWITCH + /* Context switch the PTE pointer for the Abatron BDI2000. + * The PGDIR is the second parameter. + */ + lis r5, abatron_pteptrs@h + ori r5, r5, abatron_pteptrs@l + stw r4, 0x4(r5) +#endif + mtspr SPRN_PID,r3 + isync /* Force context change */ + blr + +/* + * We put a few things here that have to be page-aligned. This stuff + * goes at the beginning of the data segment, which is page-aligned. + */ + .data +_GLOBAL(sdata) +_GLOBAL(empty_zero_page) + .space 4096 + +/* + * To support >32-bit physical addresses, we use an 8KB pgdir. + */ +_GLOBAL(swapper_pg_dir) + .space 8192 + +/* Stack for handling critical exceptions from kernel mode */ + .section .bss +critical_stack_bottom: + .space 4096 +critical_stack_top: + .previous + +/* + * This space gets a copy of optional info passed to us by the bootstrap + * which is used to pass parameters into the kernel like root=/dev/sda1, etc. + */ +_GLOBAL(cmd_line) + .space 512 + +/* + * Room for two PTE pointers, usually the kernel and current user pointers + * to their respective root page table. + */ +abatron_pteptrs: + .space 8 + +/* + * This area is used for temporarily saving registers during the + * critical exception prolog. + */ +crit_save: +_GLOBAL(crit_r10) + .space 4 +_GLOBAL(crit_r11) + .space 4 +_GLOBAL(crit_sprg0) + .space 4 +_GLOBAL(crit_sprg1) + .space 4 +_GLOBAL(crit_sprg4) + .space 4 +_GLOBAL(crit_sprg5) + .space 4 +_GLOBAL(crit_sprg6) + .space 4 +_GLOBAL(crit_sprg7) + .space 4 +_GLOBAL(crit_pid) + .space 4 +_GLOBAL(crit_srr0) + .space 4 +_GLOBAL(crit_srr1) + .space 4 diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index c076529683c9..a41d10ee1614 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -405,16 +405,20 @@ _GLOBAL(_tlbia) sync /* Flush to memory before changing mapping */ tlbia isync /* Flush shadow TLB */ -#elif defined(CONFIG_440) +#elif defined(CONFIG_44x) lis r3,0 sync 1: - tlbwe r3,r3,PPC440_TLB_PAGEID + tlbwe r3,r3,PPC44x_TLB_PAGEID addi r3,r3,1 - cmpwi 0,r3,61 + /* Load high watermark */ + lis r4,tlb_44x_hwater@h + ori r4,r4,tlb_44x_hwater@l + lwz r5,0(r4) + cmpw 0,r3,r5 ble 1b isync -#else /* !(CONFIG_40x || CONFIG_440) */ +#else /* !(CONFIG_40x || CONFIG_44x) */ #if defined(CONFIG_SMP) rlwinm r8,r1,0,0,18 lwz r8,TI_CPU(r8) @@ -465,17 +469,17 @@ _GLOBAL(_tlbie) tlbwe r3, r3, TLB_TAG isync 10: -#elif defined(CONFIG_440) +#elif defined(CONFIG_44x) mfspr r4,SPRN_MMUCR /* Get MMUCR */ - lis r5,PPC440_MMUCR_STS@h - ori r5,r5,PPC440_MMUCR_TID@l /* Create mask */ + lis r5,PPC44x_MMUCR_STS@h + ori r5,r5,PPC44x_MMUCR_TID@l /* Create mask */ andc r4,r4,r5 /* Clear out TID/STS bits */ mfspr r5,SPRN_PID /* Get PID */ or r4,r4,r5 /* Set TID bits */ mfmsr r6 /* Get MSR */ andi. r6,r6,MSR_IS@l /* TS=1? */ beq 11f /* If not, leave STS=0 */ - oris r4,r4,PPC440_MMUCR_STS@h /* Set STS=1 */ + oris r4,r4,PPC44x_MMUCR_STS@h /* Set STS=1 */ 11: mtspr SPRN_MMUCR, r4 /* Put MMUCR */ tlbsx. r3, 0, r3 @@ -486,10 +490,10 @@ _GLOBAL(_tlbie) * the V bit in the TLB_PAGEID, loading this * value will invalidate the TLB entry. */ - tlbwe r3, r3, PPC440_TLB_PAGEID + tlbwe r3, r3, PPC44x_TLB_PAGEID isync 10: -#else /* !(CONFIG_40x || CONFIG_440) */ +#else /* !(CONFIG_40x || CONFIG_44x) */ #if defined(CONFIG_SMP) rlwinm r8,r1,0,0,18 lwz r8,TI_CPU(r8) @@ -658,9 +662,9 @@ _GLOBAL(invalidate_dcache_range) #ifdef CONFIG_NOT_COHERENT_CACHE /* * 40x cores have 8K or 16K dcache and 32 byte line size. - * 440 has a 32K dcache and 32 byte line size. + * 44x has a 32K dcache and 32 byte line size. * 8xx has 1, 2, 4, 8K variants. - * For now, cover the worst case of the 440. + * For now, cover the worst case of the 44x. * Must be called with external interrupts disabled. */ #define CACHE_NWAYS 64 diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index a70d77b33147..d7daa458535f 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -155,6 +155,9 @@ EXPORT_SYMBOL(_outsl_ns); EXPORT_SYMBOL(iopa); EXPORT_SYMBOL(mm_ptov); EXPORT_SYMBOL(ioremap); +#ifdef CONFIG_44x +EXPORT_SYMBOL(ioremap64); +#endif EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ @@ -353,7 +356,7 @@ EXPORT_SYMBOL(debugger_fault_handler); EXPORT_SYMBOL(cpm_install_handler); EXPORT_SYMBOL(cpm_free_handler); #endif /* CONFIG_8xx */ -#if defined(CONFIG_8xx) || defined(CONFIG_40x) +#if defined(CONFIG_8xx) || defined(CONFIG_4xx) EXPORT_SYMBOL(__res); #endif #if defined(CONFIG_8xx) diff --git a/arch/ppc/mm/44x_mmu.c b/arch/ppc/mm/44x_mmu.c new file mode 100644 index 000000000000..8c71ed6caca6 --- /dev/null +++ b/arch/ppc/mm/44x_mmu.c @@ -0,0 +1,162 @@ +/* + * Modifications by Matt Porter (mporter@mvista.com) to support + * PPC44x Book E processors. + * + * This file contains the routines for initializing the MMU + * on the 4xx series of chips. + * -- paulus + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * 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 <linux/config.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/ptrace.h> +#include <linux/mman.h> +#include <linux/mm.h> +#include <linux/swap.h> +#include <linux/stddef.h> +#include <linux/vmalloc.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/bootmem.h> +#include <linux/highmem.h> + +#include <asm/pgalloc.h> +#include <asm/prom.h> +#include <asm/io.h> +#include <asm/mmu_context.h> +#include <asm/pgtable.h> +#include <asm/mmu.h> +#include <asm/uaccess.h> +#include <asm/smp.h> +#include <asm/bootx.h> +#include <asm/machdep.h> +#include <asm/setup.h> + +#include "mmu_decl.h" +#include "mem_pieces.h" + +extern char etext[], _stext[]; +extern struct mem_pieces phys_avail; + +/* Used by the 44x TLB replacement exception handler. + * Just needed it declared someplace. + */ +unsigned int tlb_44x_index = 0; +unsigned int tlb_44x_hwater = 61; + +/* + * "Pins" a 256MB TLB entry in AS0 for kernel lowmem + */ +static void __init +ppc44x_pin_tlb(int slot, unsigned int virt, unsigned int phys) +{ + unsigned long attrib; + + __asm__ __volatile__("\ + clrrwi %2,%2,10\n\ + ori %2,%2,%4\n\ + clrrwi %1,%1,10\n\ + li %0,0\n\ + ori %0,%0,%5\n\ + tlbwe %2,%3,%6\n\ + tlbwe %1,%3,%7\n\ + tlbwe %0,%3,%8" + : + : "r" (attrib), "r" (phys), "r" (virt), "r" (slot), + "i" (PPC44x_TLB_VALID | PPC44x_TLB_PAGESZ(PPC44x_PAGESZ_256M)), + "i" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G), + "i" (PPC44x_TLB_PAGEID), + "i" (PPC44x_TLB_XLAT), + "i" (PPC44x_TLB_ATTRIB)); +} + +/* + * Configure PPC44x TLB for AS0 exception processing. + */ +static void __init +ppc44x_tlb_config(void) +{ + unsigned int pinned_tlbs = 1; + int i; + + /* + * If lowmem is not on a pin tlb entry size boundary, + * then reserve the last page of system memory. This + * eliminates the possibility of a speculative dcache + * fetch past the end of system memory that would + * result in a machine check exception. + */ + if (total_lowmem | (PPC44x_PIN_SIZE - 1)) + mem_pieces_remove(&phys_avail, total_lowmem - PAGE_SIZE, PAGE_SIZE, 1); + + /* Determine number of entries necessary to cover lowmem */ + pinned_tlbs = (unsigned int) + (_ALIGN(total_lowmem, PPC44x_PIN_SIZE) >> PPC44x_PIN_SHIFT); + + /* Write upper watermark to save location */ + tlb_44x_hwater = PPC44x_LOW_SLOT - pinned_tlbs; + + /* If necessary, set additional pinned TLBs */ + if (pinned_tlbs > 1) + for (i = (PPC44x_LOW_SLOT-(pinned_tlbs-1)); i < PPC44x_LOW_SLOT; i++) { + unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC44x_PIN_SIZE; + ppc44x_pin_tlb(i, phys_addr+PAGE_OFFSET, phys_addr); + } +} + +/* + * MMU_init_hw does the chip-specific initialization of the MMU hardware. + */ +void __init MMU_init_hw(void) +{ + flush_instruction_cache(); + + ppc44x_tlb_config(); +} + +/* TODO: Add large page lowmem mapping support */ +unsigned long __init mmu_mapin_ram(void) +{ + unsigned long v, s, f = _PAGE_GUARDED; + phys_addr_t p; + + v = KERNELBASE; + p = PPC_MEMSTART; + + for (s = 0; s < total_lowmem; s += PAGE_SIZE) { + if ((char *) v >= _stext && (char *) v < etext) + f |= _PAGE_RAM_TEXT; + else + f |= _PAGE_RAM; + map_page(v, p, f); + v += PAGE_SIZE; + p += PAGE_SIZE; + } + + if (ppc_md.progress) + ppc_md.progress("MMU:mmu_mapin_ram done", 0x401); + + return s; +} diff --git a/arch/ppc/mm/Makefile b/arch/ppc/mm/Makefile index 01d5f46c0764..0ed5eb8aad03 100644 --- a/arch/ppc/mm/Makefile +++ b/arch/ppc/mm/Makefile @@ -11,4 +11,5 @@ obj-y := fault.o init.o mem_pieces.o extable.o \ obj-$(CONFIG_PPC_STD_MMU) += hashtable.o ppc_mmu.o tlb.o obj-$(CONFIG_40x) += 4xx_mmu.o +obj-$(CONFIG_44x) += 44x_mmu.o obj-$(CONFIG_NOT_COHERENT_CACHE) += cachemap.o diff --git a/arch/ppc/mm/cachemap.c b/arch/ppc/mm/cachemap.c index b8b9efa7fa5e..e16f8f0cc47d 100644 --- a/arch/ppc/mm/cachemap.c +++ b/arch/ppc/mm/cachemap.c @@ -48,7 +48,7 @@ #include <asm/smp.h> #include <asm/machdep.h> -int map_page(unsigned long va, unsigned long pa, int flags); +int map_page(unsigned long va, phys_addr_t pa, int flags); /* This function will allocate the requested contiguous pages and * map them into the kernel's vmalloc() space. This is done so we @@ -61,7 +61,8 @@ void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle) { int order, err; struct page *page, *free, *end; - unsigned long pa, flags, offset; + phys_addr_t pa; + unsigned long flags, offset; struct vm_struct *area = NULL; unsigned long va = 0; diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index e535c560fabb..2d775dad695f 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -6,6 +6,7 @@ * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) * * Derived from "arch/i386/mm/init.c" * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds diff --git a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h index cd7389ea8e1e..3099b7088d45 100644 --- a/arch/ppc/mm/mmu_decl.h +++ b/arch/ppc/mm/mmu_decl.h @@ -20,9 +20,10 @@ * */ #include <asm/tlbflush.h> +#include <asm/mmu.h> extern void mapin_ram(void); -extern int map_page(unsigned long va, unsigned long pa, int flags); +extern int map_page(unsigned long va, phys_addr_t pa, int flags); extern void setbat(int index, unsigned long virt, unsigned long phys, unsigned int size, int flags); extern void reserve_phys_mem(unsigned long start, unsigned long size); diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c index 3768c66520cb..de3d8224114d 100644 --- a/arch/ppc/mm/pgtable.c +++ b/arch/ppc/mm/pgtable.c @@ -55,11 +55,18 @@ void setbat(int index, unsigned long virt, unsigned long phys, #define p_mapped_by_bats(x) (0UL) #endif /* HAVE_BATS */ +#ifdef CONFIG_44x +/* 44x uses an 8kB pgdir because it has 8-byte Linux PTEs. */ +#define PGDIR_ORDER 1 +#else +#define PGDIR_ORDER 0 +#endif + pgd_t *pgd_alloc(struct mm_struct *mm) { pgd_t *ret; - if ((ret = (pgd_t *)__get_free_page(GFP_KERNEL)) != NULL) + if ((ret = (pgd_t *)__get_free_pages(GFP_KERNEL, PGDIR_ORDER)) != NULL) clear_page(ret); return ret; } @@ -110,16 +117,33 @@ void pte_free(struct page *pte) __free_page(pte); } +#ifndef CONFIG_44x +void * +ioremap(phys_addr_t addr, unsigned long size) +{ + return __ioremap(addr, size, _PAGE_NO_CACHE); +} +#else /* CONFIG_44x */ void * -ioremap(unsigned long addr, unsigned long size) +ioremap64(unsigned long long addr, unsigned long size) { return __ioremap(addr, size, _PAGE_NO_CACHE); } void * -__ioremap(unsigned long addr, unsigned long size, unsigned long flags) +ioremap(phys_addr_t addr, unsigned long size) +{ + phys_addr_t addr64 = fixup_bigphys_addr(addr, size);; + + return ioremap64(addr64, size); +} +#endif /* CONFIG_44x */ + +void * +__ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) { - unsigned long p, v, i; + unsigned long v, i; + phys_addr_t p; int err; /* @@ -144,7 +168,7 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags) */ if ( mem_init_done && (p < virt_to_phys(high_memory)) ) { - printk("__ioremap(): phys addr %0lx is RAM lr %p\n", p, + printk("__ioremap(): phys addr "PTE_FMT" is RAM lr %p\n", p, __builtin_return_address(0)); return NULL; } @@ -195,7 +219,7 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags) } out: - return (void *) (v + (addr & ~PAGE_MASK)); + return (void *) (v + ((unsigned long)addr & ~PAGE_MASK)); } void iounmap(void *addr) @@ -211,7 +235,7 @@ void iounmap(void *addr) } int -map_page(unsigned long va, unsigned long pa, int flags) +map_page(unsigned long va, phys_addr_t pa, int flags) { pmd_t *pd; pte_t *pg; @@ -261,7 +285,7 @@ void __init mapin_ram(void) * virt, phys, size must all be page-aligned. * This should only be called before ioremap is called. */ -void __init io_block_mapping(unsigned long virt, unsigned long phys, +void __init io_block_mapping(unsigned long virt, phys_addr_t phys, unsigned int size, int flags) { int i; diff --git a/arch/ppc/ocp/ocp-probe.c b/arch/ppc/ocp/ocp-probe.c index 88fd2af05b18..624ca8a00135 100644 --- a/arch/ppc/ocp/ocp-probe.c +++ b/arch/ppc/ocp/ocp-probe.c @@ -62,7 +62,6 @@ ocp_setup_dev(struct ocp_def *odef, unsigned int index) (unsigned long) dev->paddr, dev->irq, dev->pm); /* now put in global tree */ - strcpy(dev->dev.name, dev->name); sprintf(dev->dev.bus_id, "%d", index); dev->dev.parent = ocp_bus; dev->dev.bus = &ocp_bus_type; @@ -80,7 +79,7 @@ static struct device * __devinit ocp_alloc_primary_bus(void) return NULL; memset(b, 0, sizeof(struct device)); strcpy(b->bus_id, "ocp"); - strcpy(b->name, "Host/OCP Bridge"); + device_register(b); return b; diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index 759a88325c4a..9cc0b4fc9528 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -1,6 +1,6 @@ config 4xx bool - depends on 40x + depends on 40x || 44x default y menu "IBM 4xx options" @@ -57,6 +57,23 @@ config WALNUT endchoice +choice + prompt "Machine Type" + depends on 44x + default EBONY + +config EBONY + bool "Ebony" + help + This option enables support for the IBM PPC440GP evaluation board. + +config OCOTEA + bool "Ocotea" + help + This option enables support for the IBM PPC440GX evaluation board. + +endchoice + config EP405PC bool "EP405PC Support" depends on EP405 @@ -70,6 +87,26 @@ config NP405H depends on ASH default y +config 440GP + bool + depends on EBONY + default y + +config 440GX + bool + depends on OCOTEA + default y + +config 440 + bool + depends on 440GP + default y + +config 440A + bool + depends on 440GX + default y + # All 405-based cores up until the 405GPR and 405EP have this errata. config IBM405_ERR77 bool @@ -82,9 +119,25 @@ config IBM405_ERR51 depends on 40x && !405GPR default y + +config PIN_TLB + bool + depends on 44x + default y + +config BOOKE + bool + depends on 44x + default y + config IBM_OCP bool - depends on ASH || BEECH || CEDAR || CPCI405 || EP405 || REDWOOD_4 || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT + depends on ASH || BEECH || CEDAR || CPCI405 || EBONY || EP405 || OCOTEA || REDWOOD_4 || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT + default y + +config IBM_EMAC4 + bool + depends on 440GX default y config NP405L diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile index e7233f9bd9ea..5ea683316b61 100644 --- a/arch/ppc/platforms/4xx/Makefile +++ b/arch/ppc/platforms/4xx/Makefile @@ -5,8 +5,10 @@ obj-$(CONFIG_ASH) += ash.o obj-$(CONFIG_BEECH) += beech.o obj-$(CONFIG_CEDAR) += cedar.o obj-$(CONFIG_CPCI405) += cpci405.o +obj-$(CONFIG_EBONY) += ebony.o obj-$(CONFIG_EP405) += ep405.o obj-$(CONFIG_OAK) += oak.o +obj-$(CONFIG_OCOTEA) += ocotea.o obj-$(CONFIG_REDWOOD_4) += redwood.o obj-$(CONFIG_REDWOOD_5) += redwood5.o obj-$(CONFIG_REDWOOD_6) += redwood6.o @@ -21,4 +23,6 @@ obj-$(CONFIG_NP405H) += ibmnp405h.o obj-$(CONFIG_REDWOOD_6) += ibmstbx25.o obj-$(CONFIG_NP4GS3) += ibmnp4gs.o obj-$(CONFIG_405LP) += ibm405lp.o +obj-$(CONFIG_EBONY) += ibm440gp.o +obj-$(CONFIG_OCOTEA) += ibm440gx.o obj-$(CONFIG_405GPR) += ibm405gpr.o diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c new file mode 100644 index 000000000000..e2577b8f7c63 --- /dev/null +++ b/arch/ppc/platforms/4xx/ebony.c @@ -0,0 +1,536 @@ +/* + * arch/ppc/platforms/ebony.c + * + * Ebony board specific routines + * + * Matt Porter <mporter@mvista.com> + * + * Copyright 2002 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 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/config.h> +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/reboot.h> +#include <linux/pci.h> +#include <linux/kdev_t.h> +#include <linux/types.h> +#include <linux/major.h> +#include <linux/blkdev.h> +#include <linux/console.h> +#include <linux/delay.h> +#include <linux/ide.h> +#include <linux/initrd.h> +#include <linux/irq.h> +#include <linux/seq_file.h> +#include <linux/root_dev.h> +#include <linux/tty.h> +#include <linux/serial.h> +#include <linux/serial_core.h> + +#include <asm/system.h> +#include <asm/pgtable.h> +#include <asm/page.h> +#include <asm/dma.h> +#include <asm/io.h> +#include <asm/machdep.h> +#include <asm/pci-bridge.h> +#include <asm/time.h> +#include <asm/todc.h> +#include <asm/bootinfo.h> +#include <asm/ppc4xx_pic.h> + +/* + * Ebony IRQ triggering/polarity settings + */ +static u_char ebony_IRQ_initsenses[] __initdata = { + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 0: UART 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 1: UART 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 2: IIC 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 3: IIC 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 4: PCI Inb Mess */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 5: PCI Cmd Wrt */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 6: PCI PM */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 7: PCI MSI 0 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 8: PCI MSI 1 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 9: PCI MSI 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 10: MAL TX EOB */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 11: MAL RX EOB */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 12: DMA Chan 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 13: DMA Chan 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 14: DMA Chan 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 15: DMA Chan 3 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 16: Reserved */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 17: Reserved */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 18: GPT Timer 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 19: GPT Timer 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 20: GPT Timer 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 21: GPT Timer 3 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 22: GPT Timer 4 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 23: Ext Int 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 24: Ext Int 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 25: Ext Int 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 26: Ext Int 3 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 27: Ext Int 4 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* 28: Ext Int 5 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 29: Ext Int 6 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 30: UIC1 NC Int */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 31: UIC1 Crit Int */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 32: MAL SERR */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 33: MAL TXDE */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 34: MAL RXDE */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 35: ECC Unc Err */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 36: ECC Corr Err */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 37: Ext Bus Ctrl */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 38: Ext Bus Mstr */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 39: OPB->PLB */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 40: PCI MSI 3 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 41: PCI MSI 4 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 42: PCI MSI 5 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 43: PCI MSI 6 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 44: PCI MSI 7 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 45: PCI MSI 8 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 46: PCI MSI 9 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 47: PCI MSI 10 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 48: PCI MSI 11 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 49: PLB Perf Mon */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 50: Ext Int 7 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 51: Ext Int 8 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 52: Ext Int 9 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 53: Ext Int 10 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 54: Ext Int 11 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 55: Ext Int 12 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 56: Ser ROM Err */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 57: Reserved */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 58: Reserved */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 59: PCI Async Err */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 60: EMAC 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 61: EMAC 0 WOL */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 62: EMAC 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 63: EMAC 1 WOL */ +}; + +extern void abort(void); + +/* Global Variables */ +bd_t __res; + +static void __init +ebony_calibrate_decr(void) +{ + unsigned int freq; + + /* + * Determine system clock speed + * + * If we are on Rev. B silicon, then use + * default external system clock. If we are + * on Rev. C silicon then errata forces us to + * use the internal clock. + */ + switch (PVR_REV(mfspr(PVR))) { + case PVR_REV(PVR_440GP_RB): + freq = EBONY_440GP_RB_SYSCLK; + break; + case PVR_REV(PVR_440GP_RC1): + default: + freq = EBONY_440GP_RC_SYSCLK; + break; + } + + tb_ticks_per_jiffy = freq / HZ; + tb_to_us = mulhwu_scale_factor(freq, 1000000); + + /* Set the time base to zero */ + mtspr(SPRN_TBWL, 0); + mtspr(SPRN_TBWU, 0); + + /* Clear any pending timer interrupts */ + mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); + + /* Enable decrementer interrupt */ + mtspr(SPRN_TCR, TCR_DIE); +} + +static int +ebony_show_cpuinfo(struct seq_file *m) +{ + seq_printf(m, "vendor\t\t: IBM\n"); + seq_printf(m, "machine\t\t: Ebony\n"); + + return 0; +} + +static inline int +ebony_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 23, 23, 23, 23 }, /* IDSEL 1 - PCI Slot 0 */ + { 24, 24, 24, 24 }, /* IDSEL 2 - PCI Slot 1 */ + { 25, 25, 25, 25 }, /* IDSEL 3 - PCI Slot 2 */ + { 26, 26, 26, 26 }, /* IDSEL 4 - PCI Slot 3 */ + }; + + const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; +} + +#define PCIX_WRITEL(value, offset) \ + (writel(value, (u32)pcix_reg_base+offset)) + +/* + * FIXME: This is only here to "make it work". This will move + * to a ibm_pcix.c which will contain a generic IBM PCIX bridge + * configuration library. -Matt + */ +static void __init +ebony_setup_pcix(void) +{ + void *pcix_reg_base; + + pcix_reg_base = ioremap64(PCIX0_REG_BASE, PCIX0_REG_SIZE); + + /* Disable all windows */ + PCIX_WRITEL(0, PCIX0_POM0SA); + PCIX_WRITEL(0, PCIX0_POM1SA); + PCIX_WRITEL(0, PCIX0_POM2SA); + PCIX_WRITEL(0, PCIX0_PIM0SA); + PCIX_WRITEL(0, PCIX0_PIM1SA); + PCIX_WRITEL(0, PCIX0_PIM2SA); + + /* Setup 2GB PLB->PCI outbound mem window (3_8000_0000->0_8000_0000) */ + PCIX_WRITEL(0x00000003, PCIX0_POM0LAH); + PCIX_WRITEL(0x80000000, PCIX0_POM0LAL); + PCIX_WRITEL(0x00000000, PCIX0_POM0PCIAH); + PCIX_WRITEL(0x80000000, PCIX0_POM0PCIAL); + PCIX_WRITEL(0x80000001, PCIX0_POM0SA); + + /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */ + PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH); + PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL); + PCIX_WRITEL(0x80000007, PCIX0_PIM0SA); + + eieio(); +} + +static void __init +ebony_setup_hose(void) +{ + struct pci_controller *hose; + + /* Configure windows on the PCI-X host bridge */ + ebony_setup_pcix(); + + hose = pcibios_alloc_controller(); + + if (!hose) + return; + + hose->first_busno = 0; + hose->last_busno = 0xff; + + hose->pci_mem_offset = EBONY_PCI_MEM_OFFSET; + + pci_init_resource(&hose->io_resource, + EBONY_PCI_LOWER_IO, + EBONY_PCI_UPPER_IO, + IORESOURCE_IO, + "PCI host bridge"); + + pci_init_resource(&hose->mem_resources[0], + EBONY_PCI_LOWER_MEM, + EBONY_PCI_UPPER_MEM, + IORESOURCE_MEM, + "PCI host bridge"); + + hose->io_space.start = EBONY_PCI_LOWER_IO; + hose->io_space.end = EBONY_PCI_UPPER_IO; + hose->mem_space.start = EBONY_PCI_LOWER_MEM; + hose->mem_space.end = EBONY_PCI_UPPER_MEM; + isa_io_base = + (unsigned long)ioremap64(EBONY_PCI_IO_BASE, EBONY_PCI_IO_SIZE); + hose->io_base_virt = (void *)isa_io_base; + + setup_indirect_pci(hose, + EBONY_PCI_CFGA_PLB32, + EBONY_PCI_CFGD_PLB32); + hose->set_cfg_type = 1; + + hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = ebony_map_irq; +} + +TODC_ALLOC(); + +static void __init +ebony_early_serial_map(void) +{ + struct uart_port port; + + /* Setup ioremapped serial port access */ + memset(&port, 0, sizeof(port)); + port.membase = ioremap64(PPC440GP_UART0_ADDR, 8); + port.irq = 0; + port.uartclk = BASE_BAUD * 16; + port.regshift = 0; + port.iotype = SERIAL_IO_MEM; + port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + port.line = 0; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 0 failed\n"); + } + + port.membase = ioremap64(PPC440GP_UART1_ADDR, 8); + port.irq = 1; + port.line = 1; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 1 failed\n"); + } +} + +static void __init +ebony_setup_arch(void) +{ + unsigned char * vpd_base; + struct ibm440gp_clocks clocks; + +#if !defined(CONFIG_BDI_SWITCH) + /* + * The Abatron BDI JTAG debugger does not tolerate others + * mucking with the debug registers. + */ + mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM)); +#endif + + /* Retrieve MAC addresses */ + vpd_base = ioremap64(EBONY_VPD_BASE, EBONY_VPD_SIZE); + memcpy(__res.bi_enetaddr[0],EBONY_NA0_ADDR(vpd_base),6); + memcpy(__res.bi_enetaddr[1],EBONY_NA1_ADDR(vpd_base),6); + + /* + * Determine various clocks. + * To be completely correct we should get SysClk + * from FPGA, because it can be changed by on-board switches + * --ebs + */ + ibm440gp_get_clocks(&clocks, 33333333, 6 * 1843200); + __res.bi_opb_busfreq = clocks.opb; + + /* Use IIC in standard (100 kHz) mode */ + __res.bi_iic_fast[0] = __res.bi_iic_fast[1] = 0; + + /* Setup TODC access */ + TODC_INIT(TODC_TYPE_DS1743, + 0, + 0, + ioremap64(EBONY_RTC_ADDR, EBONY_RTC_SIZE), + 8); + + /* init to some ~sane value until calibrate_delay() runs */ + loops_per_jiffy = 50000000/HZ; + + /* Setup PCI host bridge */ + ebony_setup_hose(); + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif + +#ifdef CONFIG_VT + conswitchp = &dummy_con; +#endif + + ebony_early_serial_map(); + + ibm4xxPIC_InitSenses = ebony_IRQ_initsenses; + ibm4xxPIC_NumInitSenses = sizeof(ebony_IRQ_initsenses); + + /* Identify the system */ + printk("IBM Ebony port (MontaVista Software, Inc. (source@mvista.com))\n"); +} + +static void +ebony_restart(char *cmd) +{ + local_irq_disable(); + abort(); +} + +static void +ebony_power_off(void) +{ + local_irq_disable(); + for(;;); +} + +static void +ebony_halt(void) +{ + local_irq_disable(); + for(;;); +} + +/* + * Read the 440GP memory controller to get size of system memory. + */ +static unsigned long __init +ebony_find_end_of_memory(void) +{ + u32 i, bank_config; + u32 mem_size = 0; + + for (i=0; i<4; i++) + { + switch (i) + { + case 0: + mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B0CR); + break; + case 1: + mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B1CR); + break; + case 2: + mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B2CR); + break; + case 3: + mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B3CR); + break; + } + + bank_config = mfdcr(DCRN_SDRAM0_CFGDATA); + + if (!(bank_config & SDRAM_CONFIG_BANK_ENABLE)) + continue; + switch (SDRAM_CONFIG_BANK_SIZE(bank_config)) + { + case SDRAM_CONFIG_SIZE_8M: + mem_size += PPC44x_MEM_SIZE_8M; + break; + case SDRAM_CONFIG_SIZE_16M: + mem_size += PPC44x_MEM_SIZE_16M; + break; + case SDRAM_CONFIG_SIZE_32M: + mem_size += PPC44x_MEM_SIZE_32M; + break; + case SDRAM_CONFIG_SIZE_64M: + mem_size += PPC44x_MEM_SIZE_64M; + break; + case SDRAM_CONFIG_SIZE_128M: + mem_size += PPC44x_MEM_SIZE_128M; + break; + case SDRAM_CONFIG_SIZE_256M: + mem_size += PPC44x_MEM_SIZE_256M; + break; + case SDRAM_CONFIG_SIZE_512M: + mem_size += PPC44x_MEM_SIZE_512M; + break; + } + } + return mem_size; +} + +static void __init +ebony_init_irq(void) +{ + int i; + + ppc4xx_pic_init(); + + for (i = 0; i < NR_IRQS; i++) + irq_desc[i].handler = ppc4xx_pic; +} + +#ifdef CONFIG_SERIAL_TEXT_DEBUG +#include <linux/serialP.h> +#include <linux/serial_reg.h> +#include <asm/serial.h> + +static struct serial_state rs_table[RS_TABLE_SIZE] = { + SERIAL_PORT_DFNS /* Defined in <asm/serial.h> */ +}; + +static void +ebony_progress(char *s, unsigned short hex) +{ + volatile char c; + volatile unsigned long com_port; + u16 shift; + + com_port = (unsigned long)rs_table[0].iomem_base; + shift = rs_table[0].iomem_reg_shift; + + while ((c = *s++) != 0) { + while ((*((volatile unsigned char *)com_port + + (UART_LSR << shift)) & UART_LSR_THRE) == 0) + ; + *(volatile unsigned char *)com_port = c; + + } + + /* Send LF/CR to pretty up output */ + while ((*((volatile unsigned char *)com_port + + (UART_LSR << shift)) & UART_LSR_THRE) == 0) + ; + *(volatile unsigned char *)com_port = '\r'; + while ((*((volatile unsigned char *)com_port + + (UART_LSR << shift)) & UART_LSR_THRE) == 0) + ; + *(volatile unsigned char *)com_port = '\n'; +} +#endif /* CONFIG_SERIAL_TEXT_DEBUG */ + +void __init platform_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7) +{ + parse_bootinfo((struct bi_record *) (r3 + KERNELBASE)); + + ppc_md.setup_arch = ebony_setup_arch; + ppc_md.show_cpuinfo = ebony_show_cpuinfo; + ppc_md.init_IRQ = ebony_init_irq; + ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ + + ppc_md.find_end_of_memory = ebony_find_end_of_memory; + + ppc_md.restart = ebony_restart; + ppc_md.power_off = ebony_power_off; + ppc_md.halt = ebony_halt; + + ppc_md.calibrate_decr = ebony_calibrate_decr; + ppc_md.time_init = todc_time_init; + ppc_md.set_rtc_time = todc_set_rtc_time; + ppc_md.get_rtc_time = todc_get_rtc_time; + + ppc_md.nvram_read_val = todc_direct_read_val; + ppc_md.nvram_write_val = todc_direct_write_val; + +#ifdef CONFIG_SERIAL_TEXT_DEBUG + ppc_md.progress = ebony_progress; +#endif /* CONFIG_SERIAL_TEXT_DEBUG */ +#ifdef CONFIG_KGDB + ppc_md.early_serial_map = ebony_early_serial_map; +#endif +} + diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h new file mode 100755 index 000000000000..c852552f167e --- /dev/null +++ b/arch/ppc/platforms/4xx/ebony.h @@ -0,0 +1,96 @@ +/* + * arch/ppc/platforms/ebony.h + * + * Ebony board definitions + * + * Matt Porter <mporter@mvista.com> + * + * Copyright 2002 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 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifdef __KERNEL__ +#ifndef __ASM_EBONY_H__ +#define __ASM_EBONY_H__ + +#include <linux/config.h> +#include <platforms/4xx/ibm440gp.h> + +/* F/W TLB mapping used in bootloader glue to reset EMAC */ +#define PPC44x_EMAC0_MR0 0xE0000800 + +/* Macros to get at Ebony VPD info */ +#define EBONY_VPD_BASE 0x00000001fffffe00ULL +#define EBONY_VPD_SIZE 0x24 +#define EBONY_NA0_OFFSET 0x0c +#define EBONY_NA1_OFFSET 0x18 +#define EBONY_NA0_ADDR(base) (base + EBONY_NA0_OFFSET) +#define EBONY_NA1_ADDR(base) (base + EBONY_NA1_OFFSET) + +/* Default clock rates for Rev. B and Rev. C silicon */ +#define EBONY_440GP_RB_SYSCLK 33000000 +#define EBONY_440GP_RC_SYSCLK 400000000 + +/* RTC/NVRAM location */ +#define EBONY_RTC_ADDR 0x0000000148000000ULL +#define EBONY_RTC_SIZE 0x2000 + +/* Flash */ +#define EBONY_FPGA_ADDR 0x0000000148300000 +#define EBONY_BOOT_SMALL_FLASH(x) (x & 0x20) +#define EBONY_ONBRD_FLASH_EN(x) (x & 0x02) +#define EBONY_FLASH_SEL(x) (x & 0x01) +#define EBONY_SMALL_FLASH_LOW1 0x00000001ff800000 +#define EBONY_SMALL_FLASH_LOW2 0x00000001ff880000 +#define EBONY_SMALL_FLASH_HIGH1 0x00000001fff00000 +#define EBONY_SMALL_FLASH_HIGH2 0x00000001fff80000 +#define EBONY_SMALL_FLASH_SIZE 0x80000 +#define EBONY_LARGE_FLASH_LOW 0x00000001ff800000 +#define EBONY_LARGE_FLASH_HIGH 0x00000001ffc00000 +#define EBONY_LARGE_FLASH_SIZE 0x400000 + +#define EBONY_SMALL_FLASH_BASE 0x00000001fff80000 +#define EBONY_LARGE_FLASH_BASE 0x00000001ff800000 + +/* + * Serial port defines + */ + +/* OpenBIOS defined UART mappings, used before early_serial_setup */ +#define UART0_IO_BASE (u8 *) 0xE0000200 +#define UART1_IO_BASE (u8 *) 0xE0000300 + +#define BASE_BAUD 33000000/3/16 +#define UART0_INT 0 +#define UART1_INT 1 + +#define STD_UART_OP(num) \ + { 0, BASE_BAUD, 0, UART##num##_INT, \ + (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ + iomem_base: UART##num##_IO_BASE, \ + io_type: SERIAL_IO_MEM}, + +#define SERIAL_PORT_DFNS \ + STD_UART_OP(0) \ + STD_UART_OP(1) + +/* PCI support */ +#define EBONY_PCI_LOWER_IO 0x00000000 +#define EBONY_PCI_UPPER_IO 0x0000ffff +#define EBONY_PCI_LOWER_MEM 0x80002000 +#define EBONY_PCI_UPPER_MEM 0xffffefff + +#define EBONY_PCI_CFGREGS_BASE 0x000000020ec00000 +#define EBONY_PCI_CFGA_PLB32 0x0ec00000 +#define EBONY_PCI_CFGD_PLB32 0x0ec00004 + +#define EBONY_PCI_IO_BASE 0x0000000208000000ULL +#define EBONY_PCI_IO_SIZE 0x00010000 +#define EBONY_PCI_MEM_OFFSET 0x00000000 + +#endif /* __ASM_EBONY_H__ */ +#endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/ibm440gp.c b/arch/ppc/platforms/4xx/ibm440gp.c new file mode 100644 index 000000000000..7bdd7455afcd --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440gp.c @@ -0,0 +1,31 @@ +/* + * arch/ppc/platforms/4xx/ibm440gp.c + * + * PPC440GP I/O descriptions + * + * Matt Porter <mporter@mvista.com> + * + * Copyright 2002 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 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include <platforms/4xx/ibm440gp.h> +#include <asm/ocp.h> +#include <linux/init.h> + +struct ocp_def core_ocp[] __initdata = { + {OCP_VENDOR_IBM, OCP_FUNC_OPB, PPC440GP_OPB_BASE_START, OCP_IRQ_NA, OCP_CPM_NA}, + {OCP_VENDOR_IBM, OCP_FUNC_16550, PPC440GP_UART0_ADDR, UART0_INT, IBM_CPM_UART0}, + {OCP_VENDOR_IBM, OCP_FUNC_16550, PPC440GP_UART1_ADDR, UART1_INT, IBM_CPM_UART1}, + {OCP_VENDOR_IBM, OCP_FUNC_IIC, PPC440GP_IIC0_ADDR, IIC0_IRQ, IBM_CPM_IIC0}, + {OCP_VENDOR_IBM, OCP_FUNC_IIC, PPC440GP_IIC1_ADDR, IIC1_IRQ, IBM_CPM_IIC1}, + {OCP_VENDOR_IBM, OCP_FUNC_GPIO, PPC440GP_GPIO0_ADDR, OCP_IRQ_NA, IBM_CPM_GPIO0}, + {OCP_VENDOR_IBM, OCP_FUNC_EMAC, PPC440GP_EMAC0_ADDR, BL_MAC_ETH0, OCP_CPM_NA}, + {OCP_VENDOR_IBM, OCP_FUNC_EMAC, PPC440GP_EMAC1_ADDR, BL_MAC_ETH1, OCP_CPM_NA}, + {OCP_VENDOR_IBM, OCP_FUNC_ZMII, PPC440GP_ZMII_ADDR, OCP_IRQ_NA, OCP_CPM_NA}, + {OCP_VENDOR_INVALID, OCP_FUNC_INVALID, 0x0, OCP_IRQ_NA, OCP_CPM_NA}, +}; diff --git a/arch/ppc/platforms/4xx/ibm440gp.h b/arch/ppc/platforms/4xx/ibm440gp.h new file mode 100644 index 000000000000..b8c1a4fb66e7 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440gp.h @@ -0,0 +1,102 @@ +/* + * arch/ppc/platforms/4xx/ibm440gp.h + * + * PPC440GP definitions + * + * Roland Dreier <roland@digitalvampire.org> + * + * Copyright 2002 Roland Dreier + * + * 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 code that was originally in the files ibm44x.h + * and ebony.h, which were written by Matt Porter of MontaVista Software Inc. + */ + +#ifdef __KERNEL__ +#ifndef __PPC_PLATFORMS_IBM440GP_H +#define __PPC_PLATFORMS_IBM440GP_H + +#include <linux/config.h> + +#define EMAC_NUMS 2 +#define UART_NUMS 2 +#define ZMII_NUMS 1 +#define IIC_NUMS 2 +#define IIC0_IRQ 2 +#define IIC1_IRQ 3 +#define GPIO_NUMS 1 + +/* UART location */ +#define PPC440GP_UART0_ADDR 0x0000000140000200ULL +#define PPC440GP_UART1_ADDR 0x0000000140000300ULL + +/* EMAC location */ +#define PPC440GP_EMAC0_ADDR 0x0000000140000800ULL +#define PPC440GP_EMAC1_ADDR 0x0000000140000900ULL +#define PPC440GP_EMAC_SIZE 0x70 + +/* EMAC IRQ's */ +#define BL_MAC_WOL 61 /* WOL */ +#define BL_MAC_WOL1 63 /* WOL */ +#define BL_MAL_SERR 32 /* MAL SERR */ +#define BL_MAL_TXDE 33 /* MAL TXDE */ +#define BL_MAL_RXDE 34 /* MAL RXDE */ +#define BL_MAL_TXEOB 10 /* MAL TX EOB */ +#define BL_MAL_RXEOB 11 /* MAL RX EOB */ +#define BL_MAC_ETH0 60 /* MAC */ +#define BL_MAC_ETH1 62 /* MAC */ + +/* ZMII location */ +#define PPC440GP_ZMII_ADDR 0x0000000140000780ULL +#define PPC440GP_ZMII_SIZE 0x0c + +/* I2C location */ +#define PPC440GP_IIC0_ADDR 0x40000400 +#define PPC440GP_IIC1_ADDR 0x40000500 + +/* GPIO location */ +#define PPC440GP_GPIO0_ADDR 0x0000000140000700ULL + +/* Clock and Power Management */ +#define IBM_CPM_IIC0 0x80000000 /* IIC interface */ +#define IBM_CPM_IIC1 0x40000000 /* IIC interface */ +#define IBM_CPM_PCI 0x20000000 /* PCI bridge */ +#define IBM_CPM_CPU 0x02000000 /* processor core */ +#define IBM_CPM_DMA 0x01000000 /* DMA controller */ +#define IBM_CPM_BGO 0x00800000 /* PLB to OPB bus arbiter */ +#define IBM_CPM_BGI 0x00400000 /* OPB to PLB bridge */ +#define IBM_CPM_EBC 0x00200000 /* External Bux Controller */ +#define IBM_CPM_EBM 0x00100000 /* Ext Bus Master Interface */ +#define IBM_CPM_DMC 0x00080000 /* SDRAM peripheral controller */ +#define IBM_CPM_PLB 0x00040000 /* PLB bus arbiter */ +#define IBM_CPM_SRAM 0x00020000 /* SRAM memory controller */ +#define IBM_CPM_PPM 0x00002000 /* PLB Performance Monitor */ +#define IBM_CPM_UIC1 0x00001000 /* Universal Interrupt Controller */ +#define IBM_CPM_GPIO0 0x00000800 /* General Purpose IO (??) */ +#define IBM_CPM_GPT 0x00000400 /* General Purpose Timers */ +#define IBM_CPM_UART0 0x00000200 /* serial port 0 */ +#define IBM_CPM_UART1 0x00000100 /* serial port 1 */ +#define IBM_CPM_UIC0 0x00000080 /* Universal Interrupt Controller */ +#define IBM_CPM_TMRCLK 0x00000040 /* CPU timers */ + +#define DFLT_IBM4xx_PM ~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \ + | IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \ + | IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \ + | IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI) + +#define PPC440GP_OPB_BASE_START 0x0000000140000000ULL + +/* + * Serial port defines + */ +#define RS_TABLE_SIZE 2 + +#include <asm/ibm44x.h> +#include <syslib/ibm440gp_common.h> + +#endif /* __PPC_PLATFORMS_IBM440GP_H */ +#endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/ibm440gx.c b/arch/ppc/platforms/4xx/ibm440gx.c new file mode 100644 index 000000000000..42677b8b1ecf --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440gx.c @@ -0,0 +1,37 @@ +/* + * arch/ppc/platforms/ibm440gx.c + * + * PPC440GX I/O descriptions + * + * Matt Porter <mporter@mvista.com> + * + * Copyright 2002-2003 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 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/config.h> +#include <linux/init.h> +#include <linux/smp.h> +#include <linux/threads.h> +#include <linux/param.h> +#include <linux/string.h> +#include <asm/ocp.h> +#include <platforms/4xx/ibm440gx.h> + +struct ocp_def core_ocp[] __initdata = { + {OCP_VENDOR_IBM, OCP_FUNC_OPB, PPC440GX_OPB_BASE_START, OCP_IRQ_NA, OCP_CPM_NA}, + {OCP_VENDOR_IBM, OCP_FUNC_16550, PPC440GX_UART0_ADDR, UART0_IRQ, IBM_CPM_UART0}, + {OCP_VENDOR_IBM, OCP_FUNC_16550, PPC440GX_UART1_ADDR, UART1_IRQ, IBM_CPM_UART1}, + {OCP_VENDOR_IBM, OCP_FUNC_IIC, PPC440GX_IIC0_ADDR, IIC0_IRQ, IBM_CPM_IIC0}, + {OCP_VENDOR_IBM, OCP_FUNC_IIC, PPC440GX_IIC1_ADDR, IIC1_IRQ, IBM_CPM_IIC1}, + {OCP_VENDOR_IBM, OCP_FUNC_GPIO, PPC440GX_GPIO0_ADDR, OCP_IRQ_NA, IBM_CPM_GPIO0}, + {OCP_VENDOR_IBM, OCP_FUNC_EMAC, PPC440GX_EMAC0_ADDR, BL_MAC_ETH0, OCP_CPM_NA}, + {OCP_VENDOR_IBM, OCP_FUNC_EMAC, PPC440GX_EMAC1_ADDR, BL_MAC_ETH1, OCP_CPM_NA}, + {OCP_VENDOR_IBM, OCP_FUNC_ZMII, PPC440GX_ZMII_ADDR, OCP_IRQ_NA, OCP_CPM_NA}, + {OCP_VENDOR_INVALID, OCP_FUNC_INVALID, 0x0, OCP_IRQ_NA, OCP_CPM_NA}, +}; diff --git a/arch/ppc/platforms/4xx/ibm440gx.h b/arch/ppc/platforms/4xx/ibm440gx.h new file mode 100644 index 000000000000..7299b4c42319 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440gx.h @@ -0,0 +1,123 @@ +/* + * arch/ppc/platforms/ibm440gx.h + * + * PPC440GX definitions + * + * Matt Porter <mporter@mvista.com> + * + * Copyright 2002 Roland Dreier + * Copyright 2003 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 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifdef __KERNEL__ +#ifndef __PPC_PLATFORMS_IBM440GX_H +#define __PPC_PLATFORMS_IBM440GX_H + +#include <linux/config.h> + +#include <asm/ibm44x.h> + +/* UART */ +#define PPC440GX_UART0_ADDR 0x0000000140000200ULL +#define PPC440GX_UART1_ADDR 0x0000000140000300ULL +#define UART0_IRQ 0 +#define UART1_IRQ 1 + +/* EMAC */ +#define PPC440GX_EMAC0_ADDR 0x0000000140000800ULL +#define PPC440GX_EMAC1_ADDR 0x0000000140000900ULL +#define PPC440GX_EMAC2_ADDR 0x0000000140000C00ULL +#define PPC440GX_EMAC3_ADDR 0x0000000140000E00ULL +#define PPC440GX_EMAC_SIZE 0xFC +#define EMAC_NUMS 2 +#define BL_MAC_WOL 61 /* WOL */ +#define BL_MAC_WOL1 63 /* WOL */ +#define BL_MAC_WOL2 65 /* WOL */ +#define BL_MAC_WOL3 67 /* WOL */ +#define BL_MAL_SERR 32 /* MAL SERR */ +#define BL_MAL_TXDE 33 /* MAL TXDE */ +#define BL_MAL_RXDE 34 /* MAL RXDE */ +#define BL_MAL_TXEOB 10 /* MAL TX EOB */ +#define BL_MAL_RXEOB 11 /* MAL RX EOB */ +#define BL_MAC_ETH0 60 /* MAC */ +#define BL_MAC_ETH1 62 /* MAC */ +#define BL_MAC_ETH2 64 /* MAC */ +#define BL_MAC_ETH3 66 /* MAC */ +#define BL_TAH0 68 /* TAH 0 */ +#define BL_TAH1 69 /* TAH 1 */ + +/* TAH */ +#define PPC440GX_TAH0_ADDR 0x0000000140000B00ULL +#define PPC440GX_TAH1_ADDR 0x0000000140000D00ULL +#define PPC440GX_TAH_SIZE 0xFC + +/* ZMII */ +#define PPC440GX_ZMII_ADDR 0x0000000140000780ULL +#define PPC440GX_ZMII_SIZE 0x0c + +/* RGMII */ +#define PPC440GX_RGMII_ADDR 0x0000000140000790ULL +#define PPC440GX_RGMII_SIZE 0x0c + +/* IIC */ +#define PPC440GX_IIC0_ADDR 0x40000400 +#define PPC440GX_IIC1_ADDR 0x40000500 +#define IIC0_IRQ 2 +#define IIC1_IRQ 3 + +/* GPIO */ +#define PPC440GX_GPIO0_ADDR 0x0000000140000700ULL + +/* Clock and Power Management */ +#define IBM_CPM_IIC0 0x80000000 /* IIC interface */ +#define IBM_CPM_IIC1 0x40000000 /* IIC interface */ +#define IBM_CPM_PCI 0x20000000 /* PCI bridge */ +#define IBM_CPM_RGMII 0x10000000 /* RGMII */ +#define IBM_CPM_TAHOE0 0x08000000 /* TAHOE 0 */ +#define IBM_CPM_TAHOE1 0x04000000 /* TAHOE 1 */ +#define IBM_CPM_CPU 0x02000000 /* processor core */ +#define IBM_CPM_DMA 0x01000000 /* DMA controller */ +#define IBM_CPM_BGO 0x00800000 /* PLB to OPB bus arbiter */ +#define IBM_CPM_BGI 0x00400000 /* OPB to PLB bridge */ +#define IBM_CPM_EBC 0x00200000 /* External Bux Controller */ +#define IBM_CPM_EBM 0x00100000 /* Ext Bus Master Interface */ +#define IBM_CPM_DMC 0x00080000 /* SDRAM peripheral controller */ +#define IBM_CPM_PLB 0x00040000 /* PLB bus arbiter */ +#define IBM_CPM_SRAM 0x00020000 /* SRAM memory controller */ +#define IBM_CPM_PPM 0x00002000 /* PLB Performance Monitor */ +#define IBM_CPM_UIC1 0x00001000 /* Universal Interrupt Controller */ +#define IBM_CPM_GPIO0 0x00000800 /* General Purpose IO (??) */ +#define IBM_CPM_GPT 0x00000400 /* General Purpose Timers */ +#define IBM_CPM_UART0 0x00000200 /* serial port 0 */ +#define IBM_CPM_UART1 0x00000100 /* serial port 1 */ +#define IBM_CPM_UIC0 0x00000080 /* Universal Interrupt Controller */ +#define IBM_CPM_TMRCLK 0x00000040 /* CPU timers */ +#define IBM_CPM_EMAC0 0x00000020 /* EMAC 0 */ +#define IBM_CPM_EMAC1 0x00000010 /* EMAC 1 */ +#define IBM_CPM_EMAC2 0x00000008 /* EMAC 2 */ +#define IBM_CPM_EMAC3 0x00000004 /* EMAC 3 */ + +#define DFLT_IBM4xx_PM ~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \ + | IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \ + | IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \ + | IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI \ + | IBM_CPM_TAHOE0 | IBM_CPM_TAHOE1 \ + | IBM_CPM_EMAC0 | IBM_CPM_EMAC1 \ + | IBM_CPM_EMAC2 | IBM_CPM_EMAC3 ) + +/* OPB */ +#define PPC440GX_OPB_BASE_START 0x0000000140000000ULL + +/* + * Serial port defines + */ +#define RS_TABLE_SIZE 2 + +#endif /* __PPC_PLATFORMS_IBM440GX_H */ +#endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c new file mode 100644 index 000000000000..7acf4aedcc84 --- /dev/null +++ b/arch/ppc/platforms/4xx/ocotea.c @@ -0,0 +1,459 @@ +/* + * arch/ppc/platforms/ocotea.c + * + * Ocotea board specific routines + * + * Matt Porter <mporter@mvista.com> + * + * Copyright 2003 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 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/config.h> +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/reboot.h> +#include <linux/pci.h> +#include <linux/kdev_t.h> +#include <linux/types.h> +#include <linux/major.h> +#include <linux/blkdev.h> +#include <linux/console.h> +#include <linux/delay.h> +#include <linux/ide.h> +#include <linux/initrd.h> +#include <linux/irq.h> +#include <linux/seq_file.h> +#include <linux/root_dev.h> +#include <linux/tty.h> +#include <linux/serial.h> +#include <linux/serial_core.h> + +#include <asm/system.h> +#include <asm/pgtable.h> +#include <asm/page.h> +#include <asm/dma.h> +#include <asm/io.h> +#include <asm/machdep.h> +#include <asm/pci-bridge.h> +#include <asm/time.h> +#include <asm/todc.h> +#include <asm/bootinfo.h> +#include <asm/ppc4xx_pic.h> + +extern void abort(void); + +/* Global Variables */ +bd_t __res; + +static void __init +ocotea_calibrate_decr(void) +{ + unsigned int freq; + + freq = OCOTEA_SYSCLK; + + tb_ticks_per_jiffy = freq / HZ; + tb_to_us = mulhwu_scale_factor(freq, 1000000); + + /* Set the time base to zero */ + mtspr(SPRN_TBWL, 0); + mtspr(SPRN_TBWU, 0); + + /* Clear any pending timer interrupts */ + mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); + + /* Enable decrementer interrupt */ + mtspr(SPRN_TCR, TCR_DIE); +} + +static int +ocotea_show_cpuinfo(struct seq_file *m) +{ + seq_printf(m, "vendor\t\t: IBM\n"); + seq_printf(m, "machine\t\t: PPC440GX EVB (Ocotea)\n"); + + return 0; +} +static inline int +ocotea_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 23, 23, 23, 23 }, /* IDSEL 1 - PCI Slot 0 */ + { 24, 24, 24, 24 }, /* IDSEL 2 - PCI Slot 1 */ + { 25, 25, 25, 25 }, /* IDSEL 3 - PCI Slot 2 */ + { 26, 26, 26, 26 }, /* IDSEL 4 - PCI Slot 3 */ + }; + + const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; +} + +#define PCIX_READW(offset) \ + (readw((u32)pcix_reg_base+offset)) + +#define PCIX_WRITEW(value, offset) \ + (writew(value, (u32)pcix_reg_base+offset)) + +#define PCIX_WRITEL(value, offset) \ + (writel(value, (u32)pcix_reg_base+offset)) + +/* + * FIXME: This is only here to "make it work". This will move + * to a ibm_pcix.c which will contain a generic IBM PCIX bridge + * configuration library. -Matt + */ +static void __init +ocotea_setup_pcix(void) +{ + void *pcix_reg_base; + + pcix_reg_base = ioremap64(PCIX0_REG_BASE, PCIX0_REG_SIZE); + + /* Enable PCIX0 I/O, Mem, and Busmaster cycles */ + PCIX_WRITEW(PCIX_READW(PCIX0_COMMAND) | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER, PCIX0_COMMAND); + + /* Disable all windows */ + PCIX_WRITEL(0, PCIX0_POM0SA); + PCIX_WRITEL(0, PCIX0_POM1SA); + PCIX_WRITEL(0, PCIX0_POM2SA); + PCIX_WRITEL(0, PCIX0_PIM0SA); + PCIX_WRITEL(0, PCIX0_PIM0SAH); + PCIX_WRITEL(0, PCIX0_PIM1SA); + PCIX_WRITEL(0, PCIX0_PIM2SA); + PCIX_WRITEL(0, PCIX0_PIM2SAH); + + /* Setup 2GB PLB->PCI outbound mem window (3_8000_0000->0_8000_0000) */ + PCIX_WRITEL(0x00000003, PCIX0_POM0LAH); + PCIX_WRITEL(0x80000000, PCIX0_POM0LAL); + PCIX_WRITEL(0x00000000, PCIX0_POM0PCIAH); + PCIX_WRITEL(0x80000000, PCIX0_POM0PCIAL); + PCIX_WRITEL(0x80000001, PCIX0_POM0SA); + + /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */ + PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH); + PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL); + PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA); + + eieio(); +} + +static void __init +ocotea_setup_hose(void) +{ + struct pci_controller *hose; + + /* Configure windows on the PCI-X host bridge */ + ocotea_setup_pcix(); + + hose = pcibios_alloc_controller(); + + if (!hose) + return; + + hose->first_busno = 0; + hose->last_busno = 0xff; + + hose->pci_mem_offset = OCOTEA_PCI_MEM_OFFSET; + + pci_init_resource(&hose->io_resource, + OCOTEA_PCI_LOWER_IO, + OCOTEA_PCI_UPPER_IO, + IORESOURCE_IO, + "PCI host bridge"); + + pci_init_resource(&hose->mem_resources[0], + OCOTEA_PCI_LOWER_MEM, + OCOTEA_PCI_UPPER_MEM, + IORESOURCE_MEM, + "PCI host bridge"); + + hose->io_space.start = OCOTEA_PCI_LOWER_IO; + hose->io_space.end = OCOTEA_PCI_UPPER_IO; + hose->mem_space.start = OCOTEA_PCI_LOWER_MEM; + hose->mem_space.end = OCOTEA_PCI_UPPER_MEM; + isa_io_base = + (unsigned long)ioremap64(OCOTEA_PCI_IO_BASE, OCOTEA_PCI_IO_SIZE); + hose->io_base_virt = (void *)isa_io_base; + + setup_indirect_pci(hose, + OCOTEA_PCI_CFGA_PLB32, + OCOTEA_PCI_CFGD_PLB32); + hose->set_cfg_type = 1; + + hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = ocotea_map_irq; +} + + +TODC_ALLOC(); + +static void __init +ocotea_early_serial_map(void) +{ + struct uart_port port; + + /* Setup ioremapped serial port access */ + memset(&port, 0, sizeof(port)); + port.membase = ioremap64(PPC440GX_UART0_ADDR, 8); + port.irq = 0; + port.uartclk = BASE_BAUD * 16; + port.regshift = 0; + port.iotype = SERIAL_IO_MEM; + port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + port.line = 0; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 0 failed\n"); + } + + port.membase = ioremap64(PPC440GX_UART1_ADDR, 8); + port.irq = 1; + port.line = 1; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 1 failed\n"); + } +} + +static void __init +ocotea_setup_arch(void) +{ + unsigned char *addr; + unsigned long long mac64; + + /* Retrieve MAC addresses from flash */ + addr = ioremap64(OCOTEA_MAC_BASE, OCOTEA_MAC_SIZE); + mac64 = simple_strtoull(addr, 0, 16); + memcpy(__res.bi_enetaddr[0], (char *)&mac64+2, 6); + mac64 = simple_strtoull(addr+OCOTEA_MAC1_OFFSET, 0, 16); + memcpy(__res.bi_enetaddr[1], (char *)&mac64+2, 6); + iounmap(addr); + +#if !defined(CONFIG_BDI_SWITCH) + /* + * The Abatron BDI JTAG debugger does not tolerate others + * mucking with the debug registers. + */ + mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM)); +#endif + + /* Setup TODC access */ + TODC_INIT(TODC_TYPE_DS1743, + 0, + 0, + ioremap64(OCOTEA_RTC_ADDR, OCOTEA_RTC_SIZE), + 8); + + /* init to some ~sane value until calibrate_delay() runs */ + loops_per_jiffy = 50000000/HZ; + + /* Setup PCI host bridge */ + ocotea_setup_hose(); + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif + +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + + ocotea_early_serial_map(); + + /* Identify the system */ + printk("IBM Ocotea port (MontaVista Software, Inc. <source@mvista.com>)\n"); +} + +static void +ocotea_restart(char *cmd) +{ + local_irq_disable(); + abort(); +} + +static void +ocotea_power_off(void) +{ + local_irq_disable(); + for(;;); +} + +static void +ocotea_halt(void) +{ + local_irq_disable(); + for(;;); +} + +/* + * Read the 440GX memory controller to get size of system memory. + */ +static unsigned long __init +ocotea_find_end_of_memory(void) +{ + u32 i, bank_config; + u32 mem_size = 0; + + for (i=0; i<4; i++) + { + switch (i) + { + case 0: + mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B0CR); + break; + case 1: + mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B1CR); + break; + case 2: + mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B2CR); + break; + case 3: + mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B3CR); + break; + } + + bank_config = mfdcr(DCRN_SDRAM0_CFGDATA); + + if (!(bank_config & SDRAM_CONFIG_BANK_ENABLE)) + continue; + switch (SDRAM_CONFIG_BANK_SIZE(bank_config)) + { + case SDRAM_CONFIG_SIZE_8M: + mem_size += PPC44x_MEM_SIZE_8M; + break; + case SDRAM_CONFIG_SIZE_16M: + mem_size += PPC44x_MEM_SIZE_16M; + break; + case SDRAM_CONFIG_SIZE_32M: + mem_size += PPC44x_MEM_SIZE_32M; + break; + case SDRAM_CONFIG_SIZE_64M: + mem_size += PPC44x_MEM_SIZE_64M; + break; + case SDRAM_CONFIG_SIZE_128M: + mem_size += PPC44x_MEM_SIZE_128M; + break; + case SDRAM_CONFIG_SIZE_256M: + mem_size += PPC44x_MEM_SIZE_256M; + break; + case SDRAM_CONFIG_SIZE_512M: + mem_size += PPC44x_MEM_SIZE_512M; + break; + } + } + return mem_size; +} + +static void __init +ocotea_init_irq(void) +{ + int i; + + /* Enable PPC440GP interrupt compatibility mode */ + SDR_WRITE(DCRN_SDR_MFR,SDR_READ(DCRN_SDR_MFR) | DCRN_SDR_MFR_PCM); + + ppc4xx_pic_init(); + + for (i = 0; i < NR_IRQS; i++) + irq_desc[i].handler = ppc4xx_pic; +} + +#ifdef CONFIG_SERIAL_TEXT_DEBUG +#include <linux/serialP.h> +#include <linux/serial_reg.h> +#include <asm/serial.h> +struct serial_state rs_table[RS_TABLE_SIZE] = { + SERIAL_PORT_DFNS /* Defined in <asm/serial.h> */ +}; + +static void +ocotea_progress(char *s, unsigned short hex) +{ + volatile char c; + volatile unsigned long com_port; + u16 shift; + + com_port = (unsigned long)rs_table[0].iomem_base; + shift = rs_table[0].iomem_reg_shift; + + while ((c = *s++) != 0) { + while ((*((volatile unsigned char *)com_port + + (UART_LSR << shift)) & UART_LSR_THRE) == 0) + ; + *(volatile unsigned char *)com_port = c; + + } + + /* Send LF/CR to pretty up output */ + while ((*((volatile unsigned char *)com_port + + (UART_LSR << shift)) & UART_LSR_THRE) == 0) + ; + *(volatile unsigned char *)com_port = '\r'; + while ((*((volatile unsigned char *)com_port + + (UART_LSR << shift)) & UART_LSR_THRE) == 0) + ; + *(volatile unsigned char *)com_port = '\n'; +} +#endif /* CONFIG_SERIAL_TEXT_DEBUG */ + +#if 0 +static void __init +ocotea_map_io(void) +{ + io_block_mapping(0xe0000000, 0x0000000140000000, + 0x00001000, _PAGE_IO); +} +#endif + +void __init platform_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7) +{ + parse_bootinfo((struct bi_record *) (r3 + KERNELBASE)); + + ppc_md.setup_arch = ocotea_setup_arch; + ppc_md.show_cpuinfo = ocotea_show_cpuinfo; + ppc_md.init_IRQ = ocotea_init_irq; + ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ + + ppc_md.find_end_of_memory = ocotea_find_end_of_memory; + + ppc_md.restart = ocotea_restart; + ppc_md.power_off = ocotea_power_off; + ppc_md.halt = ocotea_halt; + + ppc_md.calibrate_decr = ocotea_calibrate_decr; + ppc_md.time_init = todc_time_init; + ppc_md.set_rtc_time = todc_set_rtc_time; + ppc_md.get_rtc_time = todc_get_rtc_time; + + ppc_md.nvram_read_val = todc_direct_read_val; + ppc_md.nvram_write_val = todc_direct_write_val; + +#ifdef CONFIG_SERIAL_TEXT_DEBUG + ppc_md.progress = ocotea_progress; +#endif /* CONFIG_SERIAL_TEXT_DEBUG */ +#ifdef CONFIG_KGDB + ppc_md.early_serial_map = ocotea_early_serial_map; +#endif +} diff --git a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h new file mode 100644 index 000000000000..2f2b5ab2f2b1 --- /dev/null +++ b/arch/ppc/platforms/4xx/ocotea.h @@ -0,0 +1,84 @@ +/* + * arch/ppc/platforms/ocotea.h + * + * Ocotea board definitions + * + * Matt Porter <mporter@mvista.com> + * + * Copyright 2003 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 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifdef __KERNEL__ +#ifndef __ASM_OCOTEA_H__ +#define __ASM_OCOTEA_H__ + +#include <linux/config.h> +#include <platforms/4xx/ibm440gx.h> + +/* F/W TLB mapping used in bootloader glue to reset EMAC */ +#define PPC44x_EMAC0_MR0 0xE0000800 + +/* Location of MAC addresses in firmware */ +#define OCOTEA_MAC_BASE (OCOTEA_SMALL_FLASH_HIGH+0xc0500) +#define OCOTEA_MAC_SIZE 0x200 +#define OCOTEA_MAC1_OFFSET 0x100 + +/* Default clock rate */ +#define OCOTEA_SYSCLK 25000000 + +/* RTC/NVRAM location */ +#define OCOTEA_RTC_ADDR 0x0000000148000000ULL +#define OCOTEA_RTC_SIZE 0x2000 + +/* Flash */ +#define OCOTEA_FPGA_ADDR 0x0000000148300000ULL +#define OCOTEA_BOOT_LARGE_FLASH(x) (x & 0x40) +#define OCOTEA_SMALL_FLASH_LOW 0x00000001ff900000ULL +#define OCOTEA_SMALL_FLASH_HIGH 0x00000001fff00000ULL +#define OCOTEA_SMALL_FLASH_SIZE 0x100000 +#define OCOTEA_LARGE_FLASH_LOW 0x00000001ff800000ULL +#define OCOTEA_LARGE_FLASH_HIGH 0x00000001ffc00000ULL +#define OCOTEA_LARGE_FLASH_SIZE 0x400000 + +/* + * Serial port defines + */ +#define RS_TABLE_SIZE 2 + +/* OpenBIOS defined UART mappings, used before early_serial_setup */ +#define UART0_IO_BASE (u8 *) 0xE0000200 +#define UART1_IO_BASE (u8 *) 0xE0000300 + +#define BASE_BAUD 11059200/16 +#define STD_UART_OP(num) \ + { 0, BASE_BAUD, 0, UART##num##_IRQ, \ + (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ + iomem_base: UART##num##_IO_BASE, \ + io_type: SERIAL_IO_MEM}, + +#define SERIAL_PORT_DFNS \ + STD_UART_OP(0) \ + STD_UART_OP(1) + +/* PCI support */ +#define OCOTEA_PCI_LOWER_IO 0x00000000 +#define OCOTEA_PCI_UPPER_IO 0x0000ffff +#define OCOTEA_PCI_LOWER_MEM 0x80000000 +#define OCOTEA_PCI_UPPER_MEM 0xffffefff + +#define OCOTEA_PCI_CFGREGS_BASE 0x000000020ec00000ULL +#define OCOTEA_PCI_CFGA_PLB32 0x0ec00000 +#define OCOTEA_PCI_CFGD_PLB32 0x0ec00004 + +#define OCOTEA_PCI_IO_BASE 0x0000000208000000ULL +#define OCOTEA_PCI_IO_SIZE 0x00010000 +#define OCOTEA_PCI_MEM_OFFSET 0x00000000 + +#endif /* __ASM_OCOTEA_H__ */ +#endif /* __KERNEL__ */ diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index c4621a145929..59dd330444bc 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -13,6 +13,8 @@ CFLAGS_prom_init.o += -mrelocatable-lib CFLAGS_btext.o += -mrelocatable-lib obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o +obj-$(CONFIG_44x) += ibm44x_common.o +obj-$(CONFIG_440GP) += ibm440gp_common.o ifeq ($(CONFIG_4xx),y) obj-$(CONFIG_4xx) += ppc4xx_pic.o obj-$(CONFIG_40x) += ppc4xx_setup.o @@ -33,6 +35,7 @@ obj-$(CONFIG_PPC_CHRP) += open_pic.o indirect_pci.o i8259.o obj-$(CONFIG_PPC_PREP) += open_pic.o indirect_pci.o i8259.o obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \ todc_time.o +obj-$(CONFIG_EBONY) += indirect_pci.o pci_auto.o todc_time.o obj-$(CONFIG_EV64260) += gt64260_common.o gt64260_pic.o \ indirect_pci.o todc_time.o pci_auto.o obj-$(CONFIG_GEMINI) += open_pic.o i8259.o indirect_pci.o @@ -46,6 +49,7 @@ obj-$(CONFIG_MENF1) += todc_time.o i8259.o mpc10x_common.o \ pci_auto.o indirect_pci.o obj-$(CONFIG_MVME5100) += open_pic.o todc_time.o indirect_pci.o \ i8259.o pci_auto.o pplus_common.o +obj-$(CONFIG_OCOTEA) += indirect_pci.o pci_auto.o todc_time.o obj-$(CONFIG_PAL4) += cpc700_pic.o obj-$(CONFIG_PCORE) += mpc10x_common.o todc_time.o i8259.o \ indirect_pci.o pci_auto.o diff --git a/arch/ppc/syslib/ibm440gp_common.c b/arch/ppc/syslib/ibm440gp_common.c new file mode 100644 index 000000000000..cc1382db846b --- /dev/null +++ b/arch/ppc/syslib/ibm440gp_common.c @@ -0,0 +1,77 @@ +/* + * arch/ppc/syslib/ibm440gp_common.c + * + * PPC440GP system library + * + * Matt Porter <mporter@mvista.com> + * Copyright 2002-2003 MontaVista Software Inc. + * + * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> + * Copyright (c) 2003 Zultys Technologies + * + * 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 <linux/config.h> +#include <linux/types.h> +#include <asm/ibm44x.h> +#include <asm/mmu.h> + +/* + * Calculate 440GP clocks + */ +void __init ibm440gp_get_clocks(struct ibm440gp_clocks* p, + unsigned int sys_clk, + unsigned int ser_clk) +{ + u32 cpc0_sys0 = mfdcr(DCRN_CPC0_SYS0); + u32 cpc0_cr0 = mfdcr(DCRN_CPC0_CR0); + u32 opdv, epdv; + + if (cpc0_sys0 & 0x2){ + /* Bypass system PLL */ + p->cpu = p->plb = sys_clk; + } + else { + u32 fbdv, fwdva, fwdvb, m, vco; + + fbdv = (cpc0_sys0 >> 18) & 0x0f; + if (!fbdv) + fbdv = 16; + + fwdva = 8 - ((cpc0_sys0 >> 15) & 0x7); + fwdvb = 8 - ((cpc0_sys0 >> 12) & 0x7); + + /* Feedback path */ + if (cpc0_sys0 & 0x00000080){ + /* PerClk */ + m = fwdvb * opdv * epdv; + } + else { + /* CPU clock */ + m = fbdv * fwdva; + } + vco = sys_clk * m; + p->cpu = vco / fwdva; + p->plb = vco / fwdvb; + } + + opdv = ((cpc0_sys0 >> 10) & 0x3) + 1; + epdv = ((cpc0_sys0 >> 8) & 0x3) + 1; + + p->opb = p->plb / opdv; + p->ebc = p->opb / epdv; + + if (cpc0_cr0 & 0x00400000){ + /* External UART clock */ + p->uart = ser_clk; + } + else { + /* Internal UART clock */ + u32 uart_div = ((cpc0_cr0 >> 16) & 0x1f) + 1; + p->uart = p->plb / uart_div; + } +} diff --git a/arch/ppc/syslib/ibm440gp_common.h b/arch/ppc/syslib/ibm440gp_common.h new file mode 100644 index 000000000000..63dbd4a9c434 --- /dev/null +++ b/arch/ppc/syslib/ibm440gp_common.h @@ -0,0 +1,45 @@ +/* + * arch/ppc/syslib/ibm440gp_common.h + * + * PPC440GP system library + * + * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> + * Copyright (c) 2003 Zultys Technologies + * + * 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. + * + */ +#ifdef __KERNEL__ +#ifndef __PPC_SYSLIB_IBM440GP_COMMON_H +#define __PPC_SYSLIB_IBM440GP_COMMON_H + +#ifndef __ASSEMBLY__ + +#include <linux/config.h> +#include <linux/init.h> + +/* + * All clocks are in Hz + */ +struct ibm440gp_clocks { + unsigned int cpu; /* CPUCoreClk */ + unsigned int plb; /* PLBClk */ + unsigned int opb; /* OPBClk */ + unsigned int ebc; /* PerClk */ + unsigned int uart; +}; + +/* + * Please, refer to the Figure 13.1 in 440GP user manual + * + * if internal UART clock is used, ser_clk is ignored + */ +void ibm440gp_get_clocks(struct ibm440gp_clocks*, unsigned int sys_clk, + unsigned int ser_clk) __init; + +#endif /* __ASSEMBLY__ */ +#endif /* __PPC_SYSLIB_IBM440GP_COMMON_H */ +#endif /* __KERNEL__ */ diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c new file mode 100644 index 000000000000..a0cefdc7c1da --- /dev/null +++ b/arch/ppc/syslib/ibm44x_common.c @@ -0,0 +1,37 @@ +/* + * arch/ppc/syslib/ibm44x_common.c + * + * PPC44x system library + * + * Matt Porter <mporter@mvista.com> + * Copyright 2002-2003 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 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include <linux/config.h> +#include <linux/types.h> +#include <asm/ibm44x.h> +#include <asm/mmu.h> + +phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size) +{ + phys_addr_t page_4gb = 0; + + /* + * Trap the least significant 32-bit portions of an + * address in the 440's 36-bit address space. Fix + * them up with the appropriate ERPN + */ + if ((addr >= PPC44x_IO_LO) && (addr < PPC44x_IO_HI)) + page_4gb = PPC44x_IO_PAGE; + else if ((addr >= PPC44x_PCICFG_LO) && (addr < PPC44x_PCICFG_HI)) + page_4gb = PPC44x_PCICFG_PAGE; + else if ((addr >= PPC44x_PCIMEM_LO) && (addr < PPC44x_PCIMEM_HI)) + page_4gb = PPC44x_PCIMEM_PAGE; + + return (page_4gb | addr); +}; diff --git a/arch/sparc64/kernel/semaphore.c b/arch/sparc64/kernel/semaphore.c index 4ce2f9369019..a9e66d666ceb 100644 --- a/arch/sparc64/kernel/semaphore.c +++ b/arch/sparc64/kernel/semaphore.c @@ -110,6 +110,7 @@ static void __down(struct semaphore * sem) void down(struct semaphore *sem) { + might_sleep(); /* This atomically does: * old_val = sem->count; * new_val = sem->count - 1; @@ -219,6 +220,7 @@ int down_interruptible(struct semaphore *sem) { int ret = 0; + might_sleep(); /* This atomically does: * old_val = sem->count; * new_val = sem->count - 1; diff --git a/crypto/Makefile b/crypto/Makefile index f3325db1ee76..8326b4fb5be4 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -2,11 +2,10 @@ # Cryptographic API # -autoload-crypto-$(CONFIG_KMOD) = autoload.o proc-crypto-$(CONFIG_PROC_FS) = proc.o obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o \ - $(autoload-crypto-y) $(proc-crypto-y) + $(proc-crypto-y) obj-$(CONFIG_CRYPTO_HMAC) += hmac.o obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o diff --git a/crypto/autoload.c b/crypto/autoload.c deleted file mode 100644 index 7cda40b39ddf..000000000000 --- a/crypto/autoload.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Cryptographic API. - * - * Algorithm autoloader. - * - * Copyright (c) 2002 James Morris <jmorris@intercode.com.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 <linux/kernel.h> -#include <linux/crypto.h> -#include <linux/string.h> -#include <linux/kmod.h> -#include "internal.h" - -/* - * A far more intelligent version of this is planned. For now, just - * try an exact match on the name of the algorithm. - */ -void crypto_alg_autoload(const char *name) -{ - request_module("%s", name); -} - -struct crypto_alg *crypto_alg_mod_lookup(const char *name) -{ - struct crypto_alg *alg = crypto_alg_lookup(name); - if (alg == NULL) { - crypto_alg_autoload(name); - alg = crypto_alg_lookup(name); - } - return alg; -} diff --git a/crypto/internal.h b/crypto/internal.h index 10880d149afe..8ba30b772ee3 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -15,6 +15,7 @@ #include <linux/highmem.h> #include <linux/interrupt.h> #include <linux/init.h> +#include <linux/kmod.h> #include <asm/hardirq.h> #include <asm/kmap_types.h> @@ -48,15 +49,12 @@ static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) struct crypto_alg *crypto_alg_lookup(const char *name); -#ifdef CONFIG_KMOD -void crypto_alg_autoload(const char *name); -struct crypto_alg *crypto_alg_mod_lookup(const char *name); -#else +/* A far more intelligent version of this is planned. For now, just + * try an exact match on the name of the algorithm. */ static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name) { - return crypto_alg_lookup(name); + return try_then_request_module(crypto_alg_lookup(name), name); } -#endif #ifdef CONFIG_CRYPTO_HMAC int crypto_alloc_hmac_block(struct crypto_tfm *tfm); diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index a66c2f086e25..338f48c1228f 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -15,7 +15,6 @@ */ #include <linux/init.h> #include <linux/module.h> -#include <linux/string.h> #include <linux/mm.h> #include <linux/slab.h> #include <asm/scatterlist.h> diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 1247846c538f..2fdb6f766e44 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -15,12 +15,6 @@ * * Things not working yet: * - * o We're only set up to compile as a module currently. i.e. - * you should put the source in drivers/atm/lanai.c and then - * just do "make drivers/atm/lanai.o" from the main - * source directory. This will produce a drivers/atm/lanai.o - * file suitable for insmod'ing - * * o We don't support the Speedstream 3060 yet - this card has * an on-board DSL modem chip by Alcatel and the driver will * need some extra code added to handle it @@ -245,9 +239,6 @@ struct lanai_vcc { struct atm_vcc *atmvcc; /* atm_vcc who is transmitter */ int endptr; /* last endptr from service entry */ struct sk_buff_head backlog; - struct sk_buff *inprogress; /* We're streaming this PDU */ - unsigned char *pptr; /* Where we are in above */ - int inprogleft; /* Bytes left to send "inprogress" */ void (*unqueue)(struct lanai_dev *, struct lanai_vcc *, int); } tx; }; @@ -268,8 +259,6 @@ struct lanai_dev_stats { unsigned pcierr_m_target_abort; unsigned pcierr_s_target_abort; unsigned pcierr_master_parity; - unsigned service_novcc_rx; - unsigned service_novcc_tx; unsigned service_notx; unsigned service_norx; unsigned service_rxnotaal5; @@ -297,7 +286,7 @@ struct lanai_dev { struct lanai_buffer aal0buf; /* AAL0 RX buffers */ u32 conf1, conf2; /* CONFIG[12] registers */ u32 status; /* STATUS register */ - spinlock_t txlock; + spinlock_t endtxlock; spinlock_t servicelock; struct atm_vcc *cbrvcc; int number; @@ -501,7 +490,6 @@ static inline void reg_write(const struct lanai_dev *lanai, u32 val, RWDEBUG("W [0x%08X] 0x%02X < 0x%08X\n", (unsigned int) lanai->base, (int) reg, val); writel(val, reg_addr(lanai, reg)); - mdelay(1); } static inline void conf1_write(const struct lanai_dev *lanai) @@ -537,63 +525,6 @@ static inline void reset_board(const struct lanai_dev *lanai) udelay(5); } -/* -------------------- VCC LIST LOCK: */ - -/* - * The linux-atm code disables local IRQs while managing the list of - * VCCs on a card. This is good, but it doesn't save us against - * SMP. Unfortunately, fixing this will require changes in the - * API which will have to wait a little bit. It's a hard race to - * trigger accidentally, so it isn't TOO horrible so far. - * - * One possible solution would be to have an rwlock which is - * always grabbed _irq-style on writing. This would automatically - * be grabbed (for writing) by the higher layers on things that - * would result in a change in the vcc list (_open, _close, - * probably _change_qos) - thus it would also protect the - * higher-level list of vccs on each device (atm_dev->vccs). - * The driver would be responsible for grabbing it as a read_lock - * anytime it wants to consult its table of vccs - for instance - * when handling an incoming PDU. This also explains why we would - * probably want the write_lock while in _change_qos - to prevent - * handling of PDUs while possibly in an inconsistent state. - * Also, _send would grab the lock for reading. - * - * One problem with this is that _open and _close could no longer - * do anything that might provoke a schedule. First, it would - * force us to use GFP_ATOMIC memory (which is bad), but also - * some devices pretty much require scheduling due to long - * delays (see lanai_close for an example). So in this case - * we need a way to schedule without losing the spinlock. - * The cleanest way to do this is probably have a way to mark a - * VCC as "in progress" so that the interrupt handler can - * still disregard any traffic for it while _open or _close - * are sleeping on it. Then it will need to be _open and - * _close's job to relinquish the write_lock. Thus, the - * lock could be dropped around the times that scheduling - * might occur. Perhaps the _READY flag can be used for - * this purpose. - * - * One short note about this "upper layer grabs, driver - * relinquishes" write lock - since this needs to be - * an _irq lock we're going to have problem saving - * and restoring flags (_irqsave/_irqrestore). This - * shouldn't be a problem, however - we must just - * require that those syscalls are never called with - * interrupts disabled so we can use the non-flags-saving - * versions. - * - * Anyway, all of the above is vaporware currently - fixing - * this right will require changes in the API and all of - * the drivers - this will wait until 2.5.x most likely. - * The following NOP macros are just here to mark where - * the locks will be needed in the future. - */ -#define vcclist_read_lock() do {} while (0) -#define vcclist_read_unlock() do {} while (0) -#define vcclist_write_lock() do {} while (0) -#define vcclist_write_unlock() do {} while (0) - /* -------------------- CARD SRAM UTILITIES: */ /* The SRAM is mapped into normal PCI memory space - the only catch is @@ -851,36 +782,39 @@ static void lanai_shutdown_tx_vci(struct lanai_dev *lanai, if (lvcc->vbase == 0) /* We were never bound to a VCI */ return; /* 15.2.1 - wait for queue to drain */ - spin_lock_irqsave(&lanai->txlock, flags); - if (lvcc->tx.inprogress != NULL) { - lanai_free_skb(lvcc->tx.atmvcc, lvcc->tx.inprogress); - lvcc->tx.inprogress = NULL; - } while ((skb = skb_dequeue(&lvcc->tx.backlog)) != NULL) lanai_free_skb(lvcc->tx.atmvcc, skb); + read_lock_irqsave(&vcc_sklist_lock, flags); __clear_bit(lvcc->vci, lanai->backlog_vccs); - spin_unlock_irqrestore(&lanai->txlock, flags); - timeout = jiffies + ((lanai_buf_size(&lvcc->tx.buf) * HZ) >> 17); + read_unlock_irqrestore(&vcc_sklist_lock, flags); + /* + * We need to wait for the VCC to drain but don't wait forever. We + * give each 1K of buffer size 1/128th of a second to clear out. + * TODO: maybe disable CBR if we're about to timeout? + */ + timeout = jiffies + + (((lanai_buf_size(&lvcc->tx.buf) / 1024) * HZ) >> 7); write = TXWRITEPTR_GET_PTR(cardvcc_read(lvcc, vcc_txwriteptr)); - goto start; - while (time_before_eq(jiffies, timeout)) { - schedule_timeout(HZ / 25); - start: + for (;;) { read = TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr)); if (read == write && /* Is TX buffer empty? */ (lvcc->tx.atmvcc->qos.txtp.traffic_class != ATM_CBR || (cardvcc_read(lvcc, vcc_txcbr_next) & TXCBR_NEXT_BOZO) == 0)) - goto done; + break; if (read != lastread) { /* Has there been any progress? */ lastread = read; timeout += HZ / 10; } + if (unlikely(time_after(jiffies, timeout))) { + printk(KERN_ERR DEV_LABEL "(itf %d): Timed out on " + "backlog closing vci %d\n", + lvcc->tx.atmvcc->dev->number, lvcc->vci); + DPRINTK("read, write = %d, %d\n", read, write); + break; + } + schedule_timeout(HZ / 25); } - printk(KERN_ERR DEV_LABEL "(itf %d): Timed out on backlog closing " - "vci %d\n", lvcc->tx.atmvcc->dev->number, lvcc->vci); - DPRINTK("read, write = %d, %d\n", read, write); - done: /* 15.2.2 - clear out all tx registers */ cardvcc_write(lvcc, 0, vcc_txreadptr); cardvcc_write(lvcc, 0, vcc_txwriteptr); @@ -1226,8 +1160,7 @@ static inline int vcc_tx_space(const struct lanai_vcc *lvcc, int endptr) /* test if VCC is currently backlogged */ static inline int vcc_is_backlogged(/*const*/ struct lanai_vcc *lvcc) { - return lvcc->tx.inprogress != NULL || - !skb_queue_empty(&lvcc->tx.backlog); + return !skb_queue_empty(&lvcc->tx.backlog); } /* Bit fields in the segmentation buffer descriptor */ @@ -1264,11 +1197,11 @@ static inline void vcc_tx_add_aal5_descriptor(struct lanai_vcc *lvcc, } /* Add 32-bit AAL5 trailer and leave room for its CRC */ -static inline void vcc_tx_add_aal5trailer(struct lanai_vcc *lvcc, +static inline void vcc_tx_add_aal5_trailer(struct lanai_vcc *lvcc, int len, int cpi, int uu) { APRINTK((((unsigned long) lvcc->tx.buf.ptr) & 15) == 8, - "vcc_tx_add_aal5_descriptor: bad ptr=%p\n", lvcc->tx.buf.ptr); + "vcc_tx_add_aal5_trailer: bad ptr=%p\n", lvcc->tx.buf.ptr); lvcc->tx.buf.ptr += 2; lvcc->tx.buf.ptr[-2] = cpu_to_be32((uu << 24) | (cpi << 16) | len); if (lvcc->tx.buf.ptr >= lvcc->tx.buf.end) @@ -1311,7 +1244,7 @@ static inline void vcc_tx_memzero(struct lanai_vcc *lvcc, int n) } /* Update "butt" register to specify new WritePtr */ -static inline void lanai_endtx(const struct lanai_dev *lanai, +static inline void lanai_endtx(struct lanai_dev *lanai, const struct lanai_vcc *lvcc) { int i, ptr = ((unsigned char *) lvcc->tx.buf.ptr) - @@ -1320,6 +1253,14 @@ static inline void lanai_endtx(const struct lanai_dev *lanai, "lanai_endtx: bad ptr (%d), vci=%d, start,ptr,end=%p,%p,%p\n", ptr, lvcc->vci, lvcc->tx.buf.start, lvcc->tx.buf.ptr, lvcc->tx.buf.end); + + /* + * Since the "butt register" is a shared resounce on the card we + * serialize all accesses to it through this spinlock. This is + * mostly just paranoia sicne the register is rarely "busy" anyway + * but is needed for correctness. + */ + spin_lock(&lanai->endtxlock); /* * We need to check if the "butt busy" bit is set before * updating the butt register. In theory this should @@ -1334,131 +1275,86 @@ static inline void lanai_endtx(const struct lanai_dev *lanai, } udelay(5); } + /* + * Before we tall the card to start work we need to be sure 100% of + * the info in the service buffer has been written before we tell + * the card about it + */ + wmb(); reg_write(lanai, (ptr << 12) | lvcc->vci, Butt_Reg); + spin_unlock(&lanai->endtxlock); +} + +/* + * Add one AAL5 PDU to lvcc's transmit buffer. Caller garauntees there's + * space available. "pdusize" is the number of bytes the PDU will take + */ +static void lanai_send_one_aal5(struct lanai_dev *lanai, + struct lanai_vcc *lvcc, struct sk_buff *skb, int pdusize) +{ + int pad; + APRINTK(pdusize == aal5_size(skb->len), + "lanai_send_one_aal5: wrong size packet (%d != %d)\n", + pdusize, aal5_size(skb->len)); + vcc_tx_add_aal5_descriptor(lvcc, 0, pdusize); + pad = pdusize - skb->len - 8; + APRINTK(pad >= 0, "pad is negative (%d)\n", pad); + APRINTK(pad < 48, "pad is too big (%d)\n", pad); + vcc_tx_memcpy(lvcc, skb->data, skb->len); + vcc_tx_memzero(lvcc, pad); + vcc_tx_add_aal5_trailer(lvcc, skb->len, 0, 0); + lanai_endtx(lanai, lvcc); + lanai_free_skb(lvcc->tx.atmvcc, skb); + atomic_inc(&lvcc->tx.atmvcc->stats->tx); } /* Try to fill the buffer - don't call unless there is backlog */ static void vcc_tx_unqueue_aal5(struct lanai_dev *lanai, struct lanai_vcc *lvcc, int endptr) { - int pad, n; + int n; struct sk_buff *skb; int space = vcc_tx_space(lvcc, endptr); APRINTK(vcc_is_backlogged(lvcc), "vcc_tx_unqueue() called with empty backlog (vci=%d)\n", lvcc->vci); - if (space < 64) - return; /* No space for even 1 cell+descriptor */ - if (lvcc->tx.inprogress != NULL) { - APRINTK((lvcc->tx.inprogleft % 48) == 0, - "vcc_tx_unqueue_aal5: bad progleft=%d\n", - lvcc->tx.inprogleft); - if (lvcc->tx.inprogleft + 16 > space) { /* Can't send all? */ - n = aal5_spacefor(space - 16); /* Bytes to send */ - vcc_tx_add_aal5_descriptor(lvcc, - DESCRIPTOR_AAL5_STREAM, n); - pad = lvcc->tx.pptr + n - lvcc->tx.inprogress->tail; - if (pad < 0) - pad = 0; - vcc_tx_memcpy(lvcc, lvcc->tx.pptr, n - pad); - vcc_tx_memzero(lvcc, pad); - lvcc->tx.pptr += n; - lvcc->tx.inprogleft -= n; - goto end; /* Buffer is now full */ - } - /* OK, there's at least space for all of "inprogress" skb */ - vcc_tx_add_aal5_descriptor(lvcc, 0, - lvcc->tx.inprogleft); - pad = lvcc->tx.pptr + lvcc->tx.inprogleft - - lvcc->tx.inprogress->tail; - if (pad >= lvcc->tx.inprogleft) { /* Nothing but pad left */ - APRINTK(lvcc->tx.inprogleft == 48, - "vcc_tx_unqueue_aal5: bad pure-pad=%d\n", - lvcc->tx.inprogleft); - pad = 48; - } else - vcc_tx_memcpy(lvcc, lvcc->tx.pptr, - lvcc->tx.inprogleft - pad); - vcc_tx_memzero(lvcc, pad - 8); - vcc_tx_add_aal5trailer(lvcc, lvcc->tx.inprogress->len, 0, 0); - lanai_free_skb(lvcc->tx.atmvcc, lvcc->tx.inprogress); - lvcc->tx.inprogress = NULL; - space -= lvcc->tx.inprogleft + 16; - atomic_inc(&lvcc->tx.atmvcc->stats->tx); - } while (space >= 64) { - if ((skb = skb_dequeue(&lvcc->tx.backlog)) == NULL) - break; + skb = skb_dequeue(&lvcc->tx.backlog); + if (skb == NULL) + goto no_backlog; n = aal5_size(skb->len); - if (n + 16 > space) { /* Can only send part */ - int m = aal5_spacefor(space - 16); /* Bytes to send */ - vcc_tx_add_aal5_descriptor(lvcc, - DESCRIPTOR_AAL5_STREAM, m); - lvcc->tx.pptr = skb->data + m; - pad = lvcc->tx.pptr - skb->tail; - if (pad < 0) - pad = 0; - vcc_tx_memcpy(lvcc, skb->data, m - pad); - vcc_tx_memzero(lvcc, pad); - lvcc->tx.inprogleft = n - m; - lvcc->tx.inprogress = skb; - goto end; + if (n + 16 > space) { + /* No room for this packet - put it back on queue */ + skb_queue_head(&lvcc->tx.backlog, skb); + return; } - vcc_tx_add_aal5_descriptor(lvcc, 0, n); - pad = n - skb->len - 8; - vcc_tx_memcpy(lvcc, skb->data, skb->len); - vcc_tx_memzero(lvcc, pad); - lanai_free_skb(lvcc->tx.atmvcc, skb); - vcc_tx_add_aal5trailer(lvcc, skb->len, 0, 0); + lanai_send_one_aal5(lanai, lvcc, skb, n); space -= n + 16; - atomic_inc(&lvcc->tx.atmvcc->stats->tx); } - if (skb_queue_empty(&lvcc->tx.backlog)) + if (!vcc_is_backlogged(lvcc)) { + no_backlog: __clear_bit(lvcc->vci, lanai->backlog_vccs); - end: - lanai_endtx(lanai, lvcc); + } } /* Given an skb that we want to transmit either send it now or queue */ static void vcc_tx_aal5(struct lanai_dev *lanai, struct lanai_vcc *lvcc, struct sk_buff *skb) { - int space, n, pad; + int space, n; if (vcc_is_backlogged(lvcc)) /* Already backlogged */ goto queue_it; - space = vcc_tx_space(lvcc, TXREADPTR_GET_PTR(cardvcc_read(lvcc, - vcc_txreadptr))); - if (space < 64) { /* No space at all */ - __set_bit(lvcc->vci, lanai->backlog_vccs); - goto queue_it; - } - if (space >= 16 + (n = aal5_size(skb->len))) { - /* We can send the whole thing now */ - vcc_tx_add_aal5_descriptor(lvcc, 0, n); - pad = n - skb->len; - vcc_tx_memcpy(lvcc, skb->data, skb->len); - vcc_tx_memzero(lvcc, pad - 8); - vcc_tx_add_aal5trailer(lvcc, skb->len, 0, 0); - lanai_free_skb(lvcc->tx.atmvcc, skb); - atomic_inc(&lvcc->tx.atmvcc->stats->tx); - } else { /* Space for only part of skb */ - int bytes = aal5_spacefor(space - 16); /* Bytes to send */ - vcc_tx_add_aal5_descriptor(lvcc, - DESCRIPTOR_AAL5_STREAM, bytes); - pad = bytes - skb->len; - if (pad < 0) - pad = 0; - vcc_tx_memcpy(lvcc, skb->data, bytes - pad); - vcc_tx_memzero(lvcc, pad); - lvcc->tx.inprogress = skb; - lvcc->tx.inprogleft = n - bytes; - lvcc->tx.pptr = skb->data + bytes; + space = vcc_tx_space(lvcc, + TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr))); + n = aal5_size(skb->len); + APRINTK(n + 16 >= 64, "vcc_tx_aal5: n too small (%d)\n", n); + if (space < n + 16) { /* No space for this PDU */ __set_bit(lvcc->vci, lanai->backlog_vccs); + queue_it: + skb_queue_tail(&lvcc->tx.backlog, skb); + return; } - lanai_endtx(lanai, lvcc); - return; - queue_it: - skb_queue_tail(&lvcc->tx.backlog, skb); + lanai_send_one_aal5(lanai, lvcc, skb, n); } static void vcc_tx_unqueue_aal0(struct lanai_dev *lanai, @@ -1476,28 +1372,6 @@ static void vcc_tx_aal0(struct lanai_dev *lanai, struct lanai_vcc *lvcc, lanai_free_skb(lvcc->tx.atmvcc, skb); } -/* Try to undequeue 1 backlogged vcc */ -static void iter_dequeue(struct lanai_dev *lanai, vci_t vci) -{ - struct lanai_vcc *lvcc = lanai->vccs[vci]; - int endptr; - if (lvcc == NULL || !vcc_is_backlogged(lvcc)) { - __clear_bit(vci, lanai->backlog_vccs); - return; - } - endptr = TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr)); - lvcc->tx.unqueue(lanai, lvcc, endptr); -} - -/* Try a dequeue on all backlogged connections */ -static inline void vcc_tx_dequeue_all(struct lanai_dev *lanai) -{ - unsigned long flags; - spin_lock_irqsave(&lanai->txlock, flags); - vci_bitfield_iterate(lanai, lanai->backlog_vccs, iter_dequeue); - spin_unlock_irqrestore(&lanai->txlock, flags); -} - /* -------------------- VCC RX BUFFER UTILITIES: */ /* unlike the _tx_ cousins, this doesn't update ptr */ @@ -1510,6 +1384,8 @@ static inline void vcc_rx_memcpy(unsigned char *dest, m = 0; memcpy(dest, lvcc->rx.buf.ptr, n - m); memcpy(dest + n - m, lvcc->rx.buf.start, m); + /* Make sure that these copies don't get reordered */ + barrier(); } /* Receive AAL5 data on a VCC with a particular endptr */ @@ -1527,6 +1403,11 @@ static void vcc_rx_aal5(struct lanai_vcc *lvcc, int endptr) /* Recover the second-to-last word to get true pdu length */ if ((x = &end[-2]) < lvcc->rx.buf.start) x = &lvcc->rx.buf.end[-2]; + /* + * Before we actually read from the buffer, make sure the memory + * changes have arrived + */ + rmb(); size = be32_to_cpup(x) & 0xffff; if (unlikely(n != aal5_size(size))) { /* Make sure size matches padding */ @@ -1542,9 +1423,9 @@ static void vcc_rx_aal5(struct lanai_vcc *lvcc, int endptr) goto out; } skb_put(skb, size); + vcc_rx_memcpy(skb->data, lvcc, size); ATM_SKB(skb)->vcc = lvcc->rx.atmvcc; do_gettimeofday(&skb->stamp); - vcc_rx_memcpy(skb->data, lvcc, size); lvcc->rx.atmvcc->push(lvcc->rx.atmvcc, skb); atomic_inc(&lvcc->rx.atmvcc->stats->rx); out: @@ -1555,7 +1436,7 @@ static void vcc_rx_aal5(struct lanai_vcc *lvcc, int endptr) static void vcc_rx_aal0(struct lanai_dev *lanai) { printk(KERN_INFO DEV_LABEL ": vcc_rx_aal0: not implemented\n"); - /* Remember to get vcclist_read_lock while looking up VC */ + /* Remember to get read_lock(&vcc_sklist_lock) while looking up VC */ /* Remember to increment lvcc->rx.atmvcc->stats->rx */ } @@ -1606,7 +1487,6 @@ static inline struct lanai_vcc *new_lanai_vcc(void) memset(&lvcc->stats, 0, sizeof lvcc->stats); lvcc->rx.buf.start = lvcc->tx.buf.start = NULL; skb_queue_head_init(&lvcc->tx.backlog); - lvcc->tx.inprogress = NULL; #ifdef DEBUG lvcc->tx.unqueue = NULL; lvcc->vci = -1; @@ -1617,14 +1497,14 @@ static inline struct lanai_vcc *new_lanai_vcc(void) static int lanai_get_sized_buffer(struct lanai_dev *lanai, struct lanai_buffer *buf, int max_sdu, int multiplier, - int min, const char *name) + const char *name) { int size; if (unlikely(max_sdu < 1)) max_sdu = 1; max_sdu = aal5_size(max_sdu); size = (max_sdu + 16) * multiplier + 16; - lanai_buf_allocate(buf, size, min, lanai->pci); + lanai_buf_allocate(buf, size, max_sdu + 32, lanai->pci); if (unlikely(buf->start == NULL)) return -ENOMEM; if (unlikely(lanai_buf_size(buf) < size)) @@ -1640,8 +1520,7 @@ static inline int lanai_setup_rx_vci_aal5(struct lanai_dev *lanai, struct lanai_vcc *lvcc, const struct atm_qos *qos) { return lanai_get_sized_buffer(lanai, &lvcc->rx.buf, - qos->rxtp.max_sdu, AAL5_RX_MULTIPLIER, qos->rxtp.max_sdu + 32, - "RX"); + qos->rxtp.max_sdu, AAL5_RX_MULTIPLIER, "RX"); } /* Setup a TX buffer for a currently unbound AAL5 vci */ @@ -1659,7 +1538,7 @@ static int lanai_setup_tx_vci(struct lanai_dev *lanai, struct lanai_vcc *lvcc, multiplier = AAL5_TX_MULTIPLIER; } return lanai_get_sized_buffer(lanai, &lvcc->tx.buf, max_sdu, - multiplier, 80, "TX"); + multiplier, "TX"); } static inline void host_vcc_bind(struct lanai_dev *lanai, @@ -1759,21 +1638,21 @@ static int handle_service(struct lanai_dev *lanai, u32 s) { vci_t vci = SERVICE_GET_VCI(s); struct lanai_vcc *lvcc; - vcclist_read_lock(); + read_lock(&vcc_sklist_lock); lvcc = lanai->vccs[vci]; if (unlikely(lvcc == NULL)) { - vcclist_read_unlock(); + read_unlock(&vcc_sklist_lock); DPRINTK("(itf %d) got service entry 0x%X for nonexistent " "vcc %d\n", lanai->number, (unsigned int) s, vci); if (s & SERVICE_TX) - lanai->stats.service_novcc_tx++; + lanai->stats.service_notx++; else - lanai->stats.service_novcc_rx++; + lanai->stats.service_norx++; return 0; } if (s & SERVICE_TX) { /* segmentation interrupt */ if (unlikely(lvcc->tx.atmvcc == NULL)) { - vcclist_read_unlock(); + read_unlock(&vcc_sklist_lock); DPRINTK("(itf %d) got service entry 0x%X for non-TX " "vcc %d\n", lanai->number, (unsigned int) s, vci); lanai->stats.service_notx++; @@ -1781,18 +1660,18 @@ static int handle_service(struct lanai_dev *lanai, u32 s) } __set_bit(vci, lanai->transmit_ready); lvcc->tx.endptr = SERVICE_GET_END(s); - vcclist_read_unlock(); + read_unlock(&vcc_sklist_lock); return 1; } if (unlikely(lvcc->rx.atmvcc == NULL)) { - vcclist_read_unlock(); + read_unlock(&vcc_sklist_lock); DPRINTK("(itf %d) got service entry 0x%X for non-RX " "vcc %d\n", lanai->number, (unsigned int) s, vci); lanai->stats.service_norx++; return 0; } if (unlikely(lvcc->rx.atmvcc->qos.aal != ATM_AAL5)) { - vcclist_read_unlock(); + read_unlock(&vcc_sklist_lock); DPRINTK("(itf %d) got RX service entry 0x%X for non-AAL5 " "vcc %d\n", lanai->number, (unsigned int) s, vci); lanai->stats.service_rxnotaal5++; @@ -1801,12 +1680,12 @@ static int handle_service(struct lanai_dev *lanai, u32 s) } if (likely(!(s & (SERVICE_TRASH | SERVICE_STREAM | SERVICE_CRCERR)))) { vcc_rx_aal5(lvcc, SERVICE_GET_END(s)); - vcclist_read_unlock(); + read_unlock(&vcc_sklist_lock); return 0; } if (s & SERVICE_TRASH) { int bytes; - vcclist_read_unlock(); + read_unlock(&vcc_sklist_lock); DPRINTK("got trashed rx pdu on vci %d\n", vci); atomic_inc(&lvcc->rx.atmvcc->stats->rx_err); lvcc->stats.x.aal5.service_trash++; @@ -1819,7 +1698,7 @@ static int handle_service(struct lanai_dev *lanai, u32 s) return 0; } if (s & SERVICE_STREAM) { - vcclist_read_unlock(); + read_unlock(&vcc_sklist_lock); atomic_inc(&lvcc->rx.atmvcc->stats->rx_err); lvcc->stats.x.aal5.service_stream++; printk(KERN_ERR DEV_LABEL "(itf %d): Got AAL5 stream " @@ -1832,7 +1711,7 @@ static int handle_service(struct lanai_dev *lanai, u32 s) lvcc->stats.x.aal5.service_rxcrc++; lvcc->rx.buf.ptr = &lvcc->rx.buf.start[SERVICE_GET_END(s) * 4]; cardvcc_write(lvcc, SERVICE_GET_END(s), vcc_rxreadptr); - vcclist_read_unlock(); + read_unlock(&vcc_sklist_lock); return 0; } @@ -1840,9 +1719,8 @@ static int handle_service(struct lanai_dev *lanai, u32 s) static void iter_transmit(struct lanai_dev *lanai, vci_t vci) { struct lanai_vcc *lvcc = lanai->vccs[vci]; - if (!vcc_is_backlogged(lvcc)) - return; - lvcc->tx.unqueue(lanai, lvcc, lvcc->tx.endptr); + if (vcc_is_backlogged(lvcc)) + lvcc->tx.unqueue(lanai, lvcc, lvcc->tx.endptr); } /* Run service queue -- called from interrupt context or with @@ -1862,13 +1740,11 @@ static void run_service(struct lanai_dev *lanai) } reg_write(lanai, wreg, ServRead_Reg); if (ntx != 0) { - spin_lock(&lanai->txlock); - vcclist_read_lock(); + read_lock(&vcc_sklist_lock); vci_bitfield_iterate(lanai, lanai->transmit_ready, iter_transmit); CLEAR_BITMAP(&lanai->transmit_ready, NUM_VCI); - vcclist_read_unlock(); - spin_unlock(&lanai->txlock); + read_unlock(&vcc_sklist_lock); } } @@ -1885,22 +1761,47 @@ static void get_statistics(struct lanai_dev *lanai) /* -------------------- POLLING TIMER: */ +#ifndef DEBUG_RW +/* Try to undequeue 1 backlogged vcc */ +static void iter_dequeue(struct lanai_dev *lanai, vci_t vci) +{ + struct lanai_vcc *lvcc = lanai->vccs[vci]; + int endptr; + if (lvcc == NULL || lvcc->tx.atmvcc == NULL || + !vcc_is_backlogged(lvcc)) { + __clear_bit(vci, lanai->backlog_vccs); + return; + } + endptr = TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr)); + lvcc->tx.unqueue(lanai, lvcc, endptr); +} +#endif /* !DEBUG_RW */ + static void lanai_timed_poll(unsigned long arg) { -#ifndef DEBUG_RW struct lanai_dev *lanai = (struct lanai_dev *) arg; +#ifndef DEBUG_RW unsigned long flags; #ifdef USE_POWERDOWN if (lanai->conf1 & CONFIG1_POWERDOWN) return; -#endif - spin_lock_irqsave(&lanai->servicelock, flags); - run_service(lanai); - spin_unlock_irqrestore(&lanai->servicelock, flags); - vcc_tx_dequeue_all(lanai); +#endif /* USE_POWERDOWN */ + local_irq_save(flags); + /* If we can grab the spinlock, check if any services need to be run */ + if (spin_trylock(&lanai->servicelock)) { + run_service(lanai); + spin_unlock(&lanai->servicelock); + } + /* ...and see if any backlogged VCs can make progress */ + /* unfortunately linux has no read_trylock() currently */ + read_lock(&vcc_sklist_lock); + vci_bitfield_iterate(lanai, lanai->backlog_vccs, iter_dequeue); + read_unlock(&vcc_sklist_lock); + local_irq_restore(flags); + get_statistics(lanai); +#endif /* !DEBUG_RW */ mod_timer(&lanai->timer, jiffies + LANAI_POLL_PERIOD); -#endif /* DEBUG_RW */ } static inline void lanai_timed_poll_start(struct lanai_dev *lanai) @@ -1914,7 +1815,7 @@ static inline void lanai_timed_poll_start(struct lanai_dev *lanai) static inline void lanai_timed_poll_stop(struct lanai_dev *lanai) { - del_timer(&lanai->timer); + del_timer_sync(&lanai->timer); } /* -------------------- INTERRUPT SERVICE: */ @@ -2265,13 +2166,13 @@ static int __init lanai_dev_open(struct atm_dev *atmdev) #endif lanai->cbrvcc = NULL; memset(&lanai->stats, 0, sizeof lanai->stats); - spin_lock_init(&lanai->txlock); + spin_lock_init(&lanai->endtxlock); spin_lock_init(&lanai->servicelock); atmdev->ci_range.vpi_bits = 0; atmdev->ci_range.vci_bits = 0; while (1 << atmdev->ci_range.vci_bits < lanai->num_vci) atmdev->ci_range.vci_bits++; - atmdev->link_rate = ((25600000 / 8 - 8000) / 54); + atmdev->link_rate = ATM_25_PCR; /* 3.2: PCI initialization */ if ((result = lanai_pci_start(lanai)) != 0) @@ -2342,6 +2243,7 @@ static int __init lanai_dev_open(struct atm_dev *atmdev) goto error_vcctable; } MOD_INC_USE_COUNT; /* At this point we can't fail */ + mb(); /* Make sure that all that made it */ intr_enable(lanai, INT_ALL & ~(INT_PING | INT_WAKE)); /* 3.11: initialize loop mode (i.e. turn looping off) */ lanai->conf1 = (lanai->conf1 & ~CONFIG1_MASK_LOOPMODE) | @@ -2466,16 +2368,11 @@ static int lanai_open(struct atm_vcc *atmvcc, short vpi, int vci) atmvcc->vpi = vpi; atmvcc->vci = vci; set_bit(ATM_VF_ADDR, &atmvcc->flags); - lvcc = lanai->vccs[vci]; if (atmvcc->qos.aal != ATM_AAL0 && atmvcc->qos.aal != ATM_AAL5) return -EINVAL; -#if 0 - DPRINTK(DEV_LABEL "(itf %d): open %d.%d flags=0x%lX\n", - lanai->number, (int) vpi, vci, (unsigned long) atmvcc->flags); -#else DPRINTK(DEV_LABEL "(itf %d): open %d.%d\n", lanai->number, (int) vpi, vci); -#endif + lvcc = lanai->vccs[vci]; if (lvcc == NULL) { lvcc = new_lanai_vcc(); if (unlikely(lvcc == NULL)) @@ -2517,6 +2414,11 @@ static int lanai_open(struct atm_vcc *atmvcc, short vpi, int vci) } } host_vcc_bind(lanai, lvcc, vci); + /* + * Make sure everything made it to RAM before we tell the card about + * the VCC + */ + wmb(); if (atmvcc == lvcc->rx.atmvcc) host_vcc_start_rx(lvcc); if (atmvcc == lvcc->tx.atmvcc) { @@ -2549,9 +2451,6 @@ static int lanai_ioctl(struct atm_dev *atmdev, unsigned int cmd, void *arg) run_service(lanai); spin_unlock_irqrestore(&lanai->servicelock, flags); return 0; } - case 2200001: - vcc_tx_dequeue_all(lanai); - return 0; case 2200002: get_statistics(lanai); return 0; @@ -2644,18 +2543,18 @@ static int lanai_send(struct atm_vcc *atmvcc, struct sk_buff *skb) ATM_SKB(skb)->vcc = atmvcc; switch (atmvcc->qos.aal) { case ATM_AAL5: - spin_lock_irqsave(&lanai->txlock, flags); + read_lock_irqsave(&vcc_sklist_lock, flags); vcc_tx_aal5(lanai, lvcc, skb); - spin_unlock_irqrestore(&lanai->txlock, flags); + read_unlock_irqrestore(&vcc_sklist_lock, flags); return 0; case ATM_AAL0: if (unlikely(skb->len != ATM_CELL_SIZE-1)) goto einval; /* NOTE - this next line is technically invalid - we haven't unshared skb */ cpu_to_be32s((u32 *) skb->data); - spin_lock_irqsave(&lanai->txlock, flags); + read_lock_irqsave(&vcc_sklist_lock, flags); vcc_tx_aal0(lanai, lvcc, skb); - spin_unlock_irqrestore(&lanai->txlock, flags); + read_unlock_irqrestore(&vcc_sklist_lock, flags); return 0; } DPRINTK("lanai_send: bad aal=%d on vci=%d\n", (int) atmvcc->qos.aal, @@ -2725,10 +2624,6 @@ static int lanai_proc_read(struct atm_dev *atmdev, loff_t *pos, char *page) "master_parity=%u\n", lanai->stats.pcierr_s_target_abort, lanai->stats.pcierr_master_parity); if (left-- == 0) - return sprintf(page, "service list errors: no_vcc_rx=%u, " - "no_vcc_tx=%u,\n", lanai->stats.service_novcc_rx, - lanai->stats.service_novcc_tx); - if (left-- == 0) return sprintf(page, " no_tx=%u, " "no_rx=%u, bad_rx_aal=%u\n", lanai->stats.service_norx, lanai->stats.service_notx, @@ -2737,7 +2632,7 @@ static int lanai_proc_read(struct atm_dev *atmdev, loff_t *pos, char *page) return sprintf(page, "resets: dma=%u, card=%u\n", lanai->stats.dma_reenable, lanai->stats.card_reset); /* At this point, "left" should be the VCI we're looking for */ - vcclist_read_lock(); + read_lock(&vcc_sklist_lock); for (; ; left++) { if (left >= NUM_VCI) { left = 0; @@ -2773,7 +2668,7 @@ static int lanai_proc_read(struct atm_dev *atmdev, loff_t *pos, char *page) page[left++] = '\n'; page[left] = '\0'; out: - vcclist_read_unlock(); + read_unlock(&vcc_sklist_lock); return left; } #endif /* CONFIG_PROC_FS */ diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index b34ee99f5870..42c1e5663094 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1731,7 +1731,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) int __init amiga_floppy_init(void) { - int i; + int i, ret; if (!AMIGAHW_PRESENT(AMI_FLOPPY)) return -ENXIO; @@ -1743,41 +1743,39 @@ int __init amiga_floppy_init(void) * We request DSKPTR, DSKLEN and DSKDATA only, because the other * floppy registers are too spreaded over the custom register space */ + ret = -EBUSY; if (!request_mem_region(CUSTOM_PHYSADDR+0x20, 8, "amiflop [Paula]")) { printk("fd: cannot get floppy registers\n"); - unregister_blkdev(FLOPPY_MAJOR,"fd"); - return -EBUSY; + goto out_blkdev; } + + ret = -ENOMEM; if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) == NULL) { printk("fd: cannot get chip mem buffer\n"); - release_mem_region(CUSTOM_PHYSADDR+0x20, 8); - unregister_blkdev(FLOPPY_MAJOR,"fd"); - return -ENOMEM; + goto out_memregion; } + + ret = -EBUSY; if (request_irq(IRQ_AMIGA_DSKBLK, fd_block_done, 0, "floppy_dma", NULL)) { printk("fd: cannot get irq for dma\n"); - amiga_chip_free(raw_buf); - release_mem_region(CUSTOM_PHYSADDR+0x20, 8); - unregister_blkdev(FLOPPY_MAJOR,"fd"); - return -EBUSY; + goto out_irq; } + if (request_irq(IRQ_AMIGA_CIAA_TB, ms_isr, 0, "floppy_timer", NULL)) { printk("fd: cannot get irq for timer\n"); - free_irq(IRQ_AMIGA_DSKBLK, NULL); - amiga_chip_free(raw_buf); - release_mem_region(CUSTOM_PHYSADDR+0x20, 8); - unregister_blkdev(FLOPPY_MAJOR,"fd"); - return -EBUSY; - } - if (fd_probe_drives() < 1) { /* No usable drives */ - free_irq(IRQ_AMIGA_CIAA_TB, NULL); - free_irq(IRQ_AMIGA_DSKBLK, NULL); - amiga_chip_free(raw_buf); - release_mem_region(CUSTOM_PHYSADDR+0x20, 8); - unregister_blkdev(FLOPPY_MAJOR,"fd"); - return -ENXIO; + goto out_irq2; } + + ret = -ENOMEM; + floppy_queue = blk_init_queue(do_fd_request, &amiflop_lock); + if (!floppy_queue) + goto out_queue; + + ret = -ENXIO; + if (fd_probe_drives() < 1) /* No usable drives */ + goto out_probe; + blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE, floppy_find, NULL, NULL); @@ -1804,17 +1802,6 @@ int __init amiga_floppy_init(void) post_write_timer.data = 0; post_write_timer.function = post_write; - floppy_queue = blk_init_queue(do_fd_request, &amiflop_lock); - if (!floppy_queue) { - free_irq(IRQ_AMIGA_CIAA_TB, NULL); - free_irq(IRQ_AMIGA_DSKBLK, NULL); - amiga_chip_free(raw_buf); - release_mem_region(CUSTOM_PHYSADDR+0x20, 8); - unregister_blkdev(FLOPPY_MAJOR,"fd"); - blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); - return -ENOMEM; - } - for (i = 0; i < 128; i++) mfmdecode[i]=255; for (i = 0; i < 16; i++) @@ -1826,6 +1813,20 @@ int __init amiga_floppy_init(void) /* init ms timer */ ciaa.crb = 8; /* one-shot, stop */ return 0; + +out_probe: + blk_cleanup_queue(floppy_queue); +out_queue: + free_irq(IRQ_AMIGA_CIAA_TB, NULL); +out_irq2: + free_irq(IRQ_AMIGA_DSKBLK, NULL); +out_irq: + amiga_chip_free(raw_buf); +out_memregion: + release_mem_region(CUSTOM_PHYSADDR+0x20, 8); +out_blkdev: + unregister_blkdev(FLOPPY_MAJOR,"fd"); + return ret; } #ifdef MODULE diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c index e520c51d78cf..3d9c58788373 100644 --- a/drivers/block/as-iosched.c +++ b/drivers/block/as-iosched.c @@ -255,7 +255,7 @@ static void as_remove_merge_hints(request_queue_t *q, struct as_rq *arq) { as_del_arq_hash(arq); - if (q->last_merge == &arq->request->queuelist) + if (q->last_merge == arq->request) q->last_merge = NULL; } @@ -910,12 +910,7 @@ static void as_completed_request(request_queue_t *q, struct request *rq) struct as_rq *arq = RQ_DATA(rq); struct as_io_context *aic; - if (unlikely(!blk_fs_request(rq))) - return; - - WARN_ON(blk_fs_request(rq) && arq->state == AS_RQ_NEW); - - if (arq->state != AS_RQ_DISPATCHED) + if (unlikely(arq->state != AS_RQ_DISPATCHED)) return; if (ad->changed_batch && ad->nr_dispatched == 1) { @@ -1035,7 +1030,7 @@ static void as_remove_request(request_queue_t *q, struct request *rq) { struct as_rq *arq = RQ_DATA(rq); - if (unlikely(!blk_fs_request(rq))) + if (unlikely(arq->state == AS_RQ_NEW)) return; if (!arq) { @@ -1341,9 +1336,9 @@ static void as_requeue_request(request_queue_t *q, struct request *rq) atomic_inc(&arq->io_context->aic->nr_dispatched); } else WARN_ON(blk_fs_request(rq) - && (!(rq->flags & REQ_HARDBARRIER)) ); + && (!(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) ); - list_add_tail(&rq->queuelist, ad->dispatch); + list_add(&rq->queuelist, ad->dispatch); /* Stop anticipating - let this request get through */ as_antic_stop(ad); @@ -1352,45 +1347,39 @@ static void as_requeue_request(request_queue_t *q, struct request *rq) } static void -as_insert_request(request_queue_t *q, struct request *rq, - struct list_head *insert_here) +as_insert_request(request_queue_t *q, struct request *rq, int where) { struct as_data *ad = q->elevator.elevator_data; struct as_rq *arq = RQ_DATA(rq); - if (unlikely(rq->flags & REQ_HARDBARRIER)) { - q->last_merge = NULL; - - while (ad->next_arq[REQ_SYNC]) - as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]); - - while (ad->next_arq[REQ_ASYNC]) - as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); - } - - if (unlikely(!blk_fs_request(rq))) { - if (!insert_here) - insert_here = ad->dispatch->prev; - - list_add(&rq->queuelist, insert_here); - - /* Stop anticipating - let this request get through */ - if (!list_empty(ad->dispatch) - && (ad->antic_status == ANTIC_WAIT_REQ - || ad->antic_status == ANTIC_WAIT_NEXT)) + switch (where) { + case ELEVATOR_INSERT_BACK: + while (ad->next_arq[REQ_SYNC]) + as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]); + + while (ad->next_arq[REQ_ASYNC]) + as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); + list_add_tail(&rq->queuelist, ad->dispatch); + break; + case ELEVATOR_INSERT_FRONT: + list_add(&rq->queuelist, ad->dispatch); as_antic_stop(ad); - - return; + break; + case ELEVATOR_INSERT_SORT: + BUG_ON(!blk_fs_request(rq)); + as_add_request(ad, arq); + break; + default: + printk("%s: bad insert point %d\n", __FUNCTION__,where); + return; } if (rq_mergeable(rq)) { as_add_arq_hash(ad, arq); if (!q->last_merge) - q->last_merge = &rq->queuelist; + q->last_merge = rq; } - - as_add_request(ad, arq); } /* @@ -1438,7 +1427,7 @@ as_latter_request(request_queue_t *q, struct request *rq) } static int -as_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) +as_merge(request_queue_t *q, struct request **req, struct bio *bio) { struct as_data *ad = q->elevator.elevator_data; sector_t rb_key = bio->bi_sector + bio_sectors(bio); @@ -1450,7 +1439,7 @@ as_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) */ ret = elv_try_last_merge(q, bio); if (ret != ELEVATOR_NO_MERGE) { - __rq = list_entry_rq(q->last_merge); + __rq = q->last_merge; goto out_insert; } @@ -1482,11 +1471,11 @@ as_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) return ELEVATOR_NO_MERGE; out: - q->last_merge = &__rq->queuelist; + q->last_merge = __rq; out_insert: if (ret) as_hot_arq_hash(ad, RQ_DATA(__rq)); - *insert = &__rq->queuelist; + *req = __rq; return ret; } @@ -1514,7 +1503,7 @@ static void as_merged_request(request_queue_t *q, struct request *req) */ } - q->last_merge = &req->queuelist; + q->last_merge = req; } static void diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 34b490615ce3..ce0927b36889 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2447,11 +2447,8 @@ static int __init cciss_init_one(struct pci_dev *pdev, if( i < 0 ) return (-1); if (cciss_pci_init(hba[i], pdev) != 0) - { - release_io_mem(hba[i]); - free_hba(i); - return (-1); - } + goto clean1; + sprintf(hba[i]->devname, "cciss%d", i); hba[i]->ctlr = i; hba[i]->pdev = pdev; @@ -2463,28 +2460,23 @@ static int __init cciss_init_one(struct pci_dev *pdev, printk("cciss: not using DAC cycles\n"); else { printk("cciss: no suitable DMA available\n"); - free_hba(i); - return -ENODEV; + goto clean1; } if (register_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname)) { - release_io_mem(hba[i]); - free_hba(i); - return -1; + printk(KERN_ERR "cciss: Unable to register device %s\n", + hba[i]->devname); + goto clean1; } /* make sure the board interrupts are off */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF); if( request_irq(hba[i]->intr, do_cciss_intr, SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, - hba[i]->devname, hba[i])) - { - printk(KERN_ERR "ciss: Unable to get irq %d for %s\n", + hba[i]->devname, hba[i])) { + printk(KERN_ERR "cciss: Unable to get irq %d for %s\n", hba[i]->intr, hba[i]->devname); - unregister_blkdev( COMPAQ_CISS_MAJOR+i, hba[i]->devname); - release_io_mem(hba[i]); - free_hba(i); - return(-1); + goto clean2; } hba[i]->cmd_pool_bits = kmalloc(((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long), GFP_KERNEL); hba[i]->cmd_pool = (CommandList_struct *)pci_alloc_consistent( @@ -2495,35 +2487,15 @@ static int __init cciss_init_one(struct pci_dev *pdev, &(hba[i]->errinfo_pool_dhandle)); if((hba[i]->cmd_pool_bits == NULL) || (hba[i]->cmd_pool == NULL) - || (hba[i]->errinfo_pool == NULL)) - { -err_all: - if(hba[i]->cmd_pool_bits) - kfree(hba[i]->cmd_pool_bits); - if(hba[i]->cmd_pool) - pci_free_consistent(hba[i]->pdev, - NR_CMDS * sizeof(CommandList_struct), - hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); - if(hba[i]->errinfo_pool) - pci_free_consistent(hba[i]->pdev, - NR_CMDS * sizeof( ErrorInfo_struct), - hba[i]->errinfo_pool, - hba[i]->errinfo_pool_dhandle); - free_irq(hba[i]->intr, hba[i]); - unregister_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname); - release_io_mem(hba[i]); - free_hba(i); + || (hba[i]->errinfo_pool == NULL)) { printk( KERN_ERR "cciss: out of memory"); - return(-1); + goto clean4; } - /* - * someone needs to clean up this failure handling mess - */ spin_lock_init(&hba[i]->lock); q = blk_init_queue(do_cciss_request, &hba[i]->lock); if (!q) - goto err_all; + goto clean4; hba[i]->queue = q; q->queuedata = hba[i]; @@ -2576,6 +2548,26 @@ err_all: add_disk(disk); } return(1); + +clean4: + if(hba[i]->cmd_pool_bits) + kfree(hba[i]->cmd_pool_bits); + if(hba[i]->cmd_pool) + pci_free_consistent(hba[i]->pdev, + NR_CMDS * sizeof(CommandList_struct), + hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); + if(hba[i]->errinfo_pool) + pci_free_consistent(hba[i]->pdev, + NR_CMDS * sizeof( ErrorInfo_struct), + hba[i]->errinfo_pool, + hba[i]->errinfo_pool_dhandle); + free_irq(hba[i]->intr, hba[i]); +clean2: + unregister_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname); +clean1: + release_io_mem(hba[i]); + free_hba(i); + return(-1); } static void __devexit cciss_remove_one (struct pci_dev *pdev) diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c index 66b11e3822e9..8bb37f65d536 100644 --- a/drivers/block/deadline-iosched.c +++ b/drivers/block/deadline-iosched.c @@ -33,13 +33,7 @@ static const int deadline_hash_shift = 5; #define DL_HASH_ENTRIES (1 << deadline_hash_shift) #define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) #define list_entry_hash(ptr) list_entry((ptr), struct deadline_rq, hash) -#define ON_HASH(drq) (drq)->hash_valid_count - -#define DL_INVALIDATE_HASH(dd) \ - do { \ - if (!++(dd)->hash_valid_count) \ - (dd)->hash_valid_count = 1; \ - } while (0) +#define ON_HASH(drq) (drq)->on_hash struct deadline_data { /* @@ -58,7 +52,6 @@ struct deadline_data { struct deadline_rq *next_drq[2]; struct list_head *dispatch; /* driver dispatch queue */ struct list_head *hash; /* request hash */ - unsigned long hash_valid_count; /* barrier hash count */ unsigned int batching; /* number of sequential requests made */ sector_t last_sector; /* head position */ unsigned int starved; /* times reads have starved writes */ @@ -90,7 +83,7 @@ struct deadline_rq { * request hash, key is the ending offset (for back merge lookup) */ struct list_head hash; - unsigned long hash_valid_count; + char on_hash; /* * expire fifo @@ -110,7 +103,7 @@ static kmem_cache_t *drq_pool; */ static inline void __deadline_del_drq_hash(struct deadline_rq *drq) { - drq->hash_valid_count = 0; + drq->on_hash = 0; list_del_init(&drq->hash); } @@ -125,7 +118,7 @@ deadline_remove_merge_hints(request_queue_t *q, struct deadline_rq *drq) { deadline_del_drq_hash(drq); - if (q->last_merge == &drq->request->queuelist) + if (q->last_merge == drq->request) q->last_merge = NULL; } @@ -136,7 +129,7 @@ deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq) BUG_ON(ON_HASH(drq)); - drq->hash_valid_count = dd->hash_valid_count; + drq->on_hash = 1; list_add(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]); } @@ -169,8 +162,7 @@ deadline_find_drq_hash(struct deadline_data *dd, sector_t offset) BUG_ON(!ON_HASH(drq)); - if (!rq_mergeable(__rq) - || drq->hash_valid_count != dd->hash_valid_count) { + if (!rq_mergeable(__rq)) { __deadline_del_drq_hash(drq); continue; } @@ -324,7 +316,7 @@ static void deadline_remove_request(request_queue_t *q, struct request *rq) } static int -deadline_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) +deadline_merge(request_queue_t *q, struct request **req, struct bio *bio) { struct deadline_data *dd = q->elevator.elevator_data; struct request *__rq; @@ -335,7 +327,7 @@ deadline_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) */ ret = elv_try_last_merge(q, bio); if (ret != ELEVATOR_NO_MERGE) { - __rq = list_entry_rq(q->last_merge); + __rq = q->last_merge; goto out_insert; } @@ -371,11 +363,11 @@ deadline_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) return ELEVATOR_NO_MERGE; out: - q->last_merge = &__rq->queuelist; + q->last_merge = __rq; out_insert: if (ret) deadline_hot_drq_hash(dd, RQ_DATA(__rq)); - *insert = &__rq->queuelist; + *req = __rq; return ret; } @@ -398,7 +390,7 @@ static void deadline_merged_request(request_queue_t *q, struct request *req) deadline_add_drq_rb(dd, drq); } - q->last_merge = &req->queuelist; + q->last_merge = req; } static void @@ -621,39 +613,35 @@ dispatch: } static void -deadline_insert_request(request_queue_t *q, struct request *rq, - struct list_head *insert_here) +deadline_insert_request(request_queue_t *q, struct request *rq, int where) { struct deadline_data *dd = q->elevator.elevator_data; struct deadline_rq *drq = RQ_DATA(rq); - if (unlikely(rq->flags & REQ_HARDBARRIER)) { - DL_INVALIDATE_HASH(dd); - q->last_merge = NULL; - - while (deadline_dispatch_requests(dd)) - ; - - list_add_tail(&rq->queuelist, dd->dispatch); - return; - } - - if (unlikely(!blk_fs_request(rq))) { - if (!insert_here) - insert_here = dd->dispatch->prev; - - list_add(&rq->queuelist, insert_here); - return; + switch (where) { + case ELEVATOR_INSERT_BACK: + while (deadline_dispatch_requests(dd)) + ; + list_add_tail(&rq->queuelist, dd->dispatch); + break; + case ELEVATOR_INSERT_FRONT: + list_add(&rq->queuelist, dd->dispatch); + break; + case ELEVATOR_INSERT_SORT: + BUG_ON(!blk_fs_request(rq)); + deadline_add_request(dd, drq); + break; + default: + printk("%s: bad insert point %d\n", __FUNCTION__,where); + return; } if (rq_mergeable(rq)) { deadline_add_drq_hash(dd, drq); if (!q->last_merge) - q->last_merge = &rq->queuelist; + q->last_merge = rq; } - - deadline_add_request(dd, drq); } static int deadline_queue_empty(request_queue_t *q) @@ -744,7 +732,6 @@ static int deadline_init(request_queue_t *q, elevator_t *e) dd->dispatch = &q->queue_head; dd->fifo_expire[READ] = read_expire; dd->fifo_expire[WRITE] = write_expire; - dd->hash_valid_count = 1; dd->writes_starved = writes_starved; dd->front_merges = 1; dd->fifo_batch = fifo_batch; @@ -775,7 +762,7 @@ deadline_set_request(request_queue_t *q, struct request *rq, int gfp_mask) drq->request = rq; INIT_LIST_HEAD(&drq->hash); - drq->hash_valid_count = 0; + drq->on_hash = 0; INIT_LIST_HEAD(&drq->fifo); diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c index 246c39a4962e..fcb00cfa4fd7 100644 --- a/drivers/block/elevator.c +++ b/drivers/block/elevator.c @@ -81,7 +81,7 @@ inline int elv_try_merge(struct request *__rq, struct bio *bio) inline int elv_try_last_merge(request_queue_t *q, struct bio *bio) { if (q->last_merge) - return elv_try_merge(list_entry_rq(q->last_merge), bio); + return elv_try_merge(q->last_merge, bio); return ELEVATOR_NO_MERGE; } @@ -117,12 +117,12 @@ int elevator_global_init(void) return 0; } -int elv_merge(request_queue_t *q, struct list_head **entry, struct bio *bio) +int elv_merge(request_queue_t *q, struct request **req, struct bio *bio) { elevator_t *e = &q->elevator; if (e->elevator_merge_fn) - return e->elevator_merge_fn(q, entry, bio); + return e->elevator_merge_fn(q, req, bio); return ELEVATOR_NO_MERGE; } @@ -140,7 +140,7 @@ void elv_merge_requests(request_queue_t *q, struct request *rq, { elevator_t *e = &q->elevator; - if (q->last_merge == &next->queuelist) + if (q->last_merge == next) q->last_merge = NULL; if (e->elevator_merge_req_fn) @@ -156,29 +156,25 @@ void elv_requeue_request(request_queue_t *q, struct request *rq) if (q->elevator.elevator_requeue_req_fn) q->elevator.elevator_requeue_req_fn(q, rq); else - __elv_add_request(q, rq, 0, 0); + __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); } -void __elv_add_request(request_queue_t *q, struct request *rq, int at_end, +void __elv_add_request(request_queue_t *q, struct request *rq, int where, int plug) { - struct list_head *insert = &q->queue_head; - - if (at_end) - insert = insert->prev; if (plug) blk_plug_device(q); - q->elevator.elevator_add_req_fn(q, rq, insert); + q->elevator.elevator_add_req_fn(q, rq, where); } -void elv_add_request(request_queue_t *q, struct request *rq, int at_end, +void elv_add_request(request_queue_t *q, struct request *rq, int where, int plug) { unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); - __elv_add_request(q, rq, at_end, plug); + __elv_add_request(q, rq, where, plug); spin_unlock_irqrestore(q->queue_lock, flags); } @@ -200,7 +196,7 @@ struct request *elv_next_request(request_queue_t *q) */ rq->flags |= REQ_STARTED; - if (&rq->queuelist == q->last_merge) + if (rq == q->last_merge) q->last_merge = NULL; if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn) @@ -238,7 +234,7 @@ void elv_remove_request(request_queue_t *q, struct request *rq) * deleted without ever being given to driver (merged with another * request). */ - if (&rq->queuelist == q->last_merge) + if (rq == q->last_merge) q->last_merge = NULL; if (e->elevator_remove_req_fn) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 10566621eb81..b25acb42542e 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4607,3 +4607,5 @@ MODULE_LICENSE("GPL"); __setup ("floppy=", floppy_setup); module_init(floppy_init) #endif + +MODULE_ALIAS_BLOCKDEV_MAJOR(FLOPPY_MAJOR); diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index 16a58ad04008..0cbabe9103d4 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -372,7 +372,7 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page) disk_stat_read(disk, write_merges), (unsigned long long)disk_stat_read(disk, write_sectors), jiffies_to_msec(disk_stat_read(disk, write_ticks)), - disk_stat_read(disk, in_flight), + disk->in_flight, jiffies_to_msec(disk_stat_read(disk, io_ticks)), jiffies_to_msec(disk_stat_read(disk, time_in_queue))); } @@ -492,7 +492,7 @@ static int diskstats_show(struct seq_file *s, void *v) disk_stat_read(gp, writes), disk_stat_read(gp, write_merges), (unsigned long long)disk_stat_read(gp, write_sectors), jiffies_to_msec(disk_stat_read(gp, write_ticks)), - disk_stat_read(gp, in_flight), + gp->in_flight, jiffies_to_msec(disk_stat_read(gp, io_ticks)), jiffies_to_msec(disk_stat_read(gp, time_in_queue))); diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index c403ba8429b3..541b45c519ef 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -703,7 +703,7 @@ void blk_queue_invalidate_tags(request_queue_t *q) blk_queue_end_tag(q, rq); rq->flags &= ~REQ_STARTED; - __elv_add_request(q, rq, 0, 0); + __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0); } } @@ -1632,11 +1632,16 @@ void blk_insert_request(request_queue_t *q, struct request *rq, if(reinsert) { blk_requeue_request(q, rq); } else { + int where = ELEVATOR_INSERT_BACK; + + if (at_head) + where = ELEVATOR_INSERT_FRONT; + if (blk_rq_tagged(rq)) blk_queue_end_tag(q, rq); drive_stat_acct(rq, rq->nr_sectors, 1); - __elv_add_request(q, rq, !at_head, 0); + __elv_add_request(q, rq, where, 0); } q->request_fn(q); spin_unlock_irqrestore(q->queue_lock, flags); @@ -1660,7 +1665,7 @@ void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) } if (new_io) { disk_round_stats(rq->rq_disk); - disk_stat_inc(rq->rq_disk, in_flight); + rq->rq_disk->in_flight++; } } @@ -1669,8 +1674,7 @@ void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) * queue lock is held and interrupts disabled, as we muck with the * request queue list. */ -static inline void add_request(request_queue_t * q, struct request * req, - struct list_head *insert_here) +static inline void add_request(request_queue_t * q, struct request * req) { drive_stat_acct(req, req->nr_sectors, 1); @@ -1681,7 +1685,7 @@ static inline void add_request(request_queue_t * q, struct request * req, * elevator indicated where it wants this request to be * inserted at elevator_merge time */ - __elv_add_request_pos(q, req, insert_here); + __elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0); } /* @@ -1704,10 +1708,10 @@ void disk_round_stats(struct gendisk *disk) unsigned long now = jiffies; disk_stat_add(disk, time_in_queue, - disk_stat_read(disk, in_flight) * (now - disk->stamp)); + disk->in_flight * (now - disk->stamp)); disk->stamp = now; - if (disk_stat_read(disk, in_flight)) + if (disk->in_flight) disk_stat_add(disk, io_ticks, (now - disk->stamp_idle)); disk->stamp_idle = now; } @@ -1819,7 +1823,7 @@ static int attempt_merge(request_queue_t *q, struct request *req, if (req->rq_disk) { disk_round_stats(req->rq_disk); - disk_stat_dec(req->rq_disk, in_flight); + req->rq_disk->in_flight--; } __blk_put_request(q, next); @@ -1880,7 +1884,6 @@ static int __make_request(request_queue_t *q, struct bio *bio) { struct request *req, *freereq = NULL; int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, ra; - struct list_head *insert_here; sector_t sector; sector = bio->bi_sector; @@ -1903,7 +1906,6 @@ static int __make_request(request_queue_t *q, struct bio *bio) ra = bio->bi_rw & (1 << BIO_RW_AHEAD); again: - insert_here = NULL; spin_lock_irq(q->queue_lock); if (elv_queue_empty(q)) { @@ -1913,17 +1915,13 @@ again: if (barrier) goto get_rq; - el_ret = elv_merge(q, &insert_here, bio); + el_ret = elv_merge(q, &req, bio); switch (el_ret) { case ELEVATOR_BACK_MERGE: - req = list_entry_rq(insert_here); - BUG_ON(!rq_mergeable(req)); - if (!q->back_merge_fn(q, req, bio)) { - insert_here = &req->queuelist; + if (!q->back_merge_fn(q, req, bio)) break; - } req->biotail->bi_next = bio; req->biotail = bio; @@ -1934,14 +1932,10 @@ again: goto out; case ELEVATOR_FRONT_MERGE: - req = list_entry_rq(insert_here); - BUG_ON(!rq_mergeable(req)); - if (!q->front_merge_fn(q, req, bio)) { - insert_here = req->queuelist.prev; + if (!q->front_merge_fn(q, req, bio)) break; - } bio->bi_next = req->bio; req->cbio = req->bio = bio; @@ -2029,7 +2023,7 @@ get_rq: req->rq_disk = bio->bi_bdev->bd_disk; req->start_time = jiffies; - add_request(q, req, insert_here); + add_request(q, req); out: if (freereq) __blk_put_request(q, freereq); @@ -2480,7 +2474,7 @@ void end_that_request_last(struct request *req) break; } disk_round_stats(disk); - disk_stat_dec(disk, in_flight); + disk->in_flight--; } __blk_put_request(req->q, req); /* Do this LAST! The structure may be freed immediately afterwards */ diff --git a/drivers/block/noop-iosched.c b/drivers/block/noop-iosched.c index 2eadd041914b..7511b955de70 100644 --- a/drivers/block/noop-iosched.c +++ b/drivers/block/noop-iosched.c @@ -17,17 +17,15 @@ /* * See if we can find a request that this buffer can be coalesced with. */ -int elevator_noop_merge(request_queue_t *q, struct list_head **insert, +int elevator_noop_merge(request_queue_t *q, struct request **req, struct bio *bio) { struct list_head *entry = &q->queue_head; struct request *__rq; int ret; - if ((ret = elv_try_last_merge(q, bio))) { - *insert = q->last_merge; + if ((ret = elv_try_last_merge(q, bio))) return ret; - } while ((entry = entry->prev) != &q->queue_head) { __rq = list_entry_rq(entry); @@ -41,8 +39,8 @@ int elevator_noop_merge(request_queue_t *q, struct list_head **insert, continue; if ((ret = elv_try_merge(__rq, bio))) { - *insert = &__rq->queuelist; - q->last_merge = &__rq->queuelist; + *req = __rq; + q->last_merge = __rq; return ret; } } @@ -57,8 +55,13 @@ void elevator_noop_merge_requests(request_queue_t *q, struct request *req, } void elevator_noop_add_request(request_queue_t *q, struct request *rq, - struct list_head *insert_here) + int where) { + struct list_head *insert = q->queue_head.prev; + + if (where == ELEVATOR_INSERT_FRONT) + insert = &q->queue_head; + list_add_tail(&rq->queuelist, &q->queue_head); /* @@ -67,7 +70,7 @@ void elevator_noop_add_request(request_queue_t *q, struct request *rq, if (rq->flags & REQ_HARDBARRIER) q->last_merge = NULL; else if (!q->last_merge) - q->last_merge = &rq->queuelist; + q->last_merge = rq; } struct request *elevator_noop_next_request(request_queue_t *q) diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index 94574b14f30b..3d18a7a70108 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c @@ -68,7 +68,7 @@ static int blk_do_rq(request_queue_t *q, struct block_device *bdev, rq->flags |= REQ_NOMERGE; rq->waiting = &wait; - elv_add_request(q, rq, 1, 1); + elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); generic_unplug_device(q); wait_for_completion(&wait); diff --git a/drivers/block/xd.c b/drivers/block/xd.c index 8b4972feca71..dc06ce7adfa6 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -1103,5 +1103,5 @@ __setup ("xd_geo=", xd_manual_geo_init); #endif /* MODULE */ -module_init(xd_init) - +module_init(xd_init); +MODULE_ALIAS_BLOCKDEV_MAJOR(XT_DISK_MAJOR); diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index dfd1e73e611a..4943401d71b0 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -574,3 +574,4 @@ module_exit(hci_uart_cleanup); MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>"); MODULE_DESCRIPTION("Bluetooth HCI UART driver ver " VERSION); MODULE_LICENSE("GPL"); +MODULE_ALIAS_LDISC(N_HCI); diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c index 969945a7bdb4..8503b193aea5 100644 --- a/drivers/cdrom/aztcd.c +++ b/drivers/cdrom/aztcd.c @@ -2499,3 +2499,4 @@ static int azt_bcd2bin(unsigned char bcd) } MODULE_LICENSE("GPL"); +MODULE_ALIAS_BLOCKDEV_MAJOR(AZTECH_CDROM_MAJOR); diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index 379b454684dd..5a30990de102 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c @@ -3500,3 +3500,4 @@ module_init(cdu31a_init); module_exit(cdu31a_exit); MODULE_LICENSE("GPL"); +MODULE_ALIAS_BLOCKDEV_MAJOR(CDU31A_CDROM_MAJOR); diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c index 22464a5fd19a..c462db3b81ce 100644 --- a/drivers/cdrom/cm206.c +++ b/drivers/cdrom/cm206.c @@ -1616,7 +1616,7 @@ static int __init cm206_setup(char *s) __setup("cm206=", cm206_setup); #endif /* !MODULE */ - +MODULE_ALIAS_BLOCKDEV_MAJOR(CM206_CDROM_MAJOR); /* * Local variables: diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c index b24979c1104b..111f020de66e 100644 --- a/drivers/cdrom/gscd.c +++ b/drivers/cdrom/gscd.c @@ -1029,3 +1029,4 @@ MODULE_AUTHOR("Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"); MODULE_LICENSE("GPL"); module_init(gscd_init); module_exit(gscd_exit); +MODULE_ALIAS_BLOCKDEV_MAJOR(GOLDSTAR_CDROM_MAJOR); diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c index e17822236df4..33b35e30e619 100644 --- a/drivers/cdrom/mcd.c +++ b/drivers/cdrom/mcd.c @@ -1559,3 +1559,4 @@ module_exit(mcd_exit); MODULE_AUTHOR("Martin Harriss"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_BLOCKDEV_MAJOR(MITSUMI_CDROM_MAJOR); diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c index 70719df8305d..ba4700ddbb0f 100644 --- a/drivers/cdrom/mcdx.c +++ b/drivers/cdrom/mcdx.c @@ -1970,3 +1970,4 @@ static int mcdx_setattentuator(struct s_drive_stuff *stuffp, } MODULE_LICENSE("GPL"); +MODULE_ALIAS_BLOCKDEV_MAJOR(MITSUMI_X_CDROM_MAJOR); diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c index c435e22f9fde..7e9758fe7045 100644 --- a/drivers/cdrom/optcd.c +++ b/drivers/cdrom/optcd.c @@ -2102,3 +2102,4 @@ module_init(optcd_init); module_exit(optcd_exit); MODULE_LICENSE("GPL"); +MODULE_ALIAS_BLOCKDEV_MAJOR(OPTICS_CDROM_MAJOR); diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index c57a5d82fef1..df865505d369 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -5954,6 +5954,9 @@ static int sbpcd_media_changed(struct cdrom_device_info *cdi, int disc_nr) } MODULE_LICENSE("GPL"); +/* FIXME: Old modules.conf claims MATSUSHITA_CDROM2_MAJOR and CDROM3, but + AFAICT this doesn't support those majors, so why? --RR 30 Jul 2003 */ +MODULE_ALIAS_BLOCKDEV_MAJOR(MATSUSHITA_CDROM_MAJOR); /*==========================================================================*/ /* diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c index ae6a8237d063..1c8362764e1a 100644 --- a/drivers/cdrom/sjcd.c +++ b/drivers/cdrom/sjcd.c @@ -1813,3 +1813,4 @@ module_init(sjcd_init); module_exit(sjcd_exit); MODULE_LICENSE("GPL"); +MODULE_ALIAS_BLOCKDEV_MAJOR(SANYO_CDROM_MAJOR); diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c index 2422038cc059..1467c9311000 100644 --- a/drivers/cdrom/sonycd535.c +++ b/drivers/cdrom/sonycd535.c @@ -1684,3 +1684,4 @@ module_exit(sony535_exit); MODULE_LICENSE("GPL"); +MODULE_ALIAS_BLOCKDEV_MAJOR(CDU535_CDROM_MAJOR); diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 0ba95771e9e1..8280faa7ee9e 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -331,6 +331,7 @@ __setup("agp=", agp_setup); MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>"); MODULE_DESCRIPTION("AGP GART driver"); MODULE_LICENSE("GPL and additional rights"); +MODULE_ALIAS_MISCDEV(AGPGART_MINOR); module_init(agp_init); module_exit(agp_exit); diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index 6ff8d157fc6d..ef1fa6db9570 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -1097,4 +1097,3 @@ void agp_frontend_cleanup(void) { misc_deregister(&agp_miscdev); } - diff --git a/drivers/char/busmouse.c b/drivers/char/busmouse.c index 126d77f8a215..b0416f721054 100644 --- a/drivers/char/busmouse.c +++ b/drivers/char/busmouse.c @@ -452,4 +452,5 @@ EXPORT_SYMBOL(busmouse_add_buttons); EXPORT_SYMBOL(register_busmouse); EXPORT_SYMBOL(unregister_busmouse); +MODULE_ALIAS_MISCDEV(BUSMOUSE_MINOR); MODULE_LICENSE("GPL"); diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 46be7a8ac3d3..56ffc3965d76 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -965,4 +965,5 @@ __setup("lp=", lp_setup); module_init(lp_init_module); module_exit(lp_cleanup_module); +MODULE_ALIAS("char-major-" __stringify(LP_MAJOR)); MODULE_LICENSE("GPL"); diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index 8ff16b5d21ac..3dcbbf2188be 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -982,3 +982,4 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Paul Fulghum paulkf@microgate.com"); MODULE_PARM(debuglevel, "i"); MODULE_PARM(maxframe, "i"); +MODULE_ALIAS_LDISC(N_HDLC); diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 4eae5e465df5..9c7be47fb6a4 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -1428,4 +1428,4 @@ static int r3964_receive_room(struct tty_struct *tty) MODULE_LICENSE("GPL"); - +MODULE_ALIAS_LDISC(N_R3964); diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 96daf9d5d80e..7b6ee59edf08 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -923,3 +923,4 @@ EXPORT_SYMBOL(__nvram_check_checksum); EXPORT_SYMBOL(nvram_check_checksum); EXPORT_SYMBOL(__nvram_set_checksum); EXPORT_SYMBOL(nvram_set_checksum); +MODULE_ALIAS_MISCDEV(NVRAM_MINOR); diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 3ecc2b9a666e..e14a3ce8928d 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -1,7 +1,7 @@ /* * linux/drivers/char/pcmcia/synclink_cs.c * - * $Id: synclink_cs.c,v 4.13 2003/06/18 15:29:32 paulkf Exp $ + * $Id: synclink_cs.c,v 4.15 2003/09/05 15:26:02 paulkf Exp $ * * Device driver for Microgate SyncLink PC Card * multiprotocol serial adapter. @@ -491,7 +491,7 @@ MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i"); MODULE_LICENSE("GPL"); static char *driver_name = "SyncLink PC Card driver"; -static char *driver_version = "$Revision: 4.13 $"; +static char *driver_version = "$Revision: 4.15 $"; static struct tty_driver *serial_driver; @@ -838,6 +838,9 @@ static inline int mgslpc_paranoia_check(MGSLPC_INFO *info, printk(badmagic, name, routine); return 1; } +#else + if (!info) + return 1; #endif return 0; } diff --git a/drivers/char/pty.c b/drivers/char/pty.c index f91f50897543..85fa5d9503cb 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -354,7 +354,7 @@ int __init pty_init(void) pty_slave_driver->init_termios = tty_std_termios; pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS | - TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; + TTY_DRIVER_REAL_RAW; pty_slave_driver->other = pty_driver; tty_set_operations(pty_slave_driver, &pty_ops); diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 0ee79ab3d93a..96221c5601c3 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1036,7 +1036,6 @@ static int rc_open(struct tty_struct * tty, struct file * filp) int error; struct riscom_port * port; struct riscom_board * bp; - unsigned long flags; board = RC_BOARD(tty->index); if (board >= RC_NBOARD || !(rc_board[board].flags & RC_BOARD_PRESENT)) diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 309a173c821d..fcdc4eb0b9ac 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -137,7 +137,6 @@ static int rtc_ioctl(struct inode *inode, struct file *file, static unsigned int rtc_poll(struct file *file, poll_table *wait); #endif -void get_rtc_time (struct rtc_time *rtc_tm); static void get_rtc_alm_time (struct rtc_time *alm_tm); #if RTC_IRQ static void rtc_dropped_irq(unsigned long data); @@ -482,7 +481,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) } case RTC_RD_TIME: /* Read the time/date from RTC */ { - get_rtc_time(&wtime); + rtc_get_rtc_time(&wtime); break; } case RTC_SET_TIME: /* Set the RTC */ @@ -1119,7 +1118,7 @@ static int rtc_proc_output (char *buf) p = buf; - get_rtc_time(&tm); + rtc_get_rtc_time(&tm); /* * There is no way to tell if the luser has the RTC set for local @@ -1206,7 +1205,7 @@ static inline unsigned char rtc_is_updating(void) return uip; } -void get_rtc_time(struct rtc_time *rtc_tm) +void rtc_get_rtc_time(struct rtc_time *rtc_tm) { unsigned long uip_watchdog = jiffies; unsigned char ctrl; @@ -1346,3 +1345,4 @@ static void set_rtc_irq_bit(unsigned char bit) MODULE_AUTHOR("Paul Gortmaker"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(RTC_MINOR); diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index bf80e670091d..e55e9abb184d 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -1,7 +1,7 @@ /* * linux/drivers/char/synclink.c * - * $Id: synclink.c,v 4.12 2003/06/18 15:29:32 paulkf Exp $ + * $Id: synclink.c,v 4.16 2003/09/05 15:26:02 paulkf Exp $ * * Device driver for Microgate SyncLink ISA and PCI * high speed multiprotocol serial adapters. @@ -261,6 +261,7 @@ struct mgsl_struct { int rx_enabled; int rx_overflow; + int rx_rcc_underrun; int tx_enabled; int tx_active; @@ -910,7 +911,7 @@ MODULE_PARM(txdmabufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); static char *driver_name = "SyncLink serial driver"; -static char *driver_version = "$Revision: 4.12 $"; +static char *driver_version = "$Revision: 4.16 $"; static int synclink_init_one (struct pci_dev *dev, const struct pci_device_id *ent); @@ -983,6 +984,9 @@ static inline int mgsl_paranoia_check(struct mgsl_struct *info, printk(badmagic, name, routine); return 1; } +#else + if (!info) + return 1; #endif return 0; } @@ -1125,7 +1129,16 @@ void mgsl_bh_receive(struct mgsl_struct *info) printk( "%s(%d):mgsl_bh_receive(%s)\n", __FILE__,__LINE__,info->device_name); - while( (get_rx_frame)(info) ); + do + { + if (info->rx_rcc_underrun) { + unsigned long flags; + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_start_receiver(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + return; + } + } while(get_rx_frame(info)); } void mgsl_bh_transmit(struct mgsl_struct *info) @@ -1567,6 +1580,21 @@ void mgsl_isr_misc( struct mgsl_struct *info ) printk("%s(%d):mgsl_isr_misc status=%04X\n", __FILE__,__LINE__,status); + if ((status & MISCSTATUS_RCC_UNDERRUN) && + (info->params.mode == MGSL_MODE_HDLC)) { + + /* turn off receiver and rx DMA */ + usc_EnableReceiver(info,DISABLE_UNCONDITIONAL); + usc_DmaCmd(info, DmaCmd_ResetRxChannel); + usc_UnlatchRxstatusBits(info, RXSTATUS_ALL); + usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS); + usc_DisableInterrupts(info, RECEIVE_DATA + RECEIVE_STATUS); + + /* schedule BH handler to restart receiver */ + info->pending_bh |= BH_RECEIVE; + info->rx_rcc_underrun = 1; + } + usc_ClearIrqPendingBits( info, MISC ); usc_UnlatchMiscstatusBits( info, status ); @@ -3625,7 +3653,7 @@ static inline int line_info(char *buf, struct mgsl_struct *info) if (info->icount.rxover) ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); if (info->icount.rxcrc) - ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc); + ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); } else { ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d", info->icount.tx, info->icount.rx); @@ -5190,7 +5218,11 @@ void usc_set_sdlc_mode( struct mgsl_struct *info ) usc_EnableMasterIrqBit( info ); usc_ClearIrqPendingBits( info, RECEIVE_STATUS + RECEIVE_DATA + - TRANSMIT_STATUS + TRANSMIT_DATA ); + TRANSMIT_STATUS + TRANSMIT_DATA + MISC); + + /* arm RCC underflow interrupt */ + usc_OutReg(info, SICR, (u16)(usc_InReg(info,SICR) | BIT3)); + usc_EnableInterrupts(info, MISC); info->mbre_bit = 0; outw( 0, info->io_base ); /* clear Master Bus Enable (DCAR) */ @@ -5628,6 +5660,7 @@ void usc_stop_receiver( struct mgsl_struct *info ) info->rx_enabled = 0; info->rx_overflow = 0; + info->rx_rcc_underrun = 0; } /* end of stop_receiver() */ diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index ae3d9c41b668..587dcb3a669d 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -1,5 +1,5 @@ /* - * $Id: synclinkmp.c,v 4.12 2003/06/18 15:29:33 paulkf Exp $ + * $Id: synclinkmp.c,v 4.14 2003/09/05 15:26:03 paulkf Exp $ * * Device driver for Microgate SyncLink Multiport * high speed multiprotocol serial adapter. @@ -496,7 +496,7 @@ MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICES) "i"); MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i"); static char *driver_name = "SyncLink MultiPort driver"; -static char *driver_version = "$Revision: 4.12 $"; +static char *driver_version = "$Revision: 4.14 $"; static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent); static void synclinkmp_remove_one(struct pci_dev *dev); @@ -713,6 +713,9 @@ static inline int sanity_check(SLMP_INFO *info, printk(badmagic, name, routine); return 1; } +#else + if (!info) + return 1; #endif return 0; } diff --git a/drivers/char/watchdog/wafer5823wdt.c b/drivers/char/watchdog/wafer5823wdt.c index b855ef565272..98cac9f1211e 100644 --- a/drivers/char/watchdog/wafer5823wdt.c +++ b/drivers/char/watchdog/wafer5823wdt.c @@ -57,12 +57,7 @@ static spinlock_t wafwdt_lock; */ static int wdt_stop = 0x843; -module_param(wdt_stop, int, 0); -MODULE_PARM_DESC(wdt_stop, "Wafer 5823 WDT 'stop' io port (default 0x843)"); - static int wdt_start = 0x443; -module_param(wdt_start, int, 0); -MODULE_PARM_DESC(wdt_start, "Wafer 5823 WDT 'start' io port (default 0x443)"); static int timeout = WD_TIMO; /* in seconds */ module_param(timeout, int, 0); @@ -269,7 +264,7 @@ static int __init wafwdt_init(void) spin_lock_init(&wafwdt_lock); - if (timeout < 1 || timeout > 63) { + if (timeout < 1 || timeout > 255) { timeout = WD_TIMO; printk (KERN_INFO PFX "timeout value must be 1<=x<=255, using %d\n", timeout); diff --git a/drivers/char/watchdog/wdt.c b/drivers/char/watchdog/wdt.c index e1760847f6d3..989a5a89a2ab 100644 --- a/drivers/char/watchdog/wdt.c +++ b/drivers/char/watchdog/wdt.c @@ -579,4 +579,6 @@ module_exit(wdt_exit); MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("Driver for ISA ICS watchdog cards (WDT500/501)"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +MODULE_ALIAS_MISCDEV(TEMP_MINOR); MODULE_LICENSE("GPL"); diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 17f00f61c3ac..1dcd06f98144 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -835,6 +835,13 @@ config BLK_DEV_IDEDMA_PMAC to transfer data to and from memory. Saying Y is safe and improves performance. +config BLK_DEV_IDE_PMAC_BLINK + bool "Blink laptop LED on drive activity" + depends on BLK_DEV_IDE_PMAC && ADB_PMU + help + This option enables the use of the sleep LED as a hard drive + activity LED. + config BLK_DEV_IDEDMA_PMAC_AUTO bool "Use DMA by default" depends on BLK_DEV_IDEDMA_PMAC diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 578476e1e931..fd5874b891db 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -3318,7 +3318,6 @@ static ide_driver_t ide_cdrom_driver = { .version = IDECD_VERSION, .media = ide_cdrom, .busy = 0, - .supports_dma = 1, .supports_dsc_overlap = 1, .cleanup = ide_cdrom_cleanup, .do_request = ide_do_rw_cdrom, diff --git a/drivers/ide/ide-default.c b/drivers/ide/ide-default.c index 40ecc4de0c05..0c251121a740 100644 --- a/drivers/ide/ide-default.c +++ b/drivers/ide/ide-default.c @@ -40,18 +40,12 @@ static int idedefault_attach(ide_drive_t *drive); /* * IDE subdriver functions, registered with ide.c - * - * idedefault *must* support DMA because it will be - * attached before the other drivers are loaded and - * we don't want to lose the DMA status at probe - * time. */ ide_driver_t idedefault_driver = { .name = "ide-default", .version = IDEDEFAULT_VERSION, .attach = idedefault_attach, - .supports_dma = 1, .drives = LIST_HEAD_INIT(idedefault_driver.drives) }; diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 1217e840ac02..8bf402224197 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -1689,7 +1689,8 @@ static void idedisk_setup (ide_drive_t *drive) write_cache(drive, (id->cfs_enable_2 & 0x3000)); #ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT - HWIF(drive)->ide_dma_queued_on(drive); + if (drive->using_dma) + HWIF(drive)->ide_dma_queued_on(drive); #endif } @@ -1716,7 +1717,6 @@ static ide_driver_t idedisk_driver = { .version = IDEDISK_VERSION, .media = ide_disk, .busy = 0, - .supports_dma = 1, .supports_dsc_overlap = 0, .cleanup = idedisk_cleanup, .flushcache = do_idedisk_flushcache, diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 112dc8b8676d..4a2a7273b8b4 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1854,7 +1854,6 @@ static ide_driver_t idefloppy_driver = { .version = IDEFLOPPY_VERSION, .media = ide_floppy, .busy = 0, - .supports_dma = 1, .supports_dsc_overlap = 0, .cleanup = idefloppy_cleanup, .do_request = idefloppy_do_request, diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 2b94c9450336..0d9fff1f883d 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -1387,7 +1387,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio unsigned long flags; ide_hwgroup_t *hwgroup = HWGROUP(drive); DECLARE_COMPLETION(wait); - int insert_end = 1, err; + int where = ELEVATOR_INSERT_BACK, err; int must_wait = (action == ide_wait || action == ide_head_wait); #ifdef CONFIG_BLK_DEV_PDC4030 @@ -1419,10 +1419,10 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio spin_lock_irqsave(&ide_lock, flags); if (action == ide_preempt || action == ide_head_wait) { hwgroup->rq = NULL; - insert_end = 0; + where = ELEVATOR_INSERT_FRONT; rq->flags |= REQ_PREEMPT; } - __elv_add_request(drive->queue, rq, insert_end, 0); + __elv_add_request(drive->queue, rq, where, 0); ide_do_request(hwgroup, IDE_NO_IRQ); spin_unlock_irqrestore(&ide_lock, flags); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index cb18ac6fa2b7..ef80249cda49 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -958,6 +958,10 @@ static int ide_init_queue(ide_drive_t *drive) /* needs drive->queue to be set */ ide_toggle_bounce(drive, 1); + /* enable led activity for disk drives only */ + if (drive->media == ide_disk && hwif->led_act) + blk_queue_activity_fn(q, hwif->led_act, drive); + return 0; } diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index e2bdaa457727..6c8c067df5a7 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -6316,7 +6316,6 @@ static ide_driver_t idetape_driver = { .version = IDETAPE_VERSION, .media = ide_tape, .busy = 1, - .supports_dma = 1, .supports_dsc_overlap = 1, .cleanup = idetape_cleanup, .do_request = idetape_do_request, diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 8ff22ad3f648..b6b7c97bf090 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1359,8 +1359,6 @@ static int set_io_32bit(ide_drive_t *drive, int arg) static int set_using_dma (ide_drive_t *drive, int arg) { - if (!DRIVER(drive)->supports_dma) - return -EPERM; if (!drive->id || !(drive->id->capability & 1)) return -EPERM; if (HWIF(drive)->ide_dma_check == NULL) @@ -2406,6 +2404,13 @@ static ide_startstop_t default_abort (ide_drive_t *drive, const char *msg) return ide_abort(drive, msg); } +static ide_startstop_t default_start_power_step(ide_drive_t *drive, + struct request *rq) +{ + rq->pm->pm_step = ide_pm_state_completed; + return ide_stopped; +} + static void setup_driver_defaults (ide_driver_t *d) { if (d->cleanup == NULL) d->cleanup = default_cleanup; @@ -2420,6 +2425,8 @@ static void setup_driver_defaults (ide_driver_t *d) if (d->capacity == NULL) d->capacity = default_capacity; if (d->special == NULL) d->special = default_special; if (d->attach == NULL) d->attach = default_attach; + if (d->start_power_step == NULL) + d->start_power_step = default_start_power_step; } int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version) @@ -2443,9 +2450,6 @@ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int versio if ((drive->autotune == IDE_TUNE_DEFAULT) || (drive->autotune == IDE_TUNE_AUTO)) { /* DMA timings and setup moved to ide-probe.c */ - if (!driver->supports_dma && HWIF(drive)->ide_dma_off_quietly) -// HWIF(drive)->ide_dma_off_quietly(drive); - HWIF(drive)->ide_dma_off(drive); drive->dsc_overlap = (drive->next != drive && driver->supports_dsc_overlap); drive->nice1 = 1; } diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index fdfc45505db7..0bce7cd0427d 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -140,6 +140,7 @@ static struct pci_device_id generic_pci_tbl[] = { { PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7}, { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8}, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, { 0, }, }; diff --git a/drivers/ide/pci/generic.h b/drivers/ide/pci/generic.h index 38b8c72f5966..3898e2f85f95 100644 --- a/drivers/ide/pci/generic.h +++ b/drivers/ide/pci/generic.h @@ -127,6 +127,19 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = { .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, .bootable = ON_BOARD, .extra = 0, + },{ /* 9 */ + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8237_SATA, + .name = "VIA8237SATA", + .init_chipset = init_chipset_generic, + .init_iops = NULL, + .init_hwif = init_hwif_generic, + .init_dma = init_dma_generic, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0, },{ .vendor = 0, .device = 0, diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 4bcd3bb1a1f5..3ab58903e6a0 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -748,9 +748,6 @@ static void __init init_hwif_pdc202xx (ide_hwif_t *hwif) hwif->tuneproc = &config_chipset_for_pio; hwif->quirkproc = &pdc202xx_quirkproc; - if (hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20265) - hwif->no_lba48 = (hwif->channel) ? 0 : 1; - if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) { hwif->busproc = &pdc202xx_tristate; hwif->resetproc = &pdc202xx_reset; diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 8ba89df109fa..c7e6774242c3 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -582,6 +582,7 @@ void i8042_controller_cleanup(void) static int __init i8042_check_mux(struct i8042_values *values) { unsigned char param; + static int i8042_check_mux_cookie; int i; /* @@ -589,9 +590,9 @@ static int __init i8042_check_mux(struct i8042_values *values) */ if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ, - "i8042", i8042_request_irq_cookie)) + "i8042", &i8042_check_mux_cookie)) return -1; - free_irq(values->irq, i8042_request_irq_cookie); + free_irq(values->irq, &i8042_check_mux_cookie); /* * Get rid of bytes in the queue. @@ -654,6 +655,7 @@ static int __init i8042_check_mux(struct i8042_values *values) static int __init i8042_check_aux(struct i8042_values *values) { unsigned char param; + static int i8042_check_aux_cookie; /* * Check if AUX irq is available. If it isn't, then there is no point @@ -661,9 +663,9 @@ static int __init i8042_check_aux(struct i8042_values *values) */ if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ, - "i8042", i8042_request_irq_cookie)) + "i8042", &i8042_check_aux_cookie)) return -1; - free_irq(values->irq, i8042_request_irq_cookie); + free_irq(values->irq, &i8042_check_aux_cookie); /* * Get rid of bytes in the queue. diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 65b8dbcc0bce..c66ccbf9c037 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -24,6 +24,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_DESCRIPTION("Input device TTY line discipline"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_LDISC(N_MOUSE); #define SERPORT_BUSY 1 diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 2bf1a17b6c0f..8404fefda237 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -412,7 +412,7 @@ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) { struct sk_buff *nskb; - unsigned int datalen; + int datalen; u16 errcode, datahandle; datalen = skb->len - CAPIMSG_LEN(skb->data); @@ -552,12 +552,12 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) struct capincci *np; u32 ncci; - if (CAPIMSG_COMMAND(skb->data) == CAPI_CONNECT_B3_CONF) { + if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) { u16 info = CAPIMSG_U16(skb->data, 12); // Info field if (info == 0) capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); } - if (CAPIMSG_COMMAND(skb->data) == CAPI_CONNECT_B3_IND) { + if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND) { capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); } if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) { @@ -688,7 +688,7 @@ capi_write(struct file *file, const char *buf, size_t count, loff_t *ppos) } mlen = CAPIMSG_LEN(skb->data); if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) { - if (mlen + CAPIMSG_DATALEN(skb->data) != count) { + if ((size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) { kfree_skb(skb); return -EINVAL; } @@ -700,7 +700,7 @@ capi_write(struct file *file, const char *buf, size_t count, loff_t *ppos) } CAPIMSG_SETAPPID(skb->data, cdev->ap.applid); - if (CAPIMSG_COMMAND(skb->data) == CAPI_DISCONNECT_B3_RESP) { + if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) { capincci_free(cdev, CAPIMSG_NCCI(skb->data)); } diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 8ea64ec7eea3..cdd1b90334ce 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -48,7 +48,7 @@ MODULE_PARM(debugmode, "i"); struct capidrv_contr { struct capidrv_contr *next; - + struct module *owner; u32 contrnr; char name[20]; @@ -1816,7 +1816,7 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb) capidrv_bchan *bchan; capidrv_ncci *nccip; int len = skb->len; - size_t msglen; + int msglen; u16 errcode; u16 datahandle; @@ -1844,7 +1844,7 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb) 0 /* Flags */ ); - if (capidrv_add_ack(nccip, datahandle, doack ? skb->len : -1) < 0) + if (capidrv_add_ack(nccip, datahandle, doack ? (int)skb->len : -1) < 0) return 0; capi_cmsg2message(&sendcmsg, sendcmsg.buf); @@ -1990,16 +1990,19 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) char id[20]; int i; - MOD_INC_USE_COUNT; - sprintf(id, "capidrv-%d", contr); if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) { printk(KERN_WARNING "capidrv: (%s) Could not allocate contr-struct.\n", id); - MOD_DEC_USE_COUNT; return -1; } memset(card, 0, sizeof(capidrv_contr)); + card->owner = THIS_MODULE; + if (!try_module_get(card->owner)) { + printk(KERN_WARNING "capidrv: (%s) Could not reserve module\n", id); + kfree(card); + return -1; + } init_timer(&card->listentimer); strcpy(card->name, id); card->contrnr = contr; @@ -2008,8 +2011,8 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) if (!card->bchans) { printk(KERN_WARNING "capidrv: (%s) Could not allocate bchan-structs.\n", id); + module_put(card->owner); kfree(card); - MOD_DEC_USE_COUNT; return -1; } card->interface.channels = profp->nbchannel; @@ -2042,8 +2045,8 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) if (!register_isdn(&card->interface)) { printk(KERN_ERR "capidrv: Unable to register contr %s\n", id); kfree(card->bchans); + module_put(card->owner); kfree(card); - MOD_DEC_USE_COUNT; return -1; } card->myid = card->interface.channels; @@ -2153,12 +2156,9 @@ static int capidrv_delcontr(u16 contr) } spin_unlock_irqrestore(&global_lock, flags); + module_put(card->owner); printk(KERN_INFO "%s: now down.\n", card->name); - kfree(card); - - MOD_DEC_USE_COUNT; - return 0; } @@ -2245,8 +2245,6 @@ static int __init capidrv_init(void) u32 ncontr, contr; u16 errcode; - MOD_INC_USE_COUNT; - if ((p = strchr(revision, ':')) != 0 && p[1]) { strncpy(rev, p + 2, sizeof(rev)); rev[sizeof(rev)-1] = 0; @@ -2262,7 +2260,6 @@ static int __init capidrv_init(void) global.ap.recv_message = capidrv_recv_message; errcode = capi20_register(&global.ap); if (errcode) { - MOD_DEC_USE_COUNT; return -EIO; } @@ -2271,7 +2268,6 @@ static int __init capidrv_init(void) errcode = capi20_get_profile(0, &profile); if (errcode != CAPI_NOERROR) { capi20_release(&global.ap); - MOD_DEC_USE_COUNT; return -EIO; } @@ -2285,8 +2281,6 @@ static int __init capidrv_init(void) proc_init(); printk(KERN_NOTICE "capidrv: Rev %s: loaded\n", rev); - MOD_DEC_USE_COUNT; - return 0; } diff --git a/drivers/isdn/capi/capilib.c b/drivers/isdn/capi/capilib.c index f9b33ffb8290..00d8795b9cc7 100644 --- a/drivers/isdn/capi/capilib.c +++ b/drivers/isdn/capi/capilib.c @@ -29,7 +29,7 @@ struct capilib_ncci { static inline void mq_init(struct capilib_ncci * np) { - int i; + u_int i; np->msgidqueue = 0; np->msgidlast = 0; np->nmsg = 0; diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index c59fe4fc0211..b78f7b1dc021 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -72,7 +72,7 @@ static struct sk_buff_head recv_queue; static struct work_struct tq_state_notify; static struct work_struct tq_recv_notify; -/* -------- ref counting -------------------------------------- */ +/* -------- controller ref counting -------------------------------------- */ static inline struct capi_ctr * capi_ctr_get(struct capi_ctr *card) @@ -89,6 +89,21 @@ capi_ctr_put(struct capi_ctr *card) DBG("MOD_COUNT DEC"); } +/* -------- own ref counting -------------------------------------- */ + +static inline void +kcapi_get_ref(void) +{ + if (!try_module_get(THIS_MODULE)) + printk(KERN_WARNING "%s: cannot reserve module\n", __FUNCTION__); +} + +static inline void +kcapi_put_ref(void) +{ + module_put(THIS_MODULE); +} + /* ------------------------------------------------------------- */ static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr) @@ -209,10 +224,10 @@ static int notify_push(unsigned int cmd, u32 controller, { struct capi_notifier *np; - MOD_INC_USE_COUNT; + kcapi_get_ref(); np = (struct capi_notifier *)kmalloc(sizeof(struct capi_notifier), GFP_ATOMIC); if (!np) { - MOD_DEC_USE_COUNT; + kcapi_put_ref(); return -1; } memset(np, 0, sizeof(struct capi_notifier)); @@ -226,9 +241,9 @@ static int notify_push(unsigned int cmd, u32 controller, * of devices. Devices can only removed in * user process, not in bh. */ - MOD_INC_USE_COUNT; + kcapi_get_ref(); if (schedule_work(&tq_state_notify) == 0) - MOD_DEC_USE_COUNT; + kcapi_put_ref(); return 0; } @@ -286,9 +301,9 @@ static void notify_handler(void *dummy) while ((np = notify_dequeue()) != 0) { notify_doit(np); kfree(np); - MOD_DEC_USE_COUNT; + kcapi_put_ref(); } - MOD_DEC_USE_COUNT; + kcapi_put_ref(); } /* -------- Receiver ------------------------------------------ */ @@ -626,19 +641,18 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) EXPORT_SYMBOL(capi20_put_message); -u16 capi20_get_manufacturer(u32 contr, u8 buf[CAPI_MANUFACTURER_LEN]) +u16 capi20_get_manufacturer(u32 contr, u8 *buf) { struct capi_ctr *card; if (contr == 0) { - strlcpy(buf, capi_manufakturer, sizeof(buf)); + strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } card = get_capi_ctr_by_nr(contr); if (!card || card->cardstate != CARD_RUNNING) return CAPI_REGNOTINSTALLED; - - strlcpy(buf, card->manu, sizeof(buf)); + strlcpy(buf, card->manu, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } @@ -662,19 +676,19 @@ u16 capi20_get_version(u32 contr, struct capi_version *verp) EXPORT_SYMBOL(capi20_get_version); -u16 capi20_get_serial(u32 contr, u8 serial[CAPI_SERIAL_LEN]) +u16 capi20_get_serial(u32 contr, u8 *serial) { struct capi_ctr *card; if (contr == 0) { - strlcpy(serial, driver_serial, sizeof(serial)); + strlcpy(serial, driver_serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } card = get_capi_ctr_by_nr(contr); if (!card || card->cardstate != CARD_RUNNING) return CAPI_REGNOTINSTALLED; - strlcpy((void *) serial, card->serial, sizeof(serial)); + strlcpy((void *) serial, card->serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } diff --git a/drivers/isdn/hardware/avm/avmcard.h b/drivers/isdn/hardware/avm/avmcard.h index 84b73da5d1bf..1a0ca874e882 100644 --- a/drivers/isdn/hardware/avm/avmcard.h +++ b/drivers/isdn/hardware/avm/avmcard.h @@ -95,8 +95,8 @@ typedef struct avmcard { struct avmctrl_info *ctrlinfo; - int nr_controllers; - int nlogcontr; + u_int nr_controllers; + u_int nlogcontr; struct list_head list; } avmcard; diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c index b056d619af93..22894a9a72e1 100644 --- a/drivers/isdn/hardware/avm/b1.c +++ b/drivers/isdn/hardware/avm/b1.c @@ -148,30 +148,31 @@ void b1_getrevision(avmcard *card) card->revision = inb(card->port + B1_REVISION); } +#define FWBUF_SIZE 256 int b1_load_t4file(avmcard *card, capiloaddatapart * t4file) { - unsigned char buf[256]; + unsigned char buf[FWBUF_SIZE]; unsigned char *dp; int i, left; unsigned int base = card->port; dp = t4file->data; left = t4file->len; - while (left > sizeof(buf)) { + while (left > FWBUF_SIZE) { if (t4file->user) { - if (copy_from_user(buf, dp, sizeof(buf))) + if (copy_from_user(buf, dp, FWBUF_SIZE)) return -EFAULT; } else { - memcpy(buf, dp, sizeof(buf)); + memcpy(buf, dp, FWBUF_SIZE); } - for (i = 0; i < sizeof(buf); i++) + for (i = 0; i < FWBUF_SIZE; i++) if (b1_save_put_byte(base, buf[i]) < 0) { printk(KERN_ERR "%s: corrupted firmware file ?\n", card->name); return -EIO; } - left -= sizeof(buf); - dp += sizeof(buf); + left -= FWBUF_SIZE; + dp += FWBUF_SIZE; } if (left) { if (t4file->user) { @@ -192,7 +193,7 @@ int b1_load_t4file(avmcard *card, capiloaddatapart * t4file) int b1_load_config(avmcard *card, capiloaddatapart * config) { - unsigned char buf[256]; + unsigned char buf[FWBUF_SIZE]; unsigned char *dp; unsigned int base = card->port; int i, j, left; @@ -205,21 +206,21 @@ int b1_load_config(avmcard *card, capiloaddatapart * config) b1_put_byte(base, SEND_CONFIG); b1_put_word(base, left); } - while (left > sizeof(buf)) { + while (left > FWBUF_SIZE) { if (config->user) { - if (copy_from_user(buf, dp, sizeof(buf))) + if (copy_from_user(buf, dp, FWBUF_SIZE)) return -EFAULT; } else { - memcpy(buf, dp, sizeof(buf)); + memcpy(buf, dp, FWBUF_SIZE); } - for (i = 0; i < sizeof(buf); ) { + for (i = 0; i < FWBUF_SIZE; ) { b1_put_byte(base, SEND_CONFIG); for (j=0; j < 4; j++) { b1_put_byte(base, buf[i++]); } } - left -= sizeof(buf); - dp += sizeof(buf); + left -= FWBUF_SIZE; + dp += FWBUF_SIZE; } if (left) { if (config->user) { @@ -785,7 +786,7 @@ static int __init b1_init(void) char rev[32]; if ((p = strchr(revision, ':')) != 0 && p[1]) { - strlcpy(rev, p + 2, sizeof(rev)); + strlcpy(rev, p + 2, 32); if ((p = strchr(rev, '$')) != 0 && p > rev) *(p-1) = 0; } else diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c index ac0a85458616..c4817536e324 100644 --- a/drivers/isdn/hardware/avm/c4.c +++ b/drivers/isdn/hardware/avm/c4.c @@ -189,7 +189,7 @@ static int c4_load_t4file(avmcard *card, capiloaddatapart * t4file) { u32 val; unsigned char *dp; - int left; + u_int left; u32 loadoff = 0; dp = t4file->data; @@ -664,7 +664,7 @@ static irqreturn_t c4_handle_interrupt(avmcard *card) u32 status = c4inmeml(card->mbase+DOORBELL); if (status & DBELL_RESET_HOST) { - int i; + u_int i; c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c); if (card->nlogcontr == 0) return IRQ_HANDLED; @@ -791,7 +791,8 @@ static int c4_send_config(avmcard *card, capiloaddatapart * config) { u8 val[4]; unsigned char *dp; - int left, retval; + u_int left; + int retval; if ((retval = queue_sendconfigword(card, 1)) != 0) return retval; @@ -880,7 +881,7 @@ void c4_reset_ctr(struct capi_ctr *ctrl) { avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card; avmctrl_info *cinfo; - int i; + u_int i; c4_reset(card); @@ -896,7 +897,7 @@ static void c4_remove(struct pci_dev *pdev) { avmcard *card = pci_get_drvdata(pdev); avmctrl_info *cinfo; - int i; + u_int i; c4_reset(card); diff --git a/drivers/isdn/hardware/eicon/capifunc.c b/drivers/isdn/hardware/eicon/capifunc.c index ebd22420ca36..216c644c9350 100644 --- a/drivers/isdn/hardware/eicon/capifunc.c +++ b/drivers/isdn/hardware/eicon/capifunc.c @@ -22,8 +22,8 @@ #define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR) #define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG) -static DIVA_CAPI_ADAPTER *adapter = (DIVA_CAPI_ADAPTER *) NULL; -static APPL *application = (APPL *) NULL; +DIVA_CAPI_ADAPTER *adapter = (DIVA_CAPI_ADAPTER *) NULL; +APPL *application = (APPL *) NULL; byte max_appl = MAX_APPL; static CAPI_MSG *mapped_msg = (CAPI_MSG *) NULL; @@ -45,7 +45,7 @@ static dword notify_handle; static void DIRequest(ENTITY * e); static DESCRIPTOR MAdapter; static DESCRIPTOR DAdapter; -static byte max_adapter = 0; +byte max_adapter = 0; static byte ControllerMap[MAX_DESCRIPTORS + 1]; @@ -111,7 +111,7 @@ static void no_printf(unsigned char *x, ...) /* * Controller mapping */ -static byte MapController(byte Controller) +byte MapController(byte Controller) { byte i; byte MappedController = 0; @@ -750,8 +750,6 @@ static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl, void **xbuffer_ptr, **xbuffer_internal; diva_os_spin_lock_magic_t old_irql; - DIVA_LOCK_MODULE; - if (diva_os_in_irq()) { DBG_ERR(("CAPI_REGISTER - in irq context !")) return; @@ -777,6 +775,11 @@ static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl, return; /* appl already registered */ } + if (!try_module_get(ctrl->owner)) { + printk(KERN_WARNING "%s: cannot reserve module\n", __FUNCTION__); + return; + } + /* alloc memory */ bnum = rp->level3cnt * rp->datablkcnt; @@ -784,6 +787,7 @@ static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl, if (!(DataNCCI = diva_os_malloc(0, bnum * sizeof(word)))) { DBG_ERR(("CAPI_REGISTER - memory allocation failed")) + module_put(ctrl->owner); return; } memset(DataNCCI, 0, bnum * sizeof(word)); @@ -791,6 +795,7 @@ static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl, if (!(DataFlags = diva_os_malloc(0, bnum * sizeof(word)))) { DBG_ERR(("CAPI_REGISTER - memory allocation failed")) diva_os_free(0, DataNCCI); + module_put(ctrl->owner); return; } memset(DataFlags, 0, bnum * sizeof(word)); @@ -799,6 +804,7 @@ static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl, DBG_ERR(("CAPI_REGISTER - memory allocation failed")) diva_os_free(0, DataNCCI); diva_os_free(0, DataFlags); + module_put(ctrl->owner); return; } memset(ReceiveBuffer, 0, bnum * rp->datablklen); @@ -808,6 +814,7 @@ static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl, diva_os_free(0, DataNCCI); diva_os_free(0, DataFlags); diva_os_free(0, ReceiveBuffer); + module_put(ctrl->owner); return; } memset(xbuffer_used, 0, xnum); @@ -818,6 +825,7 @@ static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl, diva_os_free(0, DataFlags); diva_os_free(0, ReceiveBuffer); diva_os_free(0, xbuffer_used); + module_put(ctrl->owner); return; } memset(xbuffer_ptr, 0, xnum * sizeof(void *)); @@ -829,6 +837,7 @@ static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl, diva_os_free(0, ReceiveBuffer); diva_os_free(0, xbuffer_used); diva_os_free(0, xbuffer_ptr); + module_put(ctrl->owner); return; } memset(xbuffer_internal, 0, xnum * sizeof(void *)); @@ -848,6 +857,7 @@ static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl, diva_os_free(0, xbuffer_used); diva_os_free(0, xbuffer_ptr); diva_os_free(0, xbuffer_internal); + module_put(ctrl->owner); return; } } @@ -935,7 +945,7 @@ static void diva_release_appl(struct capi_ctr *ctrl, __u16 appl) } diva_os_leave_spin_lock(&api_lock, &old_irql, "release_appl"); - DIVA_UNLOCK_MODULE; + module_put(ctrl->owner); } /* diff --git a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h index ba6da6581303..bfb939de6c88 100644 --- a/drivers/isdn/hardware/eicon/platform.h +++ b/drivers/isdn/hardware/eicon/platform.h @@ -201,8 +201,10 @@ void diva_os_remove_irq (void* context, byte irq); /* ** module locking */ +/* #define DIVA_LOCK_MODULE MOD_INC_USE_COUNT #define DIVA_UNLOCK_MODULE MOD_DEC_USE_COUNT +*/ /* ** Spin Lock framework diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c index b37a16780800..a099990777ae 100644 --- a/drivers/isdn/hisax/amd7930_fn.c +++ b/drivers/isdn/hisax/amd7930_fn.c @@ -692,7 +692,7 @@ dbusy_timer_handler(struct IsdnCardState *cs) if (cs->debug & L1_DEB_ISAC) debugl1(cs, "Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u", dsr1, dsr2, der, cs->tx_skb->len, cs->dc.amd7930.tx_xmtlen, dtcr, cs->tx_cnt); - if ((cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) { /* D-Channel Busy */ + if ((int)(cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) { /* D-Channel Busy */ test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); stptr = cs->stlist; while (stptr != NULL) { diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c index 533f4148bc67..ecd9cd18f375 100644 --- a/drivers/isdn/hisax/callc.c +++ b/drivers/isdn/hisax/callc.c @@ -1758,7 +1758,7 @@ HiSax_command(isdn_ctrl * ic) /* protocol specific io commands */ case (ISDN_CMD_PROT_IO): for (st = csta->stlist; st; st = st->next) - if (st->protocol == (ic->arg & 0xFF)) + if ((u_int)st->protocol == (ic->arg & 0xFF)) return(st->l3.l4l3_proto(st, ic)); return(-EINVAL); break; diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index b9996317376b..66ab32452a2b 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -751,17 +751,17 @@ setup_diva(struct IsdnCard *card) card->para[1] = pnp_port_start(pd, 0); card->para[0] = pnp_irq(pd, 0); if (pdev->function == ISAPNP_FUNCTION(0xA1)) { - if (diva_ipac_isa_probe(cs->card, cs)) + if (diva_ipac_isa_probe(card->cs, card)) return 0; return 1; } else { - if (diva_isac_isa_probe(cs->card, cs)) + if (diva_isac_isa_probe(card->cs, card)) return 0; return 1; - } else { - printk(KERN_ERR "Diva PnP: PnP error card found, no device\n"); - return(0); } + } else { + printk(KERN_ERR "Diva PnP: PnP error card found, no device\n"); + return(0); } pdev++; pnp_c=NULL; diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index 37d6321ff4ca..219374604e7c 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -838,7 +838,7 @@ elsa_probe(struct IsdnCardState *cs, struct IsdnCard *card) cs->hw.elsa.status |= ELSA_BAD_PWR; } switch (cs->subtyp) { - case ELSA_PCFPRO: bytecnt = 16; break; + case ELSA_PCFPRO: bytecnt = 16; break; } if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) goto err; diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c index ebfa936d6796..2332436a43ed 100644 --- a/drivers/isdn/hisax/elsa_ser.c +++ b/drivers/isdn/hisax/elsa_ser.c @@ -255,7 +255,7 @@ inline int write_modem(struct BCState *bcs) { int ret=0; struct IsdnCardState *cs = bcs->cs; - int count, len, fp; + u_int count, len, fp; unsigned long flags; if (!bcs->tx_skb) @@ -435,8 +435,8 @@ close_elsastate(struct BCState *bcs) } void -modem_write_cmd(struct IsdnCardState *cs, u8 *buf, int len) { - int count, fp; +modem_write_cmd(struct IsdnCardState *cs, u8 *buf, u_int len) { + u_int count, fp; u8 *msg = buf; unsigned long flags; diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c index 9435ea9976bd..5fe4f4ec687d 100644 --- a/drivers/isdn/hisax/hfc_2bds0.c +++ b/drivers/isdn/hisax/hfc_2bds0.c @@ -264,8 +264,9 @@ static void hfc_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - int idx, fcnt; - int count; + u_int idx; + int fcnt; + u_int count; u8 cip; if (!bcs->tx_skb) @@ -636,8 +637,8 @@ int receive_dmsg(struct IsdnCardState *cs) static void hfc_fill_dfifo(struct IsdnCardState *cs) { - int idx, fcnt; - int count; + int fcnt; + u_int idx, count; u8 cip; if (!cs->tx_skb) diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c index c1c106f59a2a..0cbb11c62ebe 100644 --- a/drivers/isdn/hisax/hfc_2bs0.c +++ b/drivers/isdn/hisax/hfc_2bs0.c @@ -249,8 +249,8 @@ static void hfc_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - int idx, fcnt; - int count; + int fcnt; + u_int idx, count; int z1, z2; u8 cip; diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 014fc9bb44e7..c23175e5f948 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -487,8 +487,8 @@ main_rec_hfcpci(struct BCState *bcs) static void hfcpci_fill_dfifo(struct IsdnCardState *cs) { - int fcnt; - int count, new_z1, maxlen; + int fcnt, new_z1, maxlen; + u_int count; dfifo_type *df; u8 *src, *dst, new_f1; @@ -533,7 +533,7 @@ hfcpci_fill_dfifo(struct IsdnCardState *cs) src = cs->tx_skb->data; /* source pointer */ dst = df->data + le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1); maxlen = D_FIFO_SIZE - le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1); /* end fifo */ - if (maxlen > count) + if (maxlen > (int)count) maxlen = count; /* limit size */ memcpy(dst, src, maxlen); /* first copy */ @@ -559,8 +559,8 @@ static void hfcpci_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - int maxlen, fcnt; - int count, new_z1; + int maxlen, fcnt, new_z1; + u_int count; bzfifo_type *bz; u8 *bdata; u8 new_f1, *src, *dst; @@ -591,7 +591,7 @@ hfcpci_fill_fifo(struct BCState *bcs) fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */ while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) { - if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) { + if ((int)bcs->tx_skb->len < (B_FIFO_SIZE - fcnt)) { /* data is suitable for fifo */ count = bcs->tx_skb->len; @@ -601,7 +601,7 @@ hfcpci_fill_fifo(struct BCState *bcs) src = bcs->tx_skb->data; /* source pointer */ dst = bdata + (le16_to_cpu(*z1t) - B_SUB_VAL); maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(*z1t); /* end of fifo */ - if (maxlen > count) + if (maxlen > (int)count) maxlen = count; /* limit size */ memcpy(dst, src, maxlen); /* first copy */ @@ -661,7 +661,7 @@ hfcpci_fill_fifo(struct BCState *bcs) src = bcs->tx_skb->data; /* source pointer */ dst = bdata + (le16_to_cpu(bz->za[bz->f1].z1) - B_SUB_VAL); maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(bz->za[bz->f1].z1); /* end fifo */ - if (maxlen > count) + if (maxlen > (int)count) maxlen = count; /* limit size */ memcpy(dst, src, maxlen); /* first copy */ diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c index 66b09ddbe379..461c5fce51b1 100644 --- a/drivers/isdn/hisax/hfc_sx.c +++ b/drivers/isdn/hisax/hfc_sx.c @@ -145,7 +145,7 @@ write_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u8 fifo, int trans_max count = z2 - z1; if (count <= 0) count += fifo_size; /* free bytes */ - if (count < skb->len+1) return(0); /* no room */ + if (count < (int)(skb->len+1)) return(0); /* no room */ count = fifo_size - count; /* bytes still not send */ if (count > 2 * trans_max) return(0); /* delay too long */ count = skb->len; @@ -182,7 +182,7 @@ write_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u8 fifo, int trans_max if (cs->debug & L1_DEB_ISAC_FIFO) debugl1(cs, "hfcsx_write_fifo %d count(%ld/%d)", fifo, skb->len, count); - if (count < skb->len) { + if (count < (int)skb->len) { if (cs->debug & L1_DEB_ISAC_FIFO) debugl1(cs, "hfcsx_write_fifo %d no fifo mem", fifo); return(0); diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index f32fe99a733a..e4d7a1962a74 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -265,7 +265,7 @@ struct Layer1 { struct Layer2 { int tei; int sap; - int maxlen; + u_int maxlen; unsigned long flag; unsigned int vs, va, vr; int rc; diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c index 614dcd007d61..820aa5281c84 100644 --- a/drivers/isdn/hisax/hisax_fcpcipnp.c +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c @@ -38,6 +38,8 @@ #define __debug_variable debug #include "hisax_debug.h" +// #define CONFIG_PNP_CARD 1 + #ifdef CONFIG_HISAX_DEBUG static int debug = 0; MODULE_PARM(debug, "i"); @@ -365,8 +367,8 @@ static void hdlc_fill_fifo(struct fritz_bcs *bcs) { struct fritz_adapter *adapter = bcs->adapter; struct sk_buff *skb = bcs->tx_skb; - int count; - int fifo_size = 32; + u_int count; + u_int fifo_size = 32; unsigned long flags; unsigned char *p; diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c index ce64f0b1c02e..4af5224e745d 100644 --- a/drivers/isdn/hisax/ipacx.c +++ b/drivers/isdn/hisax/ipacx.c @@ -736,5 +736,6 @@ ipacx_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipacx_dc_ops, cs->bc_hw_ops = ipacx_bc_ops; val = ipacx_read_reg(cs, IPACX_ID) & 0x3f; printk(KERN_INFO "HiSax: IPACX Design Id: %#x\n", val); + return 0; } diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c index c4c15b3efbc2..f5b65950be33 100644 --- a/drivers/isdn/hisax/isar.c +++ b/drivers/isdn/hisax/isar.c @@ -677,7 +677,7 @@ isar_fill_fifo(struct BCState *bcs) if (!(bcs->hw.isar.reg->bstat & (bcs->hw.isar.dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2))) return; - if (bcs->tx_skb->len > bcs->hw.isar.mml) { + if (bcs->tx_skb->len > (u_int)bcs->hw.isar.mml) { msb = 0; count = bcs->hw.isar.mml; } else { diff --git a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h index 857f54ede027..2de24d2c067f 100644 --- a/drivers/isdn/hisax/isdnl1.h +++ b/drivers/isdn/hisax/isdnl1.h @@ -354,7 +354,7 @@ xmit_xdu_d(struct IsdnCardState *cs, void (*reset_xmit)(struct IsdnCardState *cs } static inline unsigned char * -xmit_fill_fifo_b(struct BCState *bcs, int fifo_size, int *count, int *more) +xmit_fill_fifo_b(struct BCState *bcs, u_int fifo_size, int *count, int *more) { struct IsdnCardState *cs = bcs->cs; unsigned char *p; @@ -391,7 +391,7 @@ xmit_fill_fifo_b(struct BCState *bcs, int fifo_size, int *count, int *more) } static inline unsigned char * -xmit_fill_fifo_d(struct IsdnCardState *cs, int fifo_size, int *count, int *more) +xmit_fill_fifo_d(struct IsdnCardState *cs, u_int fifo_size, int *count, int *more) { unsigned char *p; diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c index 87142482cf05..791b9d567a78 100644 --- a/drivers/isdn/hisax/isdnl2.c +++ b/drivers/isdn/hisax/isdnl2.c @@ -103,7 +103,7 @@ static char *strL2Event[] = "EV_L2_FRAME_ERROR", }; -static int l2addrsize(struct Layer2 *l2); +static u_int l2addrsize(struct Layer2 *l2); static void set_peer_busy(struct Layer2 *l2) { @@ -178,14 +178,14 @@ clear_exception(struct Layer2 *l2) clear_peer_busy(l2); } -inline int +inline u_int l2headersize(struct Layer2 *l2, int ui) { return (((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) + (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1)); } -inline int +inline u_int l2addrsize(struct Layer2 *l2) { return (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1); @@ -295,7 +295,7 @@ IsRNR(u8 * data, struct PStack *st) int iframe_error(struct PStack *st, struct sk_buff *skb) { - int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1); + u_int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1); int rsp = *skb->data & 0x2; if (test_bit(FLG_ORIG, &st->l2.flag)) @@ -360,7 +360,7 @@ UI_error(struct PStack *st, struct sk_buff *skb) int FRMR_error(struct PStack *st, struct sk_buff *skb) { - int headers = l2addrsize(&st->l2) + 1; + u_int headers = l2addrsize(&st->l2) + 1; u8 *datap = skb->data + headers; int rsp = *skb->data & 0x2; @@ -1066,8 +1066,8 @@ l2_got_iframe(struct FsmInst *fi, int event, void *arg) struct PStack *st = fi->userdata; struct sk_buff *skb = arg; struct Layer2 *l2 = &(st->l2); - int PollFlag, ns, i; - unsigned int nr; + int PollFlag, i; + unsigned int nr, ns; i = l2addrsize(l2); if (test_bit(FLG_MOD128, &l2->flag)) { @@ -1251,8 +1251,7 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) struct sk_buff *skb, *oskb; struct Layer2 *l2 = &st->l2; u8 header[MAX_HEADER_LEN]; - int i; - int unsigned p1; + int unsigned p1, i; unsigned long flags; if (!cansend(st)) @@ -1632,7 +1631,7 @@ isdnl2_l1l2(struct PStack *st, int pr, void *arg) { struct sk_buff *skb = arg; u8 *datap; - int ret = 1, len; + u_int ret = 1, len; int c = 0; switch (pr) { diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c index b99fb2f65b65..cff09671f592 100644 --- a/drivers/isdn/hisax/l3_1tr6.c +++ b/drivers/isdn/hisax/l3_1tr6.c @@ -302,7 +302,8 @@ static void l3_1tr6_info(struct l3_process *pc, u8 pr, void *arg) { u8 *p; - int i, tmpcharge = 0; + u_int i; + int tmpcharge = 0; char a_charge[8], tmp[32]; struct sk_buff *skb = arg; @@ -400,7 +401,8 @@ l3_1tr6_disc(struct l3_process *pc, u8 pr, void *arg) { struct sk_buff *skb = arg; u8 *p; - int i, tmpcharge = 0; + u_int i; + int tmpcharge = 0; char a_charge[8], tmp[32]; StopAllL3Timer(pc); @@ -753,7 +755,8 @@ static struct stateentry manstatelist[] = static void up1tr6(struct PStack *st, int pr, void *arg) { - int i, mt, cr; + u_int i; + int mt, cr; struct l3_process *proc; struct sk_buff *skb = arg; char tmp[80]; @@ -868,7 +871,8 @@ up1tr6(struct PStack *st, int pr, void *arg) static void down1tr6(struct PStack *st, int pr, void *arg) { - int i, cr; + u_int i; + int cr; struct l3_process *proc; struct Channel *chan; char tmp[80]; @@ -915,7 +919,7 @@ down1tr6(struct PStack *st, int pr, void *arg) static void man1tr6(struct PStack *st, int pr, void *arg) { - int i; + u_int i; struct l3_process *proc = arg; if (!proc) { diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c index a2cae62f6bcc..b7ae0a6546e1 100644 --- a/drivers/isdn/hisax/l3dss1.c +++ b/drivers/isdn/hisax/l3dss1.c @@ -736,7 +736,7 @@ check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist) p += l; mt = *p++; oldpos = 0; - while ((p - skb->data) < skb->len) { + while ((p - skb->data) < (int)skb->len) { if ((*p & 0xf0) == 0x90) { /* shift codeset */ old_codeset = codeset; codeset = *p & 7; @@ -2923,7 +2923,7 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb) u8 tmp[16]; u8 *p = tmp; int l; - int i; + u_int i; struct l3_process *proc = st->l3.global; proc->callref = skb->data[2]; /* cr flag */ @@ -2961,7 +2961,8 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb) static void dss1up(struct PStack *st, int pr, void *arg) { - int i, mt, cr, cause, callState; + u_int i; + int mt, cr, cause, callState; char *ptr; u8 *p; struct sk_buff *skb = arg; @@ -2998,7 +2999,7 @@ dss1up(struct PStack *st, int pr, void *arg) return; } cr = getcallref(skb->data); - if (skb->len < ((skb->data[1] & 0x0f) + 3)) { + if (skb->len < (u_int)((skb->data[1] & 0x0f) + 3)) { l3_debug(st, "dss1up frame too short(%d)", skb->len); dev_kfree_skb(skb); return; @@ -3135,7 +3136,8 @@ dss1up(struct PStack *st, int pr, void *arg) static void dss1down(struct PStack *st, int pr, void *arg) { - int i, cr; + u_int i; + int cr; struct l3_process *proc; struct Channel *chan; @@ -3186,29 +3188,29 @@ dss1down(struct PStack *st, int pr, void *arg) static void dss1man(struct PStack *st, int pr, void *arg) { - int i; - struct l3_process *proc = arg; - - if (!proc) { - printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr); - return; - } - for (i = 0; i < MANSLLEN; i++) + u_int i; + struct l3_process *proc = arg; + + if (!proc) { + printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr); + return; + } + for (i = 0; i < MANSLLEN; i++) if ((pr == manstatelist[i].primitive) && - ((1 << proc->state) & manstatelist[i].state)) - break; - if (i == MANSLLEN) { - if (st->l3.debug & L3_DEB_STATE) { - l3_debug(st, "cr %d dss1man state %d prim %#x unhandled", - proc->callref & 0x7f, proc->state, pr); - } - } else { - if (st->l3.debug & L3_DEB_STATE) { - l3_debug(st, "cr %d dss1man state %d prim %#x", - proc->callref & 0x7f, proc->state, pr); - } - manstatelist[i].rout(proc, pr, arg); - } + ((1 << proc->state) & manstatelist[i].state)) + break; + if (i == MANSLLEN) { + if (st->l3.debug & L3_DEB_STATE) { + l3_debug(st, "cr %d dss1man state %d prim %#x unhandled", + proc->callref & 0x7f, proc->state, pr); + } + } else { + if (st->l3.debug & L3_DEB_STATE) { + l3_debug(st, "cr %d dss1man state %d prim %#x", + proc->callref & 0x7f, proc->state, pr); + } + manstatelist[i].rout(proc, pr, arg); + } } void diff --git a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c index 94ea0d0f7f47..fc3ba29ee2c7 100644 --- a/drivers/isdn/hisax/l3ni1.c +++ b/drivers/isdn/hisax/l3ni1.c @@ -685,7 +685,7 @@ check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist) p += l; mt = *p++; oldpos = 0; - while ((p - skb->data) < skb->len) { + while ((u_int)(p - skb->data) < skb->len) { if ((*p & 0xf0) == 0x90) { /* shift codeset */ old_codeset = codeset; codeset = *p & 7; @@ -2859,7 +2859,7 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb) u8 tmp[16]; u8 *p = tmp; int l; - int i; + u_int i; struct l3_process *proc = st->l3.global; if ( skb ) @@ -2900,7 +2900,8 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb) static void ni1up(struct PStack *st, int pr, void *arg) { - int i, mt, cr, cause, callState; + u_int i; + int mt, cr, cause, callState; char *ptr; u8 *p; struct sk_buff *skb = arg; @@ -2941,7 +2942,7 @@ ni1up(struct PStack *st, int pr, void *arg) return; } cr = getcallref(skb->data); - if (skb->len < ((skb->data[1] & 0x0f) + 3)) { + if (skb->len < (u_int)((skb->data[1] & 0x0f) + 3)) { l3_debug(st, "ni1up frame too short(%d)", skb->len); dev_kfree_skb(skb); return; @@ -3086,7 +3087,8 @@ ni1up(struct PStack *st, int pr, void *arg) static void ni1down(struct PStack *st, int pr, void *arg) { - int i, cr; + u_int i; + int cr; struct l3_process *proc; struct Channel *chan; @@ -3137,7 +3139,7 @@ ni1down(struct PStack *st, int pr, void *arg) static void ni1man(struct PStack *st, int pr, void *arg) { - int i; + u_int i; struct l3_process *proc = arg; if (!proc) { diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index f832b1e26d62..311d3e9a6191 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c @@ -729,7 +729,7 @@ void netjet_fill_dma(struct BCState *bcs) static void write_raw(struct BCState *bcs, u_int *buf, int cnt) { u_int mask, val, *p=buf; - u_int i, s_cnt; + int i, s_cnt; if (cnt <= 0) return; diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c index 0c186f82ea92..0e6682e6f7db 100644 --- a/drivers/isdn/hisax/q931.c +++ b/drivers/isdn/hisax/q931.c @@ -446,7 +446,7 @@ prcause(char *dest, u8 * p) { u8 *end; char *dp = dest; - int i, cause; + u_int i, cause; end = p + p[1] + 1; p += 2; @@ -871,7 +871,8 @@ static int disptext_ni1(char *dest, u8 * p) { char *dp = dest; - int l, tag, len, i; + int l, tag, len; + u_int i; p++; l = *p++ - 1; @@ -1200,7 +1201,7 @@ dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir) char *dp; unsigned char pd, cr_l, cr, mt; unsigned char sapi, tei, ftyp; - int i, cset = 0, cs_old = 0, cs_fest = 0; + u_int i, cset = 0, cs_old = 0, cs_fest = 0; int size, finish = 0; if (skb->len < 3) diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c index 1ffff0814392..af0f6019c51f 100644 --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c @@ -760,7 +760,7 @@ setup_sedlbauer(struct IsdnCard *card) printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n", pnp_irq(pd, 0), pnp_port_start(pd, 0)); pnp_device_detach(pd); - goto err; + return 0; } card->para[1] = pnp_port_start(pd, 0); card->para[0] = pnp_irq(pd, 0); @@ -777,7 +777,7 @@ setup_sedlbauer(struct IsdnCard *card) } } else { printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); - goto err; + return 0; } } pdev++; diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c index 7aade575701f..b4cfed146b24 100644 --- a/drivers/isdn/hisax/st5481_b.c +++ b/drivers/isdn/hisax/st5481_b.c @@ -31,9 +31,9 @@ static void usb_b_out(struct st5481_bcs *bcs,int buf_nr) struct st5481_b_out *b_out = &bcs->b_out; struct st5481_adapter *adapter = bcs->adapter; struct urb *urb; - unsigned int packet_size,offset; - int len,buf_size,bytes_sent; - int i; + u_int packet_size, bytes_sent; + int len, offset, buf_size; + u_int i; struct sk_buff *skb; if (test_and_set_bit(buf_nr, &b_out->busy)) { diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c index 06b91cba17bb..786c5642e95e 100644 --- a/drivers/isdn/hisax/st5481_d.c +++ b/drivers/isdn/hisax/st5481_d.c @@ -294,8 +294,8 @@ static void usb_d_out(struct st5481_adapter *adapter, int buf_nr) { struct st5481_d_out *d_out = &adapter->d_out; struct urb *urb; - unsigned int num_packets, packet_offset; - int len, buf_size, bytes_sent; + unsigned int num_packets; + int len, buf_size, bytes_sent, packet_offset; struct sk_buff *skb; struct usb_iso_packet_descriptor *desc; @@ -341,7 +341,7 @@ static void usb_d_out(struct st5481_adapter *adapter, int buf_nr) desc = &urb->iso_frame_desc[num_packets]; desc->offset = packet_offset; desc->length = SIZE_ISO_PACKETS_D_OUT; - if (len - packet_offset < desc->length) + if (len - packet_offset < (int)desc->length) desc->length = len - packet_offset; num_packets++; packet_offset += desc->length; diff --git a/drivers/isdn/i4l/isdn_audio.c b/drivers/isdn/i4l/isdn_audio.c index 47b90e49b8d8..5c9fc1ad38fb 100644 --- a/drivers/isdn/i4l/isdn_audio.c +++ b/drivers/isdn/i4l/isdn_audio.c @@ -517,7 +517,6 @@ isdn_audio_eval_dtmf(modem_info * info) dtmf_state *s; int silence; int i; - unsigned long flags; int grp[2]; char what; char *p; @@ -551,7 +550,7 @@ isdn_audio_eval_dtmf(modem_info * info) *p++ = 0x10; *p = what; skb_trim(skb, 2); - if (skb_headroom(skb) < sizeof(isdn_audio_skb)) { + if ((size_t)skb_headroom(skb) < sizeof(isdnaudio_header)) { printk(KERN_WARNING "isdn_audio: insufficient skb_headroom, dropping\n"); kfree_skb(skb); @@ -559,11 +558,7 @@ isdn_audio_eval_dtmf(modem_info * info) } ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0; - save_flags(flags); - cli(); isdn_tty_queue_tail(info, skb, 2); - restore_flags(flags); - /* Schedule dequeuing */ if ((dev->modempoll) && (info->rcvsched)) mod_timer(&info->read_timer, jiffies + 4); } else @@ -653,7 +648,6 @@ void isdn_audio_put_dle_code(modem_info * info, u_char code) { struct sk_buff *skb; - unsigned long flags; char *p; skb = dev_alloc_skb(2); @@ -666,7 +660,7 @@ isdn_audio_put_dle_code(modem_info * info, u_char code) p = (char *) skb_put(skb, 2); p[0] = 0x10; p[1] = code; - if (skb_headroom(skb) < sizeof(isdn_audio_skb)) { + if ((size_t)skb_headroom(skb) < sizeof(isdnaudio_header)) { printk(KERN_WARNING "isdn_audio: insufficient skb_headroom, dropping\n"); kfree_skb(skb); @@ -674,10 +668,7 @@ isdn_audio_put_dle_code(modem_info * info, u_char code) } ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0; - save_flags(flags); - cli(); isdn_tty_queue_tail(info, skb, 2); - restore_flags(flags); /* Schedule dequeuing */ if ((dev->modempoll) && (info->rcvsched)) mod_timer(&info->read_timer, jiffies + 4); @@ -691,7 +682,7 @@ isdn_audio_eval_silence(modem_info * info) what = ' '; - if (s->idx > (info->emu.vpar[2] * 800)) { + if (s->idx > (u_int)(info->emu.vpar[2] * 800)) { s->idx = 0; if (!s->state) { /* silence from beginning of rec */ what = 's'; @@ -699,9 +690,9 @@ isdn_audio_eval_silence(modem_info * info) what = 'q'; } } - if ((what == 's') || (what == 'q')) { - printk(KERN_DEBUG "ttyI%d: %s\n", info->line, - (what=='s') ? "silence":"quiet"); - isdn_audio_put_dle_code(info, what); - } + if ((what == 's') || (what == 'q')) { + printk(KERN_DEBUG "ttyI%d: %s\n", info->line, + (what=='s') ? "silence":"quiet"); + isdn_audio_put_dle_code(info, what); + } } diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 08562d0329f1..3de5bef85bdd 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -598,6 +598,7 @@ drv_register(struct fsm_inst *fi, int pr, void *arg) iif->statcallb = isdn_status_callback; isdn_info_update(); + return(0); } static int @@ -609,6 +610,7 @@ drv_stat_run(struct fsm_inst *fi, int pr, void *arg) drv->features = drv->interface->features; isdn_v110_add_features(drv); set_global_features(); + return(0); } static int @@ -616,6 +618,7 @@ drv_stat_stop(struct fsm_inst *fi, int pr, void *arg) { fsm_change_state(fi, ST_DRV_LOADED); set_global_features(); + return(0); } static int @@ -646,6 +649,7 @@ drv_stat_stavail(struct fsm_inst *fi, int pr, void *arg) drv->stavail += c->arg; spin_unlock_irqrestore(&stat_lock, flags); wake_up_interruptible(&drv->st_waitq); + return 0; } static int @@ -1318,20 +1322,18 @@ static ssize_t isdn_status_read(struct file *file, char *buf, size_t count, loff_t * off) { int retval; - int len = 0; + size_t len = 0; char *p; if (off != &file->f_pos) return -ESPIPE; - lock_kernel(); if (!file->private_data) { - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - goto out; - } + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; interruptible_sleep_on(&(dev->info_waitq)); } + lock_kernel(); p = isdn_statstr(); file->private_data = 0; if ((len = strlen(p)) <= count) { @@ -1362,12 +1364,10 @@ isdn_status_poll(struct file *file, poll_table *wait) { unsigned int mask = 0; - lock_kernel(); - poll_wait(file, &(dev->info_waitq), wait); + lock_kernel(); if (file->private_data) mask |= POLLIN | POLLRDNORM; - unlock_kernel(); return mask; } @@ -1464,7 +1464,7 @@ isdn_ctrl_read(struct file *file, char *buf, size_t count, loff_t * off) struct isdn_slot *slot = file->private_data; DECLARE_WAITQUEUE(wait, current); unsigned long flags; - int len = 0; + size_t len = 0; if (off != &file->f_pos) return -ESPIPE; diff --git a/drivers/isdn/i4l/isdn_net_lib.c b/drivers/isdn/i4l/isdn_net_lib.c index ad29b9628883..6acdd8ca0dc1 100644 --- a/drivers/isdn/i4l/isdn_net_lib.c +++ b/drivers/isdn/i4l/isdn_net_lib.c @@ -758,7 +758,7 @@ static int isdn_net_getphone(isdn_net_ioctl_phone * phone, char *phones) { isdn_net_dev *idev = isdn_net_findif(phone->name); - int count = 0; + u_int count = 0; char *buf = (char *)__get_free_page(GFP_KERNEL); struct isdn_net_phone *n; diff --git a/drivers/isdn/i4l/isdn_net_lib.h b/drivers/isdn/i4l/isdn_net_lib.h index 0258036dc0fb..345ac53e4eb5 100644 --- a/drivers/isdn/i4l/isdn_net_lib.h +++ b/drivers/isdn/i4l/isdn_net_lib.h @@ -133,47 +133,47 @@ struct isdn_net_local_s { /* per ISDN channel (ISDN interface) data */ struct isdn_net_dev_s { - struct isdn_slot *isdn_slot; /* Index to isdn device/channel */ - struct isdn_slot *exclusive; /* NULL if non excl */ - int pre_device; /* Preselected isdn-device */ - int pre_channel; /* Preselected isdn-channel */ - - struct timer_list dial_timer; /* dial events timer */ - struct fsm_inst fi; /* call control state machine */ - int dial_event; /* event in case of timer expiry */ - int dial; /* # of phone number just dialed */ - int outgoing; /* Flag: outgoing call */ - int dialretry; /* Counter for Dialout-retries */ - - int cps; /* current speed of this interface */ - int transcount; /* byte-counter for cps-calculation */ - int last_jiffies; /* when transcount was reset */ - int sqfull; /* Flag: netdev-queue overloaded */ - ulong sqfull_stamp; /* Start-Time of overload */ - - int huptimer; /* Timeout-counter for auto-hangup */ - int charge; /* Counter for charging units */ - int charge_state; /* ChargeInfo state machine */ - unsigned long chargetime; /* Timer for Charging info */ - int chargeint; /* Interval between charge-infos */ - - int pppbind; /* ippp device for bindings */ - - struct sk_buff_head super_tx_queue; /* List of supervisory frames to */ - /* be transmitted asap */ - int frame_cnt; /* number of frames currently */ - /* queued in HL driver */ - struct tasklet_struct tlet; - - isdn_net_local *mlp; /* Ptr to master device for all devs*/ - - struct list_head slaves; /* member of local->slaves */ - struct list_head online; /* member of local->online */ - - char name[10]; /* Name of device */ - struct list_head global_list; /* global list of all isdn_net_devs */ - void *ind_priv; /* interface types can put their - private data here */ + struct isdn_slot *isdn_slot; /* Index to isdn device/channel */ + struct isdn_slot *exclusive; /* NULL if non excl */ + int pre_device; /* Preselected isdn-device */ + int pre_channel; /* Preselected isdn-channel */ + + struct timer_list dial_timer; /* dial events timer */ + struct fsm_inst fi; /* call control state machine */ + int dial_event; /* event in case of timer expiry */ + int dial; /* # of phone number just dialed */ + int outgoing; /* Flag: outgoing call */ + int dialretry; /* Counter for Dialout-retries */ + + int cps; /* current speed of this interface */ + int transcount; /* byte-counter for cps-calculation */ + u_long last_jiffies; /* when transcount was reset */ + int sqfull; /* Flag: netdev-queue overloaded */ + u_long sqfull_stamp; /* Start-Time of overload */ + + int huptimer; /* Timeout-counter for auto-hangup */ + int charge; /* Counter for charging units */ + int charge_state; /* ChargeInfo state machine */ + u_long chargetime; /* Timer for Charging info */ + int chargeint; /* Interval between charge-infos */ + + int pppbind; /* ippp device for bindings */ + + struct sk_buff_head super_tx_queue; /* List of supervisory frames to */ + /* be transmitted asap */ + int frame_cnt; /* number of frames currently */ + /* queued in HL driver */ + struct tasklet_struct tlet; + + isdn_net_local *mlp; /* Ptr to master device for all devs*/ + + struct list_head slaves; /* member of local->slaves */ + struct list_head online; /* member of local->online */ + + char name[10]; /* Name of device */ + struct list_head global_list; /* global list of all isdn_net_devs */ + void *ind_priv; /* interface types can put their + private data here */ }; /* ====================================================================== */ diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 0bd61b05421c..389fbffc3289 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -132,7 +132,7 @@ static int isdn_tty_readbchan(struct modem_info *info, u_char * buf, u_char * fp, int len) { int count; - int count_pull; + u_int count_pull; int count_put; int dflag; struct sk_buff *skb; @@ -179,7 +179,7 @@ isdn_tty_readbchan(struct modem_info *info, u_char * buf, u_char * fp, int len) #endif /* No DLE's in buff, so simply copy it */ dflag = 1; - if ((count_pull = skb->len) > len) { + if ((int)(count_pull = skb->len) > len) { count_pull = len; dflag = 0; } @@ -315,7 +315,7 @@ isdn_tty_rcv_skb(struct isdn_slot *slot, struct sk_buff *skb) skb_pull(skb, 4); } #ifdef CONFIG_ISDN_AUDIO - if (skb_headroom(skb) < sizeof(isdn_audio_skb)) { + if ((size_t)skb_headroom(skb) < sizeof(isdnaudio_header)) { printk(KERN_WARNING "isdn_audio: insufficient skb_headroom, dropping\n"); kfree_skb(skb); @@ -1728,9 +1728,6 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) modem_info *info; int retval, line; - /* FIXME. This is not unload-race free AFAICS */ - - MOD_INC_USE_COUNT; line = tty->index; if (line < 0 || line > ISDN_MAX_CHANNELS) @@ -1738,6 +1735,8 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) info = &isdn_mdm.info[line]; if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open")) return -ENODEV; + if (!try_module_get(info->owner)) + printk(KERN_WARNING "%s: cannot reserve module\n", __FUNCTION__); #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name, info->count); @@ -1753,6 +1752,7 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open return after startup\n"); #endif + module_put(info->owner); return retval; } retval = isdn_tty_block_til_ready(tty, filp, info); @@ -1760,6 +1760,7 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open return after isdn_tty_block_til_ready \n"); #endif + module_put(info->owner); return retval; } #ifdef ISDN_DEBUG_MODEM_OPEN @@ -1779,7 +1780,9 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) ulong flags; ulong timeout; - if (!info || isdn_tty_paranoia_check(info, tty->name, "isdn_tty_close")) + if (!info) + return; + if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_close")) goto out; save_flags(flags); @@ -1859,7 +1862,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) printk(KERN_DEBUG "isdn_tty_close normal exit\n"); #endif out: - MOD_DEC_USE_COUNT; + module_put(info->owner); } /* @@ -2036,6 +2039,7 @@ isdn_tty_init(void) return -3; } #endif + info->owner = THIS_MODULE; init_MUTEX(&info->write_sem); sprintf(info->last_cause, "0000"); sprintf(info->last_num, "none"); @@ -2457,7 +2461,7 @@ isdn_tty_at_cout(char *msg, modem_info * info) (!skb_queue_empty(&info->rpqueue)))) { skb = alloc_skb(strlen(msg) #ifdef CONFIG_ISDN_AUDIO - + sizeof(isdn_audio_skb) + + sizeof(isdnaudio_header) #endif , GFP_ATOMIC); if (!skb) { @@ -2465,7 +2469,7 @@ isdn_tty_at_cout(char *msg, modem_info * info) return; } #ifdef CONFIG_ISDN_AUDIO - skb_reserve(skb, sizeof(isdn_audio_skb)); + skb_reserve(skb, sizeof(isdnaudio_header)); #endif sp = skb_put(skb, strlen(msg)); #ifdef CONFIG_ISDN_AUDIO diff --git a/drivers/isdn/i4l/isdn_ttyfax.c b/drivers/isdn/i4l/isdn_ttyfax.c index dbccc7d31133..950123d31171 100644 --- a/drivers/isdn/i4l/isdn_ttyfax.c +++ b/drivers/isdn/i4l/isdn_ttyfax.c @@ -265,7 +265,7 @@ isdn_tty_fax_bitorder(modem_info * info, struct sk_buff *skb) __u8 RightMask; __u8 fBit; __u8 Data; - int i; + u_int i; if (!info->fax->bor) { for (i = 0; i < skb->len; i++) { diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 7a0be06ce59a..925db4617f64 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -43,6 +43,8 @@ MODULE_PARM_DESC(icn_id2, "ID-String of first card, second S0 (4B only)"); static char *revision = "$Revision: 1.65.6.8 $"; +static spinlock_t icn_lock = SPIN_LOCK_UNLOCKED; + static int icn_addcard(int, char *, char *); /* @@ -59,16 +61,15 @@ icn_free_queue(icn_card * card, int channel) unsigned long flags; skb_queue_purge(queue); - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); card->xlen[channel] = 0; card->sndcount[channel] = 0; if ((skb = card->xskb[channel])) { card->xskb[channel] = NULL; - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); dev_kfree_skb(skb); } else - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); } /* Put a value into a shift-register, highest bit first. @@ -146,8 +147,7 @@ icn_lock_channel(icn_card * card, int channel) #ifdef MAP_DEBUG printk(KERN_DEBUG "icn_lock_channel %d\n", channel); #endif - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); if ((dev.channel == channel) && (card == dev.mcard)) { dev.chanlock++; retval = 1; @@ -160,7 +160,7 @@ icn_lock_channel(icn_card * card, int channel) printk(KERN_DEBUG "icn_lock_channel %d FAILED, dc=%d\n", channel, dev.channel); #endif } - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); return retval; } @@ -175,11 +175,10 @@ icn_release_channel(void) #ifdef MAP_DEBUG printk(KERN_DEBUG "icn_release_channel l=%d\n", dev.chanlock); #endif - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); if (dev.chanlock > 0) dev.chanlock--; - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); } /* @@ -195,19 +194,18 @@ icn_trymaplock_channel(icn_card * card, int channel) printk(KERN_DEBUG "trymaplock c=%d dc=%d l=%d\n", channel, dev.channel, dev.chanlock); #endif - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); if ((!dev.chanlock) || ((dev.channel == channel) && (dev.mcard == card))) { dev.chanlock++; icn_map_channel(card, channel); - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); #ifdef MAP_DEBUG printk(KERN_DEBUG "trymaplock %d OK\n", channel); #endif return 1; } - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); #ifdef MAP_DEBUG printk(KERN_DEBUG "trymaplock %d FAILED\n", channel); #endif @@ -226,13 +224,12 @@ icn_maprelease_channel(icn_card * card, int channel) #ifdef MAP_DEBUG printk(KERN_DEBUG "map_release c=%d l=%d\n", channel, dev.chanlock); #endif - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); if (dev.chanlock > 0) dev.chanlock--; if (!dev.chanlock) icn_map_channel(card, channel); - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); } /* Get Data from the B-Channel, assemble fragmented packets and put them @@ -308,14 +305,13 @@ icn_pollbchan_send(int channel, icn_card * card) (card->sndcount[channel] || skb_queue_len(&card->spqueue[channel]) || card->xskb[channel])) { - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); if (card->xmit_lock[channel]) { - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); break; } card->xmit_lock[channel]++; - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); skb = card->xskb[channel]; if (!skb) { skb = skb_dequeue(&card->spqueue[channel]); @@ -345,11 +341,10 @@ icn_pollbchan_send(int channel, icn_card * card) sbnext; /* switch to next buffer */ icn_maprelease_channel(card, mch & 2); if (!skb->len) { - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); if (card->xskb[channel]) card->xskb[channel] = NULL; - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); dev_kfree_skb(skb); if (card->xlen[channel]) { cmd.command = ISDN_STAT_BSENT; @@ -359,10 +354,9 @@ icn_pollbchan_send(int channel, icn_card * card) card->interface.statcallb(&cmd); } } else { - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); card->xskb[channel] = skb; - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); } card->xmit_lock[channel] = 0; if (!icn_trymaplock_channel(card, mch)) @@ -393,11 +387,10 @@ icn_pollbchan(unsigned long data) } if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) { /* schedule b-channel polling again */ - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); mod_timer(&card->rb_timer, jiffies+ICN_TIMER_BCREAD); card->flags |= ICN_FLAGS_RBTIMER; - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); } else card->flags &= ~ICN_FLAGS_RBTIMER; } @@ -464,9 +457,8 @@ icn_parse_status(u_char * status, int channel, icn_card * card) cmd.driver = card->myid; cmd.arg = channel; switch (action) { - case 11: - save_flags(flags); - cli(); + case 11: + spin_lock_irqsave(&icn_lock, flags); icn_free_queue(card,channel); card->rcvidx[channel] = 0; @@ -483,11 +475,10 @@ icn_parse_status(u_char * status, int channel, icn_card * card) ncmd.driver = card->myid; ncmd.arg = channel; ncmd.command = ISDN_STAT_BHUP; - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); card->interface.statcallb(&cmd); } else - restore_flags(flags); - + spin_unlock_irqrestore(&icn_lock, flags); break; case 1: icn_free_queue(card,channel); @@ -498,10 +489,9 @@ icn_parse_status(u_char * status, int channel, icn_card * card) card->flags &= ~((channel) ? ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE); icn_free_queue(card, channel); - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); card->rcvidx[channel] = 0; - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); break; case 3: { @@ -557,10 +547,9 @@ icn_parse_status(u_char * status, int channel, icn_card * card) case 8: card->flags &= ~ICN_FLAGS_B1ACTIVE; icn_free_queue(card, 0); - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); card->rcvidx[0] = 0; - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); cmd.arg = 0; cmd.driver = card->myid; card->interface.statcallb(&cmd); @@ -571,10 +560,9 @@ icn_parse_status(u_char * status, int channel, icn_card * card) cmd.command = ISDN_STAT_BHUP; card->flags &= ~ICN_FLAGS_B2ACTIVE; icn_free_queue(card, 1); - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); card->rcvidx[1] = 0; - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); cmd.arg = 1; cmd.driver = card->myid; card->interface.statcallb(&cmd); @@ -592,8 +580,7 @@ icn_putmsg(icn_card * card, unsigned char c) { ulong flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); *card->msg_buf_write++ = (c == 0xff) ? '\n' : c; if (card->msg_buf_write == card->msg_buf_read) { if (++card->msg_buf_read > card->msg_buf_end) @@ -601,7 +588,7 @@ icn_putmsg(icn_card * card, unsigned char c) } if (card->msg_buf_write > card->msg_buf_end) card->msg_buf_write = card->msg_buf; - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); } static void @@ -683,20 +670,18 @@ icn_polldchan(unsigned long data) if (!(card->flags & ICN_FLAGS_RBTIMER)) { /* schedule b-channel polling */ card->flags |= ICN_FLAGS_RBTIMER; - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); del_timer(&card->rb_timer); card->rb_timer.function = icn_pollbchan; card->rb_timer.data = (unsigned long) card; card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD; add_timer(&card->rb_timer); - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); } /* schedule again */ - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); mod_timer(&card->st_timer, jiffies+ICN_TIMER_DCREAD); - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); } /* Append a packet to the transmit buffer-queue. @@ -725,8 +710,7 @@ icn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card * card) return 0; if (card->sndcount[channel] > ICN_MAX_SQUEUE) return 0; - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); nskb = skb_clone(skb, GFP_ATOMIC); if (nskb) { /* Push ACK flag as one @@ -738,7 +722,7 @@ icn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card * card) } else len = 0; card->sndcount[channel] += len; - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); } return len; } @@ -860,11 +844,10 @@ icn_loadboot(u_char * buffer, icn_card * card) #ifdef BOOT_DEBUG printk(KERN_DEBUG "Map Bank 0\n"); #endif - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); icn_map_channel(card, 0); /* Select Bank 0 */ icn_lock_channel(card, 0); /* Lock Bank 0 */ - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); SLEEP(1); memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */ #ifdef BOOT_DEBUG @@ -875,12 +858,11 @@ icn_loadboot(u_char * buffer, icn_card * card) #ifdef BOOT_DEBUG printk(KERN_DEBUG "Map Bank 8\n"); #endif - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); icn_release_channel(); icn_map_channel(card, 2); /* Select Bank 8 */ icn_lock_channel(card, 2); /* Lock Bank 8 */ - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); SLEEP(1); memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */ #ifdef BOOT_DEBUG @@ -900,11 +882,10 @@ icn_loadboot(u_char * buffer, icn_card * card) #ifdef BOOT_DEBUG printk(KERN_DEBUG "Map Bank 0\n"); #endif - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); icn_map_channel(card, 0); /* Select Bank 0 */ icn_lock_channel(card, 0); /* Lock Bank 0 */ - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); SLEEP(1); ret = (icn_check_loader(1)); @@ -931,8 +912,7 @@ icn_loadproto(u_char * buffer, icn_card * card) if ((ret = verify_area(VERIFY_READ, (void *) buffer, ICN_CODE_STAGE2))) return ret; timer = 0; - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); if (card->secondhalf) { icn_map_channel(card, 2); icn_lock_channel(card, 2); @@ -940,7 +920,7 @@ icn_loadproto(u_char * buffer, icn_card * card) icn_map_channel(card, 0); icn_lock_channel(card, 0); } - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); while (left) { if (sbfree) { /* If there is a free buffer... */ cnt = left; @@ -995,8 +975,7 @@ icn_loadproto(u_char * buffer, icn_card * card) printk(KERN_DEBUG "Proto loaded, install poll-timer %d\n", card->secondhalf); #endif - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); init_timer(&card->st_timer); card->st_timer.expires = jiffies + ICN_TIMER_DCREAD; card->st_timer.function = icn_polldchan; @@ -1011,7 +990,7 @@ icn_loadproto(u_char * buffer, icn_card * card) add_timer(&card->other->st_timer); card->other->flags |= ICN_FLAGS_RUNNING; } - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); } icn_maprelease_channel(card, 0); return 0; @@ -1069,8 +1048,7 @@ icn_writecmd(const u_char * buf, int len, int user, icn_card * card) } else memcpy(msg, buf, count); - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); lastmap_card = dev.mcard; lastmap_channel = dev.channel; icn_map_channel(card, mch); @@ -1092,7 +1070,7 @@ icn_writecmd(const u_char * buf, int len, int user, icn_card * card) writeb((readb(&cmd_i) + count) & 0xff, &cmd_i); if (lastmap_card) icn_map_channel(lastmap_card, lastmap_channel); - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); if (len) { mdelay(1); if (loop++ > 20) @@ -1118,8 +1096,7 @@ icn_stopcard(icn_card * card) unsigned long flags; isdn_ctrl cmd; - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); if (card->flags & ICN_FLAGS_RUNNING) { card->flags &= ~ICN_FLAGS_RUNNING; del_timer(&card->st_timer); @@ -1130,7 +1107,7 @@ icn_stopcard(icn_card * card) if (card->doubleS0) icn_stopcard(card->other); } - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); } static void @@ -1154,7 +1131,7 @@ icn_disable_cards(void) icn_card *card = cards; while (card) { - if (check_region(card->port, ICN_PORTLEN)) { + if (!request_region(card->port, ICN_PORTLEN, "icn-isdn")) { printk(KERN_WARNING "icn: (%s) ports 0x%03x-0x%03x in use.\n", CID, @@ -1163,6 +1140,7 @@ icn_disable_cards(void) } else { OUTB_P(0, ICN_RUN); /* Reset Controller */ OUTB_P(0, ICN_MAPRAM); /* Disable RAM */ + release_region(card->port, ICN_PORTLEN); } card = card->next; } @@ -1184,22 +1162,22 @@ icn_command(isdn_ctrl * c, icn_card * card) switch (c->arg) { case ICN_IOCTL_SETMMIO: if (dev.memaddr != (a & 0x0ffc000)) { - if (check_mem_region(a & 0x0ffc000, 0x4000)) { + if (!request_mem_region(a & 0x0ffc000, 0x4000, "icn-isdn (all cards)")) { printk(KERN_WARNING "icn: memory at 0x%08lx in use.\n", a & 0x0ffc000); return -EINVAL; } + release_mem_region(a & 0x0ffc000, 0x4000); icn_stopallcards(); - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); if (dev.mvalid) { iounmap(dev.shmem); release_mem_region(dev.memaddr, 0x4000); } dev.mvalid = 0; dev.memaddr = a & 0x0ffc000; - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); printk(KERN_INFO "icn: (%s) mmio set to 0x%08lx\n", CID, @@ -1214,15 +1192,15 @@ icn_command(isdn_ctrl * c, icn_card * card) a == 0x308 || a == 0x318 || a == 0x328 || a == 0x338 || a == 0x348 || a == 0x358 || a == 0x368) { if (card->port != (unsigned short) a) { - if (check_region((unsigned short) a, ICN_PORTLEN)) { + if (!request_region((unsigned short) a, ICN_PORTLEN, "icn-isdn")) { printk(KERN_WARNING "icn: (%s) ports 0x%03x-0x%03x in use.\n", CID, (int) a, (int) a + ICN_PORTLEN); return -EINVAL; } + release_region((unsigned short) a, ICN_PORTLEN); icn_stopcard(card); - save_flags(flags); - cli(); + spin_lock_irqsave(&icn_lock, flags); if (card->rvalid) release_region(card->port, ICN_PORTLEN); card->port = (unsigned short) a; @@ -1231,7 +1209,7 @@ icn_command(isdn_ctrl * c, icn_card * card) card->other->port = (unsigned short) a; card->other->rvalid = 0; } - restore_flags(flags); + spin_unlock_irqrestore(&icn_lock, flags); printk(KERN_INFO "icn: (%s) port set to 0x%03x\n", CID, card->port); diff --git a/drivers/isdn/sc/card.h b/drivers/isdn/sc/card.h index 48d7cad5249b..bdb27fae6f20 100644 --- a/drivers/isdn/sc/card.h +++ b/drivers/isdn/sc/card.h @@ -94,6 +94,7 @@ typedef struct { int StartOnReset; /* Indicates startproc after reset */ int EngineUp; /* Indicates CommEngine Up */ int trace_mode; /* Indicate if tracing is on */ + spinlock_t lock; /* local lock */ } board; #endif /* CARD_H */ diff --git a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c index 54ed228d4ecd..dddc408f3b3e 100644 --- a/drivers/isdn/sc/command.c +++ b/drivers/isdn/sc/command.c @@ -419,14 +419,13 @@ int reset(int card) adapter[card]->EngineUp = 0; - save_flags(flags); - cli(); + spin_lock_irqsave(&adapter[card]->lock, flags); init_timer(&adapter[card]->reset_timer); adapter[card]->reset_timer.function = check_reset; adapter[card]->reset_timer.data = card; adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME; add_timer(&adapter[card]->reset_timer); - restore_flags(flags); + spin_unlock_irqrestore(&adapter[card]->lock, flags); outb(0x1,adapter[card]->ioport[SFT_RESET]); diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c index 01954e019ac1..1ed94d4331c5 100644 --- a/drivers/isdn/sc/init.c +++ b/drivers/isdn/sc/init.c @@ -97,11 +97,12 @@ static int __init sc_init(void) * No, I/O Base has been provided */ for (i = 0 ; i < MAX_IO_REGS - 1 ; i++) { - if(check_region(io[b] + i * 0x400, 1)) { + if(!request_region(io[b] + i * 0x400, 1, "sc test")) { pr_debug("check_region for 0x%x failed\n", io[b] + i * 0x400); io[b] = 0; break; - } + } else + release_region(io[b] + i * 0x400, 1); } /* @@ -136,11 +137,12 @@ static int __init sc_init(void) last_base = i + IOBASE_OFFSET; pr_debug(" checking 0x%x...", i); for ( j = 0 ; j < MAX_IO_REGS - 1 ; j++) { - if(check_region(i + j * 0x400, 1)) { + if(!request_region(i + j * 0x400, 1, "sc test")) { pr_debug("Failed\n"); found_io = 0; break; - } + } else + release_region(i + j * 0x400, 1); } if(found_io) { @@ -177,9 +179,10 @@ static int __init sc_init(void) * Just look for a signature and ID the * board model */ - if(!check_region(ram[b], SRAM_PAGESIZE)) { - pr_debug("check_region for RAM base 0x%x succeeded\n", ram[b]); + if(request_region(ram[b], SRAM_PAGESIZE, "sc test")) { + pr_debug("request_region for RAM base 0x%x succeeded\n", ram[b]); model = identify_board(ram[b], io[b]); + release_region(ram[b], SRAM_PAGESIZE); } } else { @@ -189,9 +192,10 @@ static int __init sc_init(void) */ for (i = SRAM_MIN ; i < SRAM_MAX ; i += SRAM_PAGESIZE) { pr_debug("Checking RAM address 0x%x...\n", i); - if(!check_region(i, SRAM_PAGESIZE)) { + if(request_region(i, SRAM_PAGESIZE, "sc test")) { pr_debug(" check_region succeeded\n"); model = identify_board(i, io[b]); + release_region(i, SRAM_PAGESIZE); if (model >= 0) { pr_debug(" Identified a %s\n", boardname[model]); @@ -201,7 +205,7 @@ static int __init sc_init(void) pr_debug(" Unidentifed or inaccessible\n"); continue; } - pr_debug(" check_region failed\n"); + pr_debug(" request failed\n"); } } /* @@ -310,6 +314,7 @@ static int __init sc_init(void) continue; } memset(adapter[cinst], 0, sizeof(board)); + spin_lock_init(&adapter[cinst]->lock); if(!register_isdn(interface)) { /* diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c index 003d6bd606dd..e32b0604504a 100644 --- a/drivers/isdn/sc/message.c +++ b/drivers/isdn/sc/message.c @@ -55,8 +55,7 @@ int receivemessage(int card, RspMessage *rspmsg) /* * Map in the DPM to the base page and copy the message */ - save_flags(flags); - cli(); + spin_lock_irqsave(&adapter[card]->lock, flags); outb((adapter[card]->shmem_magic >> 14) | 0x80, adapter[card]->ioport[adapter[card]->shmem_pgport]); dpm = (DualPortMemory *) adapter[card]->rambase; @@ -64,8 +63,7 @@ int receivemessage(int card, RspMessage *rspmsg) MSG_LEN); dpm->rsp_tail = (dpm->rsp_tail+1) % MAX_MESSAGES; inb(adapter[card]->ioport[FIFO_READ]); - restore_flags(flags); - + spin_unlock_irqrestore(&adapter[card]->lock, flags); /* * Tell the board that the message is received */ @@ -152,15 +150,14 @@ int sendmessage(int card, /* * Disable interrupts and map in shared memory */ - save_flags(flags); - cli(); + spin_lock_irqsave(&adapter[card]->lock, flags); outb((adapter[card]->shmem_magic >> 14) | 0x80, adapter[card]->ioport[adapter[card]->shmem_pgport]); dpm = (DualPortMemory *) adapter[card]->rambase; /* Fix me */ memcpy_toio(&(dpm->req_queue[dpm->req_head]),&sndmsg,MSG_LEN); dpm->req_head = (dpm->req_head+1) % MAX_MESSAGES; outb(sndmsg.sequence_no, adapter[card]->ioport[FIFO_WRITE]); - restore_flags(flags); + spin_unlock_irqrestore(&adapter[card]->lock, flags); pr_debug("%s: Sent Message seq:%d pid:%d time:%d " "cnt:%d (type,class,code):(%d,%d,%d) " diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c index efa0a8753332..663ffa0d1333 100644 --- a/drivers/isdn/sc/shmem.c +++ b/drivers/isdn/sc/shmem.c @@ -53,18 +53,17 @@ void *memcpy_toshmem(int card, void *dest, const void *src, size_t n) /* * Block interrupts and load the page */ - save_flags(flags); - cli(); + spin_lock_irqsave(&adapter[card]->lock, flags); outb(((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, adapter[card]->ioport[adapter[card]->shmem_pgport]); - pr_debug("%s: set page to %#x\n",adapter[card]->devicename, - ((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); ret = memcpy_toio(adapter[card]->rambase + ((unsigned long) dest % 0x4000), src, n); + spin_unlock_irqrestore(&adapter[card]->lock, flags); + pr_debug("%s: set page to %#x\n",adapter[card]->devicename, + ((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); pr_debug("%s: copying %d bytes from %#x to %#x\n",adapter[card]->devicename, n, (unsigned long) src, adapter[card]->rambase + ((unsigned long) dest %0x4000)); - restore_flags(flags); return ret; } @@ -97,19 +96,18 @@ void *memcpy_fromshmem(int card, void *dest, const void *src, size_t n) /* * Block interrupts and load the page */ - save_flags(flags); - cli(); + spin_lock_irqsave(&adapter[card]->lock, flags); outb(((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, adapter[card]->ioport[adapter[card]->shmem_pgport]); - pr_debug("%s: set page to %#x\n",adapter[card]->devicename, - ((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); ret = memcpy_fromio(dest,(void *)(adapter[card]->rambase + ((unsigned long) src % 0x4000)), n); + spin_unlock_irqrestore(&adapter[card]->lock, flags); + pr_debug("%s: set page to %#x\n",adapter[card]->devicename, + ((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); /* pr_debug("%s: copying %d bytes from %#x to %#x\n", adapter[card]->devicename, n, adapter[card]->rambase + ((unsigned long) src %0x4000), (unsigned long) dest); */ - restore_flags(flags); return ret; } @@ -138,16 +136,15 @@ void *memset_shmem(int card, void *dest, int c, size_t n) /* * Block interrupts and load the page */ - save_flags(flags); - cli(); + spin_lock_irqsave(&adapter[card]->lock, flags); outb(((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, adapter[card]->ioport[adapter[card]->shmem_pgport]); - pr_debug("%s: set page to %#x\n",adapter[card]->devicename, - ((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); ret = memset_io(adapter[card]->rambase + ((unsigned long) dest % 0x4000), c, n); - restore_flags(flags); + pr_debug("%s: set page to %#x\n",adapter[card]->devicename, + ((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); + spin_unlock_irqrestore(&adapter[card]->lock, flags); return ret; } diff --git a/drivers/isdn/sc/timer.c b/drivers/isdn/sc/timer.c index f5f26a6d9450..7774488cf1f1 100644 --- a/drivers/isdn/sc/timer.c +++ b/drivers/isdn/sc/timer.c @@ -62,8 +62,7 @@ void check_reset(unsigned long data) /* Setup the io ports */ setup_ports(card); - save_flags(flags); - cli(); + spin_lock_irqsave(&adapter[card]->lock, flags); outb(adapter[card]->ioport[adapter[card]->shmem_pgport], (adapter[card]->shmem_magic>>14) | 0x80); sig = (unsigned long) *((unsigned long *)(adapter[card]->rambase + SIG_OFFSET)); @@ -71,18 +70,16 @@ void check_reset(unsigned long data) /* check the signature */ if(sig == SIGNATURE) { flushreadfifo(card); - restore_flags(flags); + spin_unlock_irqrestore(&adapter[card]->lock, flags); /* See if we need to do a startproc */ if (adapter[card]->StartOnReset) startproc(card); - } - else { + } else { pr_debug("%s: No signature yet, waiting another %d jiffies.\n", adapter[card]->devicename, CHECKRESET_TIME); mod_timer(&adapter[card]->reset_timer, jiffies+CHECKRESET_TIME); + spin_unlock_irqrestore(&adapter[card]->lock, flags); } - restore_flags(flags); - } /* @@ -122,10 +119,9 @@ void check_phystat(unsigned long data) adapter[card]->phystat = adapter[card]->nphystat; /* Reinitialize the timer */ - save_flags(flags); - cli(); + spin_lock_irqsave(&adapter[card]->lock, flags); mod_timer(&adapter[card]->stat_timer, jiffies+CHECKSTAT_TIME); - restore_flags(flags); + spin_unlock_irqrestore(&adapter[card]->lock, flags); /* Send a new cePhyStatus message */ sendmessage(card, CEPID,ceReqTypePhy,ceReqClass2, @@ -146,11 +142,5 @@ void check_phystat(unsigned long data) */ void trace_timer(unsigned long data) { - unsigned long flags; - - /* - * Disable interrupts and swap the first page - */ - save_flags(flags); - cli(); + /* not implemented */ } diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index bb6409ccace2..40ca8ea7f3a2 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -1391,10 +1391,10 @@ next: if (pmu_battery_count) query_battery_state(); pmu_pass_intr(data, len); - } else + } else { pmu_pass_intr(data, len); - #endif /* CONFIG_PMAC_PBOOK */ + } goto next; } diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 76f91782da48..3f3ef3025c13 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -115,6 +115,7 @@ MODULE_PARM(v4l2,"i"); MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards"); MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_CHARDEV_MAJOR(VIDEO_MAJOR); /* kernel args */ #ifndef MODULE diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index a5a449a4a7d9..680507243d4a 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -475,6 +475,8 @@ mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt, (struct scatterlist *) SCpnt->request_buffer, SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + if (sges_left == 0) + return FAILED; } else if (SCpnt->request_bufflen) { dma_addr_t buf_dma_addr; scPrivate *my_priv; @@ -3328,9 +3330,8 @@ mptscsih_slave_configure(Scsi_Device *device) device, device->id, device->lun, device->channel)); dsprintk((KERN_INFO "sdtr %d wdtr %d ppr %d inq length=%d\n", device->sdtr, device->wdtr, device->ppr, device->inquiry_len)); - dsprintk(("tagged %d queue %d simple %d ordered %d\n", - device->tagged_supported, device->tagged_queue, - device->simple_tags, device->ordered_tags)); + dsprintk(("tagged %d simple %d ordered %d\n", + device->tagged_supported, device->simple_tags, device->ordered_tags)); /* set target parameters, queue depths, set dv flags ? */ if (hd && (hd->Targets != NULL)) { diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index df5f96439afa..74fd4100332b 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -604,7 +604,7 @@ out1: pnp_device_detach(idev); #endif out: - kfree(dev); + free_netdev(dev); return err; } diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 4e3eabe1e5ea..572de917454d 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1468,7 +1468,7 @@ free_ring: free_region: if (vp->must_free_region) release_region(ioaddr, vci->io_size); - kfree (dev); + free_netdev(dev); printk(KERN_ERR PFX "vortex_probe1 fails. Returns %d\n", retval); out: return retval; diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index a49241c1ae23..fc3c04c6c7bc 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -1768,7 +1768,7 @@ err_out_mwi: err_out_disable: pci_disable_device(pdev); err_out_free: - kfree(dev); + free_netdev(dev); return rc; } diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index bd556e7dfff4..2e3fabd23b9a 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -132,8 +132,8 @@ config TUN If you don't know what to use this for, you don't need it. config ETHERTAP - tristate "Ethertap network tap (OBSOLETE)" - depends on NETDEVICES && EXPERIMENTAL + tristate "Ethertap network tap" + depends on NETDEVICES && EXPERIMENTAL && NETLINK_DEV ---help--- If you say Y here (and have said Y to "Kernel/User network link driver", above) and create a character special file /dev/tap0 with diff --git a/drivers/net/Makefile.lib b/drivers/net/Makefile.lib index 7df0a28a5ea3..b2ade8a877ff 100644 --- a/drivers/net/Makefile.lib +++ b/drivers/net/Makefile.lib @@ -5,6 +5,7 @@ obj-$(CONFIG_A2065) += crc32.o obj-$(CONFIG_ARM_AM79C961A) += crc32.o obj-$(CONFIG_AT1700) += crc32.o obj-$(CONFIG_ATP) += crc32.o +obj-$(CONFIG_BMAC) += crc32.o obj-$(CONFIG_DE2104X) += crc32.o obj-$(CONFIG_DE4X5) += crc32.o obj-$(CONFIG_DECLANCE) += crc32.o diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 838c59729c71..be24e20a5cb1 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -32,14 +32,13 @@ */ #include <linux/config.h> #include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/trdevice.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/netlink.h> #include <linux/divert.h> -#define NEXT_DEV NULL - - /* A unified ethernet device probe. This is the easiest way to have every ethernet adaptor have the name "eth[0123...]". */ @@ -62,7 +61,6 @@ extern int eth16i_probe(struct net_device *); extern int depca_probe(struct net_device *); extern int i82596_probe(struct net_device *); extern int ewrk3_probe(struct net_device *); -extern int de4x5_probe(struct net_device *); extern int el1_probe(struct net_device *); extern int wavelan_probe(struct net_device *); extern int arlan_probe(struct net_device *); @@ -89,7 +87,6 @@ extern int apne_probe(struct net_device *); extern int bionet_probe(struct net_device *); extern int pamsnet_probe(struct net_device *); extern int cs89x0_probe(struct net_device *dev); -extern int ethertap_probe(struct net_device *dev); extern int hplance_probe(struct net_device *dev); extern int bagetlance_probe(struct net_device *); extern int mvme147lance_probe(struct net_device *dev); @@ -100,6 +97,9 @@ extern int macsonic_probe(struct net_device *dev); extern int mac8390_probe(struct net_device *dev); extern int mac89x0_probe(struct net_device *dev); extern int mc32_probe(struct net_device *dev); +extern struct net_device *sdla_init(void); +extern struct net_device *cops_probe(int unit); +extern struct net_device *ltpc_probe(void); /* Detachable devices ("pocket adaptors") */ extern int de620_probe(struct net_device *); @@ -108,7 +108,7 @@ extern int de620_probe(struct net_device *); extern int iph5526_probe(struct net_device *dev); /* SBNI adapters */ -extern int sbni_probe(struct net_device *); +extern int sbni_probe(void); struct devprobe { @@ -153,12 +153,9 @@ static int __init probe_list(struct net_device *dev, struct devprobe *plist) * This is a bit of an artificial separation as there are PCI drivers * that also probe for EISA cards (in the PCI group) and there are ISA * drivers that probe for EISA cards (in the ISA group). These are the - * EISA only driver probes, and also the legacy PCI probes + * legacy EISA only driver probes, and also the legacy PCI probes */ static struct devprobe eisa_probes[] __initdata = { -#ifdef CONFIG_DE4X5 /* DEC DE425, DE434, DE435 adapters */ - {de4x5_probe, 0}, -#endif #ifdef CONFIG_ULTRA32 {ultra32_probe, 0}, #endif @@ -357,135 +354,43 @@ static struct devprobe mips_probes[] __initdata = { * per bus interface. This drives the legacy devices only for now. */ -static int __init ethif_probe(struct net_device *dev) +static int __init ethif_probe(void) { - unsigned long base_addr = dev->base_addr; + struct net_device *dev; + int err = -ENODEV; + + dev = alloc_etherdev(0); + if (!dev) + return -ENOMEM; + + netdev_boot_setup_check(dev); /* * Backwards compatibility - historically an I/O base of 1 was * used to indicate not to probe for this ethN interface */ - if (base_addr == 1) - return 1; /* ENXIO */ + if (dev->base_addr == 1) { + free_netdev(dev); + return -ENXIO; + } /* * The arch specific probes are 1st so that any on-board ethernet * will be probed before other ISA/EISA/MCA/PCI bus cards. */ - if (probe_list(dev, m68k_probes) == 0) - return 0; - if (probe_list(dev, mips_probes) == 0) - return 0; - if (probe_list(dev, eisa_probes) == 0) - return 0; - if (probe_list(dev, mca_probes) == 0) - return 0; - if (probe_list(dev, isa_probes) == 0) - return 0; - if (probe_list(dev, parport_probes) == 0) - return 0; - return -ENODEV; -} - -#ifdef CONFIG_ETHERTAP -static struct net_device tap0_dev = { - .name = "tap0", - .base_addr = NETLINK_TAPBASE, - .next = NEXT_DEV, - .init = ethertap_probe, -}; -#undef NEXT_DEV -#define NEXT_DEV (&tap0_dev) -#endif - -#ifdef CONFIG_SDLA -extern int sdla_init(struct net_device *); -static struct net_device sdla0_dev = { - .name = "sdla0", - .next = NEXT_DEV, - .init = sdla_init, -}; -#undef NEXT_DEV -#define NEXT_DEV (&sdla0_dev) -#endif - -#if defined(CONFIG_LTPC) -extern int ltpc_probe(struct net_device *); -static struct net_device dev_ltpc = { - .name = "lt0", - .next = NEXT_DEV, - .init = ltpc_probe -}; -#undef NEXT_DEV -#define NEXT_DEV (&dev_ltpc) -#endif /* LTPC */ - -#if defined(CONFIG_COPS) -extern int cops_probe(struct net_device *); -static struct net_device cops2_dev = { - .name = "lt2", - .next = NEXT_DEV, - .init = cops_probe, -}; -static struct net_device cops1_dev = { - .name = "lt1", - .next = &cops2_dev, - .init = cops_probe, -}; -static struct net_device cops0_dev = { - .name = "lt0", - .next = &cops1_dev, - .init = cops_probe, -}; -#undef NEXT_DEV -#define NEXT_DEV (&cops0_dev) -#endif /* COPS */ - -static struct net_device eth7_dev = { - .name = "eth%d", - .next = NEXT_DEV, - .init = ethif_probe, -}; -static struct net_device eth6_dev = { - .name = "eth%d", - .next = ð7_dev, - .init = ethif_probe, -}; -static struct net_device eth5_dev = { - .name = "eth%d", - .next = ð6_dev, - .init = ethif_probe, -}; -static struct net_device eth4_dev = { - .name = "eth%d", - .next = ð5_dev, - .init = ethif_probe, -}; -static struct net_device eth3_dev = { - .name = "eth%d", - .next = ð4_dev, - .init = ethif_probe, -}; -static struct net_device eth2_dev = { - .name = "eth%d", - .next = ð3_dev, - .init = ethif_probe, -}; -static struct net_device eth1_dev = { - .name = "eth%d", - .next = ð2_dev, - .init = ethif_probe, -}; -static struct net_device eth0_dev = { - .name = "eth%d", - .next = ð1_dev, - .init = ethif_probe, -}; - -#undef NEXT_DEV -#define NEXT_DEV (ð0_dev) - + if (probe_list(dev, m68k_probes) == 0 || + probe_list(dev, mips_probes) == 0 || + probe_list(dev, eisa_probes) == 0 || + probe_list(dev, mca_probes) == 0 || + probe_list(dev, isa_probes) == 0 || + probe_list(dev, parport_probes) == 0) + err = register_netdev(dev); + + if (err) + free_netdev(dev); + return err; +} #ifdef CONFIG_TR /* Token-ring device probe */ @@ -494,129 +399,82 @@ extern int sk_isa_probe(struct net_device *); extern int proteon_probe(struct net_device *); extern int smctr_probe(struct net_device *); -static int -trif_probe(struct net_device *dev) +static __init int trif_probe(void) { - if (1 + struct net_device *dev; + int err = -ENODEV; + + dev = alloc_trdev(0); + if (!dev) + return -ENOMEM; + + netdev_boot_setup_check(dev); + if ( #ifdef CONFIG_IBMTR - && ibmtr_probe(dev) + ibmtr_probe(dev) == 0 || #endif #ifdef CONFIG_SKISA - && sk_isa_probe(dev) + sk_isa_probe(dev) == 0 || #endif #ifdef CONFIG_PROTEON - && proteon_probe(dev) + proteon_probe(dev) == 0 || #endif #ifdef CONFIG_SMCTR - && smctr_probe(dev) + smctr_probe(dev) == 0 || #endif - && 1 ) { - return 1; /* -ENODEV or -EAGAIN would be more accurate. */ - } - return 0; -} -static struct net_device tr7_dev = { - .name = "tr%d", - .next = NEXT_DEV, - .init = trif_probe, -}; -static struct net_device tr6_dev = { - .name = "tr%d", - .next = &tr7_dev, - .init = trif_probe, -}; -static struct net_device tr5_dev = { - .name = "tr%d", - .next = &tr6_dev, - .init = trif_probe, -}; -static struct net_device tr4_dev = { - .name = "tr%d", - .next = &tr5_dev, - .init = trif_probe, -}; -static struct net_device tr3_dev = { - .name = "tr%d", - .next = &tr4_dev, - .init = trif_probe, -}; -static struct net_device tr2_dev = { - .name = "tr%d", - .next = &tr3_dev, - .init = trif_probe, -}; -static struct net_device tr1_dev = { - .name = "tr%d", - .next = &tr2_dev, - .init = trif_probe, -}; -static struct net_device tr0_dev = { - .name = "tr%d", - .next = &tr1_dev, - .init = trif_probe, -}; -#undef NEXT_DEV -#define NEXT_DEV (&tr0_dev) + 0 ) + err = register_netdev(dev); + + if (err) + free_netdev(dev); + return err; -#endif - -#ifdef CONFIG_SBNI -static struct net_device sbni7_dev = { - .name = "sbni7", - .next = NEXT_DEV, - .init = sbni_probe, -}; -static struct net_device sbni6_dev = { - .name = "sbni6", - .next = &sbni7_dev, - .init = sbni_probe, -}; -static struct net_device sbni5_dev = { - .name = "sbni5", - .next = &sbni6_dev, - .init = sbni_probe, -}; -static struct net_device sbni4_dev = { - .name = "sbni4", - .next = &sbni5_dev, - .init = sbni_probe, -}; -static struct net_device sbni3_dev = { - .name = "sbni3", - .next = &sbni4_dev, - .init = sbni_probe, -}; -static struct net_device sbni2_dev = { - .name = "sbni2", - .next = &sbni3_dev, - .init = sbni_probe, -}; -static struct net_device sbni1_dev = { - .name = "sbni1", - .next = &sbni2_dev, - .init = sbni_probe, -}; -static struct net_device sbni0_dev = { - .name = "sbni0", - .next = &sbni1_dev, - .init = sbni_probe, -}; +} +#endif -#undef NEXT_DEV -#define NEXT_DEV (&sbni0_dev) -#endif /* * The loopback device is global so it can be directly referenced * by the network code. Also, it must be first on device list. */ +extern int loopback_init(void); -extern int loopback_init(struct net_device *dev); -struct net_device loopback_dev = { - .name = "lo", - .next = NEXT_DEV, - .init = loopback_init -}; +/* Statically configured drivers -- order matters here. */ +void __init probe_old_netdevs(void) +{ + int num; + + if (loopback_init()) { + printk(KERN_ERR "Network loopback device setup failed\n"); + } + + +#ifdef CONFIG_SBNI + for (num = 0; num < 8; ++num) + if (sbni_probe()) + break; +#endif +#ifdef CONFIG_TR + for (num = 0; num < 8; ++num) + if (trif_probe()) + break; +#endif + for (num = 0; num < 8; ++num) + if (ethif_probe()) + break; +#ifdef CONFIG_COPS + cops_probe(0); + cops_probe(1); + cops_probe(2); +#endif +#ifdef CONFIG_LTPC + ltpc_probe(); +#endif +#ifdef CONFIG_SDLA + sdla_init(); +#endif + +} /* * The @dev_base list is protected by @dev_base_lock and the rtln @@ -637,6 +495,6 @@ struct net_device loopback_dev = { * unregister_netdevice(), which must be called with the rtnl * semaphore held. */ -struct net_device *dev_base = &loopback_dev; +struct net_device *dev_base; rwlock_t dev_base_lock = RW_LOCK_UNLOCKED; diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index d6a4fdcec957..3350a70c2103 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -685,7 +685,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG) } if (pci_enable_device(pdev)) { - kfree(dev); + free_netdev(dev); continue; } @@ -733,7 +733,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG) if (register_netdev(dev)) { printk(KERN_ERR "acenic: device registration failed\n"); - kfree(dev); + free_netdev(dev); continue; } @@ -793,7 +793,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG) printk(KERN_ERR "%s: Driver compiled without Tigon I" " support - NIC disabled\n", dev->name); ace_init_cleanup(dev); - kfree(dev); + free_netdev(dev); continue; } #endif @@ -803,7 +803,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG) * ace_allocate_descriptors() calls * ace_init_cleanup() on error. */ - kfree(dev); + free_netdev(dev); continue; } @@ -820,7 +820,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG) /* * ace_init() calls ace_init_cleanup() on error. */ - kfree(dev); + free_netdev(dev); continue; } diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 19464a83fdfb..bc9e1bfc7220 100755 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1927,7 +1927,7 @@ err_iounmap: iounmap((void *) lp->mmio); err_free_dev: - kfree(dev); + free_netdev(dev); err_free_reg: pci_release_regions(pdev); diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c index cb8dac24f286..579cf0d2ee5b 100644 --- a/drivers/net/appletalk/cops.c +++ b/drivers/net/appletalk/cops.c @@ -92,12 +92,8 @@ static int board_type = DAYNA; /* Module exported */ static int board_type = TANGENT; #endif -#ifdef MODULE static int io = 0x240; /* Default IO for Dayna */ static int irq = 5; /* Default IRQ */ -#else -static int io; /* Default IO for Dayna */ -#endif /* * COPS Autoprobe information. @@ -146,7 +142,7 @@ static int io; /* Default IO for Dayna */ * Zero terminated list of IO ports to probe. */ -static unsigned int cops_portlist[] = { +static unsigned int ports[] = { 0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260, 0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360, 0 @@ -184,7 +180,6 @@ struct cops_local }; /* Index to functions, as function prototypes. */ -extern int cops_probe (struct net_device *dev); static int cops_probe1 (struct net_device *dev, int ioaddr); static int cops_irq (int ioaddr, int board); @@ -208,6 +203,12 @@ static int cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static int cops_close (struct net_device *dev); static struct net_device_stats *cops_get_stats (struct net_device *dev); +static void cleanup_card(struct net_device *dev) +{ + if (dev->irq) + free_irq(dev->irq, dev); + release_region(dev->base_addr, COPS_IO_EXTENT); +} /* * Check for a network adaptor of this type, and return '0' iff one exists. @@ -215,31 +216,54 @@ static struct net_device_stats *cops_get_stats (struct net_device *dev); * If dev->base_addr in [1..0x1ff], always return failure. * otherwise go with what we pass in. */ -int __init cops_probe(struct net_device *dev) +struct net_device * __init cops_probe(int unit) { - int i; - int base_addr = dev->base_addr; + struct net_device *dev; + unsigned *port; + int base_addr; + int err = 0; + + dev = alloc_netdev(sizeof(struct cops_local), "lt%d", ltalk_setup); + if (!dev) + return ERR_PTR(-ENOMEM); + + if (unit >= 0) { + sprintf(dev->name, "lt%d", unit); + netdev_boot_setup_check(dev); + irq = dev->irq; + base_addr = dev->base_addr; + } else { + base_addr = dev->base_addr = io; + } SET_MODULE_OWNER(dev); - if(base_addr == 0 && io) - base_addr=io; - - if(base_addr > 0x1ff) /* Check a single specified location. */ - return cops_probe1(dev, base_addr); - else if(base_addr != 0) /* Don't probe at all. */ - return -ENXIO; - - /* FIXME Does this really work for cards which generate irq? - * It's definitely N.G. for polled Tangent. sh - * Dayna cards don't autoprobe well at all, but if your card is - * at IRQ 5 & IO 0x240 we find it every time. ;) JS - */ - for(i=0; cops_portlist[i]; i++) - if(cops_probe1(dev, cops_portlist[i]) == 0) - return 0; - - return -ENODEV; + if (base_addr > 0x1ff) { /* Check a single specified location. */ + err = cops_probe1(dev, base_addr); + } else if (base_addr != 0) { /* Don't probe at all. */ + err = -ENXIO; + } else { + /* FIXME Does this really work for cards which generate irq? + * It's definitely N.G. for polled Tangent. sh + * Dayna cards don't autoprobe well at all, but if your card is + * at IRQ 5 & IO 0x240 we find it every time. ;) JS + */ + for (port = ports; *port && cops_probe1(dev, *port) < 0; port++) + ; + if (!*port) + err = -ENODEV; + } + if (err) + goto out; + err = register_netdev(dev); + if (err) + goto out1; + return dev; +out1: + cleanup_card(dev); +out: + kfree(dev); + return ERR_PTR(err); } /* @@ -268,16 +292,15 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr) * interrupts are typically not reported by the boards, and we must * used AutoIRQ to find them. */ + dev->irq = irq; switch (dev->irq) { case 0: /* COPS AutoIRQ routine */ dev->irq = cops_irq(ioaddr, board); - if(!dev->irq) { - retval = -EINVAL; /* No IRQ found on this port */ - goto err_out; - } - + if (dev->irq) + break; + /* No IRQ found on this port, fallthrough */ case 1: retval = -EINVAL; goto err_out; @@ -302,22 +325,13 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr) } /* Reserve any actual interrupt. */ - if(dev->irq) { + if (dev->irq) { retval = request_irq(dev->irq, &cops_interrupt, 0, dev->name, dev); if (retval) goto err_out; } - dev->base_addr = ioaddr; - - /* Initialize the private device structure. */ - dev->priv = kmalloc(sizeof(struct cops_local), GFP_KERNEL); - if(dev->priv == NULL) { - if (dev->irq) - free_irq(dev->irq, dev); - retval = -ENOMEM; - goto err_out; - } + dev->base_addr = ioaddr; lp = (struct cops_local *)dev->priv; memset(lp, 0, sizeof(struct cops_local)); @@ -326,9 +340,6 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr) /* Copy local board variable to lp struct. */ lp->board = board; - /* Fill in the fields of the device structure with LocalTalk values. */ - ltalk_setup(dev); - dev->hard_start_xmit = cops_send_packet; dev->tx_timeout = cops_timeout; dev->watchdog_timeo = HZ * 2; @@ -1013,7 +1024,7 @@ static struct net_device_stats *cops_get_stats(struct net_device *dev) } #ifdef MODULE -static struct net_device cops0_dev = { .init = cops_probe }; +static struct net_device *cops_dev; MODULE_LICENSE("GPL"); MODULE_PARM(io, "i"); @@ -1022,33 +1033,20 @@ MODULE_PARM(board_type, "i"); int init_module(void) { - int result, err; - - if(io == 0) + if (io == 0) printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n", cardname); - - /* Copy the parameters from insmod into the device structure. */ - cops0_dev.base_addr = io; - cops0_dev.irq = irq; - - err=dev_alloc_name(&cops0_dev, "lt%d"); - if(err < 0) - return err; - - if((result = register_netdev(&cops0_dev)) != 0) - return result; - + cops_dev = cops_probe(-1); + if (IS_ERR(cops_dev)) + return PTR_ERR(cops_dev); return 0; } void cleanup_module(void) { - unregister_netdev(&cops0_dev); - kfree(cops0_dev.priv); - if(cops0_dev.irq) - free_irq(cops0_dev.irq, &cops0_dev); - release_region(cops0_dev.base_addr, COPS_IO_EXTENT); + unregister_netdev(cops_dev); + cleanup_card(cops_dev); + free_netdev(cops_dev); } #endif /* MODULE */ diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c index ddbd4f765b12..1b10bc14867c 100644 --- a/drivers/net/appletalk/ltpc.c +++ b/drivers/net/appletalk/ltpc.c @@ -879,34 +879,6 @@ static int ltpc_hard_header (struct sk_buff *skb, struct net_device *dev, return 0; } -static int ltpc_init(struct net_device *dev) -{ - /* Initialize the device structure. */ - - /* Fill in the fields of the device structure with ethernet-generic values. */ - ltalk_setup(dev); - dev->hard_start_xmit = ltpc_xmit; - dev->hard_header = ltpc_hard_header; - - dev->priv = kmalloc(sizeof(struct ltpc_private), GFP_KERNEL); - if(!dev->priv) - { - printk(KERN_INFO "%s: could not allocate statistics buffer\n", dev->name); - return -ENOMEM; - } - - memset(dev->priv, 0, sizeof(struct ltpc_private)); - dev->get_stats = ltpc_get_stats; - - /* add the ltpc-specific things */ - dev->do_ioctl = <pc_ioctl; - - dev->set_multicast_list = &set_multicast_list; - dev->mc_list = NULL; - - return 0; -} - static int ltpc_poll_counter; static void ltpc_poll(unsigned long l) @@ -983,35 +955,40 @@ static struct net_device_stats *ltpc_get_stats(struct net_device *dev) /* initialization stuff */ -static int __init ltpc_probe_dma(int base) +static int __init ltpc_probe_dma(int base, int dma) { - int dma = 0; + int want = (dma == 3) ? 2 : (dma == 1) ? 1 : 3; unsigned long timeout; unsigned long f; - if (!request_dma(1,"ltpc")) { - f=claim_dma_lock(); - disable_dma(1); - clear_dma_ff(1); - set_dma_mode(1,DMA_MODE_WRITE); - set_dma_addr(1,virt_to_bus(ltdmabuf)); - set_dma_count(1,sizeof(struct lt_mem)); - enable_dma(1); - release_dma_lock(f); - dma|=1; + if (want & 1) { + if (request_dma(1,"ltpc")) { + want &= ~1; + } else { + f=claim_dma_lock(); + disable_dma(1); + clear_dma_ff(1); + set_dma_mode(1,DMA_MODE_WRITE); + set_dma_addr(1,virt_to_bus(ltdmabuf)); + set_dma_count(1,sizeof(struct lt_mem)); + enable_dma(1); + release_dma_lock(f); + } } - if (!request_dma(3,"ltpc")) { - f=claim_dma_lock(); - disable_dma(3); - clear_dma_ff(3); - set_dma_mode(3,DMA_MODE_WRITE); - set_dma_addr(3,virt_to_bus(ltdmabuf)); - set_dma_count(3,sizeof(struct lt_mem)); - enable_dma(3); - release_dma_lock(f); - dma|=2; + if (want & 2) { + if (request_dma(3,"ltpc")) { + want &= ~2; + } else { + f=claim_dma_lock(); + disable_dma(3); + clear_dma_ff(3); + set_dma_mode(3,DMA_MODE_WRITE); + set_dma_addr(3,virt_to_bus(ltdmabuf)); + set_dma_count(3,sizeof(struct lt_mem)); + enable_dma(3); + release_dma_lock(f); + } } - /* set up request */ /* FIXME -- do timings better! */ @@ -1037,65 +1014,62 @@ static int __init ltpc_probe_dma(int base) /* release the other dma channel (if we opened both of them) */ - if ( (dma&0x2) && (get_dma_residue(3)==sizeof(struct lt_mem)) ){ - dma&=1; + if ((want & 2) && (get_dma_residue(3)==sizeof(struct lt_mem))) { + want &= ~2; free_dma(3); } - - if ( (dma&0x1) && (get_dma_residue(1)==sizeof(struct lt_mem)) ){ - dma&=0x2; + + if ((want & 1) && (get_dma_residue(1)==sizeof(struct lt_mem))) { + want &= ~1; free_dma(1); } - /* fix up dma number */ - dma|=1; + if (!want) + return 0; - return dma; + return (want & 2) ? 3 : 1; } -int __init ltpc_probe(struct net_device *dev) +struct net_device * __init ltpc_probe(void) { - int err; + struct net_device *dev; + int err = -ENOMEM; int x=0,y=0; int autoirq; unsigned long f; - int portfound=0; unsigned long timeout; + dev = alloc_netdev(sizeof(struct ltpc_private), "lt%d", ltalk_setup); + if (!dev) + goto out; + SET_MODULE_OWNER(dev); /* probe for the I/O port address */ + if (io != 0x240 && request_region(0x220,8,"ltpc")) { x = inb_p(0x220+6); if ( (x!=0xff) && (x>=0xf0) ) { io = 0x220; - portfound=1; - } - else { - release_region(0x220,8); + goto got_port; } + release_region(0x220,8); } - if (io != 0x220 && request_region(0x240,8,"ltpc")) { y = inb_p(0x240+6); if ( (y!=0xff) && (y>=0xf0) ){ io = 0x240; - portfound=1; - } - else { - release_region(0x240,8); + goto got_port; } + release_region(0x240,8); } - if(io && !portfound && request_region(io,8,"ltpc")){ - portfound = 1; - } - if(!portfound) { - /* give up in despair */ - printk(KERN_ERR "LocalTalk card not found; 220 = %02x, 240 = %02x.\n", x,y); - return -1; - } + /* give up in despair */ + printk(KERN_ERR "LocalTalk card not found; 220 = %02x, 240 = %02x.\n", x,y); + err = -ENODEV; + goto out1; + got_port: /* probe for the IRQ line */ if (irq < 2) { unsigned long irq_mask; @@ -1111,22 +1085,21 @@ int __init ltpc_probe(struct net_device *dev) if (autoirq == 0) { printk(KERN_ERR "ltpc: probe at %#x failed to detect IRQ line.\n", io); - } - else { + } else { irq = autoirq; } } /* allocate a DMA buffer */ ltdmabuf = (unsigned char *) dma_mem_alloc(1000); - - if (ltdmabuf) ltdmacbuf = <dmabuf[800]; - if (!ltdmabuf) { printk(KERN_ERR "ltpc: mem alloc failed\n"); - return -1; + err = -ENOMEM; + goto out2; } + ltdmacbuf = <dmabuf[800]; + if(debug & DEBUG_VERBOSE) { printk("ltdmabuf pointer %08lx\n",(unsigned long) ltdmabuf); } @@ -1154,25 +1127,29 @@ int __init ltpc_probe(struct net_device *dev) already been specified */ /* well, 0 is a legal DMA channel, but the LTPC card doesn't use it... */ - if (dma == 0) { - dma = ltpc_probe_dma(io); - if (!dma) { /* no dma channel */ - printk(KERN_ERR "No DMA channel found on ltpc card.\n"); - return -1; - } + dma = ltpc_probe_dma(io, dma); + if (!dma) { /* no dma channel */ + printk(KERN_ERR "No DMA channel found on ltpc card.\n"); + err = -ENODEV; + goto out3; } /* print out friendly message */ - if(irq) printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, IR%d, DMA%d.\n",io,irq,dma); else printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, DMA%d. Using polled mode.\n",io,dma); - /* seems more logical to do this *after* probing the card... */ - err = ltpc_init(dev); - if (err) return err; + /* Fill in the fields of the device structure with ethernet-generic values. */ + dev->hard_start_xmit = ltpc_xmit; + dev->hard_header = ltpc_hard_header; + dev->get_stats = ltpc_get_stats; + /* add the ltpc-specific things */ + dev->do_ioctl = <pc_ioctl; + + dev->set_multicast_list = &set_multicast_list; + dev->mc_list = NULL; dev->base_addr = io; dev->irq = irq; dev->dma = dma; @@ -1212,6 +1189,7 @@ int __init ltpc_probe(struct net_device *dev) } else { if( irq ) printk(KERN_ERR "ltpc: IRQ already in use, using polled mode.\n"); + dev->irq = 0; /* polled mode -- 20 times per second */ /* this is really, really slow... should it poll more often? */ init_timer(<pc_timer); @@ -1221,8 +1199,23 @@ int __init ltpc_probe(struct net_device *dev) ltpc_timer.expires = jiffies + HZ/20; add_timer(<pc_timer); } + err = register_netdev(dev); + if (err) + goto out4; return 0; +out4: + del_timer_sync(<pc_timer); + if (dev->irq) + free_irq(dev->irq, dev); +out3: + free_pages((unsigned long)ltdmabuf, get_order(1000)); +out2: + release_region(io, 8); +out1: + kfree(dev); +out: + return ERR_PTR(err); } #ifndef MODULE @@ -1259,7 +1252,7 @@ static int __init ltpc_setup(char *str) __setup("ltpc=", ltpc_setup); #endif /* MODULE */ -static struct net_device dev_ltpc; +static struct net_device *dev_ltpc; #ifdef MODULE @@ -1272,79 +1265,47 @@ MODULE_PARM(dma, "i"); int __init init_module(void) { - int err, result; - if(io == 0) printk(KERN_NOTICE "ltpc: Autoprobing is not recommended for modules\n"); - /* Find a name for this unit */ - dev_ltpc.init = ltpc_probe; - err=dev_alloc_name(&dev_ltpc,"lt%d"); - - if(err<0) - return err; - - if ((result = register_netdev(&dev_ltpc)) != 0) { - printk(KERN_DEBUG "could not register Localtalk-PC device\n"); - return result; - } else { - if(debug & DEBUG_VERBOSE) printk("0 from register_netdev\n"); - return 0; - } + dev_ltpc = ltpc_probe(); + if (IS_ERR(dev_ltpc)) + return PTR_ERR(dev_ltpc); + return 0; } #endif static void __exit ltpc_cleanup(void) { - unsigned long timeout; + + if(debug & DEBUG_VERBOSE) printk("unregister_netdev\n"); + unregister_netdev(dev_ltpc); ltpc_timer.data = 0; /* signal the poll routine that we're done */ + del_timer_sync(<pc_timer); + if(debug & DEBUG_VERBOSE) printk("freeing irq\n"); - if(dev_ltpc.irq) { - free_irq(dev_ltpc.irq,&dev_ltpc); - dev_ltpc.irq = 0; - } - - if(del_timer(<pc_timer)) - { - /* either the poll was never started, or a poll is in process */ - if(debug & DEBUG_VERBOSE) printk("waiting\n"); - /* if it's in process, wait a bit for it to finish */ - timeout = jiffies+HZ; - add_timer(<pc_timer); - while(del_timer(<pc_timer) && time_after(timeout, jiffies)) - { - add_timer(<pc_timer); - schedule(); - } - } + if (dev_ltpc->irq) + free_irq(dev_ltpc->irq, dev_ltpc); if(debug & DEBUG_VERBOSE) printk("freeing dma\n"); - if(dev_ltpc.dma) { - free_dma(dev_ltpc.dma); - dev_ltpc.dma = 0; - } + if (dev_ltpc->dma) + free_dma(dev_ltpc->dma); if(debug & DEBUG_VERBOSE) printk("freeing ioaddr\n"); - if(dev_ltpc.base_addr) { - release_region(dev_ltpc.base_addr,8); - dev_ltpc.base_addr = 0; - } + if (dev_ltpc->base_addr) + release_region(dev_ltpc->base_addr,8); + + free_netdev(dev_ltpc); if(debug & DEBUG_VERBOSE) printk("free_pages\n"); free_pages( (unsigned long) ltdmabuf, get_order(1000)); - ltdmabuf=NULL; - ltdmacbuf=NULL; - - if(debug & DEBUG_VERBOSE) printk("unregister_netdev\n"); - - unregister_netdev(&dev_ltpc); if(debug & DEBUG_VERBOSE) printk("returning from cleanup_module\n"); } diff --git a/drivers/net/b44.c b/drivers/net/b44.c index b759af47913d..ef10d16fd679 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1834,7 +1834,7 @@ err_out_iounmap: iounmap((void *) bp->regs); err_out_free_dev: - kfree(dev); + free_netdev(dev); err_out_free_res: pci_release_regions(pdev); diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index ed7874f4fe4e..27bc8ed937cf 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -1462,7 +1462,7 @@ out2: release_OF_resource(bp->node, 0); out1: pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0); - kfree(dev); + free_netdev(dev); } static int bmac_open(struct net_device *dev) diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index 00ddd19e0fd2..d28d864cbaa5 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -1275,7 +1275,7 @@ dgrs_found_device( SET_MODULE_OWNER(dev); if (register_netdev(dev) != 0) { - kfree(dev); + free_netdev(dev); return -EIO; } @@ -1322,7 +1322,7 @@ dgrs_found_device( ret = -EIO; if (register_netdev(devN)) { - kfree(devN); + free_netdev(devN); goto fail; } privN->chan = i+1; diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index d0fba4cb4df4..76f1d66eb6c1 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -319,7 +319,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) err_out_dev: #endif - kfree (dev); + free_netdev (dev); err_out_res: pci_release_regions (pdev); diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 2a14f46f6014..02c2db84f603 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -894,7 +894,7 @@ static int __devinit speedo_found1(struct pci_dev *pdev, err_free_unlock: rtnl_unlock(); - kfree(dev); + free_netdev(dev); return -1; } diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 93fdb1469a0c..00bbf4b7baea 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -565,7 +565,7 @@ err_out_free_res: #endif pci_release_regions(pdev); err_out_free_netdev: - kfree(dev); + free_netdev(dev); return -ENODEV; } diff --git a/drivers/net/ethertap.c b/drivers/net/ethertap.c index 5f8162612c25..0656fefa9670 100644 --- a/drivers/net/ethertap.c +++ b/drivers/net/ethertap.c @@ -33,7 +33,6 @@ * Index to functions. */ -int ethertap_probe(struct net_device *dev); static int ethertap_open(struct net_device *dev); static int ethertap_start_xmit(struct sk_buff *skb, struct net_device *dev); static int ethertap_close(struct net_device *dev); @@ -45,7 +44,11 @@ static void set_multicast_list(struct net_device *dev); static int ethertap_debug; -static struct net_device *tap_map[32]; /* Returns the tap device for a given netlink */ +static int max_taps = 1; +MODULE_PARM(max_taps, "i"); +MODULE_PARM_DESC(max_taps,"Max number of ethernet tap devices"); + +static struct net_device **tap_map; /* Returns the tap device for a given netlink */ /* * Board-specific info in dev->priv. @@ -64,25 +67,29 @@ struct net_local * To call this a probe is a bit misleading, however for real * hardware it would have to check what was present. */ - -int __init ethertap_probe(struct net_device *dev) +static int __init ethertap_probe(int unit) { + struct net_device *dev; + int err = -ENOMEM; + + dev = alloc_netdev(sizeof(struct net_local), "tap%d", + ether_setup); + + if (!dev) + goto out; + SET_MODULE_OWNER(dev); + sprintf(dev->name, "tap%d", unit); + dev->base_addr = unit + NETLINK_TAPBASE; + + netdev_boot_setup_check(dev); + memcpy(dev->dev_addr, "\xFE\xFD\x00\x00\x00\x00", 6); if (dev->mem_start & 0xf) ethertap_debug = dev->mem_start & 0x7; /* - * Initialize the device structure. - */ - - dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct net_local)); - - /* * The tap specific entries in the device structure. */ @@ -94,17 +101,19 @@ int __init ethertap_probe(struct net_device *dev) dev->set_multicast_list = set_multicast_list; #endif - /* - * Setup the generic properties - */ - - ether_setup(dev); - dev->tx_queue_len = 0; dev->flags|=IFF_NOARP; - tap_map[dev->base_addr]=dev; + err = register_netdev(dev); + if (err) + goto out_free; + + tap_map[unit]=dev; return 0; +out_free: + free_netdev(dev); +out: + return err; } /* @@ -116,11 +125,12 @@ static int ethertap_open(struct net_device *dev) struct net_local *lp = (struct net_local*)dev->priv; if (ethertap_debug > 2) - printk("%s: Doing ethertap_open()...", dev->name); + printk(KERN_DEBUG "%s: Doing ethertap_open()...", dev->name); lp->nl = netlink_kernel_create(dev->base_addr, ethertap_rx); if (lp->nl == NULL) return -ENOBUFS; + netif_start_queue(dev); return 0; } @@ -302,7 +312,7 @@ static void ethertap_rx(struct sock *sk, int len) } if (ethertap_debug > 3) - printk("%s: ethertap_rx()\n", dev->name); + printk(KERN_DEBUG "%s: ethertap_rx()\n", dev->name); while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) ethertap_rx_skb(skb, dev); @@ -314,7 +324,7 @@ static int ethertap_close(struct net_device *dev) struct sock *sk = lp->nl; if (ethertap_debug > 2) - printk("%s: Shutting down.\n", dev->name); + printk(KERN_DEBUG "%s: Shutting down.\n", dev->name); netif_stop_queue(dev); @@ -332,45 +342,49 @@ static struct net_device_stats *ethertap_get_stats(struct net_device *dev) return &lp->stats; } -#ifdef MODULE - -static int unit; -MODULE_PARM(unit,"i"); -MODULE_PARM_DESC(unit,"Ethertap device number"); -static struct net_device dev_ethertap = +int __init ethertap_init(void) { - .name = " ", - .init = ethertap_probe -}; + int i, err = 0; -int init_module(void) -{ - dev_ethertap.base_addr=unit+NETLINK_TAPBASE; - sprintf(dev_ethertap.name,"tap%d",unit); - if (dev_get(dev_ethertap.name)) - { - printk(KERN_INFO "%s already loaded.\n", dev_ethertap.name); - return -EBUSY; + /* netlink can only hande 16 entries unless modified */ + if (max_taps > MAX_LINKS - NETLINK_TAPBASE) + return -E2BIG; + + tap_map = kmalloc(sizeof(struct net_device *)*max_taps, GFP_KERNEL); + if (!tap_map) + return -ENOMEM; + + for (i = 0; i < max_taps; i++) { + err = ethertap_probe(i); + if (err) { + while (--i > 0) { + unregister_netdev(tap_map[i]); + free_netdev(tap_map[i]); + } + break; + } } - if (register_netdev(&dev_ethertap) != 0) - return -EIO; - return 0; + if (err) + kfree(tap_map); + return err; } +module_init(ethertap_init); -void cleanup_module(void) +void __exit ethertap_cleanup(void) { - tap_map[dev_ethertap.base_addr]=NULL; - unregister_netdev(&dev_ethertap); - - /* - * Free up the private structure. - */ - - kfree(dev_ethertap.priv); - dev_ethertap.priv = NULL; /* gets re-allocated by ethertap_probe */ + int i; + + for (i = 0; i < max_taps; i++) { + struct net_device *dev = tap_map[i]; + if (dev) { + tap_map[i] = NULL; + unregister_netdev(dev); + free_netdev(dev); + } + } + kfree(tap_map); } +module_exit(ethertap_cleanup); -#endif /* MODULE */ MODULE_LICENSE("GPL"); - diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index de914dfc56f8..ee1e45180f86 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -689,7 +689,7 @@ err_out_free_tx: err_out_free_rx: pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma); err_out_free_dev: - kfree(dev); + free_netdev(dev); err_out_unmap: #ifndef USE_IO_OPS iounmap((void *)ioaddr); diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 36e7074c2bd8..ab87588a7ff3 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -785,7 +785,7 @@ err_out_unmap_tx: pci_free_consistent(pdev, TX_TOTAL_SIZE, hmp->tx_ring, hmp->tx_ring_dma); err_out_cleardev: - kfree (dev); + free_netdev (dev); err_out_iounmap: iounmap((char *)ioaddr); err_out_release: diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 0152d6be4065..ea53fe75059a 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -1064,6 +1064,7 @@ static void decode_data(unsigned char inbyte, struct sixpack *sp) MODULE_AUTHOR("Andreas Könsgen <ajk@ccac.rwth-aachen.de>"); MODULE_DESCRIPTION("6pack driver for AX.25"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_LDISC(N_6PACK); module_init(sixpack_init_driver); module_exit(sixpack_exit_driver); diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 2711caa9cb97..c78732698118 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -935,7 +935,7 @@ MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs"); MODULE_PARM(ax25_maxdev, "i"); MODULE_PARM_DESC(ax25_maxdev, "number of MKISS devices"); MODULE_LICENSE("GPL"); - +MODULE_ALIAS_LDISC(N_AX25); module_init(mkiss_init_driver); module_exit(mkiss_exit_driver); diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index c3b4e5f1353d..d93767489ff0 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -1512,7 +1512,7 @@ out_stop: out_res: pci_release_regions(pdev); out_free: - kfree(dev); + free_netdev(dev); return err; } diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 99d7afc609bc..0d6837d8deb6 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -651,5 +651,6 @@ module_exit(irtty_sir_cleanup); MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); MODULE_DESCRIPTION("IrDA TTY device driver"); +MODULE_ALIAS_LDISC(N_IRDA); MODULE_LICENSE("GPL"); diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index b3045c467da8..6f8c223bf68e 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -1543,7 +1543,7 @@ lan_init_chip(struct parisc_device *dev) retval = register_netdev(netdevice); if (retval) { printk(KERN_WARNING __FILE__ ": register_netdevice ret'd %d\n", retval); - kfree(netdevice); + free_netdev(netdevice); return -ENODEV; }; if (dev->id.sversion == 0x72) { diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 7382804af6b0..5dd2b3393edc 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -55,6 +55,7 @@ #include <linux/ip.h> #include <linux/tcp.h> + #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16) /* KISS: just allocate small chunks and copy bits. @@ -152,10 +153,12 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) } dev->last_rx = jiffies; - stats->rx_bytes+=skb->len; - stats->tx_bytes+=skb->len; - stats->rx_packets++; - stats->tx_packets++; + if (likely(stats)) { + stats->rx_bytes+=skb->len; + stats->tx_bytes+=skb->len; + stats->rx_packets++; + stats->tx_packets++; + } netif_rx(skb); @@ -167,36 +170,35 @@ static struct net_device_stats *get_stats(struct net_device *dev) return (struct net_device_stats *)dev->priv; } -/* Initialize the rest of the LOOPBACK device. */ -int __init loopback_init(struct net_device *dev) -{ - dev->mtu = (16 * 1024) + 20 + 20 + 12; - dev->hard_start_xmit = loopback_xmit; - dev->hard_header = eth_header; - dev->hard_header_cache = eth_header_cache; - dev->header_cache_update= eth_header_cache_update; - dev->hard_header_len = ETH_HLEN; /* 14 */ - dev->addr_len = ETH_ALEN; /* 6 */ - dev->tx_queue_len = 0; - dev->type = ARPHRD_LOOPBACK; /* 0x0001 */ - dev->rebuild_header = eth_rebuild_header; - dev->flags = IFF_LOOPBACK; - dev->features = NETIF_F_SG|NETIF_F_FRAGLIST|NETIF_F_NO_CSUM|NETIF_F_HIGHDMA; - - /* Current netfilter will die with oom linearizing large skbs, - * however this will be cured before 2.5.x is done. - */ - dev->features |= NETIF_F_TSO; - - dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct net_device_stats)); - dev->get_stats = get_stats; +struct net_device loopback_dev = { + .name = "lo", + .mtu = (16 * 1024) + 20 + 20 + 12, + .hard_start_xmit = loopback_xmit, + .hard_header = eth_header, + .hard_header_cache = eth_header_cache, + .header_cache_update = eth_header_cache_update, + .hard_header_len = ETH_HLEN, /* 14 */ + .addr_len = ETH_ALEN, /* 6 */ + .tx_queue_len = 0, + .type = ARPHRD_LOOPBACK, /* 0x0001*/ + .rebuild_header = eth_rebuild_header, + .flags = IFF_LOOPBACK, + .features = NETIF_F_SG|NETIF_F_FRAGLIST + |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA|NETIF_F_TSO, +}; - /* - * Fill in the generic fields of the device structure. - */ - - return(0); +/* Setup and register the of the LOOPBACK device. */ +int __init loopback_init(void) +{ + struct net_device_stats *stats; + + /* Can survive without statistics */ + stats = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); + if (stats) { + memset(stats, 0, sizeof(struct net_device_stats)); + loopback_dev.priv = stats; + loopback_dev.get_stats = &get_stats; + } + + return register_netdev(&loopback_dev); }; diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index fe1e255a576c..3e687d9cbd41 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -1324,7 +1324,7 @@ static int __init lp486e_init_module(void) { dev->base_addr = io; dev->init = lp486e_probe; if (register_netdev(dev) != 0) { - kfree(dev); + free_netdev(dev); return -EIO; } dev_lp486e = dev; diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index b95d3030e465..14fbbef63fb6 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -766,7 +766,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, i = pci_request_regions(pdev, dev->name); if (i) { - kfree(dev); + free_netdev(dev); return i; } @@ -774,7 +774,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, void *mmio = ioremap (ioaddr, iosize); if (!mmio) { pci_release_regions(pdev); - kfree(dev); + free_netdev(dev); return -ENOMEM; } ioaddr = (unsigned long) mmio; @@ -838,7 +838,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, if (i) { pci_release_regions(pdev); unregister_netdev(dev); - kfree(dev); + free_netdev(dev); pci_set_drvdata(pdev, NULL); return i; } diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index ad6281ef7a83..2d519b696533 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -529,6 +529,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, struct net_device *dev; struct pcnet32_access *a = NULL; u8 promaddr[6]; + int ret = -ENODEV; /* reset the chip */ pcnet32_wio_reset(ioaddr); @@ -540,19 +541,15 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, pcnet32_dwio_reset(ioaddr); if (pcnet32_dwio_read_csr(ioaddr, 0) == 4 && pcnet32_dwio_check(ioaddr)) { a = &pcnet32_dwio; - } else { - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENODEV; - } + } else + goto err_release_region; } chip_version = a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr,89) << 16); if (pcnet32_debug > 2) printk(KERN_INFO " PCnet chip version is %#x.\n", chip_version); - if ((chip_version & 0xfff) != 0x003) { - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENODEV; - } + if ((chip_version & 0xfff) != 0x003) + goto err_release_region; /* initialize variables */ fdx = mii = fset = dxsuflo = ltint = 0; @@ -614,8 +611,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, default: printk(KERN_INFO PFX "PCnet version %#x, no PCnet32 chip.\n", chip_version); - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENODEV; + goto err_release_region; } /* @@ -635,8 +631,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, dev = alloc_etherdev(0); if(!dev) { - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENOMEM; + ret = -ENOMEM; + goto err_release_region; } SET_NETDEV_DEV(dev, &pdev->dev); @@ -708,8 +704,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, dev->base_addr = ioaddr; /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */ if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) { - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENOMEM; + ret = -ENOMEM; + goto err_free_netdev; } memset(lp, 0, sizeof(*lp)); @@ -741,9 +737,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, if (!a) { printk(KERN_ERR PFX "No access methods\n"); - pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENODEV; + ret = -ENODEV; + goto err_free_consistent; } lp->a = *a; @@ -785,14 +780,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, mdelay (1); dev->irq = probe_irq_off (irq_mask); - if (dev->irq) - printk(", probed IRQ %d.\n", dev->irq); - else { + if (!dev->irq) { printk(", failed to detect IRQ line.\n"); - pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return -ENODEV; + ret = -ENODEV; + goto err_free_consistent; } + printk(", probed IRQ %d.\n", dev->irq); } /* Set the mii phy_id so that we can query the link state */ @@ -821,6 +814,14 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, printk(KERN_INFO "%s: registered as %s\n",dev->name, lp->name); cards_found++; return 0; + +err_free_consistent: + pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); +err_free_netdev: + free_netdev(dev); +err_release_region: + release_region(ioaddr, PCNET32_TOTAL_SIZE); + return ret; } diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index 09bcc8a0f26f..f6a58b4bc292 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -84,7 +84,7 @@ static int flag_time = HZ; MODULE_PARM(flag_time, "i"); MODULE_PARM_DESC(flag_time, "ppp_async: interval between flagged packets (in clock ticks)"); MODULE_LICENSE("GPL"); - +MODULE_ALIAS_LDISC(N_PPP); /* * Prototypes. diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index c96dbc2bd150..6b30d5f28c10 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -2670,3 +2670,4 @@ EXPORT_SYMBOL(ppp_unregister_compressor); EXPORT_SYMBOL(all_ppp_units); /* for debugging */ EXPORT_SYMBOL(all_channels); /* for debugging */ MODULE_LICENSE("GPL"); +MODULE_ALIAS_CHARDEV_MAJOR(PPP_MAJOR); diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index 06feb5870fc8..fc93451e6858 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -759,3 +759,4 @@ ppp_sync_cleanup(void) module_init(ppp_sync_init); module_exit(ppp_sync_cleanup); MODULE_LICENSE("GPL"); +MODULE_ALIAS_LDISC(N_SYNC_PPP); diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index a0b4b659aa0e..c11b83e6adeb 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -454,7 +454,7 @@ err_out_disable: pci_disable_device(pdev); err_out: - kfree(dev); + free_netdev(dev); return rc; } @@ -514,7 +514,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) iounmap(ioaddr); pci_release_regions(pdev); pci_disable_device(pdev); - kfree(dev); + free_netdev(dev); return rc; } diff --git a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c index f5cdead40f14..e7e1a9f2d71a 100644 --- a/drivers/net/rcpci45.c +++ b/drivers/net/rcpci45.c @@ -269,7 +269,7 @@ err_out_free_msgbuf: pci_free_consistent (pdev, MSG_BUF_SIZE, pDpa->msgbuf, pDpa->msgbuf_dma); err_out_free_dev: - kfree (dev); + free_netdev (dev); err_out: card_idx--; return error; diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index d0153f60a036..5326dee62c74 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -213,9 +213,11 @@ sb1000_probe_one(struct pnp_dev *pdev, const struct pnp_device_id *id) error = register_netdev(dev); if (error) - goto out_release_regions; + goto out_free_netdev; return 0; + out_free_netdev: + free_netdev(dev); out_release_regions: release_region(ioaddr[1], 16); out_release_region0: diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 1c79e7b9c34e..9f421480b233 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -470,7 +470,7 @@ SiS190_init_board(struct pci_dev *pdev, struct net_device **dev_out, rc = pci_set_dma_mask(pdev, 0xffffffffULL); if (rc) - goto err_out; + goto err_out_disable; mmio_start = pci_resource_start(pdev, 0); mmio_end = pci_resource_end(pdev, 0); @@ -482,18 +482,18 @@ SiS190_init_board(struct pci_dev *pdev, struct net_device **dev_out, printk(KERN_ERR PFX "region #0 not an MMIO resource, aborting\n"); rc = -ENODEV; - goto err_out; + goto err_out_disable; } // check for weird/broken PCI region reporting if (mmio_len < SiS190_MIN_IO_SIZE) { printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n"); rc = -ENODEV; - goto err_out; + goto err_out_disable; } rc = pci_request_regions(pdev, dev->name); if (rc) - goto err_out; + goto err_out_disable; // enable PCI bus-mastering pci_set_master(pdev); @@ -521,9 +521,10 @@ SiS190_init_board(struct pci_dev *pdev, struct net_device **dev_out, err_out_free_res: pci_release_regions(pdev); -err_out: +err_out_disable: pci_disable_device(pdev); - kfree(dev); +err_out: + free_netdev(dev); return rc; } @@ -603,7 +604,7 @@ SiS190_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) iounmap(ioaddr); pci_release_regions(pdev); pci_disable_device(pdev); - kfree(dev); + free_netdev(dev); return rc; } diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index b5853f1a9fbd..6422eb2a4208 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -503,7 +503,7 @@ static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_dev pci_set_drvdata(pci_dev, NULL); pci_release_regions(pci_dev); err_out: - kfree(net_dev); + free_netdev(net_dev); return ret; } diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 867cc1c3a5d6..3e60ed4c3969 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -1513,3 +1513,4 @@ out: #endif MODULE_LICENSE("GPL"); +MODULE_ALIAS_LDISC(N_SLIP); diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c index e33c7a2a2f7f..c5a085707302 100644 --- a/drivers/net/smc-mca.c +++ b/drivers/net/smc-mca.c @@ -132,7 +132,7 @@ int __init ultramca_probe(struct device *gen_dev) struct mca_device *mca_dev = to_mca_device(gen_dev); char slot = mca_dev->slot; unsigned char pos2 = 0xff, pos3 = 0xff, pos4 = 0xff, pos5 = 0xff; - int i; + int i, rc; int adapter = mca_dev->index; int tbase = 0; int tirq = 0; @@ -209,8 +209,9 @@ int __init ultramca_probe(struct device *gen_dev) SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, gen_dev); - if((i = register_netdev(dev)) != 0) - return i; + rc = register_netdev(dev); + if (rc) + goto err_free_netdev; printk(KERN_INFO "%s: %s found in slot %d\n", dev->name, smc_mca_adapter_names[adapter], slot + 1); @@ -262,11 +263,15 @@ int __init ultramca_probe(struct device *gen_dev) } } - if (dev->mem_start == 0) /* sanity check, shouldn't happen */ - return -ENODEV; + /* sanity check, shouldn't happen */ + if (dev->mem_start == 0) { + rc = -ENODEV; + goto err_unregister_netdev; + } - if (!request_region(ioaddr, ULTRA_IO_EXTENT, dev->name)) - return -EBUSY; + rc = request_region(ioaddr, ULTRA_IO_EXTENT, dev->name); + if (rc) + goto err_unregister_netdev; reg4 = inb(ioaddr + 4) & 0x7f; outb(reg4, ioaddr + 4); @@ -296,10 +301,10 @@ int __init ultramca_probe(struct device *gen_dev) /* Allocate dev->priv and fill in 8390 specific dev fields. */ - if (ethdev_init(dev)) { + rc = ethdev_init(dev); + if (rc) { printk (", no memory for dev->priv.\n"); - release_region(ioaddr, ULTRA_IO_EXTENT); - return -ENOMEM; + goto err_release_region; } gen_dev->driver_data = dev; @@ -334,6 +339,14 @@ int __init ultramca_probe(struct device *gen_dev) NS8390_init(dev, 0); return 0; + +err_release_region: + release_region(ioaddr, ULTRA_IO_EXTENT); +err_unregister_netdev: + unregister_netdev(dev); +err_free_netdev: + free_netdev(dev); + return rc; } static int ultramca_open(struct net_device *dev) diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index dcf1db7ea6ef..c2bddf1f1700 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1070,7 +1070,7 @@ err_out_cleardev: err_out_free_res: pci_release_regions (pdev); err_out_free_netdev: - kfree(dev); + free_netdev(dev); return -ENODEV; } diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 5bd8be316547..aad877c5400b 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -734,7 +734,7 @@ err_out_res: #endif pci_release_regions(pdev); err_out_netdev: - kfree (dev); + free_netdev (dev); return -ENODEV; } diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index a452e5942b52..a346fd1d4dba 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2416,13 +2416,6 @@ static int gem_nway_reset(struct net_device *dev) return 0; } -static u32 gem_get_link(struct net_device *dev) -{ - struct gem *gp = dev->priv; - - return (gp->lstate == link_up); -} - static u32 gem_get_msglevel(struct net_device *dev) { struct gem *gp = dev->priv; @@ -2441,7 +2434,6 @@ static struct ethtool_ops gem_ethtool_ops = { .get_settings = gem_get_settings, .set_settings = gem_set_settings, .nway_reset = gem_nway_reset, - .get_link = gem_get_link, .get_msglevel = gem_get_msglevel, .set_msglevel = gem_set_msglevel, }; @@ -2630,7 +2622,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, if (err) { printk(KERN_ERR PFX "No usable DMA configuration, " "aborting.\n"); - return err; + goto err_disable_device; } pci_using_dac = 0; } @@ -2641,20 +2633,23 @@ static int __devinit gem_init_one(struct pci_dev *pdev, if ((pci_resource_flags(pdev, 0) & IORESOURCE_IO) != 0) { printk(KERN_ERR PFX "Cannot find proper PCI device " "base address, aborting.\n"); - return -ENODEV; + err = -ENODEV; + goto err_disable_device; } dev = alloc_etherdev(sizeof(*gp)); if (!dev) { printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); - return -ENOMEM; + err = -ENOMEM; + goto err_disable_device; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); gp = dev->priv; - if (pci_request_regions(pdev, dev->name)) { + err = pci_request_regions(pdev, dev->name); + if (err) { printk(KERN_ERR PFX "Cannot obtain PCI resources, " "aborting.\n"); goto err_out_free_netdev; @@ -2688,6 +2683,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, if (gp->regs == 0UL) { printk(KERN_ERR PFX "Cannot map device registers, " "aborting.\n"); + err = -EIO; goto err_out_free_res; } @@ -2711,8 +2707,10 @@ static int __devinit gem_init_one(struct pci_dev *pdev, /* By default, we start with autoneg */ gp->want_autoneg = 1; - if (gem_check_invariants(gp)) + if (gem_check_invariants(gp)) { + err = -ENODEV; goto err_out_iounmap; + } /* It is guaranteed that the returned buffer will be at least * PAGE_SIZE aligned. @@ -2723,6 +2721,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, if (!gp->init_block) { printk(KERN_ERR PFX "Cannot allocate init block, " "aborting.\n"); + err = -ENOMEM; goto err_out_iounmap; } @@ -2735,6 +2734,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, if (register_netdev(dev)) { printk(KERN_ERR PFX "Cannot register net device, " "aborting.\n"); + err = -ENOMEM; goto err_out_free_consistent; } @@ -2804,9 +2804,10 @@ err_out_free_res: pci_release_regions(pdev); err_out_free_netdev: - kfree(dev); - - return -ENODEV; + free_netdev(dev); +err_disable_device: + pci_disable_device(pdev); + return err; } diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 8c786ab7b3c5..b91f7d0199bf 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2895,7 +2895,7 @@ err_out_iounmap: sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); err_out_free_netdev: - kfree(dev); + free_netdev(dev); err_out: return err; @@ -3247,7 +3247,7 @@ err_out_clear_quattro: if (qp != NULL) qp->happy_meals[qfe_slot] = NULL; - kfree(dev); + free_netdev(dev); err_out: return err; diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index b5d8879c2035..5116b5152e8a 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -949,7 +949,7 @@ out1: i = 4; out: while (i--) - kfree(qe_devs[i]); + free_netdev(qe_devs[i]); return res; } diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c31dc44a6fd2..3ebedccf00b3 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7740,7 +7740,7 @@ err_out_iounmap: iounmap((void *) tp->regs); err_out_free_dev: - kfree(dev); + free_netdev(dev); err_out_free_res: pci_release_regions(pdev); diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 5a45900a816e..c5b6999712fb 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -670,7 +670,7 @@ err_out_uninit: pci_free_consistent(priv->pciDev, priv->dmaSize, priv->dmaStorage, priv->dmaStorageDMA ); err_out_free_dev: - kfree(dev); + free_netdev(dev); err_out_regions: if (pdev) pci_release_regions(pdev); @@ -695,7 +695,7 @@ static void TLan_Eisa_Cleanup(void) release_region( dev->base_addr, 0x10); unregister_netdev( dev ); TLan_Eisa_Devices = priv->nextDevice; - kfree( dev ); + free_netdev( dev ); tlan_have_eisa--; } } diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 96fe51d22763..df234c48d9aa 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -437,6 +437,9 @@ present. <france@handhelds.org> 0.547 08-Nov-01 Use library crc32 functions by <Matt_Domsch@dell.com> + 0.548 30-Aug-03 Big 2.6 cleanup. Ported to PCI/EISA probing and + generic DMA APIs. Fixed DE425 support on Alpha. + <maz@wild-wind.fr.eu.org> ========================================================================= */ @@ -450,6 +453,7 @@ #include <linux/ioport.h> #include <linux/slab.h> #include <linux/pci.h> +#include <linux/eisa.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/spinlock.h> @@ -461,6 +465,8 @@ #include <linux/types.h> #include <linux/unistd.h> #include <linux/ctype.h> +#include <linux/dma-mapping.h> +#include <linux/moduleparam.h> #include <asm/bitops.h> #include <asm/io.h> @@ -625,13 +631,13 @@ struct parameters { #define DE4X5_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ #define DE4X5_EISA_TOTAL_SIZE 0x100 /* I/O address extent */ -#define MAX_EISA_SLOTS 16 -#define EISA_SLOT_INC 0x1000 #define EISA_ALLOWED_IRQ_LIST {5, 9, 10, 11} #define DE4X5_SIGNATURE {"DE425","DE434","DE435","DE450","DE500"} #define DE4X5_NAME_LENGTH 8 +static c_char *de4x5_signatures[] = DE4X5_SIGNATURE; + /* ** Ethernet PROM defines for DC21040 */ @@ -644,7 +650,6 @@ struct parameters { #define PCI_MAX_BUS_NUM 8 #define DE4X5_PCI_TOTAL_SIZE 0x80 /* I/O address extent */ #define DE4X5_CLASS_CODE 0x00020000 /* Network controller, Ethernet */ -#define NO_MORE_PCI -2 /* PCI bus search all done */ /* ** Memory Alignment. Each descriptor is 4 longwords long. To force a @@ -819,7 +824,6 @@ struct de4x5_private { struct timer_list timer; /* Timer info for kernel */ int tmp; /* Temporary global per card */ struct { - void *priv; /* Original kmalloc'd mem addr */ u_long lock; /* Lock the cache accesses */ s32 csr0; /* Saved Bus Mode Register */ s32 csr6; /* Saved Operating Mode Reg. */ @@ -833,7 +837,7 @@ struct de4x5_private { struct sk_buff *skb; /* Save the (re-ordered) skb's */ } cache; struct de4x5_srom srom; /* A copy of the SROM */ - struct net_device *next_module; /* Link to the next module */ + int cfrv; /* Card CFRV copy */ int rx_ovf; /* Check for 'RX overflow' tag */ int useSROM; /* For non-DEC card use SROM */ int useMII; /* Infoblock using the MII */ @@ -850,29 +854,13 @@ struct de4x5_private { u_char *rst; /* Pointer to Type 5 reset info */ u_char ibn; /* Infoblock number */ struct parameters params; /* Command line/ #defined params */ - struct pci_dev *pdev; /* Device cookie for DMA alloc */ + struct device *gendev; /* Generic device */ dma_addr_t dma_rings; /* DMA handle for rings */ int dma_size; /* Size of the DMA area */ char *rx_bufs; /* rx bufs on alpha, sparc, ... */ }; /* -** Kludge to get around the fact that the CSR addresses have different -** offsets in the PCI and EISA boards. Also note that the ethernet address -** PROM is accessed differently. -*/ -static struct de4x5_bus_type { - int bus; - int bus_num; - int device; - int chipset; - struct de4x5_srom srom; - int autosense; - int useSROM; - struct pci_dev *pdev; -} bus; - -/* ** To get around certain poxy cards that don't provide an SROM ** for the second and more DECchip, I have to key off the first ** chip's address. I'll assume there's not a bad SROM iff: @@ -919,7 +907,7 @@ static int de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); /* ** Private functions */ -static int de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev); +static int de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev); static int de4x5_init(struct net_device *dev); static int de4x5_sw_reset(struct net_device *dev); static int de4x5_rx(struct net_device *dev); @@ -962,11 +950,11 @@ static int de4x5_reset_phy(struct net_device *dev); static void reset_init_sia(struct net_device *dev, s32 sicr, s32 strr, s32 sigr); static int test_ans(struct net_device *dev, s32 irqs, s32 irq_mask, s32 msec); static int test_tp(struct net_device *dev, s32 msec); -static int EISA_signature(char *name, s32 eisa_id); -static int PCI_signature(char *name, struct de4x5_bus_type *lp); -static void DevicePresent(u_long iobase); +static int EISA_signature(char *name, struct device *device); +static int PCI_signature(char *name, struct de4x5_private *lp); +static void DevicePresent(struct net_device *dev, u_long iobase); static void enet_addr_rst(u_long aprom_addr); -static int de4x5_bad_srom(struct de4x5_bus_type *lp); +static int de4x5_bad_srom(struct de4x5_private *lp); static short srom_rd(u_long address, u_char offset); static void srom_latch(u_int command, u_long address); static void srom_command(u_int command, u_long address); @@ -994,12 +982,7 @@ static void SetMulticastFilter(struct net_device *dev); static int get_hw_addr(struct net_device *dev); static void srom_repair(struct net_device *dev, int card); static int test_bad_enet(struct net_device *dev, int status); -static int an_exception(struct de4x5_bus_type *lp); -#if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__) -static void eisa_probe(struct net_device *dev, u_long iobase); -#endif -static void pci_probe(struct net_device *dev, u_long iobase); -static void srom_search(struct pci_dev *pdev); +static int an_exception(struct de4x5_private *lp); static char *build_setup_frame(struct net_device *dev, int mode); static void disable_ast(struct net_device *dev); static void enable_ast(struct net_device *dev, u32 time_out); @@ -1008,7 +991,6 @@ static int gep_rd(struct net_device *dev); static void gep_wr(s32 data, struct net_device *dev); static void timeout(struct net_device *dev, void (*fn)(u_long data), u_long data, u_long msec); static void yawn(struct net_device *dev, int state); -static void link_modules(struct net_device *dev, struct net_device *tmp); static void de4x5_parse_params(struct net_device *dev); static void de4x5_dbg_open(struct net_device *dev); static void de4x5_dbg_mii(struct net_device *dev, int k); @@ -1028,40 +1010,25 @@ static int type4_infoblock(struct net_device *dev, u_char count, u_char *p); static int type5_infoblock(struct net_device *dev, u_char count, u_char *p); static int compact_infoblock(struct net_device *dev, u_char count, u_char *p); -#ifdef MODULE -static struct net_device *unlink_modules(struct net_device *p); -static struct net_device *insert_device(struct net_device *dev, u_long iobase, - int (*init)(struct net_device *)); -static int count_adapters(void); -static int loading_module = 1; -MODULE_PARM(de4x5_debug, "i"); -MODULE_PARM(dec_only, "i"); -MODULE_PARM(args, "s"); +/* +** Note now that module autoprobing is allowed under EISA and PCI. The +** IRQ lines will not be auto-detected; instead I'll rely on the BIOSes +** to "do the right thing". +*/ + +static int io=0x0;/* EDIT THIS LINE FOR YOUR CONFIGURATION IF NEEDED */ + +module_param(io, int, 0); +module_param(de4x5_debug, int, 0); +module_param(dec_only, int, 0); +module_param(args, charp, 0); + +MODULE_PARM_DESC(io, "de4x5 I/O base address"); MODULE_PARM_DESC(de4x5_debug, "de4x5 debug mask"); MODULE_PARM_DESC(dec_only, "de4x5 probe only for Digital boards (0-1)"); MODULE_PARM_DESC(args, "de4x5 full duplex and media type settings; see de4x5.c for details"); MODULE_LICENSE("GPL"); -# else -static int loading_module; -#endif /* MODULE */ - -static char name[DE4X5_NAME_LENGTH + 1]; -#if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__) -static u_char de4x5_irq[] = EISA_ALLOWED_IRQ_LIST; -static int lastEISA; -# ifdef DE4X5_FORCE_EISA /* Force an EISA bus probe or not */ -static int forceEISA = 1; -# else -static int forceEISA; -# endif -#endif -static int num_de4x5s; -static int cfrv, useSROM; -static int lastPCI = -1; -static struct net_device *lastModule; -static struct pci_dev *pdev; - /* ** List the SROM infoleaf functions and chipsets */ @@ -1115,37 +1082,22 @@ static int (*dc_infoblock[])(struct net_device *dev, u_char, u_char *) = { } -/* -** Autoprobing in modules is allowed here. See the top of the file for -** more info. -*/ -int __init -de4x5_probe(struct net_device *dev) -{ - u_long iobase = dev->base_addr; - - pci_probe(dev, iobase); -#if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__) - if ((lastPCI == NO_MORE_PCI) && ((num_de4x5s == 0) || forceEISA)) { - eisa_probe(dev, iobase); - } -#endif - - return (dev->priv ? 0 : -ENODEV); -} - static int __init -de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev) +de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev) { - struct de4x5_bus_type *lp = &bus; + char name[DE4X5_NAME_LENGTH + 1]; + struct de4x5_private *lp = dev->priv; + struct pci_dev *pdev = NULL; int i, status=0; - char *tmp; - + + gendev->driver_data = dev; + /* Ensure we're not sleeping */ if (lp->bus == EISA) { outb(WAKEUP, PCI_CFPM); } else { - pci_write_config_byte(lp->pdev, PCI_CFDA_PSM, WAKEUP); + pdev = to_pci_dev (gendev); + pci_write_config_byte(pdev, PCI_CFDA_PSM, WAKEUP); } mdelay(10); @@ -1158,11 +1110,11 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev) /* ** Now find out what kind of DC21040/DC21041/DC21140 board we have. */ - useSROM = FALSE; + lp->useSROM = FALSE; if (lp->bus == PCI) { PCI_signature(name, lp); } else { - EISA_signature(name, EISA_ID0); + EISA_signature(name, gendev); } if (*name == '\0') { /* Not found a board signature */ @@ -1170,13 +1122,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev) } dev->base_addr = iobase; - if (lp->bus == EISA) { - printk("%s: %s at 0x%04lx (EISA slot %ld)", - dev->name, name, iobase, ((iobase>>12)&0x0f)); - } else { /* PCI port address */ - printk("%s: %s at 0x%04lx (PCI bus %d, device %d)", dev->name, name, - iobase, lp->bus_num, lp->device); - } + printk ("%s: %s at 0x%04lx", gendev->bus_id, name, iobase); printk(", h/w address "); status = get_hw_addr(dev); @@ -1189,38 +1135,12 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev) printk(" which has an Ethernet PROM CRC error.\n"); return -ENXIO; } else { - struct de4x5_private *lp; - - /* - ** Reserve a section of kernel memory for the adapter - ** private area and the TX/RX descriptor rings. - */ - dev->priv = (void *) kmalloc(sizeof(struct de4x5_private) + DE4X5_ALIGN, - GFP_KERNEL); - if (dev->priv == NULL) { - return -ENOMEM; - } - - /* - ** Align to a longword boundary - */ - tmp = dev->priv; - dev->priv = (void *)(((u_long)dev->priv + DE4X5_ALIGN) & ~DE4X5_ALIGN); - lp = (struct de4x5_private *)dev->priv; - memset(dev->priv, 0, sizeof(struct de4x5_private)); - lp->bus = bus.bus; - lp->bus_num = bus.bus_num; - lp->device = bus.device; - lp->chipset = bus.chipset; - lp->cache.priv = tmp; lp->cache.gepc = GEP_INIT; lp->asBit = GEP_SLNK; lp->asPolarity = GEP_SLNK; lp->asBitValid = TRUE; lp->timeout = -1; - lp->useSROM = useSROM; - lp->pdev = pdev; - memcpy((char *)&lp->srom,(char *)&bus.srom,sizeof(struct de4x5_srom)); + lp->gendev = gendev; lp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; init_timer(&lp->timer); de4x5_parse_params(dev); @@ -1238,16 +1158,15 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev) } } lp->fdx = lp->params.fdx; - sprintf(lp->adapter_name,"%s (%s)", name, dev->name); + sprintf(lp->adapter_name,"%s (%s)", name, gendev->bus_id); lp->dma_size = (NUM_RX_DESC + NUM_TX_DESC) * sizeof(struct de4x5_desc); #if defined(__alpha__) || defined(__powerpc__) || defined(__sparc_v9__) || defined(DE4X5_DO_MEMCPY) lp->dma_size += RX_BUFF_SZ * NUM_RX_DESC + DE4X5_ALIGN; #endif - lp->rx_ring = pci_alloc_consistent(pdev, lp->dma_size, &lp->dma_rings); + lp->rx_ring = dma_alloc_coherent(gendev, lp->dma_size, + &lp->dma_rings, GFP_ATOMIC); if (lp->rx_ring == NULL) { - kfree(lp->cache.priv); - lp->cache.priv = NULL; return -ENOMEM; } @@ -1288,11 +1207,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev) #endif barrier(); - - request_region(iobase, (lp->bus == PCI ? DE4X5_PCI_TOTAL_SIZE : - DE4X5_EISA_TOTAL_SIZE), - lp->adapter_name); - + lp->rxRingSize = NUM_RX_DESC; lp->txRingSize = NUM_TX_DESC; @@ -1313,7 +1228,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev) create_packet(dev, lp->frame, sizeof(lp->frame)); /* Check if the RX overflow bug needs testing for */ - i = cfrv & 0x000000fe; + i = lp->cfrv & 0x000000fe; if ((lp->chipset == DC21140) && (i == 0x20)) { lp->rx_ovf = 1; } @@ -1350,7 +1265,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev) /* The DE4X5-specific entries in the device structure. */ SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); + SET_NETDEV_DEV(dev, gendev); dev->open = &de4x5_open; dev->hard_start_xmit = &de4x5_queue_pkt; dev->stop = &de4x5_close; @@ -1361,7 +1276,11 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev) dev->mem_start = 0; /* Fill in the generic fields of the device structure. */ - ether_setup(dev); + if ((status = register_netdev (dev))) { + dma_free_coherent (gendev, lp->dma_size, + lp->rx_ring, lp->dma_rings); + return status; + } /* Let the adapter sleep to save power */ yawn(dev, SLEEP); @@ -1766,9 +1685,9 @@ de4x5_rx(struct net_device *dev) static inline void de4x5_free_tx_buff(struct de4x5_private *lp, int entry) { - pci_unmap_single(lp->pdev, le32_to_cpu(lp->tx_ring[entry].buf), + dma_unmap_single(lp->gendev, le32_to_cpu(lp->tx_ring[entry].buf), le32_to_cpu(lp->tx_ring[entry].des1) & TD_TBS1, - PCI_DMA_TODEVICE); + DMA_TO_DEVICE); if ((u_long) lp->tx_skb[entry] > 1) dev_kfree_skb_irq(lp->tx_skb[entry]); lp->tx_skb[entry] = NULL; @@ -1987,7 +1906,7 @@ load_packet(struct net_device *dev, char *buf, u32 flags, struct sk_buff *skb) { struct de4x5_private *lp = (struct de4x5_private *)dev->priv; int entry = (lp->tx_new ? lp->tx_new-1 : lp->txRingSize-1); - dma_addr_t buf_dma = pci_map_single(lp->pdev, buf, flags & TD_TBS1, PCI_DMA_TODEVICE); + dma_addr_t buf_dma = dma_map_single(lp->gendev, buf, flags & TD_TBS1, DMA_TO_DEVICE); lp->tx_ring[lp->tx_new].buf = cpu_to_le32(buf_dma); lp->tx_ring[lp->tx_new].des1 &= cpu_to_le32(TD_TER); @@ -2084,75 +2003,199 @@ SetMulticastFilter(struct net_device *dev) return; } -#if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__) -/* -** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually -** the motherboard. Upto 15 EISA devices are supported. -*/ -static void __init -eisa_probe(struct net_device *dev, u_long ioaddr) +#ifdef CONFIG_EISA + +static u_char de4x5_irq[] = EISA_ALLOWED_IRQ_LIST; + +static int __init de4x5_eisa_probe (struct device *gendev) { - int i, maxSlots, status, device; - u_char irq; - u_short vendor; - u32 cfid; - u_long iobase; - struct de4x5_bus_type *lp = &bus; - char name[DE4X5_STRLEN]; + struct eisa_device *edev; + u_long iobase; + u_char irq, regval; + u_short vendor; + u32 cfid; + int status, device; + struct net_device *dev; + struct de4x5_private *lp; - if (lastEISA == MAX_EISA_SLOTS) return;/* No more EISA devices to search */ + edev = to_eisa_device (gendev); + iobase = edev->base_addr; - lp->bus = EISA; - - if (ioaddr == 0) { /* Autoprobing */ - iobase = EISA_SLOT_INC; /* Get the first slot address */ - i = 1; - maxSlots = MAX_EISA_SLOTS; - } else { /* Probe a specific location */ - iobase = ioaddr; - i = (ioaddr >> 12); - maxSlots = i + 1; - } - - for (status = -ENODEV; (i<maxSlots) && (dev!=NULL); i++, iobase+=EISA_SLOT_INC) { - if (check_region(iobase, DE4X5_EISA_TOTAL_SIZE)) continue; - if (!EISA_signature(name, EISA_ID)) continue; + if (!request_region (iobase, DE4X5_EISA_TOTAL_SIZE, "de4x5")) + return -EBUSY; + if (!request_region (iobase + DE4X5_EISA_IO_PORTS, + DE4X5_EISA_TOTAL_SIZE, "de4x5")) { + status = -EBUSY; + goto release_reg_1; + } + + if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) { + status = -ENOMEM; + goto release_reg_2; + } + lp = dev->priv; + cfid = (u32) inl(PCI_CFID); - cfrv = (u_short) inl(PCI_CFRV); + lp->cfrv = (u_short) inl(PCI_CFRV); device = (cfid >> 8) & 0x00ffff00; vendor = (u_short) cfid; /* Read the EISA Configuration Registers */ - irq = inb(EISA_REG0); - irq = de4x5_irq[(irq >> 1) & 0x03]; + regval = inb(EISA_REG0) & (ER0_INTL | ER0_INTT); +#ifdef CONFIG_ALPHA + /* Looks like the Jensen firmware (rev 2.2) doesn't really + * care about the EISA configuration, and thus doesn't + * configure the PLX bridge properly. Oh well... Simply mimic + * the EISA config file to sort it out. */ + + /* EISA REG1: Assert DecChip 21040 HW Reset */ + outb (ER1_IAM | 1, EISA_REG1); + mdelay (1); + /* EISA REG1: Deassert DecChip 21040 HW Reset */ + outb (ER1_IAM, EISA_REG1); + mdelay (1); + + /* EISA REG3: R/W Burst Transfer Enable */ + outb (ER3_BWE | ER3_BRE, EISA_REG3); + + /* 32_bit slave/master, Preempt Time=23 bclks, Unlatched Interrupt */ + outb (ER0_BSW | ER0_BMW | ER0_EPT | regval, EISA_REG0); +#endif + irq = de4x5_irq[(regval >> 1) & 0x03]; + if (is_DC2114x) { - device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143); + device = ((lp->cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143); } lp->chipset = device; + lp->bus = EISA; /* Write the PCI Configuration Registers */ outl(PCI_COMMAND_IO | PCI_COMMAND_MASTER, PCI_CFCS); outl(0x00006000, PCI_CFLT); outl(iobase, PCI_CBIO); - DevicePresent(EISA_APROM); + DevicePresent(dev, EISA_APROM); dev->irq = irq; - if ((status = de4x5_hw_init(dev, iobase, NULL)) == 0) { - num_de4x5s++; - if (loading_module) link_modules(lastModule, dev); - lastEISA = i; + + if (!(status = de4x5_hw_init (dev, iobase, gendev))) { + return 0; + } + + free_netdev (dev); + release_reg_2: + release_region (iobase + DE4X5_EISA_IO_PORTS, DE4X5_EISA_TOTAL_SIZE); + release_reg_1: + release_region (iobase, DE4X5_EISA_TOTAL_SIZE); + + return status; +} + +static int __devexit de4x5_eisa_remove (struct device *device) +{ + struct net_device *dev; + u_long iobase; + + dev = device->driver_data; + iobase = dev->base_addr; + + unregister_netdev (dev); + free_netdev (dev); + release_region (iobase + DE4X5_EISA_IO_PORTS, DE4X5_EISA_TOTAL_SIZE); + release_region (iobase, DE4X5_EISA_TOTAL_SIZE); + + return 0; +} + +static struct eisa_device_id de4x5_eisa_ids[] = { + { "DEC4250", 0 }, /* 0 is the board name index... */ + { "" } +}; + +static struct eisa_driver de4x5_eisa_driver = { + .id_table = de4x5_eisa_ids, + .driver = { + .name = "de4x5", + .probe = de4x5_eisa_probe, + .remove = __devexit_p (de4x5_eisa_remove), + } +}; +#endif + +#ifdef CONFIG_PCI + +/* +** This function searches the current bus (which is >0) for a DECchip with an +** SROM, so that in multiport cards that have one SROM shared between multiple +** DECchips, we can find the base SROM irrespective of the BIOS scan direction. +** For single port cards this is a time waster... +*/ +static void __init +srom_search(struct net_device *dev, struct pci_dev *pdev) +{ + u_char pb; + u_short vendor, status; + u_int irq = 0, device; + u_long iobase = 0; /* Clear upper 32 bits in Alphas */ + int i, j, cfrv; + struct de4x5_private *lp = dev->priv; + struct list_head *walk = &pdev->bus_list; + + for (walk = walk->next; walk != &pdev->bus_list; walk = walk->next) { + struct pci_dev *this_dev = pci_dev_b(walk); + + /* Skip the pci_bus list entry */ + if (list_entry(walk, struct pci_bus, devices) == pdev->bus) continue; + + vendor = this_dev->vendor; + device = this_dev->device << 8; + if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue; + + /* Get the chip configuration revision register */ + pb = this_dev->bus->number; + pci_read_config_dword(this_dev, PCI_REVISION_ID, &cfrv); + + /* Set the device number information */ + lp->device = PCI_SLOT(this_dev->devfn); + lp->bus_num = pb; + + /* Set the chipset information */ + if (is_DC2114x) { + device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143); + } + lp->chipset = device; + + /* Get the board I/O address (64 bits on sparc64) */ + iobase = pci_resource_start(this_dev, 0); + + /* Fetch the IRQ to be used */ + irq = this_dev->irq; + if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue; + + /* Check if I/O accesses are enabled */ + pci_read_config_word(this_dev, PCI_COMMAND, &status); + if (!(status & PCI_COMMAND_IO)) continue; + + /* Search for a valid SROM attached to this DECchip */ + DevicePresent(dev, DE4X5_APROM); + for (j=0, i=0; i<ETH_ALEN; i++) { + j += (u_char) *((u_char *)&lp->srom + SROM_HWADD + i); + } + if ((j != 0) && (j != 0x5fa)) { + last.chipset = device; + last.bus = pb; + last.irq = irq; + for (i=0; i<ETH_ALEN; i++) { + last.addr[i] = (u_char)*((u_char *)&lp->srom + SROM_HWADD + i); + } return; } } - if (ioaddr == 0) lastEISA = i; - return; } -#endif /* !(__sparc_v9__) && !(__powerpc__) && !defined(__alpha__) */ /* ** PCI bus I/O device probe @@ -2169,56 +2212,57 @@ eisa_probe(struct net_device *dev, u_long ioaddr) ** This function is only compatible with the *latest* 2.1.x kernels. For 2.0.x ** kernels use the V0.535[n] drivers. */ -#define PCI_LAST_DEV 32 -static void __init -pci_probe(struct net_device *dev, u_long ioaddr) +static int __init de4x5_pci_probe (struct pci_dev *pdev, + const struct pci_device_id *ent) { - u_char pb, pbus, dev_num, dnum, timer; - u_short vendor, index, status; - u_int irq = 0, device, class = DE4X5_CLASS_CODE; - u_long iobase = 0; /* Clear upper 32 bits in Alphas */ - struct de4x5_bus_type *lp = &bus; - - if (lastPCI == NO_MORE_PCI) return; - - lp->bus = PCI; - lp->bus_num = 0; - - if ((ioaddr < 0x1000) && loading_module) { - pbus = (u_short)(ioaddr >> 8); - dnum = (u_short)(ioaddr & 0xff); - } else { - pbus = 0; - dnum = 0; - } + u_char pb, pbus = 0, dev_num, dnum = 0, timer; + u_short vendor, status; + u_int irq = 0, device; + u_long iobase = 0; /* Clear upper 32 bits in Alphas */ + int error; + struct net_device *dev; + struct de4x5_private *lp; - for (index=lastPCI+1;(pdev = pci_find_class(class, pdev))!=NULL;index++) { dev_num = PCI_SLOT(pdev->devfn); pb = pdev->bus->number; - if ((pbus || dnum) && ((pbus != pb) || (dnum != dev_num))) continue; + + if (io) { /* probe a single PCI device */ + pbus = (u_short)(io >> 8); + dnum = (u_short)(io & 0xff); + if ((pbus != pb) || (dnum != dev_num)) + return -ENODEV; + } vendor = pdev->vendor; device = pdev->device << 8; - if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue; + if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) + return -ENODEV; + + /* Ok, the device seems to be for us. */ + if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) + return -ENOMEM; + lp = dev->priv; + lp->bus = PCI; + lp->bus_num = 0; + /* Search for an SROM on this bus */ if (lp->bus_num != pb) { lp->bus_num = pb; - srom_search(pdev); + srom_search(dev, pdev); } /* Get the chip configuration revision register */ - pci_read_config_dword(pdev, PCI_REVISION_ID, &cfrv); + pci_read_config_dword(pdev, PCI_REVISION_ID, &lp->cfrv); /* Set the device number information */ lp->device = dev_num; lp->bus_num = pb; - lp->pdev = pdev; - + /* Set the chipset information */ if (is_DC2114x) { - device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143); + device = ((lp->cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143); } lp->chipset = device; @@ -2227,7 +2271,10 @@ pci_probe(struct net_device *dev, u_long ioaddr) /* Fetch the IRQ to be used */ irq = pdev->irq; - if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue; + if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) { + error = -ENODEV; + goto free_dev; + } /* Check if I/O accesses and Bus Mastering are enabled */ pci_read_config_word(pdev, PCI_COMMAND, &status); @@ -2238,14 +2285,20 @@ pci_probe(struct net_device *dev, u_long ioaddr) pci_read_config_word(pdev, PCI_COMMAND, &status); } #endif /* __powerpc__ */ - if (!(status & PCI_COMMAND_IO)) continue; + if (!(status & PCI_COMMAND_IO)) { + error = -ENODEV; + goto free_dev; + } if (!(status & PCI_COMMAND_MASTER)) { status |= PCI_COMMAND_MASTER; pci_write_config_word(pdev, PCI_COMMAND, status); pci_read_config_word(pdev, PCI_COMMAND, &status); } - if (!(status & PCI_COMMAND_MASTER)) continue; + if (!(status & PCI_COMMAND_MASTER)) { + error = -ENODEV; + goto free_dev; + } /* Check the latency timer for values >= 0x60 */ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &timer); @@ -2253,116 +2306,61 @@ pci_probe(struct net_device *dev, u_long ioaddr) pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x60); } - DevicePresent(DE4X5_APROM); - if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) { - dev->irq = irq; - if ((status = de4x5_hw_init(dev, iobase, pdev)) == 0) { - num_de4x5s++; - lastPCI = index; - if (loading_module) link_modules(lastModule, dev); - return; - } - } else if (ioaddr != 0) { - printk("%s: region already allocated at 0x%04lx.\n", dev->name, - iobase); - } - } - - lastPCI = NO_MORE_PCI; - - return; -} + DevicePresent(dev, DE4X5_APROM); -/* -** This function searches the current bus (which is >0) for a DECchip with an -** SROM, so that in multiport cards that have one SROM shared between multiple -** DECchips, we can find the base SROM irrespective of the BIOS scan direction. -** For single port cards this is a time waster... -*/ -static void __init -srom_search(struct pci_dev *dev) -{ - u_char pb; - u_short vendor, status; - u_int irq = 0, device; - u_long iobase = 0; /* Clear upper 32 bits in Alphas */ - int i, j; - struct de4x5_bus_type *lp = &bus; - struct list_head *walk = &dev->bus_list; - - for (walk = walk->next; walk != &dev->bus_list; walk = walk->next) { - struct pci_dev *this_dev = pci_dev_b(walk); - - /* Skip the pci_bus list entry */ - if (list_entry(walk, struct pci_bus, devices) == dev->bus) continue; - - vendor = this_dev->vendor; - device = this_dev->device << 8; - if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue; - - /* Get the chip configuration revision register */ - pb = this_dev->bus->number; - pci_read_config_dword(this_dev, PCI_REVISION_ID, &cfrv); - - /* Set the device number information */ - lp->device = PCI_SLOT(this_dev->devfn); - lp->bus_num = pb; - - /* Set the chipset information */ - if (is_DC2114x) { - device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143); + if (!request_region (iobase, DE4X5_PCI_TOTAL_SIZE, "de4x5")) { + error = -EBUSY; + goto free_dev; } - lp->chipset = device; - - /* Get the board I/O address (64 bits on sparc64) */ - iobase = pci_resource_start(this_dev, 0); - - /* Fetch the IRQ to be used */ - irq = this_dev->irq; - if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue; - - /* Check if I/O accesses are enabled */ - pci_read_config_word(this_dev, PCI_COMMAND, &status); - if (!(status & PCI_COMMAND_IO)) continue; - /* Search for a valid SROM attached to this DECchip */ - DevicePresent(DE4X5_APROM); - for (j=0, i=0; i<ETH_ALEN; i++) { - j += (u_char) *((u_char *)&lp->srom + SROM_HWADD + i); - } - if ((j != 0) && (j != 0x5fa)) { - last.chipset = device; - last.bus = pb; - last.irq = irq; - for (i=0; i<ETH_ALEN; i++) { - last.addr[i] = (u_char)*((u_char *)&lp->srom + SROM_HWADD + i); - } - return; + dev->irq = irq; + + if ((error = de4x5_hw_init(dev, iobase, &pdev->dev))) { + goto release; } - } - return; + return 0; + + release: + release_region (iobase, DE4X5_PCI_TOTAL_SIZE); + free_dev: + free_netdev (dev); + return error; } -static void __init -link_modules(struct net_device *dev, struct net_device *tmp) +static void __devexit de4x5_pci_remove (struct pci_dev *pdev) { - struct net_device *p=dev; - - if (p) { - while (((struct de4x5_private *)(p->priv))->next_module) { - p = ((struct de4x5_private *)(p->priv))->next_module; - } + struct net_device *dev; + u_long iobase; + + dev = pdev->dev.driver_data; + iobase = dev->base_addr; + + unregister_netdev (dev); + free_netdev (dev); + release_region (iobase, DE4X5_PCI_TOTAL_SIZE); +} + +static struct pci_device_id de4x5_pci_tbl[] = { + { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, + { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, + { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, + { }, +}; - if (dev != tmp) { - ((struct de4x5_private *)(p->priv))->next_module = tmp; - } else { - ((struct de4x5_private *)(p->priv))->next_module = NULL; - } - } +static struct pci_driver de4x5_pci_driver = { + .name = "de4x5", + .id_table = de4x5_pci_tbl, + .probe = de4x5_pci_probe, + .remove = __devexit_p (de4x5_pci_remove), +}; - return; -} +#endif /* ** Auto configure the media here rather than setting the port at compile @@ -3945,34 +3943,20 @@ create_packet(struct net_device *dev, char *frame, int len) ** Look for a particular board name in the EISA configuration space */ static int -EISA_signature(char *name, s32 eisa_id) +EISA_signature(char *name, struct device *device) { - static c_char *signatures[] = DE4X5_SIGNATURE; - char ManCode[DE4X5_STRLEN]; - union { - s32 ID; - char Id[4]; - } Eisa; - int i, status = 0, siglen = sizeof(signatures)/sizeof(c_char *); - + int i, status = 0, siglen = sizeof(de4x5_signatures)/sizeof(c_char *); + struct eisa_device *edev; + *name = '\0'; - Eisa.ID = inl(eisa_id); - - ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40); - ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40); - ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30); - ManCode[3]=((Eisa.Id[2]&0x0f)+0x30); - ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30); - ManCode[5]='\0'; - - for (i=0;i<siglen;i++) { - if (strstr(ManCode, signatures[i]) != NULL) { - strcpy(name,ManCode); + edev = to_eisa_device (device); + i = edev->id.driver_data; + + if (i >= 0 && i < siglen) { + strcpy (name, de4x5_signatures[i]); status = 1; - break; - } } - + return status; /* return the device name string */ } @@ -3980,9 +3964,8 @@ EISA_signature(char *name, s32 eisa_id) ** Look for a particular board name in the PCI configuration space */ static int -PCI_signature(char *name, struct de4x5_bus_type *lp) +PCI_signature(char *name, struct de4x5_private *lp) { - static c_char *de4x5_signatures[] = DE4X5_SIGNATURE; int i, status = 0, siglen = sizeof(de4x5_signatures)/sizeof(c_char *); if (lp->chipset == DC21040) { @@ -4008,10 +3991,10 @@ PCI_signature(char *name, struct de4x5_bus_type *lp) ))))))); } if (lp->chipset != DC21041) { - useSROM = TRUE; /* card is not recognisably DEC */ + lp->useSROM = TRUE; /* card is not recognisably DEC */ } } else if ((lp->chipset & ~0x00ff) == DC2114x) { - useSROM = TRUE; + lp->useSROM = TRUE; } return status; @@ -4026,10 +4009,10 @@ PCI_signature(char *name, struct de4x5_bus_type *lp) ** be fixed up later). */ static void -DevicePresent(u_long aprom_addr) +DevicePresent(struct net_device *dev, u_long aprom_addr) { int i, j=0; - struct de4x5_bus_type *lp = &bus; + struct de4x5_private *lp = (struct de4x5_private *) dev->priv; if (lp->chipset == DC21040) { if (lp->bus == EISA) { @@ -4110,7 +4093,7 @@ get_hw_addr(struct net_device *dev) u_long iobase = dev->base_addr; int broken, i, k, tmp, status = 0; u_short j,chksum; - struct de4x5_bus_type *lp = &bus; + struct de4x5_private *lp = dev->priv; broken = de4x5_bad_srom(lp); @@ -4191,7 +4174,7 @@ get_hw_addr(struct net_device *dev) ** didn't seem to work here...? */ static int -de4x5_bad_srom(struct de4x5_bus_type *lp) +de4x5_bad_srom(struct de4x5_private *lp) { int i, status = 0; @@ -4225,14 +4208,14 @@ de4x5_strncmp(char *a, char *b, int n) static void srom_repair(struct net_device *dev, int card) { - struct de4x5_bus_type *lp = &bus; + struct de4x5_private *lp = dev->priv; switch(card) { case SMC: - memset((char *)&bus.srom, 0, sizeof(struct de4x5_srom)); + memset((char *)&lp->srom, 0, sizeof(struct de4x5_srom)); memcpy(lp->srom.ieee_addr, (char *)dev->dev_addr, ETH_ALEN); memcpy(lp->srom.info, (char *)&srom_repair_info[SMC-1], 100); - useSROM = TRUE; + lp->useSROM = TRUE; break; } @@ -4246,7 +4229,7 @@ srom_repair(struct net_device *dev, int card) static int test_bad_enet(struct net_device *dev, int status) { - struct de4x5_bus_type *lp = &bus; + struct de4x5_private *lp = dev->priv; int i, tmp; for (tmp=0,i=0; i<ETH_ALEN; i++) tmp += (u_char)dev->dev_addr[i]; @@ -4279,7 +4262,7 @@ test_bad_enet(struct net_device *dev, int status) ** List of board exceptions with correctly wired IRQs */ static int -an_exception(struct de4x5_bus_type *lp) +an_exception(struct de4x5_private *lp) { if ((*(u_short *)lp->srom.sub_vendor_id == 0x00c0) && (*(u_short *)lp->srom.sub_system_id == 0x95e0)) { @@ -5312,19 +5295,20 @@ yawn(struct net_device *dev, int state) break; } } else { + struct pci_dev *pdev = to_pci_dev (lp->gendev); switch(state) { case WAKEUP: - pci_write_config_byte(lp->pdev, PCI_CFDA_PSM, WAKEUP); + pci_write_config_byte(pdev, PCI_CFDA_PSM, WAKEUP); mdelay(10); break; case SNOOZE: - pci_write_config_byte(lp->pdev, PCI_CFDA_PSM, SNOOZE); + pci_write_config_byte(pdev, PCI_CFDA_PSM, SNOOZE); break; case SLEEP: outl(0, DE4X5_SICR); - pci_write_config_byte(lp->pdev, PCI_CFDA_PSM, SLEEP); + pci_write_config_byte(pdev, PCI_CFDA_PSM, SLEEP); break; } } @@ -5348,9 +5332,6 @@ de4x5_parse_params(struct net_device *dev) t = *q; *q = '\0'; -#if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__) - if (strstr(p, "force_eisa") || strstr(p, "FORCE_EISA")) forceEISA = 1; -#endif if (strstr(p, "fdx") || strstr(p, "FDX")) lp->params.fdx = 1; if (strstr(p, "autosense") || strstr(p, "AUTOSENSE")) { @@ -5758,146 +5739,29 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return status; } -#ifdef MODULE -/* -** Note now that module autoprobing is allowed under EISA and PCI. The -** IRQ lines will not be auto-detected; instead I'll rely on the BIOSes -** to "do the right thing". -*/ -#define LP(a) ((struct de4x5_private *)(a)) -static struct net_device *mdev = NULL; -static int io=0x0;/* EDIT THIS LINE FOR YOUR CONFIGURATION IF NEEDED */ -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "de4x5 I/O base address"); - -int -init_module(void) -{ - int i, num, status = -EIO; - struct net_device *p; - - num = count_adapters(); - - for (i=0; i<num; i++) { - if ((p = insert_device(NULL, io, de4x5_probe)) == NULL) - return -ENOMEM; - - if (!mdev) mdev = p; - - if (register_netdev(p) != 0) { - struct de4x5_private *lp = (struct de4x5_private *)p->priv; - if (lp) { - release_region(p->base_addr, (lp->bus == PCI ? - DE4X5_PCI_TOTAL_SIZE : - DE4X5_EISA_TOTAL_SIZE)); - if (lp->cache.priv) { /* Private area allocated? */ - kfree(lp->cache.priv); /* Free the private area */ - } - if (lp->rx_ring) { - pci_free_consistent(lp->pdev, lp->dma_size, lp->rx_ring, - lp->dma_rings); - } - } - kfree(p); - } else { - status = 0; /* At least one adapter will work */ - lastModule = p; - } - } - - return status; -} - -void -cleanup_module(void) -{ - while (mdev != NULL) { - mdev = unlink_modules(mdev); - } - - return; -} - -static struct net_device * -unlink_modules(struct net_device *p) -{ - struct net_device *next = NULL; - - if (p->priv) { /* Private areas allocated? */ - struct de4x5_private *lp = (struct de4x5_private *)p->priv; - - next = lp->next_module; - if (lp->rx_ring) { - pci_free_consistent(lp->pdev, lp->dma_size, lp->rx_ring, - lp->dma_rings); - } - release_region(p->base_addr, (lp->bus == PCI ? - DE4X5_PCI_TOTAL_SIZE : - DE4X5_EISA_TOTAL_SIZE)); - kfree(lp->cache.priv); /* Free the private area */ - } - unregister_netdev(p); - free_netdev(p); /* Free the device structure */ - - return next; -} - -static int -count_adapters(void) +static int __init de4x5_module_init (void) { - int i, j=0; - u_short vendor; - u_int class = DE4X5_CLASS_CODE; - u_int device; - -#if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__) - char name[DE4X5_STRLEN]; - u_long iobase = 0x1000; + int err = 0; - for (i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) { - if (EISA_signature(name, EISA_ID)) j++; - } +#if CONFIG_PCI + err = pci_module_init (&de4x5_pci_driver); +#endif +#ifdef CONFIG_EISA + err |= eisa_driver_register (&de4x5_eisa_driver); #endif - for (i=0; (pdev=pci_find_class(class, pdev))!= NULL; i++) { - vendor = pdev->vendor; - device = pdev->device << 8; - if (is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x) j++; - } - - return j; + return err; } -/* -** If at end of eth device list and can't use current entry, malloc -** one up. If memory could not be allocated, print an error message. -*/ -static struct net_device * __init -insert_device(struct net_device *dev, u_long iobase, int (*init)(struct net_device *)) +static void __exit de4x5_module_exit (void) { - struct net_device *new; - - new = (struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL); - if (new == NULL) { - printk("de4x5.c: Device not initialised, insufficient memory\n"); - return NULL; - } else { - memset((char *)new, 0, sizeof(struct net_device)); - new->base_addr = iobase; /* assign the io address */ - new->init = init; /* initialisation routine */ - } - - return new; +#if CONFIG_PCI + pci_unregister_driver (&de4x5_pci_driver); +#endif +#ifdef CONFIG_EISA + eisa_driver_unregister (&de4x5_eisa_driver); +#endif } -#endif /* MODULE */ - - -/* - * Local variables: - * - * Delete -DMODVERSIONS below if you didn't define this in your kernel - * - * compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -DMODVERSIONS -include /linux/include/linux/modversions.h -c de4x5.c" - * End: - */ +module_init (de4x5_module_init); +module_exit (de4x5_module_exit); diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 860e53b4d696..784a41d78ebf 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -640,3 +640,4 @@ void tun_cleanup(void) module_init(tun_init); module_exit(tun_cleanup); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(TUN_MINOR); diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index e83372b7adbb..f30b72218b30 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -2455,7 +2455,7 @@ error_out_remap: error_out_regions: pci_release_regions(pdev); error_out_dev: - kfree(dev); + free_netdev(dev); error_out: return err; } diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index c247af6bf6ad..3059d04aaf0d 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -868,7 +868,7 @@ err_out_free_res: #endif pci_release_regions(pdev); err_out_free_netdev: - kfree (dev); + free_netdev (dev); err_out: return -ENODEV; } diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 97a08cf349f3..df80c5c25e37 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -35,7 +35,7 @@ config HOSTESS_SV11 # The COSA/SRP driver has not been tested as non-modular yet. config COSA tristate "COSA/SRP sync serial boards support" - depends on WAN && ISA && m && BROKEN + depends on WAN && ISA && m ---help--- This is a driver for COSA and SRP synchronous serial boards. These boards allow to connect synchronous serial devices (for example @@ -465,7 +465,7 @@ config DLCI_MAX config SDLA tristate "SDLA (Sangoma S502/S508) support" - depends on DLCI && ISA && BROKEN_ON_SMP + depends on DLCI && ISA help Say Y here if you need a driver for the Sangoma S502A, S502E, and S508 Frame Relay Access Devices. These are multi-protocol cards, but diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index d445e916a18b..8a440eea9c60 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -357,11 +357,7 @@ static void debug_status_out(struct cosa_data *cosa, int status); /* ---------- Initialization stuff ---------- */ -#ifdef MODULE -int init_module(void) -#else static int __init cosa_init(void) -#endif { int i; @@ -398,9 +394,9 @@ static int __init cosa_init(void) } return 0; } +module_init(cosa_init); -#ifdef MODULE -void cleanup_module (void) +static void __exit cosa_exit(void) { struct cosa_data *cosa; int i; @@ -424,7 +420,7 @@ void cleanup_module (void) } unregister_chrdev(cosa_major, "cosa"); } -#endif +module_exit(cosa_exit); /* * This function should register all the net devices needed for the @@ -513,7 +509,6 @@ static int cosa_probe(int base, int irq, int dma) if (irq < 0) { unsigned long irqs; /* printk(KERN_INFO "IRQ autoprobe\n"); */ - sti(); irqs = probe_irq_on(); /* * Enable interrupt on tx buffer empty (it sure is) @@ -624,6 +619,7 @@ static void sppp_channel_init(struct channel_data *chan) if (register_netdev(d) == -1) { printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); sppp_detach(chan->pppdev.dev); + free_netdev(chan->pppdev.dev); return; } } @@ -658,7 +654,6 @@ static int cosa_sppp_open(struct net_device *d) chan->rx_done = sppp_rx_done; chan->usage=-1; chan->cosa->usage++; - MOD_INC_USE_COUNT; spin_unlock_irqrestore(&chan->cosa->lock, flags); err = sppp_open(d); @@ -666,7 +661,6 @@ static int cosa_sppp_open(struct net_device *d) spin_lock_irqsave(&chan->cosa->lock, flags); chan->usage=0; chan->cosa->usage--; - MOD_DEC_USE_COUNT; spin_unlock_irqrestore(&chan->cosa->lock, flags); return err; @@ -726,7 +720,6 @@ static int cosa_sppp_close(struct net_device *d) } chan->usage=0; chan->cosa->usage--; - MOD_DEC_USE_COUNT; spin_unlock_irqrestore(&chan->cosa->lock, flags); return 0; } @@ -1187,21 +1180,6 @@ static int cosa_ioctl_common(struct cosa_data *cosa, return cosa_gettype(cosa, (char *)arg); case COSAIORIDSTR: return cosa_getidstr(cosa, (char *)arg); -/* - * These two are _very_ugly_hack_(tm). Don't even look at this. - * Implementing this saved me few reboots after some process segfaulted - * inside this module. - */ -#ifdef MODULE -#if 0 - case COSAIOMINC: - MOD_INC_USE_COUNT; - return 0; - case COSAIOMDEC: - MOD_DEC_USE_COUNT; - return 0; -#endif -#endif case COSAIONRCARDS: return nr_cards; case COSAIONRCHANS: diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index 5aab67436cc7..380bb830d738 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -55,14 +55,13 @@ #include <asm/dma.h> #include <asm/uaccess.h> -static const char devname[] = "dlci"; static const char version[] = "DLCI driver v0.35, 4 Jan 1997, mike.mclagan@linux.org"; -static struct net_device *open_dev[CONFIG_DLCI_COUNT]; - +static LIST_HEAD(dlci_devs); +static spinlock_t dlci_dev_lock = SPIN_LOCK_UNLOCKED; static char *basename[16]; -int dlci_init(struct net_device *dev); +static void dlci_setup(struct net_device *); /* allow FRAD's to register their name as a valid FRAD */ int register_frad(const char *name) @@ -115,6 +114,7 @@ int unregister_frad(const char *name) return(0); } +EXPORT_SYMBOL(unregister_frad); /* * these encapsulate the RFC 1490 requirements as well as @@ -168,6 +168,14 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev) int process, header; dlp = dev->priv; + if (!pskb_may_pull(skb, sizeof(*hdr))) { + printk(KERN_NOTICE "%s: invalid data no header\n", + dev->name); + dlp->stats.rx_errors++; + kfree_skb(skb); + return; + } + hdr = (struct frhdr *) skb->data; process = 0; header = 0; @@ -277,7 +285,7 @@ static int dlci_transmit(struct sk_buff *skb, struct net_device *dev) return(ret); } -int dlci_config(struct net_device *dev, struct dlci_conf *conf, int get) +static int dlci_config(struct net_device *dev, struct dlci_conf *conf, int get) { struct dlci_conf config; struct dlci_local *dlp; @@ -311,7 +319,7 @@ int dlci_config(struct net_device *dev, struct dlci_conf *conf, int get) return(0); } -int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct dlci_local *dlp; @@ -401,21 +409,23 @@ static struct net_device_stats *dlci_get_stats(struct net_device *dev) return(&dlp->stats); } -int dlci_add(struct dlci_add *dlci) +static int dlci_add(struct dlci_add *dlci) { - struct net_device *master, *slave; + struct net_device *master, *slave; struct dlci_local *dlp; struct frad_local *flp; int err, i; - char buf[10]; + /* validate slave device */ - slave = __dev_get_by_name(dlci->devname); + slave = dev_get_by_name(dlci->devname); if (!slave) return(-ENODEV); - if (slave->type != ARPHRD_FRAD) + if (slave->type != ARPHRD_FRAD) { + dev_put(slave); return(-EINVAL); + } /* check for registration */ for (i=0;i<sizeof(basename) / sizeof(char *); i++) @@ -424,33 +434,22 @@ int dlci_add(struct dlci_add *dlci) (strlen(dlci->devname) > strlen(basename[i]))) break; - if (i == sizeof(basename) / sizeof(char *)) + if (i == sizeof(basename) / sizeof(char *)) { + dev_put(slave); return(-EINVAL); - - /* check for too many open devices : should this be dynamic ? */ - for(i=0;i<CONFIG_DLCI_COUNT;i++) - if (!open_dev[i]) - break; - - if (i == CONFIG_DLCI_COUNT) - return(-ENOSPC); /* #### Alan: Comments on this?? */ + } /* create device name */ - sprintf(buf, "%s%02i", devname, i); - - master = kmalloc(sizeof(*master), GFP_KERNEL); - if (!master) + master = alloc_netdev( sizeof(struct dlci_local), "dlci%d", + dlci_setup); + if (!master) { + dev_put(slave); return(-ENOMEM); - - memset(master, 0, sizeof(*master)); - - strcpy(master->name, buf); - master->init = dlci_init; - master->flags = 0; + } err = register_netdev(master); - if (err < 0) - { + if (err < 0) { + dev_put(slave); kfree(master); return(err); } @@ -459,64 +458,65 @@ int dlci_add(struct dlci_add *dlci) dlp = (struct dlci_local *) master->priv; dlp->slave = slave; + dlp->master = master; flp = slave->priv; err = flp ? (*flp->assoc)(slave, master) : -EINVAL; if (err < 0) { unregister_netdev(master); - kfree(master->priv); - kfree(master); + dev_put(slave); + free_netdev(master); return(err); } - strcpy(dlci->devname, buf); - open_dev[i] = master; - MOD_INC_USE_COUNT; + strcpy(dlci->devname, master->name); + + spin_lock_bh(&dlci_dev_lock); + list_add(&dlp->list, &dlci_devs); + spin_unlock_bh(&dlci_dev_lock); + return(0); } -int dlci_del(struct dlci_add *dlci) +static int dlci_del(struct dlci_add *dlci) { struct dlci_local *dlp; struct frad_local *flp; - struct net_device *master, *slave; - int i, err; + struct net_device *master, *slave; + int err; /* validate slave device */ master = __dev_get_by_name(dlci->devname); if (!master) return(-ENODEV); - if (netif_running(master)) + if (netif_running(master)) { return(-EBUSY); + } dlp = master->priv; slave = dlp->slave; flp = slave->priv; err = (*flp->deassoc)(slave, master); - if (err) + if (err) return(err); - unregister_netdev(master); - for(i=0;i<CONFIG_DLCI_COUNT;i++) - if (master == open_dev[i]) - break; + spin_lock_bh(&dlci_dev_lock); + list_del(&dlp->list); + spin_unlock_bh(&dlci_dev_lock); - if (i<CONFIG_DLCI_COUNT) - open_dev[i] = NULL; + unregister_netdev(master); - kfree(master->priv); + dev_put(slave); free_netdev(master); - MOD_DEC_USE_COUNT; - return(0); } -int dlci_ioctl(unsigned int cmd, void *arg) +static int dlci_ioctl(unsigned int cmd, void *arg) { struct dlci_add add; int err; @@ -548,16 +548,9 @@ int dlci_ioctl(unsigned int cmd, void *arg) return(err); } -int dlci_init(struct net_device *dev) +static void dlci_setup(struct net_device *dev) { - struct dlci_local *dlp; - - dev->priv = kmalloc(sizeof(struct dlci_local), GFP_KERNEL); - if (!dev->priv) - return(-ENOMEM); - - memset(dev->priv, 0, sizeof(struct dlci_local)); - dlp = dev->priv; + struct dlci_local *dlp = dev->priv; dev->flags = 0; dev->open = dlci_open; @@ -573,9 +566,7 @@ int dlci_init(struct net_device *dev) dev->type = ARPHRD_DLCI; dev->hard_header_len = sizeof(struct frhdr); dev->addr_len = sizeof(short); - memset(dev->dev_addr, 0, sizeof(dev->dev_addr)); - return(0); } int __init init_dlci(void) @@ -584,9 +575,6 @@ int __init init_dlci(void) dlci_ioctl_set(dlci_ioctl); printk("%s.\n", version); - - for(i=0;i<CONFIG_DLCI_COUNT;i++) - open_dev[i] = NULL; for(i=0;i<sizeof(basename) / sizeof(char *);i++) basename[i] = NULL; @@ -596,7 +584,16 @@ int __init init_dlci(void) void __exit dlci_exit(void) { + struct dlci_local *dlp, *nxt; + dlci_ioctl_set(NULL); + + list_for_each_entry_safe(dlp, nxt, &dlci_devs, list) { + unregister_netdev(dlp->master); + dev_put(dlp->slave); + free_netdev(dlp->master); + } + } module_init(init_dlci); diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 349400d4d95a..81b2f271036c 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -140,6 +140,7 @@ static void change_level( struct net_device * ); static void timeout_change_level( struct net_device * ); static u32 calc_crc32( u32, u8 *, u32 ); static struct sk_buff * get_rx_buf( struct net_device * ); +static int sbni_init( struct net_device * ); #ifdef CONFIG_SBNI_MULTILINE static int enslave( struct net_device *, struct net_device * ); @@ -205,23 +206,44 @@ sbni_isa_probe( struct net_device *dev ) } } - -int __init -sbni_probe( struct net_device *dev ) +static void __init sbni_devsetup(struct net_device *dev) { - int i; + ether_setup( dev ); + dev->init = &sbni_init; + dev->open = &sbni_open; + dev->stop = &sbni_close; + dev->hard_start_xmit = &sbni_start_xmit; + dev->get_stats = &sbni_get_stats; + dev->set_multicast_list = &set_multicast_list; + dev->do_ioctl = &sbni_ioctl; + + SET_MODULE_OWNER( dev ); +} +int __init sbni_probe(void) +{ + struct net_device *dev; static unsigned version_printed __initdata = 0; + if( version_printed++ == 0 ) printk( KERN_INFO "%s", version ); - if( !dev ) { /* simple sanity check */ - printk( KERN_ERR "sbni: NULL device!\n" ); - return -ENODEV; - } + dev = alloc_netdev(sizeof(struct net_local), "sbni%d", sbni_devsetup); + if (!dev) + return -ENOMEM; - SET_MODULE_OWNER( dev ); + netdev_boot_setup_check(dev); + + if (register_netdev(dev)) { + kfree(dev); + return -ENODEV; + } + return 0; +} +static int __init sbni_init(struct net_device *dev) +{ + int i; if( dev->base_addr ) return sbni_isa_probe( dev ); /* otherwise we have to perform search our adapter */ @@ -338,7 +360,7 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq ) dev->base_addr = ioaddr; /* Allocate dev->priv and fill in sbni-specific dev fields. */ - nl = (struct net_local *) kmalloc(sizeof(struct net_local), GFP_KERNEL); + nl = dev->priv; if( !nl ) { printk( KERN_ERR "%s: unable to get memory!\n", dev->name ); release_region( ioaddr, SBNI_IO_EXTENT ); @@ -389,14 +411,6 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq ) nl->link = NULL; #endif - dev->open = &sbni_open; - dev->stop = &sbni_close; - dev->hard_start_xmit = &sbni_start_xmit; - dev->get_stats = &sbni_get_stats; - dev->set_multicast_list = &set_multicast_list; - dev->do_ioctl = &sbni_ioctl; - ether_setup( dev ); - sbni_cards[ num++ ] = dev; return dev; } @@ -1478,15 +1492,15 @@ init_module( void ) struct net_device *dev; while( num < SBNI_MAX_NUM_CARDS ) { - if( !(dev = kmalloc(sizeof(struct net_device), GFP_KERNEL)) ){ + dev = alloc_netdev(sizeof(struct net_local), + "sbni%d", sbni_devsetup); + if( !dev) { printk( KERN_ERR "sbni: unable to allocate device!\n" ); return -ENOMEM; } - memset( dev, 0, sizeof(struct net_device) ); sprintf( dev->name, "sbni%d", num ); - dev->init = sbni_probe; if( register_netdev( dev ) ) { kfree( dev ); break; @@ -1506,7 +1520,6 @@ cleanup_module( void ) if( (dev = sbni_cards[ num ]) != NULL ) { unregister_netdev( dev ); release_region( dev->base_addr, SBNI_IO_EXTENT ); - kfree( dev->priv ); free_netdev( dev ); } } diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index 8079d8b5ddee..e11984b2bb03 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -71,6 +71,8 @@ static unsigned int valid_mem[] __initdata = { 0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, 0xDE000, 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000}; +static spinlock_t sdla_lock = SPIN_LOCK_UNLOCKED; + /********************************************************* * * these are the core routines that access the card itself @@ -79,10 +81,10 @@ static unsigned int valid_mem[] __initdata = { #define SDLA_WINDOW(dev,addr) outb((((addr) >> 13) & 0x1F), (dev)->base_addr + SDLA_REG_Z80_WINDOW) -static void sdla_read(struct net_device *dev, int addr, void *buf, short len) +static void __sdla_read(struct net_device *dev, int addr, void *buf, short len) { - unsigned long flags; - char *temp, *base; + char *temp; + const void *base; int offset, bytes; temp = buf; @@ -90,13 +92,10 @@ static void sdla_read(struct net_device *dev, int addr, void *buf, short len) { offset = addr & SDLA_ADDR_MASK; bytes = offset + len > SDLA_WINDOW_SIZE ? SDLA_WINDOW_SIZE - offset : len; - base = (void *) (dev->mem_start + offset); + base = (const void *) (dev->mem_start + offset); - save_flags(flags); - cli(); SDLA_WINDOW(dev, addr); memcpy(temp, base, bytes); - restore_flags(flags); addr += bytes; temp += bytes; @@ -104,10 +103,19 @@ static void sdla_read(struct net_device *dev, int addr, void *buf, short len) } } -static void sdla_write(struct net_device *dev, int addr, void *buf, short len) +static void sdla_read(struct net_device *dev, int addr, void *buf, short len) { unsigned long flags; - char *temp, *base; + spin_lock_irqsave(&sdla_lock, flags); + __sdla_read(dev, addr, buf, len); + spin_unlock_irqrestore(&sdla_lock, flags); +} + +static void __sdla_write(struct net_device *dev, int addr, + const void *buf, short len) +{ + const char *temp; + void *base; int offset, bytes; temp = buf; @@ -116,17 +124,27 @@ static void sdla_write(struct net_device *dev, int addr, void *buf, short len) offset = addr & SDLA_ADDR_MASK; bytes = offset + len > SDLA_WINDOW_SIZE ? SDLA_WINDOW_SIZE - offset : len; base = (void *) (dev->mem_start + offset); - save_flags(flags); - cli(); + SDLA_WINDOW(dev, addr); memcpy(base, temp, bytes); - restore_flags(flags); + addr += bytes; temp += bytes; len -= bytes; } } +static void sdla_write(struct net_device *dev, int addr, + const void *buf, short len) +{ + unsigned long flags; + + spin_lock_irqsave(&sdla_lock, flags); + __sdla_write(dev, addr, buf, len); + spin_unlock_irqrestore(&sdla_lock, flags); +} + + static void sdla_clear(struct net_device *dev) { unsigned long flags; @@ -138,8 +156,7 @@ static void sdla_clear(struct net_device *dev) bytes = SDLA_WINDOW_SIZE; base = (void *) dev->mem_start; - save_flags(flags); - cli(); + spin_lock_irqsave(&sdla_lock, flags); while(len) { SDLA_WINDOW(dev, addr); @@ -148,7 +165,8 @@ static void sdla_clear(struct net_device *dev) addr += bytes; len -= bytes; } - restore_flags(flags); + spin_unlock_irqrestore(&sdla_lock, flags); + } static char sdla_byte(struct net_device *dev, int addr) @@ -158,11 +176,10 @@ static char sdla_byte(struct net_device *dev, int addr) temp = (void *) (dev->mem_start + (addr & SDLA_ADDR_MASK)); - save_flags(flags); - cli(); + spin_lock_irqsave(&sdla_lock, flags); SDLA_WINDOW(dev, addr); byte = *temp; - restore_flags(flags); + spin_unlock_irqrestore(&sdla_lock, flags); return(byte); } @@ -414,7 +431,8 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags, struct frad_local *flp; struct sdla_cmd *cmd_buf; unsigned long pflags; - int jiffs, ret, waiting, len; + unsigned long jiffs; + int ret, waiting, len; long window; flp = dev->priv; @@ -423,8 +441,8 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags, ret = 0; len = 0; jiffs = jiffies + HZ; /* 1 second is plenty */ - save_flags(pflags); - cli(); + + spin_lock_irqsave(&sdla_lock, pflags); SDLA_WINDOW(dev, window); cmd_buf->cmd = cmd; cmd_buf->dlci = dlci; @@ -436,7 +454,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags, cmd_buf->length = inlen; cmd_buf->opp_flag = 1; - restore_flags(pflags); + spin_unlock_irqrestore(&sdla_lock, pflags); waiting = 1; len = 0; @@ -444,18 +462,17 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags, { if (waiting++ % 3) { - save_flags(pflags); - cli(); + spin_lock_irqsave(&sdla_lock, pflags); SDLA_WINDOW(dev, window); waiting = ((volatile int)(cmd_buf->opp_flag)); - restore_flags(pflags); + spin_unlock_irqrestore(&sdla_lock, pflags); } } if (!waiting) { - save_flags(pflags); - cli(); + + spin_lock_irqsave(&sdla_lock, pflags); SDLA_WINDOW(dev, window); ret = cmd_buf->retval; len = cmd_buf->length; @@ -471,7 +488,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags, if (ret) memcpy(&status, cmd_buf->data, len > sizeof(status) ? sizeof(status) : len); - restore_flags(pflags); + spin_unlock_irqrestore(&sdla_lock, pflags); } else ret = SDLA_RET_TIMEOUT; @@ -555,7 +572,6 @@ int sdla_assoc(struct net_device *slave, struct net_device *master) if (i == CONFIG_DLCI_MAX) return(-EMLINK); /* #### Alan: Comments on this ?? */ - MOD_INC_USE_COUNT; flp->master[i] = master; flp->dlci[i] = -*(short *)(master->dev_addr); @@ -588,7 +604,6 @@ int sdla_deassoc(struct net_device *slave, struct net_device *master) flp->master[i] = NULL; flp->dlci[i] = 0; - MOD_DEC_USE_COUNT; if (netif_running(slave)) { if (flp->config.station == FRAD_STATION_CPE) @@ -688,14 +703,14 @@ static int sdla_transmit(struct sk_buff *skb, struct net_device *dev) ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, NULL, skb->len, &addr, &size); if (ret == SDLA_RET_OK) { - save_flags(flags); - cli(); + + spin_lock_irqsave(&sdla_lock, flags); SDLA_WINDOW(dev, addr); pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK)); - sdla_write(dev, pbuf->buf_addr, skb->data, skb->len); - SDLA_WINDOW(dev, addr); + __sdla_write(dev, pbuf->buf_addr, skb->data, skb->len); + SDLA_WINDOW(dev, addr); pbuf->opp_flag = 1; - restore_flags(flags); + spin_unlock_irqrestore(&sdla_lock, flags); } break; } @@ -753,8 +768,7 @@ static void sdla_receive(struct net_device *dev) pbufi = NULL; pbuf = NULL; - save_flags(flags); - cli(); + spin_lock_irqsave(&sdla_lock, flags); switch (flp->type) { @@ -821,7 +835,7 @@ static void sdla_receive(struct net_device *dev) case SDLA_S502A: case SDLA_S502E: if (success) - sdla_read(dev, SDLA_502_RCV_BUF + SDLA_502_DATA_OFS, skb_put(skb,len), len); + __sdla_read(dev, SDLA_502_RCV_BUF + SDLA_502_DATA_OFS, skb_put(skb,len), len); SDLA_WINDOW(dev, SDLA_502_RCV_BUF); cmd->opp_flag = 0; @@ -834,9 +848,9 @@ static void sdla_receive(struct net_device *dev) split = addr + len > buf_top + 1 ? len - (buf_top - addr + 1) : 0; len2 = len - split; - sdla_read(dev, addr, skb_put(skb, len2), len2); + __sdla_read(dev, addr, skb_put(skb, len2), len2); if (split) - sdla_read(dev, buf_base, skb_put(skb, split), split); + __sdla_read(dev, buf_base, skb_put(skb, split), split); } /* increment the buffer we're looking at */ @@ -853,7 +867,7 @@ static void sdla_receive(struct net_device *dev) (*dlp->receive)(skb, master); } - restore_flags(flags); + spin_unlock_irqrestore(&sdla_lock, flags); } static irqreturn_t sdla_isr(int irq, void *dev_id, struct pt_regs * regs) @@ -979,8 +993,6 @@ static int sdla_close(struct net_device *dev) netif_stop_queue(dev); - MOD_DEC_USE_COUNT; - return(0); } @@ -1082,8 +1094,6 @@ static int sdla_open(struct net_device *dev) netif_start_queue(dev); - MOD_INC_USE_COUNT; - return(0); } @@ -1614,19 +1624,44 @@ static struct net_device_stats *sdla_stats(struct net_device *dev) return(&flp->stats); } -int __init sdla_init(struct net_device *dev) +static void setup_sdla(struct net_device *dev) +{ + dev->flags = 0; + dev->type = 0xFFFF; + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->mtu = SDLA_MAX_MTU; +} + +static int frad_registered; + +struct net_device * __init sdla_init(void) { + struct net_device *dev; struct frad_local *flp; + int err = -ENOMEM; + + if (!frad_registered) { + err = register_frad(devname); + if (err) { + printk(KERN_ERR "%s: frad registration failed %d\n", + devname, err); + return ERR_PTR(err); + } + frad_registered = 1; + printk("%s.\n", version); + } + - /* allocate the private data structure */ - flp = kmalloc(sizeof(struct frad_local), GFP_KERNEL); - if (!flp) - return(-ENOMEM); + dev = alloc_netdev(sizeof(struct frad_local), "sdla0", setup_sdla); + if (!dev) + goto out; - memset(flp, 0, sizeof(struct frad_local)); - dev->priv = flp; + SET_MODULE_OWNER(dev); + netdev_boot_setup_check(dev); + + flp = dev->priv; - dev->flags = 0; dev->open = sdla_open; dev->stop = sdla_close; dev->do_ioctl = sdla_ioctl; @@ -1635,12 +1670,6 @@ int __init sdla_init(struct net_device *dev) dev->hard_start_xmit = sdla_transmit; dev->change_mtu = sdla_change_mtu; - dev->type = 0xFFFF; - dev->hard_header_len = 0; - dev->addr_len = 0; - dev->mtu = SDLA_MAX_MTU; - SET_MODULE_OWNER(dev); - flp->activate = sdla_activate; flp->deactivate = sdla_deactivate; flp->assoc = sdla_assoc; @@ -1652,44 +1681,45 @@ int __init sdla_init(struct net_device *dev) flp->timer.data = (unsigned long) dev; flp->timer.function = sdla_poll; - return(0); -} - -int __init sdla_c_setup(void) -{ - printk("%s.\n", version); - register_frad(devname); - return 0; + err = register_netdev(dev); + if (err) + goto out1; + return dev; +out1: + kfree(dev); +out: + return ERR_PTR(err); } #ifdef MODULE -static struct net_device sdla0 = { - .name = "sdla0", - .init = sdla_init -}; -#endif /* MODULE */ +static struct net_device *sdla0; static int __init init_sdla(void) { int result = 0; - sdla_c_setup(); -#ifdef MODULE - result = register_netdev(&sdla0); -#endif + sdla0 = sdla_init(); + if (IS_ERR(sdla0)) + result = PTR_ERR(sdla0); + return result; } static void __exit exit_sdla(void) { -#ifdef MODULE - unregister_netdev(&sdla0); - if (sdla0.priv) - kfree(sdla0.priv); - if (sdla0.irq) - free_irq(sdla0.irq, &sdla0); -#endif + struct frad_local *flp; + + unregister_netdev(sdla0); + if (sdla0->irq) + free_irq(sdla0->irq, sdla0); + + flp = sdla0->priv; + del_timer_sync(&flp->timer); + free_netdev(sdla0); + + unregister_frad(devname); } +#endif MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 02362e27c7ae..4b78dce165f5 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -2665,11 +2665,13 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) { badmic: dev_kfree_skb_irq (skb); +#else + if (0) { +#endif badrx: OUT4500( apriv, EVACK, EV_RX); goto exitrx; } -#endif } #if WIRELESS_EXT > 15 #ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ @@ -5662,9 +5664,10 @@ static int airo_get_power(struct net_device *dev, char *extra) { struct airo_info *local = dev->priv; + int mode; readConfigRid(local, 1); - int mode = local->config.powerSaveMode; + mode = local->config.powerSaveMode; if ((vwrq->disabled = (mode == POWERSAVE_CAM))) return 0; if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h index b43fa0cf3940..b29e42a146f1 100644 --- a/drivers/net/wireless/hermes.h +++ b/drivers/net/wireless/hermes.h @@ -302,12 +302,14 @@ typedef struct hermes_response { #define hermes_read_reg(hw, off) ((hw)->io_space ? \ inw((hw)->iobase + ( (off) << (hw)->reg_spacing )) : \ readw((hw)->iobase + ( (off) << (hw)->reg_spacing ))) -#define hermes_write_reg(hw, off, val) ((hw)->io_space ? \ - outw_p((val), (hw)->iobase + ( (off) << (hw)->reg_spacing )) : \ - writew((val), (hw)->iobase + ( (off) << (hw)->reg_spacing ))) - -#define hermes_read_regn(hw, name) (hermes_read_reg((hw), HERMES_##name)) -#define hermes_write_regn(hw, name, val) (hermes_write_reg((hw), HERMES_##name, (val))) +#define hermes_write_reg(hw, off, val) do { \ + if ((hw)->io_space) \ + outw_p((val), (hw)->iobase + ((off) << (hw)->reg_spacing)); \ + else \ + writew((val), (hw)->iobase + ((off) << (hw)->reg_spacing)); \ + } while (0) +#define hermes_read_regn(hw, name) hermes_read_reg((hw), HERMES_##name) +#define hermes_write_regn(hw, name, val) hermes_write_reg((hw), HERMES_##name, (val)) /* Function prototypes */ void hermes_struct_init(hermes_t *hw, ulong address, int io_space, int reg_spacing); diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 8a3328687d1f..c22ca46b0d81 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -577,7 +577,7 @@ err_out_free_res: #endif pci_release_regions(pdev); err_out_free_netdev: - kfree (dev); + free_netdev (dev); return -ENODEV; } diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 60bb81d4649b..4e384344042c 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -1758,7 +1758,7 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) printk("53c700: scsi%d, command ", SCp->device->host->host_no); print_command(SCp->cmnd); #endif - if(SCp->device->tagged_supported && !SCp->device->tagged_queue + if(SCp->device->tagged_supported && !SCp->device->simple_tags && (hostdata->tag_negotiated &(1<<SCp->device->id)) == 0 && NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING)) { /* upper layer has indicated tags are supported. We don't diff --git a/drivers/scsi/AM53C974.c b/drivers/scsi/AM53C974.c index 85d4d0507546..904115d0eac3 100644 --- a/drivers/scsi/AM53C974.c +++ b/drivers/scsi/AM53C974.c @@ -1231,8 +1231,8 @@ static void AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs) hostdata->sel_cmd = NULL; hostdata->selecting = 0; #ifdef SCSI2 - if (!hostdata->connected->device->tagged_queue) -#endif + if (!hostdata->conneted->device->simple_tags) +#else hostdata->busy[hostdata->connected->device->id] |= (1 << hostdata->connected->device->lun); /* very strange -- use_sg is sometimes nonzero for request sense commands !! */ if ((hostdata->connected->cmnd[0] == REQUEST_SENSE) && hostdata->connected->use_sg) { @@ -1811,7 +1811,7 @@ static int AM53C974_message(struct Scsi_Host *instance, Scsi_Cmnd * cmd, case HEAD_OF_QUEUE_TAG: case ORDERED_QUEUE_TAG: case SIMPLE_QUEUE_TAG: - cmd->device->tagged_queue = 0; + cmd->device->simple_tags = 0; hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); break; default: @@ -1958,7 +1958,7 @@ static void AM53C974_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag #endif #ifdef SCSI2 - if (cmd->device->tagged_queue && (tag != TAG_NONE)) { + if (cmd->device->simple_tags && (tag != TAG_NONE)) { tmp[1] = SIMPLE_QUEUE_TAG; if (tag == TAG_NEXT) { /* 0 is TAG_NONE, used to imply no tag for this command */ diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 01218bd31486..b3c9048c3a17 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -22,6 +22,17 @@ config SCSI module if your root file system (the one containing the directory /) is located on a SCSI device. +config SCSI_PROC_FS + bool "legacy /proc/scsi/ support" + depends on SCSI + default y + ---help--- + This option enables support for the various files in + /proc/scsi. In Linux 2.6 this has been superceeded by + files in sysfs but many legacy applications rely on this. + + If unusure say Y. + comment "SCSI support type (disk, tape, CD-ROM)" depends on SCSI @@ -726,13 +737,13 @@ config IBMMCA_SCSI_DEV_RESET config SCSI_IPS tristate "IBM ServeRAID support" - depends on X86 && PCI && SCSI + depends on PCI && SCSI ---help--- This is support for the IBM ServeRAID hardware RAID controllers. See <http://www.developer.ibm.com/welcome/netfinity/serveraid.html> for more information. If this driver does not work correctly without modification please contact the author by email at - ipslinux@us.ibm.com. + ipslinux@adaptec.com. You can build this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -989,36 +1000,9 @@ config SCSI_NCR_Q720 Unless you have an NCR manufactured machine, the chances are that you do not have this SCSI card, so say N. -config SCSI_SYM53C8XX - tristate "SYM53C8XX SCSI support" - depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI - ---help--- - This driver supports all the features of recent 53C8XX chips (used - in PCI SCSI controllers), notably the hardware phase mismatch - feature of the SYM53C896. - - Older versions of the 53C8XX chips are not supported by this - driver. If your system uses either a 810 rev. < 16, a 815, or a 825 - rev. < 16 PCI SCSI processor, you must use the generic NCR53C8XX - driver ("NCR53C8XX SCSI support" above) or configure both the - NCR53C8XX and this SYM53C8XX drivers either as module or linked to - the kernel image. - - When both drivers are linked into the kernel, the SYM53C8XX driver - is called first at initialization and you can use the 'excl=ioaddr' - driver boot option to exclude attachment of adapters by the - SYM53C8XX driver. For example, entering - 'sym53c8xx=excl:0xb400,excl=0xc000' at the lilo prompt prevents - adapters at io address 0xb400 and 0xc000 from being attached by the - SYM53C8XX driver, thus allowing the NCR53C8XX driver to attach them. - The 'excl' option is also supported by the NCR53C8XX driver. - - Please read <file:Documentation/scsi/ncr53c8xx.txt> for more - information. - config SCSI_NCR53C8XX_DEFAULT_TAGS int " default tagged command queue depth" - depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) + depends on SCSI_ZALON || SCSI_NCR_Q720 default "8" ---help--- "Tagged command queuing" is a feature of SCSI-2 which improves @@ -1044,7 +1028,7 @@ config SCSI_NCR53C8XX_DEFAULT_TAGS config SCSI_NCR53C8XX_MAX_TAGS int " maximum number of queued commands" - depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) + depends on SCSI_ZALON || SCSI_NCR_Q720 default "32" ---help--- This option allows you to specify the maximum number of commands @@ -1061,7 +1045,7 @@ config SCSI_NCR53C8XX_MAX_TAGS config SCSI_NCR53C8XX_SYNC int " synchronous transfers frequency in MHz" - depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) + depends on SCSI_ZALON || SCSI_NCR_Q720 default "20" ---help--- The SCSI Parallel Interface-2 Standard defines 5 classes of transfer @@ -1095,7 +1079,7 @@ config SCSI_NCR53C8XX_SYNC config SCSI_NCR53C8XX_PROFILE bool " enable profiling" - depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) + depends on SCSI_ZALON || SCSI_NCR_Q720 help This option allows you to enable profiling information gathering. These statistics are not very accurate due to the low frequency @@ -1104,34 +1088,9 @@ config SCSI_NCR53C8XX_PROFILE The normal answer therefore is N. -config SCSI_NCR53C8XX_IOMAPPED - bool " use normal IO" - depends on SCSI_SYM53C8XX && !(SCSI_ZALON || SCSI_NCR_Q720) - help - If you say Y here, the driver will use normal IO, as opposed to - memory mapped IO. Memory mapped IO has less latency than normal IO - and works for most Intel-based hardware. Under Linux/Alpha only - normal IO is currently supported by the driver and so, this option - has no effect on those systems. - - The normal answer therefore is N; try Y only if you encounter SCSI - related problems. - -config SCSI_NCR53C8XX_PQS_PDS - bool " include support for the NCR PQS/PDS SCSI card" - depends on SCSI_SYM53C8XX - help - Say Y here if you have a special SCSI adapter produced by NCR - corporation called a PCI Quad SCSI or PCI Dual SCSI. You do not need - this if you do not have one of these adapters. However, since this - device is detected as a specific PCI device, this option is quite - safe. - - The common answer here is N, but answering Y is safe. - config SCSI_NCR53C8XX_NO_DISCONNECT bool " not allow targets to disconnect" - depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0 + depends on (SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0 help This option is only provided for safety if you suspect some SCSI device of yours to not support properly the target-disconnect @@ -1139,26 +1098,6 @@ config SCSI_NCR53C8XX_NO_DISCONNECT not allow targets to disconnect is not reasonable if there is more than 1 device on a SCSI bus. The normal answer therefore is N. -config SCSI_NCR53C8XX_SYMBIOS_COMPAT - bool " assume boards are SYMBIOS compatible (EXPERIMENTAL)" - depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720 ) && EXPERIMENTAL - ---help--- - This option allows you to enable some features depending on GPIO - wiring. These General Purpose Input/Output pins can be used for - vendor specific features or implementation of the standard SYMBIOS - features. Genuine SYMBIOS controllers use GPIO0 in output for - controller LED and GPIO3 bit as a flag indicating - singled-ended/differential interface. The Tekram DC-390U/F boards - uses a different GPIO wiring. - - Your answer to this question is ignored if all your controllers have - NVRAM, since the driver is able to detect the board type from the - NVRAM format. - - If all the controllers in your system are genuine SYMBIOS boards or - use BIOS and drivers from SYMBIOS, you would want to say Y here, - otherwise N. N is the safe answer. - config SCSI_MCA_53C9X tristate "NCR MCA 53C9x SCSI support" depends on MCA && SCSI && BROKEN_ON_SMP @@ -1298,6 +1237,16 @@ config SCSI_QLOGIC_1280 The module will be called qla1280. If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. +config SCSI_QLOGIC_1280_PIO + bool "Use PIO instead of MMIO" if !X86_VISWS + depends on SCSI_QLOGIC_1280 + default y if X86_VISWS + help + This instructs the driver to use programmed I/O ports (PIO) instead + of PCI shared memory (MMIO). This can possibly solve some problems + in case your mainboard has memory consistency issues. If unsure, + say N. + config SCSI_QLOGICPTI tristate "PTI Qlogic, ISP Driver" depends on SBUS && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index b2ed067c7b98..fb2442aeb330 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -126,7 +126,8 @@ scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ scsicam.o scsi_error.o scsi_lib.o \ scsi_scan.o scsi_syms.o scsi_sysfs.o \ scsi_devinfo.o -scsi_mod-$(CONFIG_PROC_FS) += scsi_proc.o +scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o +scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o scsi_mod-$(CONFIG_X86_PC9800) += scsi_pc98.o sd_mod-objs := sd.o diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index dba125a0db5c..7262cca5529e 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -2512,7 +2512,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { case HEAD_OF_QUEUE_TAG: case ORDERED_QUEUE_TAG: case SIMPLE_QUEUE_TAG: - cmd->device->tagged_queue = 0; + cmd->device->simple_tags = 0; hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); break; default: diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 1ec4a55cbd10..390f63b3a371 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -6362,8 +6362,8 @@ advansys_slave_configure(Scsi_Device *device) } else { scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun); } - ASC_DBG3(1, "advansys_slave_configure: shp 0x%lx, id %d, depth %d\n", - (ulong) shp, device->id, device->queue_depth); + ASC_DBG4(1, "advansys_slave_configure: device 0x%lx, boardp 0x%lx, id %d, depth %d\n", + (ulong) device, (ulong) boardp, device->id, device->queue_depth); return 0; } @@ -9354,8 +9354,8 @@ asc_prt_scsi_host(struct Scsi_Host *s) printk("Scsi_Host at addr 0x%lx\n", (ulong) s); printk( -" next 0x%lx, host_busy %u, host_no %d, last_reset %d,\n", - (ulong) s->next, s->host_busy, s->host_no, +" host_busy %u, host_no %d, last_reset %d,\n", + s->host_busy, s->host_no, (unsigned) s->last_reset); #if ASC_LINUX_KERNEL24 @@ -9399,8 +9399,8 @@ asc_prt_scsi_cmnd(Scsi_Cmnd *s) printk( " host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n", - (ulong) s->host, (ulong) s->device, s->target, s->lun, - s->channel); + (ulong) s->device->host, (ulong) s->device, s->device->id, s->device->lun, + s->device->channel); asc_prt_hex(" CDB", s->cmnd, s->cmd_len); diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index a0452a6c6122..efc61b3f2502 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -768,7 +768,7 @@ intr_ret_t acornscsi_kick(AS_Host *host) /* * tagged queueing - allocate a new tag to this command */ - if (SCpnt->device->tagged_queue) { + if (SCpnt->device->simple_tags) { SCpnt->device->current_tag += 1; if (SCpnt->device->current_tag == 0) SCpnt->device->current_tag = 1; @@ -1590,7 +1590,7 @@ void acornscsi_message(AS_Host *host) */ printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n", host->host->host_no, acornscsi_target(host)); - host->SCpnt->device->tagged_queue = 0; + host->SCpnt->device->simple_tags = 0; set_bit(host->SCpnt->device->id * 8 + host->SCpnt->device->lun, host->busyluns); break; #endif @@ -2935,7 +2935,7 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start, p += sprintf(p, " %d/%d ", scd->id, scd->lun); if (scd->tagged_supported) p += sprintf(p, "%3sabled(%3d) ", - scd->tagged_queue ? "en" : "dis", + scd->simple_tags ? "en" : "dis", scd->current_tag); else p += sprintf(p, "unsupported "); diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c index fbda4d4f78a7..2c99ea7dae85 100644 --- a/drivers/scsi/arm/fas216.c +++ b/drivers/scsi/arm/fas216.c @@ -1819,7 +1819,7 @@ static void fas216_allocate_tag(FAS216_Info *info, Scsi_Cmnd *SCpnt) /* * tagged queuing - allocate a new tag to this command */ - if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE && + if (SCpnt->device->simple_tags && SCpnt->cmnd[0] != REQUEST_SENSE && SCpnt->cmnd[0] != INQUIRY) { SCpnt->device->current_tag += 1; if (SCpnt->device->current_tag == 0) @@ -3012,7 +3012,7 @@ int fas216_print_devices(FAS216_Info *info, char *buffer) p += sprintf(p, " %d/%d ", scd->id, scd->lun); if (scd->tagged_supported) p += sprintf(p, "%3sabled(%3d) ", - scd->tagged_queue ? "en" : "dis", + scd->simple_tags ? "en" : "dis", scd->current_tag); else p += sprintf(p, "unsupported "); diff --git a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c index 943778cca0eb..d165a3af3e14 100644 --- a/drivers/scsi/cpqfcTSinit.c +++ b/drivers/scsi/cpqfcTSinit.c @@ -603,7 +603,7 @@ int cpqfcTS_ioctl( struct scsi_device *ScsiDev, int Cmnd, void *arg) return -ENOMEM; } // Now build a Scsi_Request to pass down... - ScsiPassThruReq = scsi_allocate_request(ScsiDev); + ScsiPassThruReq = scsi_allocate_request(ScsiDev, GFP_KERNEL); if (ScsiPassThruReq == NULL) { kfree(buf); return -ENOMEM; diff --git a/drivers/scsi/cpqfcTSworker.c b/drivers/scsi/cpqfcTSworker.c index b41038baa394..2b5735863b65 100644 --- a/drivers/scsi/cpqfcTSworker.c +++ b/drivers/scsi/cpqfcTSworker.c @@ -2878,7 +2878,7 @@ static void ScsiReportLunsDone(Scsi_Cmnd *Cmnd) } } -Done: +Done: ; } extern int is_private_data_of_cpqfc(CPQFCHBA *hba, void * pointer); diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index e0a1d2191eed..107c220ae086 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -224,14 +224,14 @@ static char traceoverflow[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; #define DC395x_SMP_IO_UNLOCK(dev,irq_flags) spin_unlock_irqrestore(((struct Scsi_Host*)dev)->host_lock,irq_flags) -#define DC395x_read8(acb,address) (u8)(inb(acb->IOPortBase + (address))) +#define DC395x_read8(acb,address) (u8)(inb(acb->io_port_base + (address))) #define DC395x_read8_(address, base) (u8)(inb((USHORT)(base) + (address))) -#define DC395x_read16(acb,address) (u16)(inw(acb->IOPortBase + (address))) -#define DC395x_read32(acb,address) (u32)(inl(acb->IOPortBase + (address))) -#define DC395x_write8(acb,address,value) outb((value), acb->IOPortBase + (address)) +#define DC395x_read16(acb,address) (u16)(inw(acb->io_port_base + (address))) +#define DC395x_read32(acb,address) (u32)(inl(acb->io_port_base + (address))) +#define DC395x_write8(acb,address,value) outb((value), acb->io_port_base + (address)) #define DC395x_write8_(address,value,base) outb((value), (USHORT)(base) + (address)) -#define DC395x_write16(acb,address,value) outw((value), acb->IOPortBase + (address)) -#define DC395x_write32(acb,address,value) outl((value), acb->IOPortBase + (address)) +#define DC395x_write16(acb,address,value) outw((value), acb->io_port_base + (address)) +#define DC395x_write32(acb,address,value) outl((value), acb->io_port_base + (address)) #define BUS_ADDR(sg) sg_dma_address(&(sg)) @@ -383,7 +383,8 @@ struct DeviceCtlBlk { struct AdapterCtlBlk { struct Scsi_Host *scsi_host; - u16 IOPortBase; + u16 io_port_base; + u16 io_port_len; struct list_head dcb_list; /* head of going dcb list */ struct DeviceCtlBlk *dcb_run_robin; @@ -496,10 +497,6 @@ static void request_sense(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb); static inline void set_xfer_rate(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb); -static void init_dcb(struct AdapterCtlBlk *acb, - struct DeviceCtlBlk **pdcb, u8 target, u8 lun); -static void remove_dev(struct AdapterCtlBlk *acb, - struct DeviceCtlBlk *dcb); static void waiting_timeout(unsigned long ptr); @@ -822,6 +819,7 @@ void __init eeprom_override(struct NvRamType *eeprom) * * @head: The pointer to the head of the list to count the items in. **/ +static unsigned int list_size(struct list_head *head) { unsigned int count = 0; @@ -841,6 +839,7 @@ unsigned int list_size(struct list_head *head) * @pos: The pointer the dcb for which we are searching for the * following dcb. **/ +static struct DeviceCtlBlk *dcb_get_next( struct list_head *head, struct DeviceCtlBlk *pos) @@ -1449,34 +1448,6 @@ complete: } -/*********************************************************************** - * Function static int dc395x_slave_alloc() - * - * Purpose: Allocate DCB - ***********************************************************************/ -static int dc395x_slave_alloc(struct scsi_device *sdp) -{ - struct AdapterCtlBlk *acb; - struct DeviceCtlBlk *dummy; - - acb = (struct AdapterCtlBlk *) sdp->host->hostdata; - - init_dcb(acb, &dummy, sdp->id, sdp->lun); - - return dummy ? 0 : -ENOMEM; -} - - -static void dc395x_slave_destroy(struct scsi_device *sdp) -{ - struct AdapterCtlBlk *acb; - struct DeviceCtlBlk *dcb; - - acb = (struct AdapterCtlBlk *) sdp->host->hostdata; - dcb = find_dcb(acb, sdp->id, sdp->lun); - - remove_dev(acb, dcb); -} /* @@ -1635,7 +1606,6 @@ static void reset_dev_param(struct AdapterCtlBlk *acb) dcb->sync_offset = 0; dcb->dev_mode = eeprom->target[dcb->target_id].cfg0; - /*dcb->AdpMode = eeprom->channel_cfg; */ period_index = eeprom->target[dcb->target_id].period & 0x07; dcb->min_nego_period = clock_period[period_index]; if (!(dcb->dev_mode & NTC_DO_WIDE_NEGO) @@ -1824,7 +1794,6 @@ static void selto_timer(struct AdapterCtlBlk *acb) { if (timer_pending(&acb->selto_timer)) return; - init_timer(&acb->selto_timer); acb->selto_timer.function = selection_timeout_missed; acb->selto_timer.data = (unsigned long) acb; if (time_before @@ -4049,40 +4018,8 @@ static void reselect(struct AdapterCtlBlk *acb) } -/* Dynamic device handling */ - -/* Remove dev (and DCB) */ -static -void remove_dev(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) -{ - struct DeviceCtlBlk *i; - struct DeviceCtlBlk *tmp; - - dprintkdbg(DBG_0, "remove_dev\n"); - if (list_size(&dcb->srb_going_list) > 1) { - dprintkdbg(DBG_DCB, "Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n", - dcb->target_id, dcb->target_lun, (int) dcb, - list_size(&dcb->srb_going_list)); - return; - } - acb->dcb_map[dcb->target_id] &= ~(1 << dcb->target_lun); - acb->children[dcb->target_id][dcb->target_lun] = NULL; - list_for_each_entry_safe(i, tmp, &acb->dcb_list, list) { - if (dcb == i) { - list_del(&i->list); - break; - } - } - dprintkdbg(DBG_DCB, "Driver about to free DCB (ID %i, LUN %i): %p\n", - dcb->target_id, dcb->target_lun, dcb); - if (dcb == acb->active_dcb) - acb->active_dcb = NULL; - if (dcb == acb->dcb_run_robin) - acb->dcb_run_robin = dcb_get_next(&acb->dcb_list, dcb); - dc395x_kfree(dcb); -} static inline u8 tagq_blacklist(char *name) @@ -4681,58 +4618,55 @@ void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, } -/* - ********************************************************************* - * dc395x_queue_command + + + +/** + * device_alloc - Allocate a new device instance. This create the + * devices instance and sets up all the data items. The adapter + * instance is required to obtain confiuration information for this + * device. This does *not* add this device to the adapters device + * list. * - * Function : void init_dcb - * Purpose : initialize the internal structures for a given DCB - * Inputs : cmd - pointer to this scsi cmd request block structure - ********************************************************************* - */ + * @acb: The adapter to obtain configuration information from. + * @target: The target for the new device. + * @lun: The lun for the new device. + * + * Return the new device if succesfull or NULL on failure. + **/ static -void init_dcb(struct AdapterCtlBlk *acb, struct DeviceCtlBlk **pdcb, - u8 target, u8 lun) +struct DeviceCtlBlk *device_alloc(struct AdapterCtlBlk *acb, u8 target, u8 lun) { struct NvRamType *eeprom = &acb->eeprom; - u8 period_index; + u8 period_index = eeprom->target[target].period & 0x07; struct DeviceCtlBlk *dcb; - struct DeviceCtlBlk *dcb2; - dprintkdbg(DBG_0, "init_dcb..............\n"); dcb = dc395x_kmalloc(sizeof(struct DeviceCtlBlk), GFP_ATOMIC); - /*dcb = find_dcb (acb, target, lun); */ - *pdcb = dcb; - dcb2 = NULL; - if (!dcb) - return; - - INIT_LIST_HEAD(&dcb->srb_waiting_list); + dprintkdbg(DBG_0, "device_alloc: device %p\n", dcb); + if (!dcb) { + return NULL; + } + dcb->acb = NULL; INIT_LIST_HEAD(&dcb->srb_going_list); - if (list_empty(&acb->dcb_list)) - acb->dcb_run_robin = dcb; - list_add_tail(&dcb->list, &acb->dcb_list); - - /* $$$$$$$ */ - dcb->acb = acb; - dcb->target_id = target; - dcb->target_lun = lun; - /* $$$$$$$ */ + INIT_LIST_HEAD(&dcb->srb_waiting_list); dcb->active_srb = NULL; - /* $$$$$$$ */ dcb->tag_mask = 0; - dcb->flag = 0; dcb->max_command = 1; - /* $$$$$$$ */ + dcb->target_id = target; + dcb->target_lun = lun; +#ifndef DC395x_NO_DISCONNECT + dcb->identify_msg = + IDENTIFY(dcb->dev_mode & NTC_DO_DISCONNECT, lun); +#else + dcb->identify_msg = IDENTIFY(0, lun); +#endif dcb->dev_mode = eeprom->target[target].cfg0; - /*dcb->AdpMode = eeprom->channel_cfg; */ dcb->inquiry7 = 0; dcb->sync_mode = 0; - /* $$$$$$$ */ + dcb->min_nego_period = clock_period[period_index]; dcb->sync_period = 0; dcb->sync_offset = 0; - period_index = eeprom->target[target].period & 0x07; - dcb->min_nego_period = clock_period[period_index]; + dcb->flag = 0; #ifndef DC395x_NO_WIDE if ((dcb->dev_mode & NTC_DO_WIDE_NEGO) @@ -4744,318 +4678,166 @@ void init_dcb(struct AdapterCtlBlk *acb, struct DeviceCtlBlk **pdcb, if (!(lun) || current_sync_offset) dcb->sync_mode |= SYNC_NEGO_ENABLE; #endif - /* $$$$$$$ */ -#ifndef DC395x_NO_DISCONNECT - dcb->identify_msg = - IDENTIFY(dcb->dev_mode & NTC_DO_DISCONNECT, lun); -#else - dcb->identify_msg = IDENTIFY(0, lun); -#endif - /* $$$$$$$ */ if (dcb->target_lun != 0) { /* Copy settings */ - struct DeviceCtlBlk *prevDCB; - list_for_each_entry(prevDCB, &acb->dcb_list, list) - if (prevDCB->target_id == dcb->target_id) + struct DeviceCtlBlk *p; + list_for_each_entry(p, &acb->dcb_list, list) + if (p->target_id == dcb->target_id) break; - dprintkdbg(DBG_KG, + dprintkdbg(DBG_KG, "Copy settings from %02i-%02i to %02i-%02i\n", - prevDCB->target_id, prevDCB->target_lun, + p->target_id, p->target_lun, dcb->target_id, dcb->target_lun); - dcb->sync_mode = prevDCB->sync_mode; - dcb->sync_period = prevDCB->sync_period; - dcb->min_nego_period = prevDCB->min_nego_period; - dcb->sync_offset = prevDCB->sync_offset; - dcb->inquiry7 = prevDCB->inquiry7; - }; - - acb->dcb_map[target] |= (1 << lun); - acb->children[target][lun] = dcb; + dcb->sync_mode = p->sync_mode; + dcb->sync_period = p->sync_period; + dcb->min_nego_period = p->min_nego_period; + dcb->sync_offset = p->sync_offset; + dcb->inquiry7 = p->inquiry7; + } + return dcb; } -#if debug_enabled(DBG_TRACE|DBG_TRACEALL) -/* - * Memory for trace buffers - */ +/** + * adapter_add_device - Adds the device instance to the adaptor instance. + * + * @acb: The adapter device to be updated + * @dcb: A newly created and intialised device instance to add. + **/ static -void free_tracebufs(struct AdapterCtlBlk *acb, int srb_idx) +void adapter_add_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) { - int i; - const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ; - for (i = 0; i < srb_idx; i += bufs_per_page) { - /*dprintkl(KERN_DEBUG, "Free tracebuf %p (for %i)\n", */ - /* acb->srb_array[i].debugtrace, i); */ - dc395x_kfree(acb->srb_array[i].debugtrace); - } -} + /* backpointer to adapter */ + dcb->acb = acb; + + /* set run_robin to this device if it is currently empty */ + if (list_empty(&acb->dcb_list)) + acb->dcb_run_robin = dcb; + /* add device to list */ + list_add_tail(&dcb->list, &acb->dcb_list); -static -int alloc_tracebufs(struct AdapterCtlBlk *acb) -{ - const unsigned mem_needed = - (DC395x_MAX_SRB_CNT + 1) * DEBUGTRACEBUFSZ; - int pages = (mem_needed + (PAGE_SIZE - 1)) / PAGE_SIZE; - const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ; - int srb_idx = 0; - unsigned i = 0; - unsigned char *ptr; - /*dprintkl(KERN_DEBUG, "Alloc %i pages for tracebufs\n", pages); */ - while (pages--) { - ptr = dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!ptr) { - free_tracebufs(acb, srb_idx); - return 1; - } - /*dprintkl(KERN_DEBUG, "Alloc %li bytes at %p for tracebuf %i\n", */ - /* PAGE_SIZE, ptr, srb_idx); */ - i = 0; - while (i < bufs_per_page && srb_idx < DC395x_MAX_SRB_CNT) - acb->srb_array[srb_idx++].debugtrace = - ptr + (i++ * DEBUGTRACEBUFSZ); - } - if (i < bufs_per_page) { - acb->srb.debugtrace = ptr + (i * DEBUGTRACEBUFSZ); - acb->srb.debugtrace[0] = 0; - } else - dprintkl(KERN_DEBUG, "No space for tmsrb tracebuf reserved?!\n"); - return 0; + /* update device maps */ + acb->dcb_map[dcb->target_id] |= (1 << dcb->target_lun); + acb->children[dcb->target_id][dcb->target_lun] = dcb; } -#endif -/* Free SG tables */ -static void free_sg_tables(struct AdapterCtlBlk *acb, int srb_idx) +/** + * adapter_remove_device - Removes the device instance from the adaptor + * instance. The device instance is not check in any way or freed by this. + * The caller is expected to take care of that. This will simply remove the + * device from the adapters data strcutures. + * + * @acb: The adapter device to be updated + * @dcb: A device that has previously been added to the adapter. + **/ +static +void adapter_remove_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) { - int i; - const unsigned srbs_per_page = - PAGE_SIZE / (DC395x_MAX_SG_LISTENTRY * sizeof(struct SGentry)); - for (i = 0; i < srb_idx; i += srbs_per_page) { - /*dprintkl(KERN_DEBUG, "Free SG segs %p (for %i)\n", */ - /* acb->srb_array[i].segment_x, i); */ - dc395x_kfree(acb->srb_array[i].segment_x); - } -} + struct DeviceCtlBlk *i; + struct DeviceCtlBlk *tmp; + dprintkdbg(DBG_0, "adapter_remove_device: Remove device (ID %i, LUN %i): %p\n", + dcb->target_id, dcb->target_lun, dcb); + /* fix up any pointers to this device that we have in the adapter */ + if (acb->active_dcb == dcb) + acb->active_dcb = NULL; + if (acb->dcb_run_robin == dcb) + acb->dcb_run_robin = dcb_get_next(&acb->dcb_list, dcb); -/* - * Allocate SG tables; as we have to pci_map them, an SG list (struct SGentry*) - * should never cross a page boundary */ -static int alloc_sg_tables(struct AdapterCtlBlk *acb) -{ - const unsigned mem_needed = - (DC395x_MAX_SRB_CNT + - 1) * DC395x_MAX_SG_LISTENTRY * sizeof(struct SGentry); - int pages = (mem_needed + (PAGE_SIZE - 1)) / PAGE_SIZE; - const unsigned srbs_per_page = - PAGE_SIZE / (DC395x_MAX_SG_LISTENTRY * sizeof(struct SGentry)); - int srb_idx = 0; - unsigned i = 0; - struct SGentry *ptr; - /*dprintkl(KERN_DEBUG, "Alloc %i pages for SG tables\n", pages); */ - while (pages--) { - ptr = (struct SGentry *) dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!ptr) { - free_sg_tables(acb, srb_idx); - return 1; + /* unlink from list */ + list_for_each_entry_safe(i, tmp, &acb->dcb_list, list) + if (dcb == i) { + list_del(&i->list); + break; } - /*dprintkl(KERN_DEBUG, "Alloc %li bytes at %p for SG segments %i\n", */ - /* PAGE_SIZE, ptr, srb_idx); */ - i = 0; - while (i < srbs_per_page && srb_idx < DC395x_MAX_SRB_CNT) - acb->srb_array[srb_idx++].segment_x = - ptr + (i++ * DC395x_MAX_SG_LISTENTRY); - } - if (i < srbs_per_page) - acb->srb.segment_x = - ptr + (i * DC395x_MAX_SG_LISTENTRY); - else - dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n"); - return 0; + + /* clear map and children */ + acb->dcb_map[dcb->target_id] &= ~(1 << dcb->target_lun); + acb->children[dcb->target_id][dcb->target_lun] = NULL; + dcb->acb = NULL; } -/* - ******************************************************************** - * scsiio - * init_acb - ******************************************************************** +/** + * adapter_remove_and_free_device - Removes a single device from the adapter + * and then frees the device information. + * + * @acb: The adapter device to be updated + * @dcb: A device that has previously been added to the adapter. */ -static void __init link_srb(struct AdapterCtlBlk *acb) +static +void adapter_remove_and_free_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) { - int i; - - for (i = 0; i < acb->srb_count - 1; i++) - srb_free_insert(acb, &acb->srb_array[i]); + if (list_size(&dcb->srb_going_list) > 1) { + dprintkdbg(DBG_DCB, "adapter_remove_and_free_device: " + "Won't remove because of %i active requests\n", + list_size(&dcb->srb_going_list)); + return; + } + adapter_remove_device(acb, dcb); + dc395x_kfree(dcb); } -/* - *********************************************************************** - * host_init +/** + * adapter_remove_and_free_all_devices - Removes and frees all of the + * devices associated with the specified adapter. * - * Function : static void init_acb - * Purpose : initialize the internal structures for a given SCSI host - * Inputs : host - pointer to this host adapter's structure - *********************************************************************** - */ + * @acb: The adapter from which all devices should be removed. + **/ static -int __init init_acb(struct Scsi_Host *host, u32 io_port, u8 irq) +void adapter_remove_and_free_all_devices(struct AdapterCtlBlk* acb) { - struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata; - struct NvRamType *eeprom = &acb->eeprom; - u16 i; + struct DeviceCtlBlk *dcb; + struct DeviceCtlBlk *tmp; + dprintkdbg(DBG_DCB, "adapter_remove_and_free_all_devices: Free all devices (%i devices)\n", + list_size(&acb->dcb_list)); - host->max_cmd_len = 24; - host->can_queue = DC395x_MAX_CMD_QUEUE; - host->cmd_per_lun = DC395x_MAX_CMD_PER_LUN; - host->this_id = (int) eeprom->scsi_id; - host->io_port = io_port; - host->n_io_port = 0x80; - host->dma_channel = -1; - host->unique_id = io_port; - host->irq = irq; - host->last_reset = jiffies; + list_for_each_entry_safe(dcb, tmp, &acb->dcb_list, list) + adapter_remove_and_free_device(acb, dcb); +} - host->max_id = 16; - if (host->max_id - 1 == eeprom->scsi_id) - host->max_id--; -#ifdef CONFIG_SCSI_MULTI_LUN - if (eeprom->channel_cfg & NAC_SCANLUN) - host->max_lun = 8; - else - host->max_lun = 1; -#else - host->max_lun = 1; -#endif - /* - ******************************** - */ - acb->scsi_host = host; - acb->IOPortBase = (u16) io_port; - acb->dcb_run_robin = NULL; - acb->active_dcb = NULL; - acb->srb_count = DC395x_MAX_SRB_CNT; - acb->scsi_host->this_id = eeprom->scsi_id; - acb->hostid_bit = (1 << acb->scsi_host->this_id); - /*acb->scsi_host->this_lun = 0; */ - acb->irq_level = irq; - acb->tag_max_num = 1 << eeprom->max_tag; - if (acb->tag_max_num > 30) - acb->tag_max_num = 30; - acb->acb_flag = 0; /* RESET_DETECT, RESET_DONE, RESET_DEV */ - acb->scan_devices = 1; - acb->msg_len = 0; - acb->gmode2 = eeprom->channel_cfg; - if (eeprom->channel_cfg & NAC_SCANLUN) - acb->lun_chk = 1; - /* - * link all device's SRB Q of this adapter - */ - if (alloc_sg_tables(acb)) { - dprintkl(KERN_DEBUG, "SG table allocation failed!\n"); - return 1; - } -#if debug_enabled(DBG_TRACE|DBG_TRACEALL) - if (alloc_tracebufs(acb)) { - dprintkl(KERN_DEBUG, "SG trace buffer allocation failed!\n"); - free_sg_tables(acb, DC395x_MAX_SRB_CNT); - return 1; - } -#endif - INIT_LIST_HEAD(&acb->dcb_list); - INIT_LIST_HEAD(&acb->srb_free_list); - link_srb(acb); +/** + * dc395x_slave_alloc - Called by the scsi mid layer to tell us about a new + * scsi device that we need to deal with. We allocate a new device and then + * insert that device into the adapters device list. + * + * @scsi_device: The new scsi device that we need to handle. + **/ +static +int dc395x_slave_alloc(struct scsi_device *scsi_device) +{ + struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)scsi_device->host->hostdata; + struct DeviceCtlBlk *dcb; - /* - * temp SRB for Q tag used or abort command used - */ - acb->tmp_srb = &acb->srb; - init_timer(&acb->waiting_timer); + dcb = device_alloc(acb, scsi_device->id, scsi_device->lun); + if (!dcb) + return -ENOMEM; + adapter_add_device(acb, dcb); - for (i = 0; i < DC395x_MAX_SCSI_ID; i++) - acb->dcb_map[i] = 0; - dprintkdbg(DBG_0, "acb = %p, pdcb_map = %p, psrb_array = %p\n", acb, - acb->dcb_map, acb->srb_array); - dprintkdbg(DBG_0, "ACB size= %04x, DCB size= %04x, SRB size= %04x\n", - sizeof(struct AdapterCtlBlk), sizeof(struct DeviceCtlBlk), - sizeof(struct ScsiReqBlk)); return 0; } -/*=========================================================================== - Init - ===========================================================================*/ /** - * init_adapter - Initialize the SCSI chip control registers - * - * @host: This hosts adapter strcuture - * @io_port: The base I/O port - * @irq: IRQ + * dc395x_slave_destroy - Called by the scsi mid layer to tell us about a + * device that is going away. * - * Returns 0 if the initialization succeeds, any other value on failure. + * @scsi_device: The new scsi device that we need to handle. **/ static -int __init init_adapter(struct Scsi_Host *host, u32 io_port, u8 irq) +void dc395x_slave_destroy(struct scsi_device *scsi_device) { - struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata; - struct NvRamType *eeprom = &acb->eeprom; - - if (!request_region(io_port, host->n_io_port, DC395X_NAME)) { - dprintkl(KERN_ERR, "Failed to reserve IO region 0x%x\n", io_port); - return -1; - } - if (request_irq(irq, dc395x_interrupt, SA_SHIRQ, DC395X_NAME, acb)) { - /* release the region we just claimed */ - release_region(io_port, host->n_io_port); - dprintkl(KERN_INFO, "Failed to register IRQ!\n"); - return -1; - } - - acb->IOPortBase = io_port; - - /* selection timeout = 250 ms */ - acb->sel_timeout = DC395x_SEL_TIMEOUT; - - /* Mask all the interrupt */ - DC395x_write8(acb, TRM_S1040_DMA_INTEN, 0x00); - DC395x_write8(acb, TRM_S1040_SCSI_INTEN, 0x00); - - /* Reset SCSI module */ - DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_RSTMODULE); - - /* Reset PCI/DMA module */ - DC395x_write8(acb, TRM_S1040_DMA_CONTROL, DMARESETMODULE); - udelay(20); - - /* program configuration 0 */ - acb->config = HCC_AUTOTERM | HCC_PARITY; - if (DC395x_read8(acb, TRM_S1040_GEN_STATUS) & WIDESCSI) - acb->config |= HCC_WIDE_CARD; - - if (eeprom->channel_cfg & NAC_POWERON_SCSI_RESET) - acb->config |= HCC_SCSI_RESET; - - if (acb->config & HCC_SCSI_RESET) { - dprintkl(KERN_INFO, "Performing initial SCSI bus reset\n"); - DC395x_write8(acb, TRM_S1040_SCSI_CONTROL, DO_RSTSCSI); - - /*while (!( DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS) & INT_SCSIRESET )); */ - /*spin_unlock_irq (&io_request_lock); */ - udelay(500); + struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)scsi_device->host->hostdata; + struct DeviceCtlBlk *dcb = find_dcb(acb, scsi_device->id, scsi_device->lun); + if (dcb) + adapter_remove_and_free_device(acb, dcb); +} - acb->scsi_host->last_reset = - jiffies + HZ / 2 + - HZ * acb->eeprom.delay_time; - /*spin_lock_irq (&io_request_lock); */ - } - set_basic_config(acb); - return 0; -} /** @@ -5363,20 +5145,161 @@ void __init check_eeprom(struct NvRamType *eeprom, u16 io_port) } + + /** - * print_config - print adapter connection and termination + * print_eeprom_settings - output the eeprom settings + * to the kernel log so people can see what they were. + * + * @eeprom: The eeprom data strucutre to show details for. + **/ +static +void __init print_eeprom_settings(struct NvRamType *eeprom) +{ + dprintkl(KERN_INFO, "Used settings: AdapterID=%02i, Speed=%i(%02i.%01iMHz), dev_mode=0x%02x\n", + eeprom->scsi_id, + eeprom->target[0].period, + clock_speed[eeprom->target[0].period] / 10, + clock_speed[eeprom->target[0].period] % 10, + eeprom->target[0].cfg0); + dprintkl(KERN_INFO, " AdaptMode=0x%02x, Tags=%i(%02i), DelayReset=%is\n", + eeprom->channel_cfg, + eeprom->max_tag, + 1 << eeprom->max_tag, + eeprom->delay_time); +} + + + +#if debug_enabled(DBG_TRACE|DBG_TRACEALL) +/* + * Memory for trace buffers + */ +static +void free_tracebufs(struct AdapterCtlBlk *acb) +{ + int i; + const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ; + + for (i = 0; i < srb_idx; i += bufs_per_page) + if (acb->srb_array[i].debugtrace) + dc395x_kfree(acb->srb_array[i].debugtrace); +} + + +static +int alloc_tracebufs(struct AdapterCtlBlk *acb) +{ + const unsigned mem_needed = + (DC395x_MAX_SRB_CNT + 1) * DEBUGTRACEBUFSZ; + int pages = (mem_needed + (PAGE_SIZE - 1)) / PAGE_SIZE; + const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ; + int srb_idx = 0; + unsigned i = 0; + unsigned char *ptr; + + for (i = 0; i < DC395x_MAX_SRB_CNT; i++) + acb->srb_array[i].debugtrace = NULL; + + while (pages--) { + ptr = dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!ptr) { + free_tracebufs(acb); + return 1; + } + /*dprintkl(KERN_DEBUG, "Alloc %li bytes at %p for tracebuf %i\n", */ + /* PAGE_SIZE, ptr, srb_idx); */ + i = 0; + while (i < bufs_per_page && srb_idx < DC395x_MAX_SRB_CNT) + acb->srb_array[srb_idx++].debugtrace = + ptr + (i++ * DEBUGTRACEBUFSZ); + } + if (i < bufs_per_page) { + acb->srb.debugtrace = ptr + (i * DEBUGTRACEBUFSZ); + acb->srb.debugtrace[0] = 0; + } else + dprintkl(KERN_DEBUG, "No space for tmsrb tracebuf reserved?!\n"); + return 0; +} +#else +static void free_tracebufs(struct AdapterCtlBlk *acb) {} +static int alloc_tracebufs(struct AdapterCtlBlk *acb) { return 0; } +#endif + +/* Free SG tables */ +static +void adapter_sg_tables_free(struct AdapterCtlBlk *acb) +{ + int i; + const unsigned srbs_per_page = PAGE_SIZE/(DC395x_MAX_SG_LISTENTRY + *sizeof(struct SGentry)); + + for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page) + if (acb->srb_array[i].segment_x) + dc395x_kfree(acb->srb_array[i].segment_x); +} + + +/* + * Allocate SG tables; as we have to pci_map them, an SG list (struct SGentry*) + * should never cross a page boundary */ +static +int __init adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) +{ + const unsigned mem_needed = (DC395x_MAX_SRB_CNT+1) + *DC395x_MAX_SG_LISTENTRY + *sizeof(struct SGentry); + int pages = (mem_needed+(PAGE_SIZE-1))/PAGE_SIZE; + const unsigned srbs_per_page = PAGE_SIZE/(DC395x_MAX_SG_LISTENTRY + *sizeof(struct SGentry)); + int srb_idx = 0; + unsigned i = 0; + struct SGentry *ptr; + + for (i = 0; i < DC395x_MAX_SRB_CNT; i++) + acb->srb_array[i].segment_x = NULL; + + dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages); + while (pages--) { + ptr = (struct SGentry *)dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!ptr) { + adapter_sg_tables_free(acb); + return 1; + } + dprintkdbg(DBG_1, "Allocate %li bytes at %p for SG segments %i\n", + PAGE_SIZE, ptr, srb_idx); + i = 0; + while (i < srbs_per_page && srb_idx < DC395x_MAX_SRB_CNT) + acb->srb_array[srb_idx++].segment_x = + ptr + (i++ * DC395x_MAX_SG_LISTENTRY); + } + if (i < srbs_per_page) + acb->srb.segment_x = + ptr + (i * DC395x_MAX_SG_LISTENTRY); + else + dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n"); + return 0; +} + + + +/** + * adapter_print_config - print adapter connection and termination * config * - * @acb: adapter control block + * The io port in the adapter needs to have been set before calling + * this function. + * + * @acb: The adapter to print the information for. **/ static -void __init print_config(struct AdapterCtlBlk *acb) +void __init adapter_print_config(struct AdapterCtlBlk *acb) { u8 bval; bval = DC395x_read8(acb, TRM_S1040_GEN_STATUS); - dprintkl(KERN_INFO, "%c: Connectors: ", - ((bval & WIDESCSI) ? 'W' : ' ')); + dprintkl(KERN_INFO, "%s Connectors: ", + ((bval & WIDESCSI) ? "(Wide)" : "")); if (!(bval & CON5068)) printk("ext%s ", !(bval & EXT68HIGH) ? "68" : "50"); if (!(bval & CON68)) @@ -5403,77 +5326,290 @@ void __init print_config(struct AdapterCtlBlk *acb) /** - * print_eeprom_settings - output the eeprom settings - * to the kernel log so people can see what they were. + * adapter_init_params - Initialize the various parameters in the + * adapter structure. Note that the pointer to the scsi_host is set + * early (when this instance is created) and the io_port and irq + * values are set later after they have been reserved. This just gets + * everything set to a good starting position. * - * @eeprom: The eeprom data strucutre to show details for. + * The eeprom structure in the adapter needs to have been set before + * calling this function. + * + * @acb: The adapter to initialize. **/ static -void __init print_eeprom_settings(struct NvRamType *eeprom) +void __init adapter_init_params(struct AdapterCtlBlk *acb) { - dprintkl(KERN_INFO, "Used settings: AdapterID=%02i, Speed=%i(%02i.%01iMHz), dev_mode=0x%02x\n", - eeprom->scsi_id, - eeprom->target[0].period, - clock_speed[eeprom->target[0].period] / 10, - clock_speed[eeprom->target[0].period] % 10, - eeprom->target[0].cfg0); - dprintkl(KERN_INFO, " AdaptMode=0x%02x, Tags=%i(%02i), DelayReset=%is\n", - eeprom->channel_cfg, - eeprom->max_tag, - 1 << eeprom->max_tag, - eeprom->delay_time); + struct NvRamType *eeprom = &acb->eeprom; + int i; + + /* NOTE: acb->scsi_host is set at scsi_host/acb creation time */ + /* NOTE: acb->io_port_base is set at port registration time */ + /* NOTE: acb->io_port_len is set at port registration time */ + + INIT_LIST_HEAD(&acb->dcb_list); + acb->dcb_run_robin = NULL; + acb->active_dcb = NULL; + + INIT_LIST_HEAD(&acb->srb_free_list); + /* temp SRB for Q tag used or abort command used */ + acb->tmp_srb = &acb->srb; + init_timer(&acb->waiting_timer); + init_timer(&acb->selto_timer); + + acb->srb_count = DC395x_MAX_SRB_CNT; + + acb->sel_timeout = DC395x_SEL_TIMEOUT; /* timeout=250ms */ + /* NOTE: acb->irq_level is set at IRQ registration time */ + + acb->tag_max_num = 1 << eeprom->max_tag; + if (acb->tag_max_num > 30) + acb->tag_max_num = 30; + + acb->acb_flag = 0; /* RESET_DETECT, RESET_DONE, RESET_DEV */ + acb->gmode2 = eeprom->channel_cfg; + acb->config = 0; /* NOTE: actually set in adapter_init_chip */ + + if (eeprom->channel_cfg & NAC_SCANLUN) + acb->lun_chk = 1; + acb->scan_devices = 1; + + acb->scsi_host->this_id = eeprom->scsi_id; + acb->hostid_bit = (1 << acb->scsi_host->this_id); + + for (i = 0; i < DC395x_MAX_SCSI_ID; i++) + acb->dcb_map[i] = 0; + + acb->msg_len = 0; + + /* link static array of srbs into the srb free list */ + for (i = 0; i < acb->srb_count - 1; i++) + srb_free_insert(acb, &acb->srb_array[i]); } -/* - ********************************************************************* - * DC395x_detect +/** + * adapter_init_host - Initialize the scsi host instance based on + * values that we have already stored in the adapter instance. There's + * some mention that a lot of these are deprecated, so we won't use + * them (we'll use the ones in the adapter instance) but we'll fill + * them in in case something else needs them. * - * Function : static int host_init (struct Scsi_Host *host) - * Purpose : initialize the internal structures for a given SCSI host - * Inputs : host - pointer to this host adapter's structure/ - * Preconditions : when this function is called, the chip_type - * field of the acb structure MUST have been set. - ********************************************************************* - */ + * The eeprom structure, irq and io ports in the adapter need to have + * been set before calling this function. + * + * @host: The scsi host instance to fill in the values for. + **/ static -struct Scsi_Host *__init host_init(Scsi_Host_Template * host_template, - u32 io_port, u8 irq) +void __init adapter_init_scsi_host(struct Scsi_Host *host) { - struct Scsi_Host *host; - struct AdapterCtlBlk *acb; + struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata; + struct NvRamType *eeprom = &acb->eeprom; + + host->max_cmd_len = 24; + host->can_queue = DC395x_MAX_CMD_QUEUE; + host->cmd_per_lun = DC395x_MAX_CMD_PER_LUN; + host->this_id = (int)eeprom->scsi_id; + host->io_port = acb->io_port_base; + host->n_io_port = acb->io_port_len; + host->dma_channel = -1; + host->unique_id = acb->io_port_base; + host->irq = acb->irq_level; + host->last_reset = jiffies; - host = scsi_host_alloc(host_template, sizeof(struct AdapterCtlBlk)); - if (!host) { - dprintkl(KERN_INFO, "scsi_host_alloc failed\n"); + host->max_id = 16; + if (host->max_id - 1 == eeprom->scsi_id) + host->max_id--; + +#ifdef CONFIG_SCSI_MULTI_LUN + if (eeprom->channel_cfg & NAC_SCANLUN) + host->max_lun = 8; + else + host->max_lun = 1; +#else + host->max_lun = 1; +#endif + +} + + +/** + * adapter_init_chip - Get the chip into a know state and figure out + * some of the settings that apply to this adapter. + * + * The io port in the adapter needs to have been set before calling + * this function. The config will be configured correctly on return. + * + * @acb: The adapter which we are to init. + **/ +void __init adapter_init_chip(struct AdapterCtlBlk *acb) +{ + struct NvRamType *eeprom = &acb->eeprom; + + /* Mask all the interrupt */ + DC395x_write8(acb, TRM_S1040_DMA_INTEN, 0x00); + DC395x_write8(acb, TRM_S1040_SCSI_INTEN, 0x00); + + /* Reset SCSI module */ + DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_RSTMODULE); + + /* Reset PCI/DMA module */ + DC395x_write8(acb, TRM_S1040_DMA_CONTROL, DMARESETMODULE); + udelay(20); + + /* program configuration 0 */ + acb->config = HCC_AUTOTERM | HCC_PARITY; + if (DC395x_read8(acb, TRM_S1040_GEN_STATUS) & WIDESCSI) + acb->config |= HCC_WIDE_CARD; + + if (eeprom->channel_cfg & NAC_POWERON_SCSI_RESET) + acb->config |= HCC_SCSI_RESET; + + if (acb->config & HCC_SCSI_RESET) { + dprintkl(KERN_INFO, "Performing initial SCSI bus reset\n"); + DC395x_write8(acb, TRM_S1040_SCSI_CONTROL, DO_RSTSCSI); + + /*while (!( DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS) & INT_SCSIRESET )); */ + /*spin_unlock_irq (&io_request_lock); */ + udelay(500); + + acb->scsi_host->last_reset = + jiffies + HZ / 2 + + HZ * acb->eeprom.delay_time; + + /*spin_lock_irq (&io_request_lock); */ + } +} + + +/** + * init_adapter - Grab the resource for the card, setup the adapter + * information, set the card into a known state, create the various + * tables etc etc. This basically gets all adapter information all up + * to date, intialised and gets the chip in sync with it. + * + * @host: This hosts adapter structure + * @io_port: The base I/O port + * @irq: IRQ + * + * Returns 0 if the initialization succeeds, any other value on + * failure. + **/ +static +int __init adapter_init(struct AdapterCtlBlk *acb, u32 io_port, u32 io_port_len, u8 irq) +{ + if (!request_region(io_port, io_port_len, DC395X_NAME)) { + dprintkl(KERN_ERR, "Failed to reserve IO region 0x%x\n", io_port); goto failed; } - acb = (struct AdapterCtlBlk *)host->hostdata; + /* store port base to indicate we have registered it */ + acb->io_port_base = io_port; + acb->io_port_len = io_port_len; + + if (request_irq(irq, dc395x_interrupt, SA_SHIRQ, DC395X_NAME, acb)) { + /* release the region we just claimed */ + dprintkl(KERN_INFO, "Failed to register IRQ\n"); + goto failed; + } + /* store irq to indicate we have registered it */ + acb->irq_level = irq; + /* get eeprom configuration information and command line settings etc */ check_eeprom(&acb->eeprom, (u16)io_port); print_eeprom_settings(&acb->eeprom); - if (init_acb(host, io_port, irq)) { + /* setup adapter control block */ + adapter_init_params(acb); + + /* display card connectors/termination settings */ + adapter_print_config(acb); + + if (adapter_sg_tables_alloc(acb)) { + dprintkl(KERN_DEBUG, "Memory allocation for SG tables failed\n"); goto failed; } - print_config(acb); - - if (init_adapter(host, io_port, irq)) { - dprintkl(KERN_INFO, "DC395x_initAdapter initial ERROR\n"); + if (alloc_tracebufs(acb)) { + dprintkl(KERN_DEBUG, "Memory allocation for trace buffers failed\n"); goto failed; } + adapter_init_scsi_host(acb->scsi_host); + adapter_init_chip(acb); + set_basic_config(acb); - return host; + dprintkdbg(DBG_0, "adapter_init: acb=%p, pdcb_map=%p " + "psrb_array=%p ACB size=%04x, DCB size=%04x " + "SRB size=%04x\n", + acb, acb->dcb_map, acb->srb_array, sizeof(struct AdapterCtlBlk), + sizeof(struct DeviceCtlBlk), sizeof(struct ScsiReqBlk)); + return 0; failed: - if (host) - scsi_host_put(host); - return NULL; + if (acb->irq_level) + free_irq(acb->irq_level, acb); + if (acb->io_port_base) + release_region(acb->io_port_base, acb->io_port_len); + adapter_sg_tables_free(acb); + free_tracebufs(acb); + + return 1; } -#undef SEARCH -#undef YESNO -#undef SCANF + +/** + * adapter_uninit_chip - cleanly shut down the scsi controller chip, + * stopping all operations and disabling interrupt generation on the + * card. + * + * @acb: The adapter which we are to shutdown. + **/ +static +void adapter_uninit_chip(struct AdapterCtlBlk *acb) +{ + /* disable interrupts */ + DC395x_write8(acb, TRM_S1040_DMA_INTEN, 0); + DC395x_write8(acb, TRM_S1040_SCSI_INTEN, 0); + + /* reset the scsi bus */ + if (acb->config & HCC_SCSI_RESET) + reset_scsi_bus(acb); + + /* clear any pending interupt state */ + DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS); +} + + + +/** + * adapter_uninit - Shut down the chip and release any resources that + * we had allocated. Once this returns the adapter should not be used + * anymore. + * + * @acb: The adapter which we are to un-initialize. + **/ +static +void adapter_uninit(struct AdapterCtlBlk *acb) +{ + unsigned long flags; + DC395x_LOCK_IO(acb->scsi_host, flags); + + /* remove timers */ + if (timer_pending(&acb->waiting_timer)) + del_timer(&acb->waiting_timer); + if (timer_pending(&acb->selto_timer)) + del_timer(&acb->selto_timer); + + adapter_uninit_chip(acb); + adapter_remove_and_free_all_devices(acb); + DC395x_UNLOCK_IO(acb->scsi_host, flags); + + if (acb->irq_level) + free_irq(acb->irq_level, acb); + if (acb->io_port_base) + release_region(acb->io_port_base, acb->io_port_len); + + adapter_sg_tables_free(acb); + free_tracebufs(acb); +} /* @@ -5500,6 +5636,7 @@ failed: #undef SPRINTF #define SPRINTF(args...) pos += sprintf(pos, args) +#undef YESNO #define YESNO(YN) \ if (YN) SPRINTF(" Yes ");\ else SPRINTF(" No ") @@ -5526,7 +5663,7 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o SPRINTF("SCSI Host Nr %i, ", host->host_no); SPRINTF("DC395U/UW/F DC315/U %s\n", (acb->config & HCC_WIDE_CARD) ? "Wide" : ""); - SPRINTF("IOPortBase 0x%04x, ", acb->IOPortBase); + SPRINTF("io_port_base 0x%04x, ", acb->io_port_base); SPRINTF("irq_level 0x%02x, ", acb->irq_level); SPRINTF(" SelTimeout %ims\n", (1638 * acb->sel_timeout) / 1000); @@ -5633,84 +5770,6 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o } -/** - * chip_shutdown - cleanly shut down the scsi controller chip, - * stopping all operations and disablig interrupt generation on the - * card. - * - * @acb: The scsi adapter control block of the adapter to shut down. - **/ -static -void chip_shutdown(struct AdapterCtlBlk *acb) -{ - /* disable interrupt */ - DC395x_write8(acb, TRM_S1040_DMA_INTEN, 0); - DC395x_write8(acb, TRM_S1040_SCSI_INTEN, 0); - - /* remove timers */ - if (timer_pending(&acb->waiting_timer)) - del_timer(&acb->waiting_timer); - if (timer_pending(&acb->selto_timer)) - del_timer(&acb->selto_timer); - - /* reset the scsi bus */ - if (acb->config & HCC_SCSI_RESET) - reset_scsi_bus(acb); - - /* clear any pending interupt state */ - DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS); - - /* release chip resources */ -#if debug_enabled(DBG_TRACE|DBG_TRACEALL) - free_tracebufs(acb, DC395x_MAX_SRB_CNT); -#endif - free_sg_tables(acb, DC395x_MAX_SRB_CNT); -} - - -/** - * free_dcbs - Free all of the DCBs. - * - * @acb: Adapter to remove the DCBs for. - **/ -static -void free_dcbs(struct AdapterCtlBlk* acb) -{ - struct DeviceCtlBlk *dcb; - struct DeviceCtlBlk *tmp; - - dprintkdbg(DBG_DCB, "Free %i DCBs\n", list_size(&acb->dcb_list)); - - list_for_each_entry_safe(dcb, tmp, &acb->dcb_list, list) { - dprintkdbg(DBG_DCB, "Free DCB (ID %i, LUN %i): %p\n", - dcb->target_id, dcb->target_lun, dcb); - remove_dev(acb, dcb); - } -} - -/** - * host_release - shutdown device and release resources that were - * allocate for it. Called once for each card as it is shutdown. - * - * @host: The adapter instance to shutdown. - **/ -static -void host_release(struct Scsi_Host *host) -{ - struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)(host->hostdata); - unsigned long flags; - - dprintkl(KERN_DEBUG, "DC395x release\n"); - - DC395x_LOCK_IO(acb->scsi_host, flags); - chip_shutdown(acb); - free_dcbs(acb); - - free_irq(host->irq, acb); - release_region(host->io_port, host->n_io_port); - - DC395x_UNLOCK_IO(acb->scsi_host, flags); -} /* @@ -5737,6 +5796,22 @@ static Scsi_Host_Template dc395x_driver_template = { /** + * banner_display - Display banner on first instance of driver + * initialized. + **/ +static +void banner_display(void) +{ + static int banner_done = 0; + if (!banner_done) + { + dprintkl(KERN_INFO, "%s %s\n", DC395X_BANNER, DC395X_VERSION); + banner_done = 1; + } +} + + +/** * dc395x_init_one - Initialise a single instance of the adapter. * * The PCI layer will call this once for each instance of the adapter @@ -5753,51 +5828,55 @@ static int __devinit dc395x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - unsigned int io_port; - u8 irq; struct Scsi_Host *scsi_host; - static int banner_done = 0; - int error = 0; - - dprintkdbg(DBG_0, "Init one instance of the dc395x\n"); - if (!banner_done) - { - dprintkl(KERN_INFO, "%s %s\n", DC395X_BANNER, DC395X_VERSION); - banner_done = 1; - } + struct AdapterCtlBlk *acb; + unsigned int io_port_base; + unsigned int io_port_len; + u8 irq; + + dprintkdbg(DBG_0, "Init one instance (%s)\n", pci_name(dev)); + banner_display(); if (pci_enable_device(dev)) { dprintkl(KERN_INFO, "PCI Enable device failed.\n"); return -ENODEV; } - - dprintkdbg(DBG_0, "Get resources...\n"); - io_port = pci_resource_start(dev, 0) & PCI_BASE_ADDRESS_IO_MASK; + io_port_base = pci_resource_start(dev, 0) & PCI_BASE_ADDRESS_IO_MASK; + io_port_len = pci_resource_len(dev, 0); irq = dev->irq; - dprintkdbg(DBG_0, "IO_PORT=%04x,IRQ=%x\n", (unsigned int) io_port, irq); + dprintkdbg(DBG_0, "IO_PORT=%04x, IRQ=%x\n", io_port_base, dev->irq); - scsi_host = host_init(&dc395x_driver_template, io_port, irq); - if (!scsi_host) - { - dprintkdbg(DBG_0, "host_init failed\n"); + /* allocate scsi host information (includes out adapter) */ + scsi_host = scsi_host_alloc(&dc395x_driver_template, + sizeof(struct AdapterCtlBlk)); + if (!scsi_host) { + dprintkl(KERN_INFO, "scsi_host_alloc failed\n"); return -ENOMEM; } - ((struct AdapterCtlBlk *)(scsi_host->hostdata))->dev = dev; + acb = (struct AdapterCtlBlk*)scsi_host->hostdata; + acb->scsi_host = scsi_host; + + /* initialise the adapter and everything we need */ + if (adapter_init(acb, io_port_base, io_port_len, irq)) { + dprintkl(KERN_INFO, "DC395x_initAdapter initial ERROR\n"); + scsi_host_put(scsi_host); + return -ENODEV; + } + pci_set_master(dev); - pci_set_drvdata(dev, scsi_host); /* get the scsi mid level to scan for new devices on the bus */ - error = scsi_add_host(scsi_host, &dev->dev); - if (error) { + if (scsi_add_host(scsi_host, &dev->dev)) { dprintkl(KERN_ERR, "scsi_add_host failed\n"); - error = -ENODEV; - host_release(scsi_host); + adapter_uninit(acb); scsi_host_put(scsi_host); - } else - scsi_scan_host(scsi_host); + return -ENODEV; + } + pci_set_drvdata(dev, scsi_host); + scsi_scan_host(scsi_host); - return error; + return 0; } @@ -5809,16 +5888,14 @@ int __devinit dc395x_init_one(struct pci_dev *dev, **/ static void __devexit dc395x_remove_one(struct pci_dev *dev) { - struct Scsi_Host *host = pci_get_drvdata(dev); + struct Scsi_Host *scsi_host = pci_get_drvdata(dev); + struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)(scsi_host->hostdata); dprintkdbg(DBG_0, "Removing instance\n"); - if (!host) { - dprintkl(KERN_ERR, "no host allocated\n"); - return; - } - scsi_remove_host(host); - host_release(host); - scsi_host_put(host); + + scsi_remove_host(scsi_host); + adapter_uninit(acb); + scsi_host_put(scsi_host); pci_set_drvdata(dev, NULL); } diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 19b77daaf4ee..6ffd2df205b6 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -4990,7 +4990,7 @@ static int ioc_resetdrv(unsigned long arg, char *cmnd) cmd.u.cache.DeviceNo = res.number; #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev); + srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) return -ENOMEM; srp->sr_cmd_len = 12; @@ -5091,7 +5091,7 @@ static int ioc_general(unsigned long arg, char *cmnd) #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev); + srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) return -ENOMEM; srp->sr_cmd_len = 12; @@ -5164,7 +5164,7 @@ static int ioc_hdrlist(unsigned long arg, char *cmnd) #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev); + srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) return -ENOMEM; srp->sr_cmd_len = 12; @@ -5253,7 +5253,7 @@ static int ioc_rescan(unsigned long arg, char *cmnd) #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev); + srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) return -ENOMEM; srp->sr_cmd_len = 12; @@ -5631,7 +5631,7 @@ static void gdth_flush(int hanum) #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev); + srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) return; srp->sr_cmd_len = 12; @@ -5727,7 +5727,7 @@ void gdth_halt(void) TRACE2(("gdth_halt(): reset controller %d\n", hanum)); #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev); + srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) { #if LINUX_VERSION_CODE >= 0x020100 unregister_reboot_notifier(&gdth_notifier); diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c index 9c4485b2fd1c..ef67f26855fd 100644 --- a/drivers/scsi/gdth_proc.c +++ b/drivers/scsi/gdth_proc.c @@ -44,7 +44,7 @@ static int gdth_set_info(char *buffer,int length,int hanum,int busnum) #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_request(sdev); + scp = scsi_allocate_request(sdev, GFP_KERNEL); if (!scp) return -ENOMEM; scp->sr_cmd_len = 12; @@ -797,7 +797,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset, #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_request(sdev); + scp = scsi_allocate_request(sdev, GFP_KERNEL); if (!scp) return -ENOMEM; scp->sr_cmd_len = 12; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index b270dac4e2d2..b631105fbdb2 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -627,7 +627,6 @@ static ide_driver_t idescsi_driver = { .version = IDESCSI_VERSION, .media = ide_scsi, .busy = 0, - .supports_dma = 1, .supports_dsc_overlap = 0, .attach = idescsi_attach, .cleanup = idescsi_cleanup, diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index 3c8377c3aa48..bcee9b28fbfe 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -86,6 +86,7 @@ int imm_release(struct Scsi_Host *host) int host_no = host->unique_id; printk("Releasing imm%i\n", host_no); + scsi_unregister(host); parport_unregister_device(imm_hosts[host_no].dev); return 0; } diff --git a/drivers/scsi/imm.h b/drivers/scsi/imm.h index c00f1539a43f..4b5b28f965fd 100644 --- a/drivers/scsi/imm.h +++ b/drivers/scsi/imm.h @@ -100,7 +100,6 @@ static char *IMM_MODE_STRING[] = [IMM_NIBBLE] = "SPP", [IMM_PS2] = "PS/2", [IMM_EPP_8] = "EPP 8 bit", - [IMM_EPP_16] = "EPP 16 bit", #ifdef CONFIG_SCSI_IZIP_EPP16 [IMM_EPP_16] = "EPP 16 bit", #else diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 46b0069406e9..7213e6263642 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -199,7 +199,7 @@ MODULE_PARM(ips, "s"); #define IPS_VERSION_LOW ".90-BETA" #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__) -#error "This driver has only been tested on the x86/ia64/x86_64 platforms" +#warning "This driver has only been tested on the x86/ia64/x86_64 platforms" #endif #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) @@ -284,9 +284,9 @@ IPS_DEFINE_COMPAT_TABLE( Compatable ); /* Version Compatability Table */ /* This table describes all ServeRAID Adapters */ static struct pci_device_id ips_pci_table[] = { { 0x1014, 0x002E, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, - { 0x1014, 0x01BD, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, - { 0x9005, 0x0250, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, - { 0, } + { 0x1014, 0x01BD, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, + { 0x9005, 0x0250, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, + { 0, } }; MODULE_DEVICE_TABLE( pci, ips_pci_table ); @@ -300,7 +300,7 @@ struct pci_driver ips_pci_driver = { .name = ips_hot_plug_name, .id_table = ips_pci_table, .probe = ips_insert_device, - .remove = __devexit_p(ips_remove_device), + .remove = __devexit_p(ips_remove_device), }; diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index f0e8d85e6500..4fa1a9955ddf 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -4357,19 +4357,6 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) } cp->cmd = cmd; - /*--------------------------------------------------- - ** - ** Enable tagged queue if asked by scsi ioctl - ** - **---------------------------------------------------- - */ -#if 0 /* This stuff was only useful for linux-1.2.13 */ - if (lp && !lp->numtags && cmd->device && cmd->device->tagged_queue) { - lp->numtags = tp->usrtags; - ncr_setup_tags (np, cmd->device->id, cmd->device->lun); - } -#endif - /*---------------------------------------------------- ** ** Build the identify / tag / sdtr message diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 48afbdd2faa8..c6bfb85db04b 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -316,7 +316,7 @@ static Scsi_Request * osst_do_scsi(Scsi_Request *SRpnt, OS_Scsi_Tape *STp, static int repeat = 0; #endif if (SRpnt == NULL) { - if ((SRpnt = scsi_allocate_request(STp->device)) == NULL) { + if ((SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC)) == NULL) { printk(KERN_ERR "%s:E: Can't get SCSI request.\n", tape_name(STp)); if (signal_pending(current)) (STp->buffer)->syscall_result = (-EINTR); diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig index 4cadd40bca98..4eda8c41cff5 100644 --- a/drivers/scsi/pcmcia/Kconfig +++ b/drivers/scsi/pcmcia/Kconfig @@ -3,7 +3,7 @@ # menu "PCMCIA SCSI adapter support" - depends on SCSI!=n && PCMCIA!=n + depends on SCSI!=n && PCMCIA!=n && MODULES config PCMCIA_AHA152X tristate "Adaptec AHA152X PCMCIA support" diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index bd05b2a7268f..5de0a6329d8a 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -331,11 +331,17 @@ */ #define QL1280_LUN_SUPPORT 0 #define WATCHDOGTIMER 0 -#define MEMORY_MAPPED_IO 1 + #define DEBUG_QLA1280_INTR 0 #define DEBUG_PRINT_NVRAM 0 #define DEBUG_QLA1280 0 +#ifdef CONFIG_SCSI_QLOGIC_1280_PIO +#define MEMORY_MAPPED_IO 0 +#else +#define MEMORY_MAPPED_IO 1 +#endif + #define UNIQUE_FW_NAME #include "qla1280.h" #include "ql12160_fw.h" /* ISP RISC codes */ @@ -3649,7 +3655,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); /* Enable simple tag queuing if device supports it. */ - if (cmd->device->tagged_queue) + if (cmd->device->simple_tags) pkt->control_flags |= cpu_to_le16(BIT_3); /* Load SCSI command packet. */ @@ -3949,7 +3955,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); /* Enable simple tag queuing if device supports it. */ - if (cmd->device->tagged_queue) + if (cmd->device->simple_tags) pkt->control_flags |= cpu_to_le16(BIT_3); /* Load SCSI command packet. */ @@ -4909,7 +4915,7 @@ qla12160_get_target_parameters(struct scsi_qla_host *ha, Scsi_Device *device) } else printk(" Async"); - if (device->tagged_queue) + if (device->simple_tags) printk(", Tagged queuing: depth %d", device->queue_depth); printk("\n"); } diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index d5894886fcea..cda15b271b21 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -113,26 +113,21 @@ const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = { * * Purpose: Allocate a request descriptor. * - * Arguments: device - device for which we want a request + * Arguments: device - device for which we want a request + * gfp_mask - allocation flags passed to kmalloc * * Lock status: No locks assumed to be held. This function is SMP-safe. * * Returns: Pointer to request block. - * - * Notes: With the new queueing code, it becomes important - * to track the difference between a command and a - * request. A request is a pending item in the queue that - * has not yet reached the top of the queue. - * - * XXX(hch): Need to add a gfp_mask argument. */ -struct scsi_request *scsi_allocate_request(struct scsi_device *sdev) +struct scsi_request *scsi_allocate_request(struct scsi_device *sdev, + int gfp_mask) { const int offset = ALIGN(sizeof(struct scsi_request), 4); const int size = offset + sizeof(struct request); struct scsi_request *sreq; - sreq = kmalloc(size, GFP_ATOMIC); + sreq = kmalloc(size, gfp_mask); if (likely(sreq != NULL)) { memset(sreq, 0, size); sreq->sr_request = (struct request *)(((char *)sreq) + offset); @@ -1006,9 +1001,12 @@ static int __init init_scsi(void) error = scsi_init_hosts(); if (error) goto cleanup_devlist; - error = scsi_sysfs_register(); + error = scsi_init_sysctl(); if (error) goto cleanup_hosts; + error = scsi_sysfs_register(); + if (error) + goto cleanup_sysctl; for (i = 0; i < NR_CPUS; i++) INIT_LIST_HEAD(&done_q[i]); @@ -1018,6 +1016,8 @@ static int __init init_scsi(void) printk(KERN_NOTICE "SCSI subsystem initialized\n"); return 0; +cleanup_sysctl: + scsi_exit_sysctl(); cleanup_hosts: scsi_exit_hosts(); cleanup_devlist: @@ -1034,6 +1034,7 @@ cleanup_queue: static void __exit exit_scsi(void) { scsi_sysfs_unregister(); + scsi_exit_sysctl(); scsi_exit_hosts(); scsi_exit_devinfo(); devfs_remove("scsi"); diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 8424c445c6b7..4b5a903704b4 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -381,6 +381,7 @@ int scsi_get_device_flags(unsigned char *vendor, unsigned char *model) return scsi_default_dev_flags; } +#ifdef CONFIG_SCSI_PROC_FS /* * proc_scsi_dev_info_read: dump the scsi_dev_info_list via * /proc/scsi/device_info @@ -451,6 +452,7 @@ out: free_page((unsigned long)buffer); return err; } +#endif /* CONFIG_SCSI_PROC_FS */ module_param_string(dev_flags, scsi_dev_flags, sizeof(scsi_dev_flags), 0); MODULE_PARM_DESC(dev_flags, @@ -471,7 +473,9 @@ void scsi_exit_devinfo(void) struct list_head *lh, *lh_next; struct scsi_dev_info_list *devinfo; +#ifdef CONFIG_SCSI_PROC_FS remove_proc_entry("scsi/device_info", 0); +#endif list_for_each_safe(lh, lh_next, &scsi_dev_info_list) { devinfo = list_entry(lh, struct scsi_dev_info_list, @@ -490,7 +494,9 @@ void scsi_exit_devinfo(void) **/ int scsi_init_devinfo(void) { +#ifdef CONFIG_SCSI_PROC_FS struct proc_dir_entry *p; +#endif int error, i; error = scsi_dev_info_list_add_str(scsi_dev_flags); @@ -507,6 +513,7 @@ int scsi_init_devinfo(void) goto out; } +#ifdef CONFIG_SCSI_PROC_FS p = create_proc_entry("scsi/device_info", 0, NULL); if (!p) { error = -ENOMEM; @@ -516,6 +523,7 @@ int scsi_init_devinfo(void) p->owner = THIS_MODULE; p->get_info = proc_scsi_devinfo_read; p->write_proc = proc_scsi_devinfo_write; +#endif /* CONFIG_SCSI_PROC_FS */ out: if (error) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 6e4906ab2241..fce6a580363c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1339,7 +1339,7 @@ static void scsi_eh_lock_done(struct scsi_cmnd *scmd) **/ static void scsi_eh_lock_door(struct scsi_device *sdev) { - struct scsi_request *sreq = scsi_allocate_request(sdev); + struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); if (unlikely(!sreq)) { printk(KERN_ERR "%s: request allocate failed," diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 3dfdcf1f5bc8..53d4b5dd5344 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -98,7 +98,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); - sreq = scsi_allocate_request(sdev); + sreq = scsi_allocate_request(sdev, GFP_KERNEL); if (!sreq) { printk("SCSI internal ioctl failed, no memory\n"); return -ENOMEM; @@ -321,7 +321,7 @@ int scsi_ioctl_send_command(struct scsi_device *sdev, break; } - sreq = scsi_allocate_request(sdev); + sreq = scsi_allocate_request(sdev, GFP_KERNEL); if (!sreq) { result = -EINTR; goto error; @@ -408,30 +408,6 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void *arg) return 0; case SCSI_IOCTL_GET_BUS_NUMBER: return put_user(sdev->host->host_no, (int *)arg); - /* - * The next two ioctls either need to go or need to be changed to - * pass tagged queueing changes through the low level drivers. - * Simply enabling or disabling tagged queueing without the knowledge - * of the low level driver is a *BAD* thing. - * - * Oct. 10, 2002 - Doug Ledford <dledford@redhat.com> - */ - case SCSI_IOCTL_TAGGED_ENABLE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (!sdev->tagged_supported) - return -EINVAL; - sdev->tagged_queue = 1; - sdev->current_tag = 1; - return 0; - case SCSI_IOCTL_TAGGED_DISABLE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (!sdev->tagged_supported) - return -EINVAL; - sdev->tagged_queue = 0; - sdev->current_tag = 0; - return 0; case SCSI_IOCTL_PROBE_HOST: return ioctl_probe(sdev->host, arg); case SCSI_IOCTL_SEND_COMMAND: diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 415be0cf47b0..e9e374cbdb4f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1454,7 +1454,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, unsigned char *buffer, int len, int timeout, int retries, struct scsi_mode_data *data) { - struct scsi_request *sreq = scsi_allocate_request(sdev); + struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); int ret; if (!sreq) diff --git a/drivers/scsi/scsi_logging.h b/drivers/scsi/scsi_logging.h index a282c84c8ef5..b0a31a11ffcf 100644 --- a/drivers/scsi/scsi_logging.h +++ b/drivers/scsi/scsi_logging.h @@ -37,39 +37,23 @@ #define SCSI_LOG_HLCOMPLETE_BITS 3 #define SCSI_LOG_IOCTL_BITS 3 +extern unsigned int scsi_logging_level; #ifdef CONFIG_SCSI_LOGGING -extern unsigned int scsi_logging_level; #define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) \ { \ unsigned int mask = (1 << (BITS)) - 1; \ if (((scsi_logging_level >> (SHIFT)) & mask) > (LEVEL)) \ (CMD); \ } - -#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL) \ -{ \ - unsigned int mask = ((1 << (BITS)) - 1) << SHIFT; \ - scsi_logging_level = ((scsi_logging_level & ~mask) \ - | ((LEVEL << SHIFT) & mask)); \ -} #else -/* - * With no logging enabled, stub these out so they don't do anything. - */ #define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) -#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL) #endif /* CONFIG_SCSI_LOGGING */ /* * These are the macros that are actually used throughout the code to * log events. If logging isn't enabled, they are no-ops and will be * completely absent from the user's code. - * - * The 'set' versions of the macros are really intended to only be called - * from the /proc filesystem, and in production kernels this will be about - * all that is ever used. It could be useful in a debugging environment to - * bump the logging level when certain strange events are detected, however. */ #define SCSI_LOG_ERROR_RECOVERY(LEVEL,CMD) \ SCSI_CHECK_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL,CMD); @@ -92,26 +76,4 @@ extern unsigned int scsi_logging_level; #define SCSI_LOG_IOCTL(LEVEL,CMD) \ SCSI_CHECK_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL,CMD); - -#define SCSI_SET_ERROR_RECOVERY_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL); -#define SCSI_SET_TIMEOUT_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_TIMEOUT_SHIFT, SCSI_LOG_TIMEOUT_BITS, LEVEL); -#define SCSI_SET_SCAN_BUS_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_SCAN_SHIFT, SCSI_LOG_SCAN_BITS, LEVEL); -#define SCSI_SET_MLQUEUE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS, LEVEL); -#define SCSI_SET_MLCOMPLETE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_MLCOMPLETE_SHIFT, SCSI_LOG_MLCOMPLETE_BITS, LEVEL); -#define SCSI_SET_LLQUEUE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_LLQUEUE_SHIFT, SCSI_LOG_LLQUEUE_BITS, LEVEL); -#define SCSI_SET_LLCOMPLETE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_LLCOMPLETE_SHIFT, SCSI_LOG_LLCOMPLETE_BITS, LEVEL); -#define SCSI_SET_HLQUEUE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, LEVEL); -#define SCSI_SET_HLCOMPLETE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_HLCOMPLETE_SHIFT, SCSI_LOG_HLCOMPLETE_BITS, LEVEL); -#define SCSI_SET_IOCTL_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL); - #endif /* _SCSI_LOGGING_H */ diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 8608752c0fa4..62123cefb4c3 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -1,6 +1,17 @@ #ifndef _SCSI_PRIV_H #define _SCSI_PRIV_H +#include <linux/config.h> +#include <linux/device.h> + +struct request_queue; +struct scsi_cmnd; +struct scsi_device; +struct scsi_host_template; +struct scsi_request; +struct Scsi_Host; + + /* * These are the values that the owner field can take. * They are used as an indication of who the command belongs to. @@ -98,7 +109,7 @@ extern int scsi_init_queue(void); extern void scsi_exit_queue(void); /* scsi_proc.c */ -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS extern void scsi_proc_hostdir_add(struct scsi_host_template *); extern void scsi_proc_hostdir_rm(struct scsi_host_template *); extern void scsi_proc_host_add(struct Scsi_Host *); @@ -115,12 +126,21 @@ extern void scsi_exit_procfs(void); #endif /* CONFIG_PROC_FS */ /* scsi_scan.c */ -int scsi_scan_host_selected(struct Scsi_Host *, unsigned int, unsigned int, - unsigned int, int); +extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int, + unsigned int, unsigned int, int); extern void scsi_forget_host(struct Scsi_Host *); extern void scsi_free_sdev(struct scsi_device *); extern void scsi_rescan_device(struct device *); +/* scsi_sysctl.c */ +#ifdef CONFIG_SYSCTL +extern int scsi_init_sysctl(void); +extern void scsi_exit_sysctl(void); +#else +# define scsi_init_sysctl() (0) +# define scsi_exit_sysctl() do { } while (0) +#endif /* CONFIG_SYSCTL */ + /* scsi_sysfs.c */ extern int scsi_device_register(struct scsi_device *); extern int scsi_sysfs_add_host(struct Scsi_Host *); diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index dd8bfd4b36c6..f72dd45bb651 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -37,9 +37,7 @@ /* 4K page size, but our output routines, use some slack for overruns */ #define PROC_BLOCK_SIZE (3*1024) -/* XXX: this shouldn't really be exposed to drivers. */ -struct proc_dir_entry *proc_scsi; -EXPORT_SYMBOL(proc_scsi); +static struct proc_dir_entry *proc_scsi; /* Protect sht->present and sht->proc_dir */ static DECLARE_MUTEX(global_host_template_sem); @@ -235,106 +233,28 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, char *buffer, *p; int err; - if (!buf || length>PAGE_SIZE) + if (!buf || length > PAGE_SIZE) return -EINVAL; buffer = (char *)__get_free_page(GFP_KERNEL); if (!buffer) return -ENOMEM; - if (copy_from_user(buffer, buf, length)) { - err =-EFAULT; + + err = -EFAULT; + if (copy_from_user(buffer, buf, length)) goto out; - } err = -EINVAL; - if (length < PAGE_SIZE) buffer[length] = '\0'; else if (buffer[PAGE_SIZE-1]) goto out; - if (length < 11 || strncmp("scsi", buffer, 4)) - goto out; - -#ifdef CONFIG_SCSI_LOGGING - /* - * Usage: echo "scsi log token #N" > /proc/scsi/scsi - * where token is one of [error,scan,mlqueue,mlcomplete,llqueue, - * llcomplete,hlqueue,hlcomplete] - */ - if (!strncmp("log", buffer + 5, 3)) { - char *token; - unsigned int level; - - p = buffer + 9; - token = p; - while (*p != ' ' && *p != '\t' && *p != '\0') { - p++; - } - - if (*p == '\0') { - if (strncmp(token, "all", 3) == 0) { - /* - * Turn on absolutely everything. - */ - scsi_logging_level = ~0; - } else if (strncmp(token, "none", 4) == 0) { - /* - * Turn off absolutely everything. - */ - scsi_logging_level = 0; - } else { - goto out; - } - } else { - *p++ = '\0'; - - level = simple_strtoul(p, NULL, 0); - - /* - * Now figure out what to do with it. - */ - if (strcmp(token, "error") == 0) { - SCSI_SET_ERROR_RECOVERY_LOGGING(level); - } else if (strcmp(token, "timeout") == 0) { - SCSI_SET_TIMEOUT_LOGGING(level); - } else if (strcmp(token, "scan") == 0) { - SCSI_SET_SCAN_BUS_LOGGING(level); - } else if (strcmp(token, "mlqueue") == 0) { - SCSI_SET_MLQUEUE_LOGGING(level); - } else if (strcmp(token, "mlcomplete") == 0) { - SCSI_SET_MLCOMPLETE_LOGGING(level); - } else if (strcmp(token, "llqueue") == 0) { - SCSI_SET_LLQUEUE_LOGGING(level); - } else if (strcmp(token, "llcomplete") == 0) { - SCSI_SET_LLCOMPLETE_LOGGING(level); - } else if (strcmp(token, "hlqueue") == 0) { - SCSI_SET_HLQUEUE_LOGGING(level); - } else if (strcmp(token, "hlcomplete") == 0) { - SCSI_SET_HLCOMPLETE_LOGGING(level); - } else if (strcmp(token, "ioctl") == 0) { - SCSI_SET_IOCTL_LOGGING(level); - } else { - goto out; - } - } - - printk(KERN_INFO "scsi logging level set to 0x%8.8x\n", scsi_logging_level); - } -#endif /* CONFIG_SCSI_LOGGING */ - /* * Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi * with "0 1 2 3" replaced by your "Host Channel Id Lun". - * Consider this feature BETA. - * CAUTION: This is not for hotplugging your peripherals. As - * SCSI was not designed for this you could damage your - * hardware ! - * However perhaps it is legal to switch on an - * already connected device. It is perhaps not - * guaranteed this device doesn't corrupt an ongoing data transfer. */ - if (!strncmp("add-single-device", buffer + 5, 17)) { + if (!strncmp("scsi add-single-device", buffer, 22)) { p = buffer + 23; host = simple_strtoul(p, &p, 0); @@ -345,18 +265,12 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, err = scsi_add_single_device(host, channel, id, lun); if (err >= 0) err = length; + /* * Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi * with "0 1 2 3" replaced by your "Host Channel Id Lun". - * - * Consider this feature pre-BETA. - * - * CAUTION: This is not for hotplugging your peripherals. As - * SCSI was not designed for this you could damage your - * hardware and thoroughly confuse the SCSI subsystem. - * */ - } else if (!strncmp("remove-single-device", buffer + 5, 20)) { + } else if (!strncmp("scsi remove-single-device", buffer, 25)) { p = buffer + 26; host = simple_strtoul(p, &p, 0); @@ -366,8 +280,8 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, err = scsi_remove_single_device(host, channel, id, lun); } -out: - + + out: free_page((unsigned long)buffer); return err; } diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index cef0c4467a92..65807367d046 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -30,6 +30,7 @@ #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/blkdev.h> +#include <asm/semaphore.h> #include "scsi.h" #include "hosts.h" @@ -94,6 +95,13 @@ MODULE_PARM_DESC(max_report_luns, " between 1 and 16384)"); #endif +/* + * This mutex serializes all scsi scanning activity from kernel- and + * userspace. It could easily be made per-host but I'd like to avoid + * the overhead for now. + */ +static DECLARE_MUTEX(scsi_scan_mutex); + /** * scsi_unlock_floptical - unlock device via a special MODE SENSE command * @sreq: used to send the command @@ -685,7 +693,7 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host, sdev = scsi_alloc_sdev(host, channel, id, lun); if (!sdev) goto out; - sreq = scsi_allocate_request(sdev); + sreq = scsi_allocate_request(sdev, GFP_ATOMIC); if (!sreq) goto out_free_sdev; result = kmalloc(256, GFP_ATOMIC | @@ -898,7 +906,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, if (bflags & BLIST_NOLUN) return 0; - sreq = scsi_allocate_request(sdev); + sreq = scsi_allocate_request(sdev, GFP_ATOMIC); if (!sreq) goto out; @@ -1067,9 +1075,12 @@ struct scsi_device *scsi_add_device(struct Scsi_Host *shost, struct scsi_device *sdev; int res; + down(&scsi_scan_mutex); res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, &sdev, 1); if (res != SCSI_SCAN_LUN_PRESENT) sdev = ERR_PTR(-ENODEV); + up(&scsi_scan_mutex); + return sdev; } @@ -1191,11 +1202,14 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) return -EINVAL; + down(&scsi_scan_mutex); if (channel == SCAN_WILD_CARD) for (channel = 0; channel <= shost->max_channel; channel++) scsi_scan_channel(shost, channel, id, lun, rescan); else scsi_scan_channel(shost, channel, id, lun, rescan); + up(&scsi_scan_mutex); + return 0; } diff --git a/drivers/scsi/scsi_sysctl.c b/drivers/scsi/scsi_sysctl.c new file mode 100644 index 000000000000..04d06c25132b --- /dev/null +++ b/drivers/scsi/scsi_sysctl.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2003 Christoph Hellwig. + * Released under GPL v2. + */ + +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/sysctl.h> + +#include "scsi_logging.h" + + +static ctl_table scsi_table[] = { + { .ctl_name = DEV_SCSI_LOGGING_LEVEL, + .procname = "logging_level", + .data = &scsi_logging_level, + .maxlen = sizeof(scsi_logging_level), + .mode = 0644, + .proc_handler = &proc_dointvec }, + { } +}; + +static ctl_table scsi_dir_table[] = { + { .ctl_name = DEV_SCSI, + .procname = "scsi", + .mode = 0555, + .child = scsi_table }, + { } +}; + +static ctl_table scsi_root_table[] = { + { .ctl_name = CTL_DEV, + .procname = "dev", + .mode = 0555, + .child = scsi_dir_table }, + { } +}; + +static struct ctl_table_header *scsi_table_header; + +int __init scsi_init_sysctl(void) +{ + scsi_table_header = register_sysctl_table(scsi_root_table, 1); + if (!scsi_table_header) + return -ENOMEM; + return 0; +} + +void scsi_exit_sysctl(void) +{ + unregister_sysctl_table(scsi_table_header); +} diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 2d9c592537b7..2bd0ee80e138 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -370,25 +370,24 @@ static int sd_open(struct inode *inode, struct file *filp) if (!scsi_block_when_processing_errors(sdev)) goto error_out; - if (sdev->removable) { + if (sdev->removable || sdkp->write_prot) check_disk_change(inode->i_bdev); - /* - * If the drive is empty, just let the open fail. - */ - retval = -ENOMEDIUM; - if ((!sdkp->media_present) && !(filp->f_flags & O_NDELAY)) - goto error_out; + /* + * If the drive is empty, just let the open fail. + */ + retval = -ENOMEDIUM; + if (sdev->removable && !sdkp->media_present && + !(filp->f_flags & O_NDELAY)) + goto error_out; - /* - * Similarly, if the device has the write protect tab set, - * have the open fail if the user expects to be able to write - * to the thing. - */ - retval = -EROFS; - if ((sdkp->write_prot) && (filp->f_mode & FMODE_WRITE)) - goto error_out; - } + /* + * If the device has the write protect tab set, have the open fail + * if the user expects to be able to write to the thing. + */ + retval = -EROFS; + if (sdkp->write_prot && (filp->f_mode & FMODE_WRITE)) + goto error_out; /* * It is possible that the disk changing stuff resulted in @@ -1174,7 +1173,7 @@ static int sd_revalidate_disk(struct gendisk *disk) if (!sdp->online) goto out; - sreq = scsi_allocate_request(sdp); + sreq = scsi_allocate_request(sdp, GFP_KERNEL); if (!sreq) { printk(KERN_WARNING "(sd_revalidate_disk:) Request allocation " "failure.\n"); @@ -1355,12 +1354,12 @@ static int sd_remove(struct device *dev) static void sd_shutdown(struct device *dev) { struct scsi_device *sdp = to_scsi_device(dev); - struct scsi_disk *sdkp; + struct scsi_disk *sdkp; struct scsi_request *sreq; int retries, res; - sdkp = dev_get_drvdata(dev); - if (!sdkp) + sdkp = dev_get_drvdata(dev); + if (!sdkp) return; /* this can happen */ if (!sdp->online || !sdkp->WCE) @@ -1369,7 +1368,7 @@ static void sd_shutdown(struct device *dev) printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: ", sdkp->disk->disk_name); - sreq = scsi_allocate_request(sdp); + sreq = scsi_allocate_request(sdp, GFP_KERNEL); if (!sreq) { printk("FAILED\n No memory for request\n"); return; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 813364338aea..0a5497ea2389 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -70,7 +70,7 @@ static int sg_version_num = 30529; /* 2 digits for each component */ #include "scsi_logging.h" -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS #include <linux/proc_fs.h> static int sg_proc_init(void); static void sg_proc_cleanup(void); @@ -222,7 +222,7 @@ static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len); // static void sg_unmap_and(Sg_scatter_hold * schp, int free_also); static Sg_device *sg_get_dev(int dev); static inline unsigned char *sg_scatg2virt(const struct scatterlist *sclp); -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS static int sg_last_dev(void); #endif @@ -680,7 +680,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, sg_finish_rem_req(srp); return -ENODEV; } - SRpnt = scsi_allocate_request(sdp->device); + SRpnt = scsi_allocate_request(sdp->device, GFP_ATOMIC); if (SRpnt == NULL) { SCSI_LOG_TIMEOUT(1, printk("sg_write: no mem\n")); sg_finish_rem_req(srp); @@ -1516,18 +1516,18 @@ init_sg(void) rc = scsi_register_interface(&sg_interface); if (rc) return rc; -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS sg_proc_init(); -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_SCSI_PROC_FS */ return 0; } static void __exit exit_sg(void) { -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS sg_proc_cleanup(); -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_SCSI_PROC_FS */ scsi_unregister_interface(&sg_interface); unregister_chrdev(SCSI_GENERIC_MAJOR, "sg"); if (sg_dev_arr != NULL) { @@ -2225,7 +2225,7 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id) return resp; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS static Sg_request * sg_get_nth_request(Sg_fd * sfp, int nth) { @@ -2317,7 +2317,7 @@ sg_remove_request(Sg_fd * sfp, Sg_request * srp) return res; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS static Sg_fd * sg_get_nth_sfp(Sg_device * sdp, int nth) { @@ -2548,7 +2548,7 @@ sg_allow_access(unsigned char opcode, char dev_type) return 0; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS static int sg_last_dev(void) { @@ -2579,11 +2579,11 @@ sg_get_dev(int dev) return sdp; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS static struct proc_dir_entry *sg_proc_sgp = NULL; -static char sg_proc_sg_dirname[] = "sg"; +static char sg_proc_sg_dirname[] = "scsi/sg"; static int sg_proc_adio_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data); @@ -2657,10 +2657,6 @@ static struct sg_proc_leaf sg_proc_leaf_arr[] = { size : begin + len - offset; \ } while(0) -/* this should _really_ be private to the scsi midlayer. But - /proc/scsi/sg is an established name, so.. */ -extern struct proc_dir_entry *proc_scsi; - static int sg_proc_init(void) { @@ -2670,10 +2666,8 @@ sg_proc_init(void) struct proc_dir_entry *pdep; struct sg_proc_leaf * leaf; - if (!proc_scsi) - return 1; sg_proc_sgp = create_proc_entry(sg_proc_sg_dirname, - S_IFDIR | S_IRUGO | S_IXUGO, proc_scsi); + S_IFDIR | S_IRUGO | S_IXUGO, NULL); if (!sg_proc_sgp) return 1; for (k = 0; k < num_leaves; ++k) { @@ -2696,11 +2690,11 @@ sg_proc_cleanup(void) int num_leaves = sizeof (sg_proc_leaf_arr) / sizeof (sg_proc_leaf_arr[0]); - if ((!proc_scsi) || (!sg_proc_sgp)) + if (!sg_proc_sgp) return; for (k = 0; k < num_leaves; ++k) remove_proc_entry(sg_proc_leaf_arr[k].name, sg_proc_sgp); - remove_proc_entry(sg_proc_sg_dirname, proc_scsi); + remove_proc_entry(sg_proc_sg_dirname, NULL); } static int @@ -2971,7 +2965,7 @@ sg_proc_version_info(char *buffer, int *len, off_t * begin, PRINT_PROC("%d\t%s\n", sg_version_num, sg_version_str); return 1; } -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_SCSI_PROC_FS */ module_init(init_sg); module_exit(exit_sg); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index bbef9a48030f..089510b7a819 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -599,7 +599,7 @@ static void get_sectorsize(struct scsi_cd *cd) buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) goto Enomem; - SRpnt = scsi_allocate_request(cd->device); + SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL); if (!SRpnt) goto Enomem; @@ -713,7 +713,7 @@ static void get_capabilities(struct scsi_cd *cd) }; /* allocate a request for the TEST_UNIT_READY */ - SRpnt = scsi_allocate_request(cd->device); + SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL); if (!SRpnt) { printk(KERN_WARNING "(get_capabilities:) Request allocation " "failure.\n"); diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index 7eb274c0a33d..0416030f717f 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -82,7 +82,7 @@ int sr_do_ioctl(Scsi_CD *cd, struct cdrom_generic_command *cgc) int result, err = 0, retries = 0; SDev = cd->device; - SRpnt = scsi_allocate_request(SDev); + SRpnt = scsi_allocate_request(SDev, GFP_KERNEL); if (!SRpnt) { printk(KERN_ERR "Unable to allocate SCSI request in sr_do_ioctl"); err = -ENOMEM; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 85969cd26c84..ed0a5ab2667b 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -374,7 +374,7 @@ static Scsi_Request * unsigned char *bp; if (SRpnt == NULL) { - SRpnt = scsi_allocate_request(STp->device); + SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC); if (SRpnt == NULL) { DEBC( printk(KERN_ERR "%s: Can't get SCSI request.\n", tape_name(STp)); ); diff --git a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c index c549d49e3c30..a31642785f19 100644 --- a/drivers/scsi/sym53c8xx.c +++ b/drivers/scsi/sym53c8xx.c @@ -6594,19 +6594,6 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) } cp->cmd = cmd; - /*--------------------------------------------------- - ** - ** Enable tagged queue if asked by scsi ioctl - ** - **---------------------------------------------------- - */ -#if 0 /* This stuff was only useful for linux-1.2.13 */ - if (lp && !lp->numtags && cmd->device && cmd->device->tagged_queue) { - lp->numtags = tp->usrtags; - ncr_setup_tags (np, cp->target, cp->lun); - } -#endif - /*---------------------------------------------------- ** ** Build the identify / tag / sdtr message diff --git a/drivers/scsi/sym53c8xx_2/sym_conf.h b/drivers/scsi/sym53c8xx_2/sym_conf.h index 8bc52f731a5a..705ffaadb31f 100644 --- a/drivers/scsi/sym53c8xx_2/sym_conf.h +++ b/drivers/scsi/sym53c8xx_2/sym_conf.h @@ -131,11 +131,6 @@ /* #define SYM_CONF_IARB_SUPPORT */ /* - * Support for some PCI fix-ups (or assumed so). - */ -#define SYM_CONF_PCI_FIX_UP - -/* * Number of lists for the optimization of the IO timeout handling. * Not used under FreeBSD and Linux. */ diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h index 70649d107d6a..f8344b42dfd1 100644 --- a/drivers/scsi/sym53c8xx_2/sym_defs.h +++ b/drivers/scsi/sym53c8xx_2/sym_defs.h @@ -74,8 +74,8 @@ #define PCI_ID_SYM53C896 0xb #define PCI_ID_SYM53C895A 0x12 #define PCI_ID_SYM53C875A 0x13 -#define PCI_ID_LSI53C1010 0x20 -#define PCI_ID_LSI53C1010_2 0x21 +#define PCI_ID_LSI53C1010_33 0x20 +#define PCI_ID_LSI53C1010_66 0x21 #define PCI_ID_LSI53C1510D 0xa /* diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c index bcdd7c5297e0..5b24d1fe9652 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw.c +++ b/drivers/scsi/sym53c8xx_2/sym_fw.c @@ -270,13 +270,13 @@ sym_fw2_patch(hcb_p np) * Remove a couple of work-arounds specific to C1010 if * they are not desirable. See `sym_fw2.h' for more details. */ - if (!(np->device_id == PCI_ID_LSI53C1010_2 && + if (!(np->device_id == PCI_ID_LSI53C1010_66 && np->revision_id < 0x1 && np->pciclk_khz < 60000)) { scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP); scripta0->datao_phase[1] = cpu_to_scr(0); } - if (!(np->device_id == PCI_ID_LSI53C1010 && + if (!(np->device_id == PCI_ID_LSI53C1010_33 && /* np->revision_id < 0xff */ 1)) { scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP); scripta0->sel_done[1] = cpu_to_scr(0); diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index a8cb6c5ad4fe..26dcbea2b562 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -57,7 +57,7 @@ #define NAME53C "sym53c" #define NAME53C8XX "sym53c8xx" -static int __init +static int __devinit pci_get_base_address(struct pci_dev *pdev, int index, u_long *base) { u32 tmp; @@ -77,30 +77,6 @@ pci_get_base_address(struct pci_dev *pdev, int index, u_long *base) #undef PCI_BAR_OFFSET } -/* - * Insert a delay in micro-seconds and milli-seconds. - */ -void sym_udelay(int us) { udelay(us); } -void sym_mdelay(int ms) { mdelay(ms); } - -/* - * SMP threading. - * - * The whole SCSI sub-system under Linux is basically single-threaded. - * Everything, including low-level driver interrupt routine, happens - * with the `io_request_lock' held. - * The sym53c8xx-1.x drivers series ran their interrupt code using a - * spin mutex per controller. This added complexity without improving - * scalability significantly. the sym-2 driver still use a spinlock - * per controller for safety, but basically runs with the damned - * io_request_lock held. - */ - -spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED; - -#define SYM_LOCK_DRIVER(flags) spin_lock_irqsave(&sym53c8xx_lock, flags) -#define SYM_UNLOCK_DRIVER(flags) spin_unlock_irqrestore(&sym53c8xx_lock,flags) - #define SYM_INIT_LOCK_HCB(np) spin_lock_init((np)->s.host->host_lock); #define SYM_LOCK_HCB(np, flags) \ spin_lock_irqsave((np)->s.host->host_lock, flags) @@ -118,6 +94,9 @@ spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED; #define ktime_add(a, o) ((a) + (u_long)(o)) #define ktime_sub(a, o) ((a) - (u_long)(o)) +/* This lock protects only the memory allocation/free. */ +spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED; + /* * Wrappers to the generic memory allocator. */ @@ -125,58 +104,53 @@ void *sym_calloc(int size, char *name) { u_long flags; void *m; - SYM_LOCK_DRIVER(flags); + spin_lock_irqsave(&sym53c8xx_lock, flags); m = sym_calloc_unlocked(size, name); - SYM_UNLOCK_DRIVER(flags); + spin_unlock_irqrestore(&sym53c8xx_lock, flags); return m; } void sym_mfree(void *m, int size, char *name) { u_long flags; - SYM_LOCK_DRIVER(flags); + spin_lock_irqsave(&sym53c8xx_lock, flags); sym_mfree_unlocked(m, size, name); - SYM_UNLOCK_DRIVER(flags); + spin_unlock_irqrestore(&sym53c8xx_lock, flags); } -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING - void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name) { u_long flags; void *m; - SYM_LOCK_DRIVER(flags); + spin_lock_irqsave(&sym53c8xx_lock, flags); m = __sym_calloc_dma_unlocked(dev_dmat, size, name); - SYM_UNLOCK_DRIVER(flags); + spin_unlock_irqrestore(&sym53c8xx_lock, flags); return m; } void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name) { u_long flags; - SYM_LOCK_DRIVER(flags); + spin_lock_irqsave(&sym53c8xx_lock, flags); __sym_mfree_dma_unlocked(dev_dmat, m, size, name); - SYM_UNLOCK_DRIVER(flags); + spin_unlock_irqrestore(&sym53c8xx_lock, flags); } m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m) { u_long flags; m_addr_t b; - SYM_LOCK_DRIVER(flags); + spin_lock_irqsave(&sym53c8xx_lock, flags); b = __vtobus_unlocked(dev_dmat, m); - SYM_UNLOCK_DRIVER(flags); + spin_unlock_irqrestore(&sym53c8xx_lock, flags); return b; } -#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */ - - /* * Map/unmap a PCI memory window. */ #ifndef SYM_OPT_NO_BUS_MEMORY_MAPPING -static u_long __init pci_map_mem(u_long base, u_long size) +static u_long __devinit pci_map_mem(u_long base, u_long size) { u_long page_base = ((u_long) base) & PAGE_MASK; u_long page_offs = ((u_long) base) - page_base; @@ -185,19 +159,13 @@ static u_long __init pci_map_mem(u_long base, u_long size) return page_remapped? (page_remapped + page_offs) : 0UL; } -static void __init pci_unmap_mem(u_long vaddr, u_long size) +static void __devinit pci_unmap_mem(u_long vaddr, u_long size) { if (vaddr) iounmap((void *) (vaddr & PAGE_MASK)); } #endif -/* - * Used to retrieve the host structure when the - * driver is called from the proc FS. - */ -static struct Scsi_Host *first_host = NULL; - #define scsi_data_direction(cmd) (cmd->sc_data_direction) /* @@ -210,11 +178,7 @@ struct host_data { /* * Some type that fit DMA addresses as seen from BUS. */ -#ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING -typedef u_long bus_addr_t; -#else typedef dma_addr_t bus_addr_t; -#endif /* * Used by the eh thread to wait for command completion. @@ -233,10 +197,8 @@ struct sym_eh_wait { */ struct sym_ucmd { /* Override the SCSI pointer structure */ SYM_QUEHEAD link_cmdq; /* Must stay at offset ZERO */ -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING bus_addr_t data_mapping; u_char data_mapped; -#endif struct sym_eh_wait *eh_wait; }; @@ -249,39 +211,18 @@ typedef struct sym_ucmd *ucmd_p; /* * Deal with DMA mapping/unmapping. */ - -#ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING - -/* Linux versions prior to pci bus iommu kernel interface */ - -#define __unmap_scsi_data(pdev, cmd) do {; } while (0) -#define __map_scsi_single_data(pdev, cmd) (__vtobus(pdev,(cmd)->request_buffer)) -#define __map_scsi_sg_data(pdev, cmd) ((cmd)->use_sg) -#define __sync_scsi_data(pdev, cmd) do {; } while (0) - -#define bus_sg_dma_address(sc) vtobus((sc)->address) -#define bus_sg_dma_len(sc) ((sc)->length) - -#else /* Linux version with pci bus iommu kernel interface */ - #define bus_unmap_sg(pdev, sgptr, sgcnt, dir) \ pci_unmap_sg(pdev, sgptr, sgcnt, dir) - #define bus_unmap_single(pdev, mapping, bufptr, dir) \ pci_unmap_single(pdev, mapping, bufptr, dir) - #define bus_map_single(pdev, bufptr, bufsiz, dir) \ pci_map_single(pdev, bufptr, bufsiz, dir) - #define bus_map_sg(pdev, sgptr, sgcnt, dir) \ pci_map_sg(pdev, sgptr, sgcnt, dir) - #define bus_dma_sync_sg(pdev, sgptr, sgcnt, dir) \ pci_dma_sync_sg(pdev, sgptr, sgcnt, dir) - #define bus_dma_sync_single(pdev, mapping, bufsiz, dir) \ pci_dma_sync_single(pdev, mapping, bufsiz, dir) - #define bus_sg_dma_address(sc) sg_dma_address(sc) #define bus_sg_dma_len(sc) sg_dma_len(sc) @@ -345,8 +286,6 @@ static void __sync_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) } } -#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */ - #define unmap_scsi_data(np, cmd) \ __unmap_scsi_data(np->s.device, cmd) #define map_scsi_single_data(np, cmd) \ @@ -1656,13 +1595,13 @@ static int sym_host_info(hcb_p np, char *ptr, off_t offset, int len) copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, " "revision id 0x%x\n", np->s.chip_name, np->device_id, np->revision_id); - copy_info(&info, "On PCI bus %d, device %d, function %d, " + copy_info(&info, "At PCI address %s, " #ifdef __sparc__ "IRQ %s\n", #else "IRQ %d\n", #endif - np->s.bus, (np->s.device_fn & 0xf8) >> 3, np->s.device_fn & 7, + pci_name(np->s.device), #ifdef __sparc__ __irq_itoa(np->s.irq)); #else @@ -1748,7 +1687,6 @@ static void sym_free_resources(hcb_p np) /* * Ask/tell the system about DMA addressing. */ -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING static int sym_setup_bus_dma_mask(hcb_p np) { #if SYM_CONF_DMA_ADDRESSING_MODE == 0 @@ -1780,7 +1718,6 @@ out_err32: sym_name(np)); return -1; } -#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */ /* * Host attach and initialisations. @@ -1791,7 +1728,7 @@ out_err32: * If all is OK, install interrupt handling and * start the timer daemon. */ -static int __init +static int __devinit sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) { struct host_data *host_data; @@ -1802,15 +1739,14 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) struct sym_fw *fw; printk(KERN_INFO - "sym%d: <%s> rev 0x%x on pci bus %d device %d function %d " + "sym%d: <%s> rev 0x%x at pci %s " #ifdef __sparc__ "irq %s\n", #else "irq %d\n", #endif unit, dev->chip.name, dev->chip.revision_id, - dev->s.bus, (dev->s.device_fn & 0xf8) >> 3, - dev->s.device_fn & 7, + pci_name(dev->pdev), #ifdef __sparc__ __irq_itoa(dev->s.irq)); #else @@ -1837,7 +1773,6 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) * We keep track in the HCB of all the resources that * are to be released on error. */ -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING np = __sym_calloc_dma(dev->pdev, sizeof(*np), "HCB"); if (np) { np->s.device = dev->pdev; @@ -1845,11 +1780,7 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) } else goto attach_failed; -#else - np = sym_calloc_dma(sizeof(*np), "HCB"); - if (!np) - goto attach_failed; -#endif + host_data->ncb = np; np->s.host = instance; @@ -1866,8 +1797,6 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) np->s.unit = unit; np->device_id = dev->chip.device_id; np->revision_id = dev->chip.revision_id; - np->s.bus = dev->s.bus; - np->s.device_fn = dev->s.device_fn; np->features = dev->chip.features; np->clock_divn = dev->chip.nr_divisor; np->maxoffs = dev->chip.offset_max; @@ -1883,10 +1812,8 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) /* * Ask/tell the system about DMA addressing. */ -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING if (sym_setup_bus_dma_mask(np)) goto attach_failed; -#endif /* * Try to map the controller chip to @@ -1987,12 +1914,6 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) sym_timer (np); /* - * Done. - */ - if (!first_host) - first_host = instance; - - /* * Fill Linux host instance structure * and return success. */ @@ -2039,7 +1960,7 @@ attach_failed: * Detect and try to read SYMBIOS and TEKRAM NVRAM. */ #if SYM_CONF_NVRAM_SUPPORT -static void __init sym_get_nvram(sym_device *devp, sym_nvram *nvp) +static void __devinit sym_get_nvram(sym_device *devp, sym_nvram *nvp) { if (!nvp) return; @@ -2087,37 +2008,6 @@ char *sym53c8xx = 0; /* command line passed by insmod */ MODULE_PARM(sym53c8xx, "s"); #endif -static void __init sym53c8xx_print_driver_setup(void) -{ - printf_info (NAME53C8XX ": setup=" - "mpar:%d,spar:%d,tags:%d,sync:%d,burst:%d," - "led:%d,wide:%d,diff:%d,irqm:%d, buschk:%d\n", - sym_driver_setup.pci_parity, - sym_driver_setup.scsi_parity, - sym_driver_setup.max_tag, - sym_driver_setup.min_sync, - sym_driver_setup.burst_order, - sym_driver_setup.scsi_led, - sym_driver_setup.max_wide, - sym_driver_setup.scsi_diff, - sym_driver_setup.irq_mode, - sym_driver_setup.scsi_bus_check); - printf_info (NAME53C8XX ": setup=" - "hostid:%d,offs:%d,luns:%d,pcifix:%d,revprob:%d," - "verb:%d,debug:0x%x,setlle_delay:%d\n", - sym_driver_setup.host_id, - sym_driver_setup.max_offs, - sym_driver_setup.max_lun, - sym_driver_setup.pci_fix_up, - sym_driver_setup.reverse_probe, - sym_driver_setup.verbose, - sym_driver_setup.debug, - sym_driver_setup.settle_delay); -#ifdef DEBUG_2_0_X -MDELAY(5000); -#endif -}; - #define OPT_PCI_PARITY 1 #define OPT_SCSI_PARITY 2 #define OPT_MAX_TAG 3 @@ -2131,15 +2021,13 @@ MDELAY(5000); #define OPT_HOST_ID 11 #define OPT_MAX_OFFS 12 #define OPT_MAX_LUN 13 -#define OPT_PCI_FIX_UP 14 - -#define OPT_REVERSE_PROBE 15 -#define OPT_VERBOSE 16 -#define OPT_DEBUG 17 -#define OPT_SETTLE_DELAY 18 -#define OPT_USE_NVRAM 19 -#define OPT_EXCLUDE 20 -#define OPT_SAFE_SETUP 21 +#define OPT_REVERSE_PROBE 14 +#define OPT_VERBOSE 15 +#define OPT_DEBUG 16 +#define OPT_SETTLE_DELAY 17 +#define OPT_USE_NVRAM 18 +#define OPT_EXCLUDE 19 +#define OPT_SAFE_SETUP 20 static char setup_token[] __initdata = "mpar:" "spar:" @@ -2148,11 +2036,10 @@ static char setup_token[] __initdata = "wide:" "diff:" "irqm:" "buschk:" "hostid:" "offset:" - "luns:" "pcifix:" - "revprob:" "verb:" - "debug:" "settle:" - "nvram:" "excl:" - "safe:" + "luns:" "revprob:" + "verb:" "debug:" + "settle:" "nvram:" + "excl:" "safe:" ; #ifdef MODULE @@ -2239,7 +2126,6 @@ int __init sym53c8xx_setup(char *str) __SIMPLE_OPTION(HOST_ID, host_id) __SIMPLE_OPTION(MAX_OFFS, max_offs) __SIMPLE_OPTION(MAX_LUN, max_lun) - __SIMPLE_OPTION(PCI_FIX_UP, pci_fix_up) __SIMPLE_OPTION(REVERSE_PROBE, reverse_probe) __SIMPLE_OPTION(VERBOSE, verbose) __SIMPLE_OPTION(DEBUG, debug) @@ -2269,19 +2155,16 @@ __setup("sym53c8xx=", sym53c8xx_setup); * boards and save data for attaching after all boards have * been detected. */ -static int __init +static int __devinit sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device) { - u_short vendor_id, device_id, command, status_reg; - u_char cache_line_size; - u_char suggested_cache_line_size = 0; - u_char pci_fix_up = SYM_SETUP_PCI_FIX_UP; + u_short vendor_id, device_id, status_reg; u_char revision; u_int irq; u_long base, base_2; u_long base_c, base_2_c, io_port; int i; - sym_chip *chip; + struct sym_pci_chip *chip; /* Choose some short name for this device */ sprintf(device->s.inst_name, "sym.%d.%d.%d", pdev->bus->number, @@ -2393,25 +2276,6 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device) pci_set_master(pdev); /* - * Read additionnal info from the configuration space. - */ - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size); - - /* - * If cache line size is not configured, suggest - * a value for well known CPUs. - */ -#if defined(__i386__) && !defined(MODULE) - if (!cache_line_size && boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { - switch(boot_cpu_data.x86) { - case 4: suggested_cache_line_size = 4; break; - case 6: if (boot_cpu_data.x86_model > 8) break; - case 5: suggested_cache_line_size = 8; break; - } - } -#endif /* __i386__ */ - - /* * Some features are required to be enabled in order to * work around some chip problems. :) ;) * (ITEM 12 of a DEL about the 896 I haven't yet). @@ -2420,31 +2284,12 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device) */ if (device_id == PCI_DEVICE_ID_NCR_53C896 && revision < 0x4) { chip->features |= (FE_WRIE | FE_CLSE); - pci_fix_up |= 3; /* Force appropriate PCI fix-up */ - } - -#ifdef SYM_CONF_PCI_FIX_UP - /* - * Try to fix up PCI config according to wished features. - */ - if ((pci_fix_up & 1) && (chip->features & FE_CLSE) && - !cache_line_size && suggested_cache_line_size) { - cache_line_size = suggested_cache_line_size; - pci_write_config_byte(pdev, - PCI_CACHE_LINE_SIZE, cache_line_size); - printf_info("%s: PCI_CACHE_LINE_SIZE set to %d.\n", - sym_name(device), cache_line_size); } - pci_read_config_word(pdev, PCI_COMMAND, &command); - if ((pci_fix_up & 2) && cache_line_size && - (chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) { - printf_info("%s: setting PCI_COMMAND_INVALIDATE.\n", - sym_name(device)); - command |= PCI_COMMAND_INVALIDATE; - pci_write_config_word(pdev, PCI_COMMAND, command); + if (chip->features & FE_WRIE) { + if (pci_set_mwi(pdev)) + return -1; } -#endif /* SYM_CONF_PCI_FIX_UP */ /* * Work around for errant bit in 895A. The 66Mhz @@ -2461,8 +2306,7 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device) if (chip->features & FE_66MHZ) { if (!(status_reg & PCI_STATUS_66MHZ)) chip->features &= ~FE_66MHZ; - } - else { + } else { if (status_reg & PCI_STATUS_66MHZ) { status_reg = PCI_STATUS_66MHZ; pci_write_config_word(pdev, PCI_STATUS, status_reg); @@ -2474,8 +2318,6 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device) * Initialise device structure with items required by sym_attach. */ device->pdev = pdev; - device->s.bus = pdev->bus->number; - device->s.device_fn = pdev->devfn; device->s.base = base; device->s.base_2 = base_2; device->s.base_c = base_c; @@ -2487,203 +2329,6 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device) return 0; } -#if 0 -/* - * Detect all 53c8xx hosts and then attach them. - * - * If we are using NVRAM, once all hosts are detected, we need to - * check any NVRAM for boot order in case detect and boot order - * differ and attach them using the order in the NVRAM. - * - * If no NVRAM is found or data appears invalid attach boards in - * the order they are detected. - */ -int __init sym53c8xx_detect(struct scsi_host_template *tpnt) -{ - struct pci_dev *pcidev; - int i, j, chips, hosts, count; - int attach_count = 0; - sym_device *devtbl, *devp; - sym_nvram nvram; -#if SYM_CONF_NVRAM_SUPPORT - sym_nvram nvram0, *nvp; -#endif - - /* - * Initialize driver general stuff. - */ -#ifdef SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT -#ifdef MODULE -if (sym53c8xx) - sym53c8xx_setup(sym53c8xx); -#endif -#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT - sym_debug_flags = sym_driver_setup.debug; -#endif - if (boot_verbose >= 2) - sym53c8xx_print_driver_setup(); -#endif /* SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT */ - - /* - * Allocate the device table since we donnot want to - * overflow the kernel stack. - * 1 x 4K PAGE is enough for more than 40 devices for i386. - */ - devtbl = sym_calloc(PAGE_SIZE, "DEVTBL"); - if (!devtbl) - return 0; - - /* - * Detect all NCR PQS/PDS memory controllers. - */ -#ifdef SYM_CONF_PQS_PDS_SUPPORT - sym_detect_pqs_pds(); -#endif - - /* - * Detect all 53c8xx hosts. - * Save the first Symbios NVRAM content if any - * for the boot order. - */ - chips = sizeof(sym_chip_ids) / sizeof(sym_chip_ids[0]); - hosts = PAGE_SIZE / sizeof(*devtbl); -#if SYM_CONF_NVRAM_SUPPORT - nvp = (sym_driver_setup.use_nvram & 0x1) ? &nvram0 : 0; -#endif - j = 0; - count = 0; - pcidev = NULL; - while (1) { - char *msg = ""; - if (count >= hosts) - break; - if (j >= chips) - break; - i = sym_driver_setup.reverse_probe ? chips - 1 - j : j; - pcidev = pci_find_device(PCI_VENDOR_ID_NCR, sym_chip_ids[i], - pcidev); - if (pcidev == NULL) { - ++j; - continue; - } - /* This one is guaranteed by AC to do nothing :-) */ - if (pci_enable_device(pcidev)) - continue; - devp = &devtbl[count]; - devp->host_id = SYM_SETUP_HOST_ID; - if (sym53c8xx_pci_init(pcidev, devp)) { - continue; - } - ++count; -#if SYM_CONF_NVRAM_SUPPORT - if (nvp) { - sym_get_nvram(devp, nvp); - switch(nvp->type) { - case SYM_SYMBIOS_NVRAM: - /* - * Switch to the other nvram buffer, so that - * nvram0 will contain the first Symbios - * format NVRAM content with boot order. - */ - nvp = &nvram; - msg = "with Symbios NVRAM"; - break; - case SYM_TEKRAM_NVRAM: - msg = "with Tekram NVRAM"; - break; - } - } -#endif -#ifdef SYM_CONF_PQS_PDS_SUPPORT - /* - * Match the BUS number for PQS/PDS devices. - * Read the SCSI ID from a special register mapped - * into the configuration space of the individual - * 875s. This register is set up by the PQS bios - */ - for(i = 0; i < SYM_CONF_MAX_PQS_BUS && pqs_bus[i] != -1; i++) { - u_char tmp; - if (pqs_bus[i] == pcidev->bus->number) { - pci_read_config_byte(pcidev, 0x84, &tmp); - devp->pqs_pds = 1; - devp->host_id = tmp; - break; - } - } - if (devp->pqs_pds) - msg = "(NCR PQS/PDS)"; -#endif - if (boot_verbose) - printf_info("%s: 53c%s detected %s\n", - sym_name(devp), devp->chip.name, msg); - } - - /* - * If we have found a SYMBIOS NVRAM, use first the NVRAM boot - * sequence as device boot order. - * check devices in the boot record against devices detected. - * attach devices if we find a match. boot table records that - * do not match any detected devices will be ignored. - * devices that do not match any boot table will not be attached - * here but will attempt to be attached during the device table - * rescan. - */ -#if SYM_CONF_NVRAM_SUPPORT - if (!nvp || nvram0.type != SYM_SYMBIOS_NVRAM) - goto next; - for (i = 0; i < 4; i++) { - Symbios_host *h = &nvram0.data.Symbios.host[i]; - for (j = 0 ; j < count ; j++) { - devp = &devtbl[j]; - if (h->device_fn != devp->s.device_fn || - h->bus_nr != devp->s.bus || - h->device_id != devp->chip.device_id) - continue; - if (devp->attach_done) - continue; - if (h->flags & SYMBIOS_INIT_SCAN_AT_BOOT) { - sym_get_nvram(devp, nvp); - if (!sym_attach (tpnt, attach_count, devp)) - attach_count++; - } - else if (!(sym_driver_setup.use_nvram & 0x80)) - printf_info( - "%s: 53c%s state OFF thus not attached\n", - sym_name(devp), devp->chip.name); - else - continue; - - devp->attach_done = 1; - break; - } - } -next: -#endif - - /* - * Rescan device list to make sure all boards attached. - * Devices without boot records will not be attached yet - * so try to attach them here. - */ - for (i= 0; i < count; i++) { - devp = &devtbl[i]; - if (!devp->attach_done) { - devp->nvram = &nvram; - nvram.type = 0; -#if SYM_CONF_NVRAM_SUPPORT - sym_get_nvram(devp, nvp); -#endif - if (!sym_attach (tpnt, attach_count, devp)) - attach_count++; - } - } - - sym_mfree(devtbl, PAGE_SIZE, "DEVTBL"); - - return attach_count; -} -#endif - /* * Linux release module stuff. @@ -2717,15 +2362,6 @@ static int sym_detach(hcb_p np) return 1; } -#if 0 -int sym53c8xx_release(struct Scsi_Host *host) -{ - sym_detach(((struct host_data *) host->hostdata)->ncb); - - return 0; -} -#endif - MODULE_LICENSE("Dual BSD/GPL"); /* @@ -2734,10 +2370,6 @@ MODULE_LICENSE("Dual BSD/GPL"); static struct scsi_host_template sym2_template = { .module = THIS_MODULE, .name = "sym53c8xx", -#if 0 - .detect = sym53c8xx_detect, - .release = sym53c8xx_release, -#endif .info = sym53c8xx_info, .queuecommand = sym53c8xx_queue_command, .slave_configure = sym53c8xx_slave_configure, @@ -2839,7 +2471,6 @@ static int __devinit sym2_probe(struct pci_dev *pdev, sym_dev.host_id = SYM_SETUP_HOST_ID; if (sym53c8xx_pci_init(pdev, &sym_dev)) return -ENODEV; - printk(KERN_INFO "%s: 53c%s detected\n", sym_name(&sym_dev), sym_dev.chip.name); sym_dev.nvram = &nvram; nvram.type = 0; diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h index 5ee8c1b63f0f..a8f5a81cad40 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.h +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h @@ -111,8 +111,6 @@ typedef u_long vm_offset_t; /* * Configuration addendum for Linux. */ -#define SYM_LINUX_DYNAMIC_DMA_MAPPING - #define SYM_CONF_TIMER_INTERVAL ((HZ+1)/2) #define SYM_OPT_HANDLE_DIR_UNKNOWN @@ -121,10 +119,7 @@ typedef u_long vm_offset_t; #define SYM_OPT_SNIFF_INQUIRY #define SYM_OPT_LIMIT_COMMAND_REORDERING #define SYM_OPT_ANNOUNCE_TRANSFER_RATE - -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING #define SYM_OPT_BUS_DMA_ABSTRACTION -#endif /* * Print a message with severity. @@ -142,8 +137,8 @@ typedef u_long vm_offset_t; /* * Insert a delay in micro-seconds and milli-seconds. */ -void sym_udelay(int us); -void sym_mdelay(int ms); +#define sym_udelay(us) udelay(us) +#define sym_mdelay(ms) mdelay(ms) /* * Let the compiler know about driver data structure names. @@ -426,9 +421,6 @@ struct sym_shcb { struct Scsi_Host *host; - u_char bus; /* PCI BUS number */ - u_char device_fn; /* PCI BUS device and function */ - vm_offset_t mmio_va; /* MMIO kernel virtual address */ vm_offset_t ram_va; /* RAM kernel virtual address */ u_long io_port; /* IO port address cookie */ @@ -455,8 +447,6 @@ struct sym_shcb { * used as sub-field 's' of another structure. */ typedef struct { - int bus; - u_char device_fn; u_long base; u_long base_2; u_long base_c; @@ -469,12 +459,11 @@ typedef struct { } sym_slot; typedef struct sym_nvram sym_nvram; -typedef struct sym_pci_chip sym_chip; typedef struct { struct pci_dev *pdev; sym_slot s; - sym_chip chip; + struct sym_pci_chip chip; sym_nvram *nvram; u_short device_id; u_char host_id; @@ -496,9 +485,7 @@ typedef u_long m_addr_t; /* Enough bits to represent any address */ #ifdef MODULE #define SYM_MEM_FREE_UNUSED /* Free unused pages immediately */ #endif -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING typedef struct pci_dev *m_pool_ident_t; -#endif /* * Include driver soft definitions. @@ -521,19 +508,7 @@ typedef struct pci_dev *m_pool_ident_t; void *sym_calloc(int size, char *name); void sym_mfree(void *m, int size, char *name); -#ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING /* - * Simple case. - * All the memory assummed DMAable and O/S providing virtual - * to bus physical address translation. - */ -#define __sym_calloc_dma(pool_id, size, name) sym_calloc(size, name) -#define __sym_mfree_dma(pool_id, m, size, name) sym_mfree(m, size, name) -#define __vtobus(b, p) virt_to_bus(p) - -#else /* SYM_LINUX_DYNAMIC_DMA_MAPPING */ -/* - * Complex case. * We have to provide the driver memory allocator with methods for * it to maintain virtual to bus physical address translations. */ @@ -560,15 +535,12 @@ static __inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp) } #define sym_m_create_dma_mem_tag(mp) (0) - #define sym_m_delete_dma_mem_tag(mp) do { ; } while (0) void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name); void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name); m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m); -#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */ - /* * Set the status field of a CAM CCB. */ diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 7d83f2c28869..a8984f6ee40e 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -50,7 +50,7 @@ * SUCH DAMAGE. */ -#define SYM_DRIVER_NAME "sym-2.1.16a" +#define SYM_DRIVER_NAME "sym-2.1.17a" #ifdef __FreeBSD__ #include <dev/sym/sym_glue.h> @@ -289,7 +289,7 @@ int sym_reset_scsi_bus(hcb_p np, int enab_int) ((INW(nc_sbdl) & 0xff00) << 10) | /* d15-8 */ INB(nc_sbcl); /* req ack bsy sel atn msg cd io */ - if (!(np->features & FE_WIDE)) + if (!np->maxwide) term &= 0x3ffff; if (term != (2<<7)) { @@ -744,6 +744,12 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram) u32 period; int i; +#ifdef CONFIG_PARISC + unsigned long pdc_period; + char scsi_mode = -1; + struct hardware_path hwpath; +#endif + /* * Wide ? */ @@ -800,6 +806,31 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram) * Btw, 'period' is in tenths of nanoseconds. */ period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz; + +#if defined(CONFIG_PARISC) + /* Host firmware (PDC) keeps a table for crippling SCSI capabilities. + * Many newer machines export one channel of 53c896 chip + * as SE, 50-pin HD. Also used for Multi-initiator SCSI clusters + * to set the SCSI Initiator ID. + */ + get_pci_node_path(np->s.device, &hwpath); + if (pdc_get_initiator(&hwpath, &np->myaddr, &pdc_period, &np->maxwide, &scsi_mode)) + { + if (scsi_mode >= 0) { + /* C3000 PDC reports period/mode */ + SYM_SETUP_SCSI_DIFF = 0; + switch(scsi_mode) { + case 0: np->scsi_mode = SMODE_SE; break; + case 1: np->scsi_mode = SMODE_HVD; break; + case 2: np->scsi_mode = SMODE_LVD; break; + default: break; + } + } + + period = (u32) pdc_period; + } +#endif + if (period <= 250) np->minsync = 10; else if (period <= 303) np->minsync = 11; else if (period <= 500) np->minsync = 12; @@ -862,7 +893,7 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram) * In dual channel mode, contention occurs if internal cycles * are used. Disable internal cycles. */ - if (np->device_id == PCI_ID_LSI53C1010 && + if (np->device_id == PCI_ID_LSI53C1010_33 && np->revision_id < 0x1) np->rv_ccntl0 |= DILS; @@ -1362,17 +1393,17 @@ static struct sym_pci_chip sym_pci_dev_table[] = { FE_WIDE|FE_ULTRA|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| FE_RAM|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ} , - {PCI_ID_LSI53C1010, 0x00, "1010-33", 6, 31, 7, 8, + {PCI_ID_LSI53C1010_33, 0x00, "1010-33", 6, 31, 7, 8, FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN| FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC| FE_C10} , - {PCI_ID_LSI53C1010, 0xff, "1010-33", 6, 31, 7, 8, + {PCI_ID_LSI53C1010_33, 0xff, "1010-33", 6, 31, 7, 8, FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN| FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC| FE_C10|FE_U3EN} , - {PCI_ID_LSI53C1010_2, 0xff, "1010-66", 6, 31, 7, 8, + {PCI_ID_LSI53C1010_66, 0xff, "1010-66", 6, 31, 7, 8, FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN| FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_66MHZ|FE_CRC| FE_C10|FE_U3EN} @@ -1809,7 +1840,7 @@ void sym_start_up (hcb_p np, int reason) /* * For now, disable AIP generation on C1010-66. */ - if (np->device_id == PCI_ID_LSI53C1010_2) + if (np->device_id == PCI_ID_LSI53C1010_66) OUTB (nc_aipcntl1, DISAIP); /* @@ -1819,7 +1850,7 @@ void sym_start_up (hcb_p np, int reason) * that from SCRIPTS for each selection/reselection, but * I just don't want. :) */ - if (np->device_id == PCI_ID_LSI53C1010 && + if (np->device_id == PCI_ID_LSI53C1010_33 && np->revision_id < 1) OUTB (nc_stest1, INB(nc_stest1) | 0x30); diff --git a/drivers/scsi/sym53c8xx_2/sym_misc.h b/drivers/scsi/sym53c8xx_2/sym_misc.h index 3a4b41f13907..2b01031c5283 100644 --- a/drivers/scsi/sym53c8xx_2/sym_misc.h +++ b/drivers/scsi/sym53c8xx_2/sym_misc.h @@ -77,23 +77,8 @@ * should be enough). */ -#if defined __i386__ -#define __READ_BARRIER() \ - __asm__ volatile("lock; addl $0,0(%%esp)": : :"memory") -#define __WRITE_BARRIER() __asm__ volatile ("": : :"memory") -#elif defined __powerpc__ -#define __READ_BARRIER() __asm__ volatile("eieio; sync" : : : "memory") -#define __WRITE_BARRIER() __asm__ volatile("eieio; sync" : : : "memory") -#elif defined __ia64__ -#define __READ_BARRIER() __asm__ volatile("mf.a; mf" : : : "memory") -#define __WRITE_BARRIER() __asm__ volatile("mf.a; mf" : : : "memory") -#elif defined __alpha__ -#define __READ_BARRIER() __asm__ volatile("mb": : :"memory") -#define __WRITE_BARRIER() __asm__ volatile("mb": : :"memory") -#else -#define __READ_BARRIER() mb() -#define __WRITE_BARRIER() mb() -#endif +#define __READ_BARRIER() rmb() +#define __WRITE_BARRIER() wmb() #ifndef MEMORY_READ_BARRIER #define MEMORY_READ_BARRIER() __READ_BARRIER() diff --git a/drivers/scsi/sym53c8xx_defs.h b/drivers/scsi/sym53c8xx_defs.h index 289e3f06bca9..13a68b562dda 100644 --- a/drivers/scsi/sym53c8xx_defs.h +++ b/drivers/scsi/sym53c8xx_defs.h @@ -259,17 +259,6 @@ #endif /* - * Vendor specific stuff - */ -#ifdef CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT -#define SCSI_NCR_SETUP_LED_PIN (1) -#define SCSI_NCR_SETUP_DIFF_SUPPORT (4) -#else -#define SCSI_NCR_SETUP_LED_PIN (0) -#define SCSI_NCR_SETUP_DIFF_SUPPORT (0) -#endif - -/* * Settle time after reset at boot-up */ #define SCSI_NCR_SETUP_SETTLE_TIME (2) @@ -926,10 +915,10 @@ struct ncr_driver_setup { SCSI_NCR_SETUP_DEFAULT_SYNC, \ 0x00, \ 7, \ - SCSI_NCR_SETUP_LED_PIN, \ + 0, \ 1, \ SCSI_NCR_SETUP_SETTLE_TIME, \ - SCSI_NCR_SETUP_DIFF_SUPPORT, \ + 0, \ 0, \ 1, \ 0, \ diff --git a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c index 7692b54a9ad6..d104be2f167a 100644 --- a/drivers/serial/8250_acpi.c +++ b/drivers/serial/8250_acpi.c @@ -108,3 +108,6 @@ static void __exit acpi_serial_exit(void) module_init(acpi_serial_init); module_exit(acpi_serial_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Generic 8250/16x50 ACPI serial driver"); diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index c85528623cfa..4205682ea286 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c @@ -798,7 +798,7 @@ int __init hiddev_init(void) return usb_register(&hiddev_driver); } -void __exit hiddev_exit(void) +void hiddev_exit(void) { usb_deregister(&hiddev_driver); devfs_remove("usb/hid"); @@ -296,7 +296,7 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len, unsigned int offset) { request_queue_t *q = bdev_get_queue(bio->bi_bdev); - int fail_segments = 0, retried_segments = 0; + int retried_segments = 0; struct bio_vec *bvec; /* @@ -315,18 +315,15 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len, * we might lose a segment or two here, but rather that than * make this too complex. */ -retry_segments: - if (bio_phys_segments(q, bio) >= q->max_phys_segments - || bio_hw_segments(q, bio) >= q->max_hw_segments) - fail_segments = 1; - if (fail_segments) { + while (bio_phys_segments(q, bio) >= q->max_phys_segments + || bio_hw_segments(q, bio) >= q->max_hw_segments) { + if (retried_segments) return 0; bio->bi_flags &= ~(1 << BIO_SEG_VALID); retried_segments = 1; - goto retry_segments; } /* diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 153a4b0ff288..10114ce265da 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,14 @@ +Version 0.91 +------------ +Fix oops in reopen_files when invalid dentry. drop dentry on server rename +and on revalidate errors. Fix cases where pid is now tgid. Fix return code +on create hard link when server does not support them. + +Version 0.90 +------------ +Fix scheduling while atomic error in getting inode info on newly created file. +Fix truncate of existing files opened with O_CREAT but not O_TRUNC set. + Version 0.89 ------------ Fix oops on write to dead tcp session. Remove error log write for case when file open diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 9643932c9df2..ef523c53f680 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1,7 +1,7 @@ /* * fs/cifs/cifssmb.c * - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (C) International Business Machines Corp., 2002,2003 * Author(s): Steve French (sfrench@us.ibm.com) * * Contains the routines for constructing the SMB PDUs themselves @@ -656,7 +656,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, pSMB->AndXCommand = 0xFF; /* none */ pSMB->Fid = smb_file_id; /* netfid stays le */ - pSMB->Locks[0].Pid = cpu_to_le16(current->pid); + pSMB->Locks[0].Pid = cpu_to_le16(current->tgid); pSMB->Locks[0].Length = cpu_to_le64(len); pSMB->Locks[0].Offset = cpu_to_le64(offset); pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 7795f24d90b4..8873ca0447c9 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -3,7 +3,7 @@ * * vfs operations that deal with dentries * - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (C) International Business Machines Corp., 2002,2003 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -134,6 +134,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, struct inode *newinode = NULL; struct cifsFileInfo * pCifsFile = NULL; struct cifsInodeInfo * pCifsInode; + int disposition = FILE_OVERWRITE_IF; xid = GetXid(); @@ -151,6 +152,16 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, desiredAccess = GENERIC_WRITE; else if ((nd->intent.open.flags & O_ACCMODE) == O_RDWR) desiredAccess = GENERIC_ALL; + + if((nd->intent.open.flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + disposition = FILE_CREATE; + else if((nd->intent.open.flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) + disposition = FILE_OVERWRITE_IF; + else if((nd->intent.open.flags & O_CREAT) == O_CREAT) + disposition = FILE_OPEN_IF; + else { + cFYI(1,("Create flag not set in create function")); + } } /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */ @@ -158,7 +169,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, oplock = REQ_OPLOCK; buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); - rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF, + rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &fileHandle, &oplock, buf, cifs_sb->local_nls); if (rc) { @@ -205,7 +216,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, memset((char *)pCifsFile, 0, sizeof (struct cifsFileInfo)); pCifsFile->netfid = fileHandle; - pCifsFile->pid = current->pid; + pCifsFile->pid = current->tgid; pCifsFile->pInode = newinode; /* pCifsFile->pfile = file; */ /* put in at open time */ write_lock(&GlobalSMBSeslock); @@ -297,6 +308,9 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name (" parent inode = 0x%p name is: %s and dentry = 0x%p", parent_dir_inode, direntry->d_name.name, direntry)); + if(nd) { /* BB removeme */ + cFYI(1,("In lookup nd flags 0x%x open intent flags 0x%x",nd->flags,nd->intent.open.flags)); + } /* BB removeme BB */ /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */ /* check whether path exists */ diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 49f9c88c65cc..247a39b899b3 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -3,7 +3,7 @@ * * vfs operations that deal with files * - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (C) International Business Machines Corp., 2002,2003 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -144,6 +144,10 @@ cifs_open(struct inode *inode, struct file *file) list_add(&pCifsFile->tlist,&pTcon->openFileList); pCifsInode = CIFS_I(file->f_dentry->d_inode); if(pCifsInode) { + list_add(&pCifsFile->flist,&pCifsInode->openFileList); + write_unlock(&GlobalSMBSeslock); + write_unlock(&file->f_owner.lock); + if (pTcon->ses->capabilities & CAP_UNIX) rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode, full_path, inode->i_sb); @@ -151,16 +155,16 @@ cifs_open(struct inode *inode, struct file *file) rc = cifs_get_inode_info(&file->f_dentry->d_inode, full_path, buf, inode->i_sb); - list_add(&pCifsFile->flist,&pCifsInode->openFileList); if(oplock == OPLOCK_EXCLUSIVE) { pCifsInode->clientCanCacheAll = TRUE; pCifsInode->clientCanCacheRead = TRUE; cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode)); } else if(oplock == OPLOCK_READ) pCifsInode->clientCanCacheRead = TRUE; + } else { + write_unlock(&GlobalSMBSeslock); + write_unlock(&file->f_owner.lock); } - write_unlock(&GlobalSMBSeslock); - write_unlock(&file->f_owner.lock); if(file->f_flags & O_CREAT) { /* time to set mode which we can not set earlier due to problems creating new read-only files */ @@ -221,16 +225,21 @@ int reopen_files(struct cifsTconInfo * pTcon, struct nls_table * nlsinfo) if(file) { file->private_data = NULL; read_unlock(&GlobalSMBSeslock); - rc = cifs_open(file->f_dentry->d_inode,file); - read_lock(&GlobalSMBSeslock); - if(rc) { - cFYI(1,("reconnecting file %s failed with %d", - file->f_dentry->d_name.name,rc)); + if(file->f_dentry == 0) { + cFYI(1,("Null dentry for file %p",file)); + read_lock(&GlobalSMBSeslock); } else { - cFYI(1,("reconnection of %s succeeded", - file->f_dentry->d_name.name)); - } - } + rc = cifs_open(file->f_dentry->d_inode,file); + read_lock(&GlobalSMBSeslock); + if(rc) { + cFYI(1,("reconnecting file %s failed with %d", + file->f_dentry->d_name.name,rc)); + } else { + cFYI(1,("reconnection of %s succeeded", + file->f_dentry->d_name.name)); + } + } + } } } read_unlock(&GlobalSMBSeslock); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 62625e532132..3625916ca351 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1,7 +1,7 @@ /* * fs/cifs/inode.c * - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (C) International Business Machines Corp., 2002,2003 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -345,6 +345,8 @@ cifs_unlink(struct inode *inode, struct dentry *direntry) if (!rc) { direntry->d_inode->i_nlink--; + } else if (rc == -ENOENT) { + d_drop(direntry); } else if (rc == -ETXTBSY) { int oplock = FALSE; __u16 netfid; @@ -585,12 +587,24 @@ cifs_revalidate(struct dentry *direntry) } } - if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) - cifs_get_inode_info_unix(&direntry->d_inode, full_path, + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) { + rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path, direntry->d_sb); - else - cifs_get_inode_info(&direntry->d_inode, full_path, NULL, + if(rc) { + cFYI(1,("error on getting revalidate info %d",rc)); +/* if(rc != -ENOENT) + rc = 0; */ /* BB should we cache info on certain errors? */ + } + } else { + rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL, direntry->d_sb); + if(rc) { + cFYI(1,("error on getting revalidate info %d",rc)); +/* if(rc != -ENOENT) + rc = 0; */ /* BB should we cache info on certain errors? */ + } + } + /* should we remap certain errors, access denied?, to zero */ /* BB if not oplocked, invalidate inode pages if mtime has changed */ diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 9717910ee514..93c200f49f51 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -1,7 +1,7 @@ /* * fs/cifs/link.c * - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (C) International Business Machines Corp., 2002,2003 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -51,9 +51,12 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX) rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, cifs_sb_target->local_nls); - else + else { rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, cifs_sb_target->local_nls); + if(rc == -EIO) + rc = -EOPNOTSUPP; + } /* if (!rc) */ { diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index b9a5137df6d7..65d84985a3ce 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -1,7 +1,7 @@ /* * fs/cifs/misc.c * - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (c) International Business Machines Corp., 2002,2003 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -213,7 +213,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , buffer->Command = smb_command; buffer->Flags = 0x00; /* case sensitive */ buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES; - tmp = cpu_to_le32(current->pid); + tmp = cpu_to_le32(current->tgid); buffer->Pid = tmp & 0xFFFF; tmp >>= 16; buffer->PidHigh = tmp & 0xFFFF; diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 23a295cf2269..e042f16e8764 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -356,10 +356,9 @@ static struct file_operations proc_slabinfo_operations = { .release = seq_release, }; -static int kstat_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) +int show_stat(struct seq_file *p, void *v) { - int i, len; + int i; extern unsigned long total_forks; u64 jif; unsigned int sum = 0, user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0; @@ -379,10 +378,10 @@ static int kstat_read_proc(char *page, char **start, off_t off, jif = ((u64)now.tv_sec * HZ) + (now.tv_usec/(1000000/HZ)) - jif; do_div(jif, HZ); - for (i = 0 ; i < NR_CPUS; i++) { + for (i = 0; i < NR_CPUS; i++) { int j; - if(!cpu_online(i)) continue; + if (!cpu_online(i)) continue; user += kstat_cpu(i).cpustat.user; nice += kstat_cpu(i).cpustat.nice; system += kstat_cpu(i).cpustat.system; @@ -394,7 +393,7 @@ static int kstat_read_proc(char *page, char **start, off_t off, sum += kstat_cpu(i).irqs[j]; } - len = sprintf(page, "cpu %u %u %u %u %u %u %u\n", + seq_printf(p, "cpu %u %u %u %u %u %u %u\n", jiffies_to_clock_t(user), jiffies_to_clock_t(nice), jiffies_to_clock_t(system), @@ -402,9 +401,9 @@ static int kstat_read_proc(char *page, char **start, off_t off, jiffies_to_clock_t(iowait), jiffies_to_clock_t(irq), jiffies_to_clock_t(softirq)); - for (i = 0 ; i < NR_CPUS; i++){ + for (i = 0; i < NR_CPUS; i++){ if (!cpu_online(i)) continue; - len += sprintf(page + len, "cpu%d %u %u %u %u %u %u %u\n", + seq_printf(p, "cpu%d %u %u %u %u %u %u %u\n", i, jiffies_to_clock_t(kstat_cpu(i).cpustat.user), jiffies_to_clock_t(kstat_cpu(i).cpustat.nice), @@ -414,14 +413,14 @@ static int kstat_read_proc(char *page, char **start, off_t off, jiffies_to_clock_t(kstat_cpu(i).cpustat.irq), jiffies_to_clock_t(kstat_cpu(i).cpustat.softirq)); } - len += sprintf(page + len, "intr %u", sum); + seq_printf(p, "intr %u", sum); #if !defined(CONFIG_PPC64) && !defined(CONFIG_ALPHA) - for (i = 0 ; i < NR_IRQS ; i++) - len += sprintf(page + len, " %u", kstat_irqs(i)); + for (i = 0; i < NR_IRQS; i++) + seq_printf(p, " %u", kstat_irqs(i)); #endif - len += sprintf(page + len, + seq_printf(p, "\nctxt %lu\n" "btime %lu\n" "processes %lu\n" @@ -433,9 +432,39 @@ static int kstat_read_proc(char *page, char **start, off_t off, nr_running(), nr_iowait()); - return proc_calc_metrics(page, start, off, count, eof, len); + return 0; } +static int stat_open(struct inode *inode, struct file *file) +{ + unsigned size = 4096 * (1 + num_online_cpus() / 32); + char *buf; + struct seq_file *m; + int res; + + /* don't ask for more than the kmalloc() max size, currently 128 KB */ + if (size > 128 * 1024) + size = 128 * 1024; + buf = kmalloc(size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + res = single_open(file, show_stat, NULL); + if (!res) { + m = file->private_data; + m->buf = buf; + m->size = size; + } else + kfree(buf); + return res; +} +static struct file_operations proc_stat_operations = { + .open = stat_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int devices_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -626,7 +655,6 @@ void __init proc_misc_init(void) #ifdef CONFIG_STRAM_PROC {"stram", stram_read_proc}, #endif - {"stat", kstat_read_proc}, {"devices", devices_read_proc}, {"filesystems", filesystems_read_proc}, {"cmdline", cmdline_read_proc}, @@ -648,6 +676,7 @@ void __init proc_misc_init(void) entry->proc_fops = &proc_kmsg_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); create_seq_entry("interrupts", 0, &proc_interrupts_operations); create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations); create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations); diff --git a/include/asm-alpha/semaphore.h b/include/asm-alpha/semaphore.h index ab26cfbaddbf..a363f018a35f 100644 --- a/include/asm-alpha/semaphore.h +++ b/include/asm-alpha/semaphore.h @@ -88,14 +88,18 @@ extern void __up_wakeup(struct semaphore *); static inline void __down(struct semaphore *sem) { - long count = atomic_dec_return(&sem->count); + long count; + might_sleep(); + count = atomic_dec_return(&sem->count); if (unlikely(count < 0)) __down_failed(sem); } static inline int __down_interruptible(struct semaphore *sem) { - long count = atomic_dec_return(&sem->count); + long count; + might_sleep(); + count = atomic_dec_return(&sem->count); if (unlikely(count < 0)) return __down_failed_interruptible(sem); return 0; diff --git a/include/asm-arm/assembler.h b/include/asm-arm/assembler.h index 677eedee6694..84ab93eb4643 100644 --- a/include/asm-arm/assembler.h +++ b/include/asm-arm/assembler.h @@ -1,18 +1,23 @@ /* - * linux/asm/assembler.h + * linux/include/asm-arm/assembler.h * - * This file contains arm architecture specific defines - * for the different processors. + * Copyright (C) 1996-2000 Russell King * - * Do not include any C declarations in this file - it is included by - * assembler source. + * 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. + * + * This file contains arm architecture specific defines + * for the different processors. + * + * Do not include any C declarations in this file - it is included by + * assembler source. */ #ifndef __ASSEMBLY__ #error "Only include this from assembly code" #endif -#include <asm/proc/ptrace.h> -#include <asm/proc/assembler.h> +#include <asm/ptrace.h> /* * Endian independent macros for shifting bytes within registers. @@ -36,3 +41,63 @@ #define PLD(code...) #endif +#define MODE_USR USR_MODE +#define MODE_FIQ FIQ_MODE +#define MODE_IRQ IRQ_MODE +#define MODE_SVC SVC_MODE + +#define DEFAULT_FIQ MODE_FIQ + +/* + * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc}) + */ +#ifdef __STDC__ +#define LOADREGS(cond, base, reglist...)\ + ldm##cond base,reglist +#else +#define LOADREGS(cond, base, reglist...)\ + ldm/**/cond base,reglist +#endif + +/* + * Build a return instruction for this processor type. + */ +#define RETINSTR(instr, regs...)\ + instr regs + +/* + * Save the current IRQ state and disable IRQs. Note that this macro + * assumes FIQs are enabled, and that the processor is in SVC mode. + */ + .macro save_and_disable_irqs, oldcpsr, temp + mrs \oldcpsr, cpsr + mov \temp, #PSR_I_BIT | MODE_SVC + msr cpsr_c, \temp + .endm + +/* + * Restore interrupt state previously stored in a register. We don't + * guarantee that this will preserve the flags. + */ + .macro restore_irqs, oldcpsr + msr cpsr_c, \oldcpsr + .endm + +/* + * These two are used to save LR/restore PC over a user-based access. + * The old 26-bit architecture requires that we do. On 32-bit + * architecture, we can safely ignore this requirement. + */ + .macro save_lr + .endm + + .macro restore_pc + mov pc, lr + .endm + +#define USER(x...) \ +9999: x; \ + .section __ex_table,"a"; \ + .align 3; \ + .long 9999b,9001f; \ + .previous diff --git a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h index ba9e4b72d821..e8e2cd1d69f1 100644 --- a/include/asm-arm/atomic.h +++ b/include/asm-arm/atomic.h @@ -27,7 +27,7 @@ typedef struct { volatile int counter; } atomic_t; #define ATOMIC_INIT(i) { (i) } #ifdef __KERNEL__ -#include <asm/proc/system.h> +#include <asm/system.h> #define atomic_read(v) ((v)->counter) #define atomic_set(v,i) (((v)->counter) = (i)) diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index f5f2b2a3e199..30a47cba4d4b 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h @@ -1,7 +1,7 @@ /* * linux/include/asm-arm/cacheflush.h * - * Copyright (C) 2000-2002 Russell King + * Copyright (C) 1999-2002 Russell King * * 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 @@ -12,6 +12,275 @@ #include <linux/sched.h> #include <linux/mm.h> -#include <asm/proc/cache.h> + +#include <asm/mman.h> +#include <asm/glue.h> + +/* + * Cache Model + * =========== + */ +#undef _CACHE +#undef MULTI_CACHE + +#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE v3 +# endif +#endif + +#if defined(CONFIG_CPU_ARM720T) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE v4 +# endif +#endif + +#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \ + defined(CONFIG_CPU_ARM1020) +# define MULTI_CACHE 1 +#endif + +#if defined(CONFIG_CPU_ARM926T) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE arm926 +# endif +#endif + +#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE v4wb +# endif +#endif + +#if defined(CONFIG_CPU_XSCALE) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE xscale +# endif +#endif + +#if !defined(_CACHE) && !defined(MULTI_CACHE) +#error Unknown cache maintainence model +#endif + +/* + * This flag is used to indicate that the page pointed to by a pte + * is dirty and requires cleaning before returning it to the user. + */ +#define PG_dcache_dirty PG_arch_1 + +/* + * MM Cache Management + * =================== + * + * The arch/arm/mm/cache-*.S and arch/arm/mm/proc-*.S files + * implement these methods. + * + * Start addresses are inclusive and end addresses are exclusive; + * start addresses should be rounded down, end addresses up. + * + * See linux/Documentation/cachetlb.txt for more information. + * Please note that the implementation of these, and the required + * effects are cache-type (VIVT/VIPT/PIPT) specific. + * + * flush_cache_kern_all() + * + * Unconditionally clean and invalidate the entire cache. + * + * flush_cache_user_mm(mm) + * + * Clean and invalidate all user space cache entries + * before a change of page tables. + * + * flush_cache_user_range(start, end, flags) + * + * Clean and invalidate a range of cache entries in the + * specified address space before a change of page tables. + * - start - user start address (inclusive, page aligned) + * - end - user end address (exclusive, page aligned) + * - flags - vma->vm_flags field + * + * coherent_kern_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start, end. If you have non-snooping + * Harvard caches, you need to implement this function. + * - start - virtual start address + * - end - virtual end address + * + * DMA Cache Coherency + * =================== + * + * dma_inv_range(start, end) + * + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. + * - start - virtual start address + * - end - virtual end address + * + * dma_clean_range(start, end) + * + * Clean (write back) the specified virtual address range. + * - start - virtual start address + * - end - virtual end address + * + * dma_flush_range(start, end) + * + * Clean and invalidate the specified virtual address range. + * - start - virtual start address + * - end - virtual end address + */ + +struct cpu_cache_fns { + void (*flush_kern_all)(void); + void (*flush_user_all)(void); + void (*flush_user_range)(unsigned long, unsigned long, unsigned int); + + void (*coherent_kern_range)(unsigned long, unsigned long); + void (*flush_kern_dcache_page)(void *); + + void (*dma_inv_range)(unsigned long, unsigned long); + void (*dma_clean_range)(unsigned long, unsigned long); + void (*dma_flush_range)(unsigned long, unsigned long); +}; + +/* + * Select the calling method + */ +#ifdef MULTI_CACHE + +extern struct cpu_cache_fns cpu_cache; + +#define __cpuc_flush_kern_all cpu_cache.flush_kern_all +#define __cpuc_flush_user_all cpu_cache.flush_user_all +#define __cpuc_flush_user_range cpu_cache.flush_user_range +#define __cpuc_coherent_kern_range cpu_cache.coherent_kern_range +#define __cpuc_flush_dcache_page cpu_cache.flush_kern_dcache_page + +/* + * These are private to the dma-mapping API. Do not use directly. + * Their sole purpose is to ensure that data held in the cache + * is visible to DMA, or data written by DMA to system memory is + * visible to the CPU. + */ +#define dmac_inv_range cpu_cache.dma_inv_range +#define dmac_clean_range cpu_cache.dma_clean_range +#define dmac_flush_range cpu_cache.dma_flush_range + +#else + +#define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) +#define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all) +#define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range) +#define __cpuc_coherent_kern_range __glue(_CACHE,_coherent_kern_range) +#define __cpuc_flush_dcache_page __glue(_CACHE,_flush_kern_dcache_page) + +extern void __cpuc_flush_kern_all(void); +extern void __cpuc_flush_user_all(void); +extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int); +extern void __cpuc_coherent_kern_range(unsigned long, unsigned long); +extern void __cpuc_flush_dcache_page(void *); + +/* + * These are private to the dma-mapping API. Do not use directly. + * Their sole purpose is to ensure that data held in the cache + * is visible to DMA, or data written by DMA to system memory is + * visible to the CPU. + */ +#define dmac_inv_range __glue(_CACHE,_dma_inv_range) +#define dmac_clean_range __glue(_CACHE,_dma_clean_range) +#define dmac_flush_range __glue(_CACHE,_dma_flush_range) + +extern void dmac_inv_range(unsigned long, unsigned long); +extern void dmac_clean_range(unsigned long, unsigned long); +extern void dmac_flush_range(unsigned long, unsigned long); + +#endif + +/* + * Convert calls to our calling convention. + */ +#define flush_cache_all() __cpuc_flush_kern_all() + +static inline void flush_cache_mm(struct mm_struct *mm) +{ + if (current->active_mm == mm) + __cpuc_flush_user_all(); +} + +static inline void +flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) +{ + if (current->active_mm == vma->vm_mm) + __cpuc_flush_user_range(start & PAGE_MASK, PAGE_ALIGN(end), + vma->vm_flags); +} + +static inline void +flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr) +{ + if (current->active_mm == vma->vm_mm) { + unsigned long addr = user_addr & PAGE_MASK; + __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); + } +} + +/* + * Perform necessary cache operations to ensure that data previously + * stored within this range of addresses can be executed by the CPU. + */ +#define flush_icache_range(s,e) __cpuc_coherent_kern_range(s,e) + +/* + * Perform necessary cache operations to ensure that the TLB will + * see data written in the specified area. + */ +#define clean_dcache_area(start,size) cpu_dcache_clean_area(start, size) + +/* + * flush_dcache_page is used when the kernel has written to the page + * cache page at virtual address page->virtual. + * + * If this page isn't mapped (ie, page->mapping = NULL), or it has + * userspace mappings (page->mapping->i_mmap or page->mapping->i_mmap_shared) + * then we _must_ always clean + invalidate the dcache entries associated + * with the kernel mapping. + * + * Otherwise we can defer the operation, and clean the cache when we are + * about to change to user space. This is the same method as used on SPARC64. + * See update_mmu_cache for the user space part. + */ +#define mapping_mapped(map) (!list_empty(&(map)->i_mmap) || \ + !list_empty(&(map)->i_mmap_shared)) + +extern void __flush_dcache_page(struct page *); + +static inline void flush_dcache_page(struct page *page) +{ + if (page->mapping && !mapping_mapped(page->mapping)) + set_bit(PG_dcache_dirty, &page->flags); + else + __flush_dcache_page(page); +} + +#define flush_icache_user_range(vma,page,addr,len) \ + flush_dcache_page(page) + +/* + * We don't appear to need to do anything here. In fact, if we did, we'd + * duplicate cache flushing elsewhere performed by flush_dcache_page(). + */ +#define flush_icache_page(vma,page) do { } while (0) #endif diff --git a/include/asm-arm/cpu-multi26.h b/include/asm-arm/cpu-multi26.h deleted file mode 100644 index 415ce60471dd..000000000000 --- a/include/asm-arm/cpu-multi26.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * linux/include/asm-arm/cpu-multi26.h - * - * Copyright (C) 2000 Russell King - * - * 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. - */ -#ifndef __ASSEMBLY__ - -#include <asm/page.h> - -/* forward-declare task_struct */ -struct task_struct; - -/* - * Don't change this structure - ASM code - * relies on it. - */ -extern struct processor { - /* Set up any processor specifics */ - void (*_proc_init)(void); - /* Disable any processor specifics */ - void (*_proc_fin)(void); - /* set the MEMC hardware mappings */ - void (*_switch_mm)(pgd_t *pgd); - /* XCHG */ - unsigned long (*_xchg_1)(unsigned long x, volatile void *ptr); - unsigned long (*_xchg_4)(unsigned long x, volatile void *ptr); -} processor; - -extern const struct processor arm2_processor_functions; -extern const struct processor arm250_processor_functions; -extern const struct processor arm3_processor_functions; - -#define cpu_proc_init() processor._proc_init() -#define cpu_proc_fin() processor._proc_fin() -#define cpu_do_idle() do { } while (0) -#define cpu_switch_mm(pgd,mm) processor._switch_mm(pgd) -#define cpu_xchg_1(x,ptr) processor._xchg_1(x,ptr) -#define cpu_xchg_4(x,ptr) processor._xchg_4(x,ptr) - -extern void cpu_memc_update_all(pgd_t *pgd); -extern void cpu_memc_update_entry(pgd_t *pgd, unsigned long phys_pte, unsigned long log_addr); - -#endif diff --git a/include/asm-arm/proc-armv/domain.h b/include/asm-arm/domain.h index 67f889162c31..87f9734a8a4a 100644 --- a/include/asm-arm/proc-armv/domain.h +++ b/include/asm-arm/domain.h @@ -1,5 +1,5 @@ /* - * linux/include/asm-arm/proc-armv/domain.h + * linux/include/asm-arm/domain.h * * Copyright (C) 1999 Russell King. * diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h index 536b2d6f2854..b67e06c0f588 100644 --- a/include/asm-arm/elf.h +++ b/include/asm-arm/elf.h @@ -7,7 +7,6 @@ #include <asm/ptrace.h> #include <asm/user.h> -#include <asm/proc/elf.h> #include <asm/procinfo.h> typedef unsigned long elf_greg_t; @@ -42,6 +41,7 @@ typedef struct user_fp elf_fpregset_t; #define ELF_ARCH EM_ARM #define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 /* This is the location that an ET_DYN program is loaded if exec'ed. Typical use of this is to invoke "./ld.so someprog" to test out a new version of @@ -76,4 +76,29 @@ typedef struct user_fp elf_fpregset_t; extern char elf_platform[]; #define ELF_PLATFORM (elf_platform) +#ifdef __KERNEL__ + +/* + * 32-bit code is always OK. Some cpus can do 26-bit, some can't. + */ +#define ELF_PROC_OK(x) (ELF_THUMB_OK(x) && ELF_26BIT_OK(x)) + +#define ELF_THUMB_OK(x) \ + (( (elf_hwcap & HWCAP_THUMB) && ((x)->e_entry & 1) == 1) || \ + ((x)->e_entry & 3) == 0) + +#define ELF_26BIT_OK(x) \ + (( (elf_hwcap & HWCAP_26BIT) && (x)->e_flags & EF_ARM_APCS26) || \ + ((x)->e_flags & EF_ARM_APCS26) == 0) + +/* Old NetWinder binaries were compiled in such a way that the iBCS + heuristic always trips on them. Until these binaries become uncommon + enough not to care, don't trust the `ibcs' flag here. In any case + there is no other ELF system currently supported by iBCS. + @@ Could print a warning message to encourage users to upgrade. */ +#define SET_PERSONALITY(ex,ibcs2) \ + set_personality(((ex).e_flags&EF_ARM_APCS26 ?PER_LINUX :PER_LINUX_32BIT)) + +#endif + #endif diff --git a/include/asm-arm/proc-armv/locks.h b/include/asm-arm/locks.h index 13248f903677..435ed505feda 100644 --- a/include/asm-arm/proc-armv/locks.h +++ b/include/asm-arm/locks.h @@ -1,5 +1,5 @@ /* - * linux/include/asm-arm/proc-armv/locks.h + * linux/include/asm-arm/locks.h * * Copyright (C) 2000 Russell King * diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h index 1b61a0e02c20..588c47d26338 100644 --- a/include/asm-arm/memory.h +++ b/include/asm-arm/memory.h @@ -15,6 +15,8 @@ #include <linux/config.h> #include <asm/arch/memory.h> +#ifndef __ASSEMBLY__ + /* * PFNs are used to describe any physical page; this means * PFN 0 == physical address 0. @@ -120,3 +122,5 @@ static inline void *phys_to_virt(unsigned long x) #define page_to_bus(page) (virt_to_bus(page_address(page))) #endif + +#endif diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h index ca379e1f9184..94aeae2a4fb1 100644 --- a/include/asm-arm/page.h +++ b/include/asm-arm/page.h @@ -1,9 +1,27 @@ +/* + * linux/include/asm-arm/page.h + * + * Copyright (C) 1995-2003 Russell King + * + * 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. + */ #ifndef _ASMARM_PAGE_H #define _ASMARM_PAGE_H #include <linux/config.h> +/* PAGE_SHIFT determines the page size */ +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + #ifdef __KERNEL__ + +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) + #ifndef __ASSEMBLY__ #include <asm/glue.h> @@ -119,10 +137,12 @@ extern void copy_page(void *to, void *from); */ typedef struct { unsigned long pte; } pte_t; typedef struct { unsigned long pmd; } pmd_t; +typedef struct { unsigned long pgd[2]; } pgd_t; typedef struct { unsigned long pgprot; } pgprot_t; #define pte_val(x) ((x).pte) #define pmd_val(x) ((x).pmd) +#define pgd_val(x) ((x).pgd[0]) #define pgprot_val(x) ((x).pgprot) #define __pte(x) ((pte_t) { (x) } ) @@ -135,10 +155,12 @@ typedef struct { unsigned long pgprot; } pgprot_t; */ typedef unsigned long pte_t; typedef unsigned long pmd_t; +typedef unsigned long pgd_t[2]; typedef unsigned long pgprot_t; #define pte_val(x) (x) #define pmd_val(x) (x) +#define pgd_val(x) ((x)[0]) #define pgprot_val(x) (x) #define __pte(x) (x) @@ -146,19 +168,6 @@ typedef unsigned long pgprot_t; #define __pgprot(x) (x) #endif /* STRICT_MM_TYPECHECKS */ -#endif /* !__ASSEMBLY__ */ -#endif /* __KERNEL__ */ - -#include <asm/proc/page.h> - -#define PAGE_SIZE (1UL << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) - -/* to align the pointer to the (next) page boundary */ -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) - -#ifdef __KERNEL__ -#ifndef __ASSEMBLY__ /* Pure 2^n version of get_order */ static inline int get_order(unsigned long size) diff --git a/include/asm-arm/param.h b/include/asm-arm/param.h index 2bf8b1d793f6..c1ccdcbe2bd1 100644 --- a/include/asm-arm/param.h +++ b/include/asm-arm/param.h @@ -11,7 +11,6 @@ #define __ASM_PARAM_H #include <asm/arch/param.h> /* for HZ */ -#include <asm/proc/page.h> /* for EXEC_PAGE_SIZE */ #ifndef __KERNEL_HZ #define __KERNEL_HZ 100 @@ -25,6 +24,8 @@ # define HZ 100 #endif +#define EXEC_PAGESIZE 4096 + #ifndef NGROUPS #define NGROUPS 32 #endif diff --git a/include/asm-arm/pgalloc.h b/include/asm-arm/pgalloc.h index 81a7eccf2991..23eb321f4af2 100644 --- a/include/asm-arm/pgalloc.h +++ b/include/asm-arm/pgalloc.h @@ -11,7 +11,8 @@ #define _ASMARM_PGALLOC_H #include <asm/processor.h> -#include <asm/proc/pgalloc.h> +#include <asm/cacheflush.h> +#include <asm/tlbflush.h> /* * Since we have only two-level page tables, these are trivial @@ -28,4 +29,104 @@ extern void free_pgd_slow(pgd_t *pgd); #define check_pgt_cache() do { } while (0) +/* + * Allocate one PTE table. + * + * This actually allocates two hardware PTE tables, but we wrap this up + * into one table thus: + * + * +------------+ + * | h/w pt 0 | + * +------------+ + * | h/w pt 1 | + * +------------+ + * | Linux pt 0 | + * +------------+ + * | Linux pt 1 | + * +------------+ + */ +static inline pte_t * +pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) +{ + pte_t *pte; + + pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); + if (pte) { + clear_page(pte); + clean_dcache_area(pte, sizeof(pte_t) * PTRS_PER_PTE); + pte += PTRS_PER_PTE; + } + + return pte; +} + +static inline struct page * +pte_alloc_one(struct mm_struct *mm, unsigned long addr) +{ + struct page *pte; + + pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0); + if (pte) { + void *page = page_address(pte); + clear_page(page); + clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE); + } + + return pte; +} + +/* + * Free one PTE table. + */ +static inline void pte_free_kernel(pte_t *pte) +{ + if (pte) { + pte -= PTRS_PER_PTE; + free_page((unsigned long)pte); + } +} + +static inline void pte_free(struct page *pte) +{ + __free_page(pte); +} + +/* + * Populate the pmdp entry with a pointer to the pte. This pmd is part + * of the mm address space. + * + * Ensure that we always set both PMD entries. + */ +static inline void +pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) +{ + unsigned long pte_ptr = (unsigned long)ptep; + unsigned long pmdval; + + BUG_ON(mm != &init_mm); + + /* + * The pmd must be loaded with the physical + * address of the PTE table + */ + pte_ptr -= PTRS_PER_PTE * sizeof(void *); + pmdval = __pa(pte_ptr) | _PAGE_KERNEL_TABLE; + pmdp[0] = __pmd(pmdval); + pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); + flush_pmd_entry(pmdp); +} + +static inline void +pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep) +{ + unsigned long pmdval; + + BUG_ON(mm == &init_mm); + + pmdval = page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE; + pmdp[0] = __pmd(pmdval); + pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); + flush_pmd_entry(pmdp); +} + #endif diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h index e2ed74082ae1..473b238e6fbc 100644 --- a/include/asm-arm/pgtable.h +++ b/include/asm-arm/pgtable.h @@ -1,7 +1,7 @@ /* * linux/include/asm-arm/pgtable.h * - * Copyright (C) 2000-2002 Russell King + * Copyright (C) 1995-2002 Russell King * * 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 @@ -16,15 +16,24 @@ #include <asm/arch/vmalloc.h> /* + * We pull a couple of tricks here: + * 1. We wrap the PMD into the PGD. + * 2. We lie about the size of the PTE and PGD. + * Even though we have 256 PTE entries and 4096 PGD entries, we tell + * Linux that we actually have 512 PTE entries and 2048 PGD entries. + * Each "Linux" PGD entry is made up of two hardware PGD entries, and + * each PTE table is actually two hardware PTE tables. + */ +#define PTRS_PER_PTE 512 +#define PTRS_PER_PMD 1 +#define PTRS_PER_PGD 2048 + +/* * PMD_SHIFT determines the size of the area a second-level page table can map * PGDIR_SHIFT determines what a third-level page table entry can map */ #define PMD_SHIFT 20 -#ifdef CONFIG_CPU_32 #define PGDIR_SHIFT 21 -#else -#define PGDIR_SHIFT 20 -#endif #define LIBRARY_TEXT_START 0x0c000000 @@ -47,6 +56,117 @@ extern void __pgd_error(const char *file, int line, unsigned long val); #define USER_PTRS_PER_PGD ((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR) /* + * Hardware page table definitions. + * + * + Level 1 descriptor (PMD) + * - common + */ +#define PMD_TYPE_MASK (3 << 0) +#define PMD_TYPE_FAULT (0 << 0) +#define PMD_TYPE_TABLE (1 << 0) +#define PMD_TYPE_SECT (2 << 0) +#define PMD_BIT4 (1 << 4) +#define PMD_DOMAIN(x) ((x) << 5) +#define PMD_PROTECTION (1 << 9) /* v5 */ +/* + * - section + */ +#define PMD_SECT_BUFFERABLE (1 << 2) +#define PMD_SECT_CACHEABLE (1 << 3) +#define PMD_SECT_AP_WRITE (1 << 10) +#define PMD_SECT_AP_READ (1 << 11) +#define PMD_SECT_TEX(x) ((x) << 12) /* v5 */ +#define PMD_SECT_APX (1 << 15) /* v6 */ +#define PMD_SECT_S (1 << 16) /* v6 */ +#define PMD_SECT_nG (1 << 17) /* v6 */ + +#define PMD_SECT_UNCACHED (0) +#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE) +#define PMD_SECT_WT (PMD_SECT_CACHEABLE) +#define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) +#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE) +#define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) + +/* + * - coarse table (not used) + */ + +/* + * + Level 2 descriptor (PTE) + * - common + */ +#define PTE_TYPE_MASK (3 << 0) +#define PTE_TYPE_FAULT (0 << 0) +#define PTE_TYPE_LARGE (1 << 0) +#define PTE_TYPE_SMALL (2 << 0) +#define PTE_TYPE_EXT (3 << 0) /* v5 */ +#define PTE_BUFFERABLE (1 << 2) +#define PTE_CACHEABLE (1 << 3) + +/* + * - extended small page/tiny page + */ +#define PTE_EXT_AP_UNO_SRO (0 << 4) +#define PTE_EXT_AP_UNO_SRW (1 << 4) +#define PTE_EXT_AP_URO_SRW (2 << 4) +#define PTE_EXT_AP_URW_SRW (3 << 4) +#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */ + +/* + * - small page + */ +#define PTE_SMALL_AP_UNO_SRO (0x00 << 4) +#define PTE_SMALL_AP_UNO_SRW (0x55 << 4) +#define PTE_SMALL_AP_URO_SRW (0xaa << 4) +#define PTE_SMALL_AP_URW_SRW (0xff << 4) +#define PTE_AP_READ PTE_SMALL_AP_URO_SRW +#define PTE_AP_WRITE PTE_SMALL_AP_UNO_SRW + +/* + * "Linux" PTE definitions. + * + * We keep two sets of PTEs - the hardware and the linux version. + * This allows greater flexibility in the way we map the Linux bits + * onto the hardware tables, and allows us to have YOUNG and DIRTY + * bits. + * + * The PTE table pointer refers to the hardware entries; the "Linux" + * entries are stored 1024 bytes below. + */ +#define L_PTE_PRESENT (1 << 0) +#define L_PTE_FILE (1 << 1) /* only when !PRESENT */ +#define L_PTE_YOUNG (1 << 1) +#define L_PTE_BUFFERABLE (1 << 2) /* matches PTE */ +#define L_PTE_CACHEABLE (1 << 3) /* matches PTE */ +#define L_PTE_USER (1 << 4) +#define L_PTE_WRITE (1 << 5) +#define L_PTE_EXEC (1 << 6) +#define L_PTE_DIRTY (1 << 7) + +#ifndef __ASSEMBLY__ + +#include <asm/domain.h> + +#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER)) +#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL)) + +/* + * The following macros handle the cache and bufferable bits... + */ +#define _L_PTE_DEFAULT L_PTE_PRESENT | L_PTE_YOUNG +#define _L_PTE_READ L_PTE_USER | L_PTE_EXEC | L_PTE_CACHEABLE | L_PTE_BUFFERABLE + +#define PAGE_NONE __pgprot(_L_PTE_DEFAULT) +#define PAGE_COPY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ) +#define PAGE_SHARED __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_WRITE) +#define PAGE_READONLY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ) +#define PAGE_KERNEL __pgprot(_L_PTE_DEFAULT | L_PTE_CACHEABLE | L_PTE_BUFFERABLE | L_PTE_DIRTY | L_PTE_WRITE | L_PTE_EXEC) + +#define _PAGE_CHG_MASK (PAGE_MASK | L_PTE_DIRTY | L_PTE_YOUNG) + +#endif /* __ASSEMBLY__ */ + +/* * The table below defines the page protection levels that we insert into our * Linux page table version. These get translated into the best that the * architecture can perform. Note that on most ARM hardware: @@ -86,9 +206,82 @@ extern struct page *empty_zero_page; #define pte_none(pte) (!pte_val(pte)) #define pte_clear(ptep) set_pte((ptep), __pte(0)) #define pte_page(pte) (pfn_to_page(pte_pfn(pte))) +#define pte_offset_kernel(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr)) +#define pte_offset_map(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr)) +#define pte_offset_map_nested(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr)) +#define pte_unmap(pte) do { } while (0) +#define pte_unmap_nested(pte) do { } while (0) + +#define set_pte(ptep, pte) cpu_set_pte(ptep,pte) + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) +#define pte_read(pte) (pte_val(pte) & L_PTE_USER) +#define pte_write(pte) (pte_val(pte) & L_PTE_WRITE) +#define pte_exec(pte) (pte_val(pte) & L_PTE_EXEC) +#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) +#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) + +/* + * The following only works if pte_present() is not true. + */ +#define pte_file(pte) (pte_val(pte) & L_PTE_FILE) +#define pte_to_pgoff(x) (pte_val(x) >> 2) +#define pgoff_to_pte(x) __pte(((x) << 2) | L_PTE_FILE) + +#define PTE_FILE_MAX_BITS 30 + +#define PTE_BIT_FUNC(fn,op) \ +static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } + +/*PTE_BIT_FUNC(rdprotect, &= ~L_PTE_USER);*/ +/*PTE_BIT_FUNC(mkread, |= L_PTE_USER);*/ +PTE_BIT_FUNC(wrprotect, &= ~L_PTE_WRITE); +PTE_BIT_FUNC(mkwrite, |= L_PTE_WRITE); +PTE_BIT_FUNC(exprotect, &= ~L_PTE_EXEC); +PTE_BIT_FUNC(mkexec, |= L_PTE_EXEC); +PTE_BIT_FUNC(mkclean, &= ~L_PTE_DIRTY); +PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY); +PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG); +PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG); + +/* + * Mark the prot value as uncacheable and unbufferable. + */ +#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) & ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE)) +#define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~L_PTE_CACHEABLE) #define pmd_none(pmd) (!pmd_val(pmd)) #define pmd_present(pmd) (pmd_val(pmd)) +#define pmd_bad(pmd) (pmd_val(pmd) & 2) + +#define set_pmd(pmdp,pmd) \ + do { \ + *pmdp = pmd; \ + flush_pmd_entry(pmdp); \ + } while (0) + +#define pmd_clear(pmdp) \ + do { \ + pmdp[0] = __pmd(0); \ + pmdp[1] = __pmd(0); \ + clean_pmd_entry(pmdp); \ + } while (0) + +static inline pte_t *pmd_page_kernel(pmd_t pmd) +{ + unsigned long ptr; + + ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1); + ptr += PTRS_PER_PTE * sizeof(void *); + + return __va(ptr); +} + +#define pmd_page(pmd) virt_to_page(__va(pmd_val(pmd))) /* * Permanent address of a page. We never have highmem, so this is trivial. @@ -129,8 +322,6 @@ extern struct page *empty_zero_page; /* Find an entry in the third-level page table.. */ #define __pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) -#include <asm/proc/pgtable.h> - static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); @@ -164,6 +355,8 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; typedef pte_t *pte_addr_t; +#define pgtable_cache_init() do { } while (0) + #endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_PGTABLE_H */ diff --git a/include/asm-arm/proc-armo/assembler.h b/include/asm-arm/proc-armo/assembler.h deleted file mode 100644 index 7f6bd57cba74..000000000000 --- a/include/asm-arm/proc-armo/assembler.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * linux/asm-arm/proc-armo/assembler.h - * - * Copyright (C) 1996 Russell King - * - * 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. - * - * This file contains arm architecture specific defines - * for the different processors - */ -#define MODE_USR USR26_MODE -#define MODE_FIQ FIQ26_MODE -#define MODE_IRQ IRQ26_MODE -#define MODE_SVC SVC26_MODE - -#define DEFAULT_FIQ MODE_FIQ - -#ifdef __STDC__ -#define LOADREGS(cond, base, reglist...)\ - ldm##cond base,reglist^ - -#define RETINSTR(instr, regs...)\ - instr##s regs -#else -#define LOADREGS(cond, base, reglist...)\ - ldm/**/cond base,reglist^ - -#define RETINSTR(instr, regs...)\ - instr/**/s regs -#endif - -#define MODENOP\ - mov r0, r0 - -#define MODE(savereg,tmpreg,mode) \ - mov savereg, pc; \ - bic tmpreg, savereg, $0x0c000003; \ - orr tmpreg, tmpreg, $mode; \ - teqp tmpreg, $0 - -#define RESTOREMODE(savereg) \ - teqp savereg, $0 - -#define SAVEIRQS(tmpreg) - -#define RESTOREIRQS(tmpreg) - -#define DISABLEIRQS(tmpreg)\ - teqp pc, $0x08000003 - -#define ENABLEIRQS(tmpreg)\ - teqp pc, $0x00000003 - -#define USERMODE(tmpreg)\ - teqp pc, $0x00000000;\ - mov r0, r0 - -#define SVCMODE(tmpreg)\ - teqp pc, $0x00000003;\ - mov r0, r0 - - -/* - * Save the current IRQ state and disable IRQs - * Note that this macro assumes FIQs are enabled, and - * that the processor is in SVC mode. - */ - .macro save_and_disable_irqs, oldcpsr, temp - mov \oldcpsr, pc - orr \temp, \oldcpsr, #0x08000000 - teqp \temp, #0 - .endm - -/* - * Restore interrupt state previously stored in - * a register - * ** Actually do nothing on Arc - hope that the caller uses a MOVS PC soon - * after! - */ - .macro restore_irqs, oldcpsr - @ This be restore_irqs - .endm - -/* - * These two are used to save LR/restore PC over a user-based access. - * The old 26-bit architecture requires that we do. On 32-bit - * architecture, we can safely ignore this requirement. - */ - .macro save_lr - str lr, [sp, #-4]! - .endm - - .macro restore_pc - ldmfd sp!, {pc}^ - .endm - -#define USER(x...) \ -9999: x; \ - .section __ex_table,"a"; \ - .align 3; \ - .long 9999b,9001f; \ - .previous - - diff --git a/include/asm-arm/proc-armo/cache.h b/include/asm-arm/proc-armo/cache.h deleted file mode 100644 index 47c8125fa719..000000000000 --- a/include/asm-arm/proc-armo/cache.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * linux/include/asm-arm/proc-armo/cache.h - * - * Copyright (C) 1999-2001 Russell King - * - * 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. - * - * Cache handling for 26-bit ARM processors. - */ -#define flush_cache_all() do { } while (0) -#define flush_cache_mm(mm) do { } while (0) -#define flush_cache_range(vma,start,end) do { } while (0) -#define flush_cache_page(vma,vmaddr) do { } while (0) - -#define invalidate_dcache_range(start,end) do { } while (0) -#define clean_dcache_range(start,end) do { } while (0) -#define flush_dcache_range(start,end) do { } while (0) -#define flush_dcache_page(page) do { } while (0) -#define clean_dcache_entry(_s) do { } while (0) -#define clean_cache_entry(_start) do { } while (0) - -#define flush_icache_range(start,end) do { } while (0) -#define flush_icache_page(vma,page) do { } while (0) - -/* DAG: ARM3 will flush cache on MEMC updates anyway? so don't bother */ -#define clean_cache_area(_start,_size) do { } while (0) diff --git a/include/asm-arm/proc-armo/elf.h b/include/asm-arm/proc-armo/elf.h deleted file mode 100644 index b5901f767c6d..000000000000 --- a/include/asm-arm/proc-armo/elf.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * ELF definitions for 26-bit CPUs - */ - -#define ELF_EXEC_PAGESIZE 32768 - -#ifdef __KERNEL__ - -/* We can only execute 26-bit code. */ -#define ELF_PROC_OK(x) \ - ((x)->e_flags & EF_ARM_APCS26) - -#define SET_PERSONALITY(ex,ibcs2) set_personality(PER_LINUX) - -#endif diff --git a/include/asm-arm/proc-armo/locks.h b/include/asm-arm/proc-armo/locks.h deleted file mode 100644 index 81b3bda2ed00..000000000000 --- a/include/asm-arm/proc-armo/locks.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * linux/include/asm-arm/proc-armo/locks.h - * - * Copyright (C) 2000 Russell King - * Fixes for 26 bit machines, (C) 2000 Dave Gilbert - * - * 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. - * - * Interrupt safe locking assembler. - */ -#ifndef __ASM_PROC_LOCKS_H -#define __ASM_PROC_LOCKS_H - -/* Decrements by 1, fails if value < 0 */ -#define __down_op(ptr,fail) \ - ({ \ - __asm__ __volatile__ ( \ - "@ atomic down operation\n" \ -" mov ip, pc\n" \ -" orr lr, ip, #0x08000000\n" \ -" teqp lr, #0\n" \ -" ldr lr, [%0]\n" \ -" and ip, ip, #0x0c000003\n" \ -" subs lr, lr, #1\n" \ -" str lr, [%0]\n" \ -" orrmi ip, ip, #0x80000000 @ set N\n" \ -" teqp ip, #0\n" \ -" movmi ip, %0\n" \ -" blmi " #fail \ - : \ - : "r" (ptr) \ - : "ip", "lr", "cc"); \ - }) - -#define __down_op_ret(ptr,fail) \ - ({ \ - unsigned int result; \ - __asm__ __volatile__ ( \ -" @ down_op_ret\n" \ -" mov ip, pc\n" \ -" orr lr, ip, #0x08000000\n" \ -" teqp lr, #0\n" \ -" ldr lr, [%1]\n" \ -" and ip, ip, #0x0c000003\n" \ -" subs lr, lr, #1\n" \ -" str lr, [%1]\n" \ -" orrmi ip, ip, #0x80000000 @ set N\n" \ -" teqp ip, #0\n" \ -" movmi ip, %1\n" \ -" movpl ip, #0\n" \ -" blmi " #fail "\n" \ -" mov %0, ip" \ - : "=&r" (result) \ - : "r" (ptr) \ - : "ip", "lr", "cc"); \ - result; \ - }) - -#define __up_op(ptr,wake) \ - ({ \ - __asm__ __volatile__ ( \ - "@ up_op\n" \ -" mov ip, pc\n" \ -" orr lr, ip, #0x08000000\n" \ -" teqp lr, #0\n" \ -" ldr lr, [%0]\n" \ -" and ip, ip, #0x0c000003\n" \ -" adds lr, lr, #1\n" \ -" str lr, [%0]\n" \ -" orrle ip, ip, #0x80000000 @ set N - should this be mi ??? DAG ! \n" \ -" teqp ip, #0\n" \ -" movmi ip, %0\n" \ -" blmi " #wake \ - : \ - : "r" (ptr) \ - : "ip", "lr", "cc"); \ - }) - -/* - * The value 0x01000000 supports up to 128 processors and - * lots of processes. BIAS must be chosen such that sub'ing - * BIAS once per CPU will result in the long remaining - * negative. - */ -#define RW_LOCK_BIAS 0x01000000 -#define RW_LOCK_BIAS_STR "0x01000000" - -/* Decrements by RW_LOCK_BIAS rather than 1, fails if value != 0 */ -#define __down_op_write(ptr,fail) \ - ({ \ - __asm__ __volatile__( \ - "@ down_op_write\n" \ -" mov ip, pc\n" \ -" orr lr, ip, #0x08000000\n" \ -" teqp lr, #0\n" \ -" and ip, ip, #0x0c000003\n" \ -\ -" ldr lr, [%0]\n" \ -" subs lr, lr, %1\n" \ -" str lr, [%0]\n" \ -\ -" orreq ip, ip, #0x40000000 @ set Z \n"\ -" teqp ip, #0\n" \ -" movne ip, %0\n" \ -" blne " #fail \ - : \ - : "r" (ptr), "I" (RW_LOCK_BIAS) \ - : "ip", "lr", "cc"); \ - }) - -/* Increments by RW_LOCK_BIAS, wakes if value >= 0 */ -#define __up_op_write(ptr,wake) \ - ({ \ - __asm__ __volatile__( \ - "@ up_op_read\n" \ -" mov ip, pc\n" \ -" orr lr, ip, #0x08000000\n" \ -" teqp lr, #0\n" \ -\ -" ldr lr, [%0]\n" \ -" and ip, ip, #0x0c000003\n" \ -" adds lr, lr, %1\n" \ -" str lr, [%0]\n" \ -\ -" orrcs ip, ip, #0x20000000 @ set C\n" \ -" teqp ip, #0\n" \ -" movcs ip, %0\n" \ -" blcs " #wake \ - : \ - : "r" (ptr), "I" (RW_LOCK_BIAS) \ - : "ip", "lr", "cc"); \ - }) - -#define __down_op_read(ptr,fail) \ - __down_op(ptr, fail) - -#define __up_op_read(ptr,wake) \ - ({ \ - __asm__ __volatile__( \ - "@ up_op_read\n" \ -" mov ip, pc\n" \ -" orr lr, ip, #0x08000000\n" \ -" teqp lr, #0\n" \ -\ -" ldr lr, [%0]\n" \ -" and ip, ip, #0x0c000003\n" \ -" adds lr, lr, %1\n" \ -" str lr, [%0]\n" \ -\ -" orreq ip, ip, #0x40000000 @ Set Z \n" \ -" teqp ip, #0\n" \ -" moveq ip, %0\n" \ -" bleq " #wake \ - : \ - : "r" (ptr), "I" (1) \ - : "ip", "lr", "cc"); \ - }) - -#endif diff --git a/include/asm-arm/proc-armo/page.h b/include/asm-arm/proc-armo/page.h deleted file mode 100644 index d32a7af23b7a..000000000000 --- a/include/asm-arm/proc-armo/page.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * linux/include/asm-arm/proc-armo/page.h - * - * Copyright (C) 1995-2002 Russell King - * - * 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. - */ -#ifndef __ASM_PROC_PAGE_H -#define __ASM_PROC_PAGE_H - -#include <linux/config.h> - -/* PAGE_SHIFT determines the page size. This is configurable. */ -#if defined(CONFIG_PAGESIZE_16) -#define PAGE_SHIFT 14 /* 16K */ -#else /* default */ -#define PAGE_SHIFT 15 /* 32K */ -#endif - -#define EXEC_PAGESIZE 32768 - -#ifndef __ASSEMBLY__ -#ifdef STRICT_MM_TYPECHECKS - -typedef struct { unsigned long pgd; } pgd_t; - -#define pgd_val(x) ((x).pgd) - -#else - -typedef unsigned long pgd_t; - -#define pgd_val(x) (x) - -#endif -#endif /* __ASSEMBLY__ */ - -#endif /* __ASM_PROC_PAGE_H */ diff --git a/include/asm-arm/proc-armo/pgalloc.h b/include/asm-arm/proc-armo/pgalloc.h deleted file mode 100644 index 7b9bf375abc7..000000000000 --- a/include/asm-arm/proc-armo/pgalloc.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * linux/include/asm-arm/proc-armo/pgalloc.h - * - * Copyright (C) 2001-2002 Russell King - * - * Page table allocation/freeing primitives for 26-bit ARM processors. - */ - -#include <linux/slab.h> - -extern kmem_cache_t *pte_cache; - -static inline pte_t * -pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) -{ - return kmem_cache_alloc(pte_cache, GFP_KERNEL); -} - -static inline void pte_free_kernel(pte_t *pte) -{ - if (pte) - kmem_cache_free(pte_cache, pte); -} - -/* - * Populate the pmdp entry with a pointer to the pte. This pmd is part - * of the mm address space. - * - * If 'mm' is the init tasks mm, then we are doing a vmalloc, and we - * need to set stuff up correctly for it. - */ -static inline void -pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) -{ - set_pmd(pmdp, __mk_pmd(ptep, _PAGE_TABLE)); -} - -/* - * We use the old 2.5.5-rmk1 hack for this. - * This is not truly correct, but should be functional. - */ -#define pte_alloc_one(mm,addr) ((struct page *)pte_alloc_one_kernel(mm,addr)) -#define pte_free(pte) pte_free_kernel((pte_t *)pte) -#define pmd_populate(mm,pmdp,ptep) pmd_populate_kernel(mm,pmdp,(pte_t *)ptep) diff --git a/include/asm-arm/proc-armo/pgtable.h b/include/asm-arm/proc-armo/pgtable.h deleted file mode 100644 index 152504bc9888..000000000000 --- a/include/asm-arm/proc-armo/pgtable.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * linux/include/asm-arm/proc-armo/pgtable.h - * - * Copyright (C) 1995-2002 Russell King - * - * 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. - * - * 18-Oct-1997 RMK Now two-level (32x32) - */ -#ifndef __ASM_PROC_PGTABLE_H -#define __ASM_PROC_PGTABLE_H - -/* - * entries per page directory level: they are two-level, so - * we don't really have any PMD directory. - */ -#define PTRS_PER_PTE 32 -#define PTRS_PER_PMD 1 -#define PTRS_PER_PGD 32 - -/* - * The vmalloc() routines leaves a hole of 4kB between each vmalloced - * area for the same reason. ;) - */ -#define VMALLOC_START 0x01a00000 -#define VMALLOC_VMADDR(x) ((unsigned long)(x)) -#define VMALLOC_END 0x01c00000 - -#define _PAGE_TABLE (0x01) - -#define pmd_bad(pmd) ((pmd_val(pmd) & 0xfc000002)) -#define set_pmd(pmdp,pmd) ((*(pmdp)) = (pmd)) -#define pmd_clear(pmdp) set_pmd(pmdp, __pmd(0)) - -static inline pmd_t __mk_pmd(pte_t *ptep, unsigned long prot) -{ - unsigned long pte_ptr = (unsigned long)ptep; - pmd_t pmd; - - pmd_val(pmd) = __virt_to_phys(pte_ptr) | prot; - - return pmd; -} - -static inline unsigned long pmd_page(pmd_t pmd) -{ - return __phys_to_virt(pmd_val(pmd) & ~_PAGE_TABLE); -} - -#define pte_offset_kernel(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr)) -#define pte_offset_map(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr)) -#define pte_offset_map_nested(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr)) -#define pte_unmap(pte) do { } while (0) -#define pte_unmap_nested(pte) do { } while (0) - -#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval)) - -#define _PAGE_PRESENT 0x01 -#define _PAGE_READONLY 0x02 -#define _PAGE_NOT_USER 0x04 -#define _PAGE_OLD 0x08 -#define _PAGE_CLEAN 0x10 - -/* -- present -- -- !dirty -- --- !write --- ---- !user --- */ -#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY | _PAGE_NOT_USER) -#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_CLEAN ) -#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY ) -#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY ) -#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_NOT_USER) - -#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_OLD | _PAGE_CLEAN) - - -/* - * The following only work if pte_present() is true. - * Undefined behaviour if not.. - */ -#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) -#define pte_read(pte) (!(pte_val(pte) & _PAGE_NOT_USER)) -#define pte_write(pte) (!(pte_val(pte) & _PAGE_READONLY)) -#define pte_exec(pte) (!(pte_val(pte) & _PAGE_NOT_USER)) -#define pte_dirty(pte) (!(pte_val(pte) & _PAGE_CLEAN)) -#define pte_young(pte) (!(pte_val(pte) & _PAGE_OLD)) - -static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_READONLY; return pte; } -static inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) |= _PAGE_NOT_USER; return pte; } -static inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) |= _PAGE_NOT_USER; return pte; } -static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) |= _PAGE_CLEAN; return pte; } -static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) |= _PAGE_OLD; return pte; } - -static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= ~_PAGE_READONLY; return pte; } -static inline pte_t pte_mkread(pte_t pte) { pte_val(pte) &= ~_PAGE_NOT_USER; return pte; } -static inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) &= ~_PAGE_NOT_USER; return pte; } -static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) &= ~_PAGE_CLEAN; return pte; } -static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) &= ~_PAGE_OLD; return pte; } - -/* - * We don't store cache state bits in the page table here. - */ -#define pgprot_noncached(prot) (prot) - -extern void pgtable_cache_init(void); - -#endif /* __ASM_PROC_PGTABLE_H */ diff --git a/include/asm-arm/proc-armo/processor.h b/include/asm-arm/proc-armo/processor.h deleted file mode 100644 index aba9dbaa61b7..000000000000 --- a/include/asm-arm/proc-armo/processor.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * linux/include/asm-arm/proc-armo/processor.h - * - * Copyright (C) 1996 Russell King. - * - * 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. - * - * Changelog: - * 27-06-1996 RMK Created - * 10-10-1996 RMK Brought up to date with SA110 - * 26-09-1996 RMK Added 'EXTRA_THREAD_STRUCT*' - * 28-09-1996 RMK Moved start_thread into the processor dependencies - * 11-01-1998 RMK Added new uaccess_t - * 09-09-1998 PJB Delete redundant `wp_works_ok' - * 30-05-1999 PJB Save sl across context switches - */ -#ifndef __ASM_PROC_PROCESSOR_H -#define __ASM_PROC_PROCESSOR_H - -#include <linux/string.h> - -#define KERNEL_STACK_SIZE 4096 - -typedef struct { - void (*put_byte)(void); /* Special calling convention */ - void (*get_byte)(void); /* Special calling convention */ - void (*put_half)(void); /* Special calling convention */ - void (*get_half)(void); /* Special calling convention */ - void (*put_word)(void); /* Special calling convention */ - void (*get_word)(void); /* Special calling convention */ - unsigned long (*copy_from_user)(void *to, const void *from, unsigned long sz); - unsigned long (*copy_to_user)(void *to, const void *from, unsigned long sz); - unsigned long (*clear_user)(void *addr, unsigned long sz); - unsigned long (*strncpy_from_user)(char *to, const char *from, unsigned long sz); - unsigned long (*strnlen_user)(const char *s, long n); -} uaccess_t; - -extern uaccess_t uaccess_user, uaccess_kernel; - -#define EXTRA_THREAD_STRUCT \ - uaccess_t *uaccess; /* User access functions*/ - -#define EXTRA_THREAD_STRUCT_INIT \ - .uaccess = &uaccess_kernel, - -#define start_thread(regs,pc,sp) \ -({ \ - unsigned long *stack = (unsigned long *)sp; \ - set_fs(USER_DS); \ - memzero(regs->uregs, sizeof (regs->uregs)); \ - regs->ARM_pc = pc; /* pc */ \ - regs->ARM_sp = sp; /* sp */ \ - regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ - regs->ARM_r1 = stack[1]; /* r1 (argv) */ \ - regs->ARM_r0 = stack[0]; /* r0 (argc) */ \ -}) - -#define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1020]) -#define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1018]) - -#endif diff --git a/include/asm-arm/proc-armo/ptrace.h b/include/asm-arm/proc-armo/ptrace.h deleted file mode 100644 index 79d44f4f71d8..000000000000 --- a/include/asm-arm/proc-armo/ptrace.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * linux/include/asm-arm/proc-armo/ptrace.h - * - * Copyright (C) 1996-2001 Russell King - * - * 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. - */ -#ifndef __ASM_PROC_PTRACE_H -#define __ASM_PROC_PTRACE_H - -#define USR26_MODE 0x00000000 -#define FIQ26_MODE 0x00000001 -#define IRQ26_MODE 0x00000002 -#define SVC26_MODE 0x00000003 -#define USR_MODE USR26_MODE -#define FIQ_MODE FIQ26_MODE -#define IRQ_MODE IRQ26_MODE -#define SVC_MODE SVC26_MODE -#define MODE_MASK 0x00000003 -#define PSR_F_BIT 0x04000000 -#define PSR_I_BIT 0x08000000 -#define PSR_V_BIT 0x10000000 -#define PSR_C_BIT 0x20000000 -#define PSR_Z_BIT 0x40000000 -#define PSR_N_BIT 0x80000000 -#define PCMASK 0xfc000003 - -#ifndef __ASSEMBLY__ - -/* this struct defines the way the registers are stored on the - stack during a system call. */ - -struct pt_regs { - long uregs[17]; -}; - -#define ARM_pc uregs[15] -#define ARM_lr uregs[14] -#define ARM_sp uregs[13] -#define ARM_ip uregs[12] -#define ARM_fp uregs[11] -#define ARM_r10 uregs[10] -#define ARM_r9 uregs[9] -#define ARM_r8 uregs[8] -#define ARM_r7 uregs[7] -#define ARM_r6 uregs[6] -#define ARM_r5 uregs[5] -#define ARM_r4 uregs[4] -#define ARM_r3 uregs[3] -#define ARM_r2 uregs[2] -#define ARM_r1 uregs[1] -#define ARM_r0 uregs[0] -#define ARM_ORIG_r0 uregs[16] - -#ifdef __KERNEL__ - -#define processor_mode(regs) \ - ((regs)->ARM_pc & MODE_MASK) - -#define user_mode(regs) \ - (processor_mode(regs) == USR26_MODE) - -#define thumb_mode(regs) (0) - -#define interrupts_enabled(regs) \ - (!((regs)->ARM_pc & PSR_I_BIT)) - -#define fast_interrupts_enabled(regs) \ - (!((regs)->ARM_pc & PSR_F_BIT)) - -#define condition_codes(regs) \ - ((regs)->ARM_pc & (PSR_V_BIT|PSR_C_BIT|PSR_Z_BIT|PSR_N_BIT)) - -/* Are the current registers suitable for user mode? - * (used to maintain security in signal handlers) - */ -static inline int valid_user_regs(struct pt_regs *regs) -{ - if (user_mode(regs) && - (regs->ARM_pc & (PSR_F_BIT | PSR_I_BIT)) == 0) - return 1; - - /* - * force it to be something sensible - */ - regs->ARM_pc &= ~(MODE_MASK | PSR_F_BIT | PSR_I_BIT); - - return 0; -} - -#endif /* __KERNEL__ */ - -#endif /* __ASSEMBLY__ */ - -#endif - diff --git a/include/asm-arm/proc-armo/shmparam.h b/include/asm-arm/proc-armo/shmparam.h deleted file mode 100644 index 6b106f1419e8..000000000000 --- a/include/asm-arm/proc-armo/shmparam.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * linux/include/asm-arm/proc-armo/shmparam.h - * - * Copyright (C) 1996 Russell King - * - * 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. - * - * definitions for the shared process memory on the ARM3 - */ -#ifndef __ASM_PROC_SHMPARAM_H -#define __ASM_PROC_SHMPARAM_H - -#ifndef SHMMAX -#define SHMMAX 0x003fa000 -#endif - -#endif diff --git a/include/asm-arm/proc-armo/system.h b/include/asm-arm/proc-armo/system.h deleted file mode 100644 index 9e46e58f56e4..000000000000 --- a/include/asm-arm/proc-armo/system.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * linux/include/asm-arm/proc-armo/system.h - * - * Copyright (C) 1995, 1996 Russell King - * - * 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. - */ -#ifndef __ASM_PROC_SYSTEM_H -#define __ASM_PROC_SYSTEM_H - -#define vectors_base() (0) - -static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) -{ - extern void __bad_xchg(volatile void *, int); - - switch (size) { - case 1: return cpu_xchg_1(x, ptr); - case 4: return cpu_xchg_4(x, ptr); - default: __bad_xchg(ptr, size); - } - return 0; -} - -/* - * We need to turn the caches off before calling the reset vector - RiscOS - * messes up if we don't - */ -#define proc_hard_reset() cpu_proc_fin() - -/* - * A couple of speedups for the ARM - */ - -/* - * Save the current interrupt enable state & disable IRQs - */ -#define local_save_flags_cli(x) \ - do { \ - unsigned long temp; \ - __asm__ __volatile__( \ -" mov %0, pc @ save_flags_cli\n" \ -" orr %1, %0, #0x08000000\n" \ -" and %0, %0, #0x0c000000\n" \ -" teqp %1, #0\n" \ - : "=r" (x), "=r" (temp) \ - : \ - : "memory"); \ - } while (0) - -/* - * Enable IRQs - */ -#define local_irq_enable() \ - do { \ - unsigned long temp; \ - __asm__ __volatile__( \ -" mov %0, pc @ sti\n" \ -" bic %0, %0, #0x08000000\n" \ -" teqp %0, #0\n" \ - : "=r" (temp) \ - : \ - : "memory"); \ - } while(0) - -/* - * Disable IRQs - */ -#define local_irq_disable() \ - do { \ - unsigned long temp; \ - __asm__ __volatile__( \ -" mov %0, pc @ cli\n" \ -" orr %0, %0, #0x08000000\n" \ -" teqp %0, #0\n" \ - : "=r" (temp) \ - : \ - : "memory"); \ - } while(0) - -#define __clf() do { \ - unsigned long temp; \ - __asm__ __volatile__( \ -" mov %0, pc @ clf\n" \ -" orr %0, %0, #0x04000000\n" \ -" teqp %0, #0\n" \ - : "=r" (temp)); \ - } while(0) - -#define __stf() do { \ - unsigned long temp; \ - __asm__ __volatile__( \ -" mov %0, pc @ stf\n" \ -" bic %0, %0, #0x04000000\n" \ -" teqp %0, #0\n" \ - : "=r" (temp)); \ - } while(0) - -/* - * save current IRQ & FIQ state - */ -#define local_save_flags(x) \ - do { \ - __asm__ __volatile__( \ -" mov %0, pc @ save_flags\n" \ -" and %0, %0, #0x0c000000\n" \ - : "=r" (x)); \ - } while (0) - -/* - * restore saved IRQ & FIQ state - */ -#define local_irq_restore(x) \ - do { \ - unsigned long temp; \ - __asm__ __volatile__( \ -" mov %0, pc @ restore_flags\n" \ -" bic %0, %0, #0x0c000000\n" \ -" orr %0, %0, %1\n" \ -" teqp %0, #0\n" \ - : "=&r" (temp) \ - : "r" (x) \ - : "memory"); \ - } while (0) - -#endif diff --git a/include/asm-arm/proc-armo/tlbflush.h b/include/asm-arm/proc-armo/tlbflush.h deleted file mode 100644 index f10e5b66b596..000000000000 --- a/include/asm-arm/proc-armo/tlbflush.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * TLB flushing: - * - * - flush_tlb_all() flushes all processes TLBs - * - flush_tlb_mm(mm) flushes the specified mm context TLB's - * - flush_tlb_page(vma, vmaddr) flushes one page - * - flush_tlb_range(vma, start, end) flushes a range of pages - */ -#define flush_tlb_all() memc_update_all() -#define flush_tlb_mm(mm) memc_update_mm(mm) -#define flush_tlb_range(vma,start,end) \ - do { memc_update_mm(vma->vm_mm); (void)(start); (void)(end); } while (0) -#define flush_tlb_page(vma, vmaddr) do { } while (0) - -/* - * The following handle the weird MEMC chip - */ -static inline void memc_update_all(void) -{ - struct task_struct *p; - - cpu_memc_update_all(init_mm.pgd); - for_each_task(p) { - if (!p->mm) - continue; - cpu_memc_update_all(p->mm->pgd); - } - processor._set_pgd(current->active_mm->pgd); -} - -static inline void memc_update_mm(struct mm_struct *mm) -{ - cpu_memc_update_all(mm->pgd); - - if (mm == current->active_mm) - processor._set_pgd(mm->pgd); -} - -static inline void -memc_clear(struct mm_struct *mm, struct page *page) -{ - cpu_memc_update_entry(mm->pgd, (unsigned long) page_address(page), 0); - - if (mm == current->active_mm) - processor._set_pgd(mm->pgd); -} - -static inline void -memc_update_addr(struct mm_struct *mm, pte_t pte, unsigned long vaddr) -{ - cpu_memc_update_entry(mm->pgd, pte_val(pte), vaddr); - - if (mm == current->active_mm) - processor._set_pgd(mm->pgd); -} - -static inline void -update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) -{ - struct mm_struct *mm = vma->vm_mm; - memc_update_addr(mm, pte, addr); -} - diff --git a/include/asm-arm/proc-armo/uaccess.h b/include/asm-arm/proc-armo/uaccess.h deleted file mode 100644 index 77fcf9e482a5..000000000000 --- a/include/asm-arm/proc-armo/uaccess.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * linux/include/asm-arm/proc-armo/segment.h - * - * Copyright (C) 1996 Russell King - * - * 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 fs functions are implemented on the ARM2 and ARM3 architectures - * manually. - * Use *_user functions to access user memory with faulting behaving - * as though the user is accessing the memory. - * Use set_fs(get_ds()) and then the *_user functions to allow them to - * access kernel memory. - */ - -/* - * These are the values used to represent the user `fs' and the kernel `ds' - */ -#define KERNEL_DS 0x03000000 -#define USER_DS 0x02000000 - -extern uaccess_t uaccess_user, uaccess_kernel; - -static inline void set_fs (mm_segment_t fs) -{ - current->addr_limit = fs; - current->thread.uaccess = fs == USER_DS ? &uaccess_user : &uaccess_kernel; -} - -#define __range_ok(addr,size) ({ \ - unsigned long flag, sum; \ - __asm__ __volatile__("subs %1, %0, %3; cmpcs %1, %2; movcs %0, #0" \ - : "=&r" (flag), "=&r" (sum) \ - : "r" (addr), "Ir" (size), "0" (current->addr_limit) \ - : "cc"); \ - flag; }) - -#define __addr_ok(addr) ({ \ - unsigned long flag; \ - __asm__ __volatile__("cmp %2, %0; movlo %0, #0" \ - : "=&r" (flag) \ - : "0" (current->addr_limit), "r" (addr) \ - : "cc"); \ - (flag == 0); }) - -#define __put_user_asm_byte(x,addr,err) \ - __asm__ __volatile__( \ - " mov r0, %1\n" \ - " mov r1, %2\n" \ - " mov r2, %0\n" \ - " mov lr, pc\n" \ - " mov pc, %3\n" \ - " mov %0, r2\n" \ - : "=r" (err) \ - : "r" (x), "r" (addr), "r" (current->thread.uaccess->put_byte), \ - "0" (err) \ - : "r0", "r1", "r2", "lr") - -#define __put_user_asm_half(x,addr,err) \ - __asm__ __volatile__( \ - " mov r0, %1\n" \ - " mov r1, %2\n" \ - " mov r2, %0\n" \ - " mov lr, pc\n" \ - " mov pc, %3\n" \ - " mov %0, r2\n" \ - : "=r" (err) \ - : "r" (x), "r" (addr), "r" (current->thread.uaccess->put_half), \ - "0" (err) \ - : "r0", "r1", "r2", "lr") - -#define __put_user_asm_word(x,addr,err) \ - __asm__ __volatile__( \ - " mov r0, %1\n" \ - " mov r1, %2\n" \ - " mov r2, %0\n" \ - " mov lr, pc\n" \ - " mov pc, %3\n" \ - " mov %0, r2\n" \ - : "=r" (err) \ - : "r" (x), "r" (addr), "r" (current->thread.uaccess->put_word), \ - "0" (err) \ - : "r0", "r1", "r2", "lr") - -#define __get_user_asm_byte(x,addr,err) \ - __asm__ __volatile__( \ - " mov r0, %2\n" \ - " mov r1, %0\n" \ - " mov lr, pc\n" \ - " mov pc, %3\n" \ - " mov %0, r1\n" \ - " mov %1, r0\n" \ - : "=r" (err), "=r" (x) \ - : "r" (addr), "r" (current->thread.uaccess->get_byte), "0" (err) \ - : "r0", "r1", "r2", "lr") - -#define __get_user_asm_half(x,addr,err) \ - __asm__ __volatile__( \ - " mov r0, %2\n" \ - " mov r1, %0\n" \ - " mov lr, pc\n" \ - " mov pc, %3\n" \ - " mov %0, r1\n" \ - " mov %1, r0\n" \ - : "=r" (err), "=r" (x) \ - : "r" (addr), "r" (current->thread.uaccess->get_half), "0" (err) \ - : "r0", "r1", "r2", "lr") - -#define __get_user_asm_word(x,addr,err) \ - __asm__ __volatile__( \ - " mov r0, %2\n" \ - " mov r1, %0\n" \ - " mov lr, pc\n" \ - " mov pc, %3\n" \ - " mov %0, r1\n" \ - " mov %1, r0\n" \ - : "=r" (err), "=r" (x) \ - : "r" (addr), "r" (current->thread.uaccess->get_word), "0" (err) \ - : "r0", "r1", "r2", "lr") - -#define __do_copy_from_user(to,from,n) \ - (n) = current->thread.uaccess->copy_from_user((to),(from),(n)) - -#define __do_copy_to_user(to,from,n) \ - (n) = current->thread.uaccess->copy_to_user((to),(from),(n)) - -#define __do_clear_user(addr,sz) \ - (sz) = current->thread.uaccess->clear_user((addr),(sz)) - -#define __do_strncpy_from_user(dst,src,count,res) \ - (res) = current->thread.uaccess->strncpy_from_user(dst,src,count) - -#define __do_strnlen_user(s,n,res) \ - (res) = current->thread.uaccess->strnlen_user(s,n) diff --git a/include/asm-arm/proc-armv/assembler.h b/include/asm-arm/proc-armv/assembler.h deleted file mode 100644 index 64916c820b33..000000000000 --- a/include/asm-arm/proc-armv/assembler.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * linux/asm-arm/proc-armv/assembler.h - * - * Copyright (C) 1996-2000 Russell King - * - * 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. - * - * This file contains ARM processor specifics for - * the ARM6 and better processors. - */ -#define MODE_USR USR_MODE -#define MODE_FIQ FIQ_MODE -#define MODE_IRQ IRQ_MODE -#define MODE_SVC SVC_MODE - -#define DEFAULT_FIQ MODE_FIQ - -/* - * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc}) - */ -#ifdef __STDC__ -#define LOADREGS(cond, base, reglist...)\ - ldm##cond base,reglist -#else -#define LOADREGS(cond, base, reglist...)\ - ldm/**/cond base,reglist -#endif - -/* - * Build a return instruction for this processor type. - */ -#define RETINSTR(instr, regs...)\ - instr regs - -/* - * Save the current IRQ state and disable IRQs. Note that this macro - * assumes FIQs are enabled, and that the processor is in SVC mode. - */ - .macro save_and_disable_irqs, oldcpsr, temp - mrs \oldcpsr, cpsr - mov \temp, #PSR_I_BIT | MODE_SVC - msr cpsr_c, \temp - .endm - -/* - * Restore interrupt state previously stored in a register. We don't - * guarantee that this will preserve the flags. - */ - .macro restore_irqs, oldcpsr - msr cpsr_c, \oldcpsr - .endm - -/* - * These two are used to save LR/restore PC over a user-based access. - * The old 26-bit architecture requires that we do. On 32-bit - * architecture, we can safely ignore this requirement. - */ - .macro save_lr - .endm - - .macro restore_pc - mov pc, lr - .endm - -#define USER(x...) \ -9999: x; \ - .section __ex_table,"a"; \ - .align 3; \ - .long 9999b,9001f; \ - .previous - - diff --git a/include/asm-arm/proc-armv/cache.h b/include/asm-arm/proc-armv/cache.h deleted file mode 100644 index 250a69e335ff..000000000000 --- a/include/asm-arm/proc-armv/cache.h +++ /dev/null @@ -1,278 +0,0 @@ -/* - * linux/include/asm-arm/proc-armv/cache.h - * - * Copyright (C) 1999-2002 Russell King - * - * 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. - */ -#include <asm/mman.h> -#include <asm/glue.h> - -/* - * Cache Model - * =========== - */ -#undef _CACHE -#undef MULTI_CACHE - -#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE v3 -# endif -#endif - -#if defined(CONFIG_CPU_ARM720T) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE v4 -# endif -#endif - -#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \ - defined(CONFIG_CPU_ARM1020) -# define MULTI_CACHE 1 -#endif - -#if defined(CONFIG_CPU_ARM926T) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE arm926 -# endif -#endif - -#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE v4wb -# endif -#endif - -#if defined(CONFIG_CPU_XSCALE) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE xscale -# endif -#endif - -#if !defined(_CACHE) && !defined(MULTI_CACHE) -#error Unknown cache maintainence model -#endif - -/* - * This flag is used to indicate that the page pointed to by a pte - * is dirty and requires cleaning before returning it to the user. - */ -#define PG_dcache_dirty PG_arch_1 - -/* - * MM Cache Management - * =================== - * - * The arch/arm/mm/cache-*.S and arch/arm/mm/proc-*.S files - * implement these methods. - * - * Start addresses are inclusive and end addresses are exclusive; - * start addresses should be rounded down, end addresses up. - * - * See linux/Documentation/cachetlb.txt for more information. - * Please note that the implementation of these, and the required - * effects are cache-type (VIVT/VIPT/PIPT) specific. - * - * flush_cache_kern_all() - * - * Unconditionally clean and invalidate the entire cache. - * - * flush_cache_user_mm(mm) - * - * Clean and invalidate all user space cache entries - * before a change of page tables. - * - * flush_cache_user_range(start, end, flags) - * - * Clean and invalidate a range of cache entries in the - * specified address space before a change of page tables. - * - start - user start address (inclusive, page aligned) - * - end - user end address (exclusive, page aligned) - * - flags - vma->vm_flags field - * - * coherent_kern_range(start, end) - * - * Ensure coherency between the Icache and the Dcache in the - * region described by start, end. If you have non-snooping - * Harvard caches, you need to implement this function. - * - start - virtual start address - * - end - virtual end address - * - * DMA Cache Coherency - * =================== - * - * dma_inv_range(start, end) - * - * Invalidate (discard) the specified virtual address range. - * May not write back any entries. If 'start' or 'end' - * are not cache line aligned, those lines must be written - * back. - * - start - virtual start address - * - end - virtual end address - * - * dma_clean_range(start, end) - * - * Clean (write back) the specified virtual address range. - * - start - virtual start address - * - end - virtual end address - * - * dma_flush_range(start, end) - * - * Clean and invalidate the specified virtual address range. - * - start - virtual start address - * - end - virtual end address - */ - -struct cpu_cache_fns { - void (*flush_kern_all)(void); - void (*flush_user_all)(void); - void (*flush_user_range)(unsigned long, unsigned long, unsigned int); - - void (*coherent_kern_range)(unsigned long, unsigned long); - void (*flush_kern_dcache_page)(void *); - - void (*dma_inv_range)(unsigned long, unsigned long); - void (*dma_clean_range)(unsigned long, unsigned long); - void (*dma_flush_range)(unsigned long, unsigned long); -}; - -/* - * Select the calling method - */ -#ifdef MULTI_CACHE - -extern struct cpu_cache_fns cpu_cache; - -#define __cpuc_flush_kern_all cpu_cache.flush_kern_all -#define __cpuc_flush_user_all cpu_cache.flush_user_all -#define __cpuc_flush_user_range cpu_cache.flush_user_range -#define __cpuc_coherent_kern_range cpu_cache.coherent_kern_range -#define __cpuc_flush_dcache_page cpu_cache.flush_kern_dcache_page - -/* - * These are private to the dma-mapping API. Do not use directly. - * Their sole purpose is to ensure that data held in the cache - * is visible to DMA, or data written by DMA to system memory is - * visible to the CPU. - */ -#define dmac_inv_range cpu_cache.dma_inv_range -#define dmac_clean_range cpu_cache.dma_clean_range -#define dmac_flush_range cpu_cache.dma_flush_range - -#else - -#define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) -#define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all) -#define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range) -#define __cpuc_coherent_kern_range __glue(_CACHE,_coherent_kern_range) -#define __cpuc_flush_dcache_page __glue(_CACHE,_flush_kern_dcache_page) - -extern void __cpuc_flush_kern_all(void); -extern void __cpuc_flush_user_all(void); -extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int); -extern void __cpuc_coherent_kern_range(unsigned long, unsigned long); -extern void __cpuc_flush_dcache_page(void *); - -/* - * These are private to the dma-mapping API. Do not use directly. - * Their sole purpose is to ensure that data held in the cache - * is visible to DMA, or data written by DMA to system memory is - * visible to the CPU. - */ -#define dmac_inv_range __glue(_CACHE,_dma_inv_range) -#define dmac_clean_range __glue(_CACHE,_dma_clean_range) -#define dmac_flush_range __glue(_CACHE,_dma_flush_range) - -extern void dmac_inv_range(unsigned long, unsigned long); -extern void dmac_clean_range(unsigned long, unsigned long); -extern void dmac_flush_range(unsigned long, unsigned long); - -#endif - -/* - * Convert calls to our calling convention. - */ -#define flush_cache_all() __cpuc_flush_kern_all() - -static inline void flush_cache_mm(struct mm_struct *mm) -{ - if (current->active_mm == mm) - __cpuc_flush_user_all(); -} - -static inline void -flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) -{ - if (current->active_mm == vma->vm_mm) - __cpuc_flush_user_range(start & PAGE_MASK, PAGE_ALIGN(end), - vma->vm_flags); -} - -static inline void -flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr) -{ - if (current->active_mm == vma->vm_mm) { - unsigned long addr = user_addr & PAGE_MASK; - __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); - } -} - -/* - * Perform necessary cache operations to ensure that data previously - * stored within this range of addresses can be executed by the CPU. - */ -#define flush_icache_range(s,e) __cpuc_coherent_kern_range(s,e) - -/* - * Perform necessary cache operations to ensure that the TLB will - * see data written in the specified area. - */ -#define clean_dcache_area(start,size) cpu_dcache_clean_area(start, size) - -/* - * flush_dcache_page is used when the kernel has written to the page - * cache page at virtual address page->virtual. - * - * If this page isn't mapped (ie, page->mapping = NULL), or it has - * userspace mappings (page->mapping->i_mmap or page->mapping->i_mmap_shared) - * then we _must_ always clean + invalidate the dcache entries associated - * with the kernel mapping. - * - * Otherwise we can defer the operation, and clean the cache when we are - * about to change to user space. This is the same method as used on SPARC64. - * See update_mmu_cache for the user space part. - */ -#define mapping_mapped(map) (!list_empty(&(map)->i_mmap) || \ - !list_empty(&(map)->i_mmap_shared)) - -extern void __flush_dcache_page(struct page *); - -static inline void flush_dcache_page(struct page *page) -{ - if (page->mapping && !mapping_mapped(page->mapping)) - set_bit(PG_dcache_dirty, &page->flags); - else - __flush_dcache_page(page); -} - -#define flush_icache_user_range(vma,page,addr,len) \ - flush_dcache_page(page) - -/* - * We don't appear to need to do anything here. In fact, if we did, we'd - * duplicate cache flushing elsewhere performed by flush_dcache_page(). - */ -#define flush_icache_page(vma,page) do { } while (0) diff --git a/include/asm-arm/proc-armv/elf.h b/include/asm-arm/proc-armv/elf.h deleted file mode 100644 index 1b8a0ac3b2b5..000000000000 --- a/include/asm-arm/proc-armv/elf.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * ELF definitions for 32-bit CPUs - */ - -#define ELF_EXEC_PAGESIZE 4096 - -#ifdef __KERNEL__ - -/* - * 32-bit code is always OK. Some cpus can do 26-bit, some can't. - */ -#define ELF_PROC_OK(x) (ELF_THUMB_OK(x) && ELF_26BIT_OK(x)) - -#define ELF_THUMB_OK(x) \ - (( (elf_hwcap & HWCAP_THUMB) && ((x)->e_entry & 1) == 1) || \ - ((x)->e_entry & 3) == 0) - -#define ELF_26BIT_OK(x) \ - (( (elf_hwcap & HWCAP_26BIT) && (x)->e_flags & EF_ARM_APCS26) || \ - ((x)->e_flags & EF_ARM_APCS26) == 0) - -/* Old NetWinder binaries were compiled in such a way that the iBCS - heuristic always trips on them. Until these binaries become uncommon - enough not to care, don't trust the `ibcs' flag here. In any case - there is no other ELF system currently supported by iBCS. - @@ Could print a warning message to encourage users to upgrade. */ -#define SET_PERSONALITY(ex,ibcs2) \ - set_personality(((ex).e_flags&EF_ARM_APCS26 ?PER_LINUX :PER_LINUX_32BIT)) - -#endif diff --git a/include/asm-arm/proc-armv/page.h b/include/asm-arm/proc-armv/page.h deleted file mode 100644 index 726b16df7195..000000000000 --- a/include/asm-arm/proc-armv/page.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * linux/include/asm-arm/proc-armv/page.h - * - * Copyright (C) 1995-2002 Russell King - * - * 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. - */ -#ifndef __ASM_PROC_PAGE_H -#define __ASM_PROC_PAGE_H - -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT 12 - -#define EXEC_PAGESIZE 4096 - -#ifndef __ASSEMBLY__ -#ifdef STRICT_MM_TYPECHECKS - -typedef struct { - unsigned long pgd0; - unsigned long pgd1; -} pgd_t; - -#define pgd_val(x) ((x).pgd0) - -#else - -typedef unsigned long pgd_t[2]; - -#define pgd_val(x) ((x)[0]) - -#endif -#endif /* __ASSEMBLY__ */ - -#endif /* __ASM_PROC_PAGE_H */ diff --git a/include/asm-arm/proc-armv/pgalloc.h b/include/asm-arm/proc-armv/pgalloc.h deleted file mode 100644 index 0e65ab7362e4..000000000000 --- a/include/asm-arm/proc-armv/pgalloc.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * linux/include/asm-arm/proc-armv/pgalloc.h - * - * Copyright (C) 2001-2002 Russell King - * - * Page table allocation/freeing primitives for 32-bit ARM processors. - */ -#include <asm/cacheflush.h> -#include <asm/tlbflush.h> -#include "pgtable.h" - -/* - * Allocate one PTE table. - * - * This actually allocates two hardware PTE tables, but we wrap this up - * into one table thus: - * - * +------------+ - * | h/w pt 0 | - * +------------+ - * | h/w pt 1 | - * +------------+ - * | Linux pt 0 | - * +------------+ - * | Linux pt 1 | - * +------------+ - */ -static inline pte_t * -pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) -{ - pte_t *pte; - - pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); - if (pte) { - clear_page(pte); - clean_dcache_area(pte, sizeof(pte_t) * PTRS_PER_PTE); - pte += PTRS_PER_PTE; - } - - return pte; -} - -static inline struct page * -pte_alloc_one(struct mm_struct *mm, unsigned long addr) -{ - struct page *pte; - - pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0); - if (pte) { - void *page = page_address(pte); - clear_page(page); - clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE); - } - - return pte; -} - -/* - * Free one PTE table. - */ -static inline void pte_free_kernel(pte_t *pte) -{ - if (pte) { - pte -= PTRS_PER_PTE; - free_page((unsigned long)pte); - } -} - -static inline void pte_free(struct page *pte) -{ - __free_page(pte); -} - -/* - * Populate the pmdp entry with a pointer to the pte. This pmd is part - * of the mm address space. - * - * Ensure that we always set both PMD entries. - */ -static inline void -pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) -{ - unsigned long pte_ptr = (unsigned long)ptep; - unsigned long pmdval; - - BUG_ON(mm != &init_mm); - - /* - * The pmd must be loaded with the physical - * address of the PTE table - */ - pte_ptr -= PTRS_PER_PTE * sizeof(void *); - pmdval = __pa(pte_ptr) | _PAGE_KERNEL_TABLE; - pmdp[0] = __pmd(pmdval); - pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); - flush_pmd_entry(pmdp); -} - -static inline void -pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep) -{ - unsigned long pmdval; - - BUG_ON(mm == &init_mm); - - pmdval = page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE; - pmdp[0] = __pmd(pmdval); - pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); - flush_pmd_entry(pmdp); -} diff --git a/include/asm-arm/proc-armv/pgtable.h b/include/asm-arm/proc-armv/pgtable.h deleted file mode 100644 index 4b1cb65443ae..000000000000 --- a/include/asm-arm/proc-armv/pgtable.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * linux/include/asm-arm/proc-armv/pgtable.h - * - * Copyright (C) 1995-2002 Russell King - * - * 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. - * - * 12-Jan-1997 RMK Altered flushing routines to use function pointers - * now possible to combine ARM6, ARM7 and StrongARM versions. - * 17-Apr-1999 RMK Now pass an area size to clean_cache_area and - * flush_icache_area. - */ -#ifndef __ASM_PROC_PGTABLE_H -#define __ASM_PROC_PGTABLE_H - -/* - * We pull a couple of tricks here: - * 1. We wrap the PMD into the PGD. - * 2. We lie about the size of the PTE and PGD. - * Even though we have 256 PTE entries and 4096 PGD entries, we tell - * Linux that we actually have 512 PTE entries and 2048 PGD entries. - * Each "Linux" PGD entry is made up of two hardware PGD entries, and - * each PTE table is actually two hardware PTE tables. - */ -#define PTRS_PER_PTE 512 -#define PTRS_PER_PMD 1 -#define PTRS_PER_PGD 2048 - -/* - * Hardware page table definitions. - * - * + Level 1 descriptor (PMD) - * - common - */ -#define PMD_TYPE_MASK (3 << 0) -#define PMD_TYPE_FAULT (0 << 0) -#define PMD_TYPE_TABLE (1 << 0) -#define PMD_TYPE_SECT (2 << 0) -#define PMD_BIT4 (1 << 4) -#define PMD_DOMAIN(x) ((x) << 5) -#define PMD_PROTECTION (1 << 9) /* v5 */ -/* - * - section - */ -#define PMD_SECT_BUFFERABLE (1 << 2) -#define PMD_SECT_CACHEABLE (1 << 3) -#define PMD_SECT_AP_WRITE (1 << 10) -#define PMD_SECT_AP_READ (1 << 11) -#define PMD_SECT_TEX(x) ((x) << 12) /* v5 */ -#define PMD_SECT_APX (1 << 15) /* v6 */ -#define PMD_SECT_S (1 << 16) /* v6 */ -#define PMD_SECT_nG (1 << 17) /* v6 */ - -#define PMD_SECT_UNCACHED (0) -#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE) -#define PMD_SECT_WT (PMD_SECT_CACHEABLE) -#define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) -#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE) -#define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) - -/* - * - coarse table (not used) - */ - -/* - * + Level 2 descriptor (PTE) - * - common - */ -#define PTE_TYPE_MASK (3 << 0) -#define PTE_TYPE_FAULT (0 << 0) -#define PTE_TYPE_LARGE (1 << 0) -#define PTE_TYPE_SMALL (2 << 0) -#define PTE_TYPE_EXT (3 << 0) /* v5 */ -#define PTE_BUFFERABLE (1 << 2) -#define PTE_CACHEABLE (1 << 3) - -/* - * - extended small page/tiny page - */ -#define PTE_EXT_AP_UNO_SRO (0 << 4) -#define PTE_EXT_AP_UNO_SRW (1 << 4) -#define PTE_EXT_AP_URO_SRW (2 << 4) -#define PTE_EXT_AP_URW_SRW (3 << 4) -#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */ - -/* - * - small page - */ -#define PTE_SMALL_AP_UNO_SRO (0x00 << 4) -#define PTE_SMALL_AP_UNO_SRW (0x55 << 4) -#define PTE_SMALL_AP_URO_SRW (0xaa << 4) -#define PTE_SMALL_AP_URW_SRW (0xff << 4) -#define PTE_AP_READ PTE_SMALL_AP_URO_SRW -#define PTE_AP_WRITE PTE_SMALL_AP_UNO_SRW - -/* - * "Linux" PTE definitions. - * - * We keep two sets of PTEs - the hardware and the linux version. - * This allows greater flexibility in the way we map the Linux bits - * onto the hardware tables, and allows us to have YOUNG and DIRTY - * bits. - * - * The PTE table pointer refers to the hardware entries; the "Linux" - * entries are stored 1024 bytes below. - */ -#define L_PTE_PRESENT (1 << 0) -#define L_PTE_FILE (1 << 1) /* only when !PRESENT */ -#define L_PTE_YOUNG (1 << 1) -#define L_PTE_BUFFERABLE (1 << 2) /* matches PTE */ -#define L_PTE_CACHEABLE (1 << 3) /* matches PTE */ -#define L_PTE_USER (1 << 4) -#define L_PTE_WRITE (1 << 5) -#define L_PTE_EXEC (1 << 6) -#define L_PTE_DIRTY (1 << 7) - -#ifndef __ASSEMBLY__ - -#include <asm/proc/domain.h> - -#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER)) -#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL)) - -#define pmd_bad(pmd) (pmd_val(pmd) & 2) - -#define set_pmd(pmdp,pmd) \ - do { \ - *pmdp = pmd; \ - flush_pmd_entry(pmdp); \ - } while (0) - -#define pmd_clear(pmdp) \ - do { \ - pmdp[0] = __pmd(0); \ - pmdp[1] = __pmd(0); \ - clean_pmd_entry(pmdp); \ - } while (0) - -static inline pte_t *pmd_page_kernel(pmd_t pmd) -{ - unsigned long ptr; - - ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1); - ptr += PTRS_PER_PTE * sizeof(void *); - - return __va(ptr); -} - -#define pmd_page(pmd) virt_to_page(__va(pmd_val(pmd))) - -#define pte_offset_kernel(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr)) -#define pte_offset_map(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr)) -#define pte_offset_map_nested(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr)) -#define pte_unmap(pte) do { } while (0) -#define pte_unmap_nested(pte) do { } while (0) - -#define set_pte(ptep, pte) cpu_set_pte(ptep,pte) - -/* - * The following macros handle the cache and bufferable bits... - */ -#define _L_PTE_DEFAULT L_PTE_PRESENT | L_PTE_YOUNG -#define _L_PTE_READ L_PTE_USER | L_PTE_EXEC | L_PTE_CACHEABLE | L_PTE_BUFFERABLE - -#define PAGE_NONE __pgprot(_L_PTE_DEFAULT) -#define PAGE_COPY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ) -#define PAGE_SHARED __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_WRITE) -#define PAGE_READONLY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ) -#define PAGE_KERNEL __pgprot(_L_PTE_DEFAULT | L_PTE_CACHEABLE | L_PTE_BUFFERABLE | L_PTE_DIRTY | L_PTE_WRITE | L_PTE_EXEC) - -#define _PAGE_CHG_MASK (PAGE_MASK | L_PTE_DIRTY | L_PTE_YOUNG) - - -/* - * The following only work if pte_present() is true. - * Undefined behaviour if not.. - */ -#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) -#define pte_read(pte) (pte_val(pte) & L_PTE_USER) -#define pte_write(pte) (pte_val(pte) & L_PTE_WRITE) -#define pte_exec(pte) (pte_val(pte) & L_PTE_EXEC) -#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) -#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) -#define pte_file(pte) (pte_val(pte) & L_PTE_FILE) - -#define PTE_BIT_FUNC(fn,op) \ -static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } - -/*PTE_BIT_FUNC(rdprotect, &= ~L_PTE_USER);*/ -/*PTE_BIT_FUNC(mkread, |= L_PTE_USER);*/ -PTE_BIT_FUNC(wrprotect, &= ~L_PTE_WRITE); -PTE_BIT_FUNC(mkwrite, |= L_PTE_WRITE); -PTE_BIT_FUNC(exprotect, &= ~L_PTE_EXEC); -PTE_BIT_FUNC(mkexec, |= L_PTE_EXEC); -PTE_BIT_FUNC(mkclean, &= ~L_PTE_DIRTY); -PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY); -PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG); -PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG); - -/* - * Mark the prot value as uncacheable and unbufferable. - */ -#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) & ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE)) -#define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~L_PTE_CACHEABLE) - -#define pgtable_cache_init() do { } while (0) - -#define pte_to_pgoff(x) (pte_val(x) >> 2) -#define pgoff_to_pte(x) __pte(((x) << 2) | L_PTE_FILE) - -#define PTE_FILE_MAX_BITS 30 - -#endif /* __ASSEMBLY__ */ - -#endif /* __ASM_PROC_PGTABLE_H */ diff --git a/include/asm-arm/proc-armv/processor.h b/include/asm-arm/proc-armv/processor.h deleted file mode 100644 index 373ca267700c..000000000000 --- a/include/asm-arm/proc-armv/processor.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * linux/include/asm-arm/proc-armv/processor.h - * - * Copyright (C) 1996-1999 Russell King. - * - * 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. - * - * Changelog: - * 20-09-1996 RMK Created - * 26-09-1996 RMK Added 'EXTRA_THREAD_STRUCT*' - * 28-09-1996 RMK Moved start_thread into the processor dependencies - * 09-09-1998 PJB Delete redundant `wp_works_ok' - * 30-05-1999 PJB Save sl across context switches - * 31-07-1999 RMK Added 'domain' stuff - */ -#ifndef __ASM_PROC_PROCESSOR_H -#define __ASM_PROC_PROCESSOR_H - -#include <asm/proc/domain.h> - -#define KERNEL_STACK_SIZE PAGE_SIZE - -#define INIT_EXTRA_THREAD_INFO \ - .cpu_domain = domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ - domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ - domain_val(DOMAIN_IO, DOMAIN_CLIENT) - -#define start_thread(regs,pc,sp) \ -({ \ - unsigned long *stack = (unsigned long *)sp; \ - set_fs(USER_DS); \ - memzero(regs->uregs, sizeof(regs->uregs)); \ - if (current->personality & ADDR_LIMIT_32BIT) \ - regs->ARM_cpsr = USR_MODE; \ - else \ - regs->ARM_cpsr = USR26_MODE; \ - if (elf_hwcap & HWCAP_THUMB && pc & 1) \ - regs->ARM_cpsr |= PSR_T_BIT; \ - regs->ARM_pc = pc & ~1; /* pc */ \ - regs->ARM_sp = sp; /* sp */ \ - regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ - regs->ARM_r1 = stack[1]; /* r1 (argv) */ \ - regs->ARM_r0 = stack[0]; /* r0 (argc) */ \ -}) - -#define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1019]) -#define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1017]) - -#endif diff --git a/include/asm-arm/proc-armv/ptrace.h b/include/asm-arm/proc-armv/ptrace.h deleted file mode 100644 index d70d3724612a..000000000000 --- a/include/asm-arm/proc-armv/ptrace.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * linux/include/asm-arm/proc-armv/ptrace.h - * - * Copyright (C) 1996-1999 Russell King - * - * 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. - */ -#ifndef __ASM_PROC_PTRACE_H -#define __ASM_PROC_PTRACE_H - -#include <linux/config.h> - -/* - * PSR bits - */ -#define USR26_MODE 0x00000000 -#define FIQ26_MODE 0x00000001 -#define IRQ26_MODE 0x00000002 -#define SVC26_MODE 0x00000003 -#define USR_MODE 0x00000010 -#define FIQ_MODE 0x00000011 -#define IRQ_MODE 0x00000012 -#define SVC_MODE 0x00000013 -#define ABT_MODE 0x00000017 -#define UND_MODE 0x0000001b -#define SYSTEM_MODE 0x0000001f -#define MODE32_BIT 0x00000010 -#define MODE_MASK 0x0000001f -#define PSR_T_BIT 0x00000020 -#define PSR_F_BIT 0x00000040 -#define PSR_I_BIT 0x00000080 -#define PSR_J_BIT 0x01000000 -#define PSR_Q_BIT 0x08000000 -#define PSR_V_BIT 0x10000000 -#define PSR_C_BIT 0x20000000 -#define PSR_Z_BIT 0x40000000 -#define PSR_N_BIT 0x80000000 -#define PCMASK 0 - -/* - * Groups of PSR bits - */ -#define PSR_f 0xff000000 /* Flags */ -#define PSR_s 0x00ff0000 /* Status */ -#define PSR_x 0x0000ff00 /* Extension */ -#define PSR_c 0x000000ff /* Control */ - -/* - * CR1 bits - */ -#define CR1_M 0x00000001 /* MMU */ -#define CR1_A 0x00000002 /* Alignment fault */ -#define CR1_C 0x00000004 /* Dcache */ -#define CR1_W 0x00000008 /* Write buffer */ -#define CR1_P 0x00000010 /* Prog32 */ -#define CR1_D 0x00000020 /* Data32 */ -#define CR1_L 0x00000040 /* Late abort */ -#define CR1_B 0x00000080 /* Big endian */ -#define CR1_S 0x00000100 /* System protection */ -#define CR1_R 0x00000200 /* ROM protection */ -#define CR1_F 0x00000400 -#define CR1_Z 0x00000800 /* BTB enable */ -#define CR1_I 0x00001000 /* Icache */ -#define CR1_V 0x00002000 /* Vector relocation */ -#define CR1_RR 0x00004000 /* Round Robin */ - -#ifndef __ASSEMBLY__ - -/* this struct defines the way the registers are stored on the - stack during a system call. */ - -struct pt_regs { - long uregs[18]; -}; - -#define ARM_cpsr uregs[16] -#define ARM_pc uregs[15] -#define ARM_lr uregs[14] -#define ARM_sp uregs[13] -#define ARM_ip uregs[12] -#define ARM_fp uregs[11] -#define ARM_r10 uregs[10] -#define ARM_r9 uregs[9] -#define ARM_r8 uregs[8] -#define ARM_r7 uregs[7] -#define ARM_r6 uregs[6] -#define ARM_r5 uregs[5] -#define ARM_r4 uregs[4] -#define ARM_r3 uregs[3] -#define ARM_r2 uregs[2] -#define ARM_r1 uregs[1] -#define ARM_r0 uregs[0] -#define ARM_ORIG_r0 uregs[17] - -#ifdef __KERNEL__ - -#define user_mode(regs) \ - (((regs)->ARM_cpsr & 0xf) == 0) - -#ifdef CONFIG_ARM_THUMB -#define thumb_mode(regs) \ - (((regs)->ARM_cpsr & PSR_T_BIT)) -#else -#define thumb_mode(regs) (0) -#endif - -#define processor_mode(regs) \ - ((regs)->ARM_cpsr & MODE_MASK) - -#define interrupts_enabled(regs) \ - (!((regs)->ARM_cpsr & PSR_I_BIT)) - -#define fast_interrupts_enabled(regs) \ - (!((regs)->ARM_cpsr & PSR_F_BIT)) - -#define condition_codes(regs) \ - ((regs)->ARM_cpsr & (PSR_V_BIT|PSR_C_BIT|PSR_Z_BIT|PSR_N_BIT)) - -/* Are the current registers suitable for user mode? - * (used to maintain security in signal handlers) - */ -static inline int valid_user_regs(struct pt_regs *regs) -{ - if (user_mode(regs) && - (regs->ARM_cpsr & (PSR_F_BIT|PSR_I_BIT)) == 0) - return 1; - - /* - * Force CPSR to something logical... - */ - regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT; - - return 0; -} - -#endif /* __KERNEL__ */ - -#endif /* __ASSEMBLY__ */ - -#endif - diff --git a/include/asm-arm/proc-armv/shmparam.h b/include/asm-arm/proc-armv/shmparam.h deleted file mode 100644 index 5b692cc5b3e8..000000000000 --- a/include/asm-arm/proc-armv/shmparam.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * linux/include/asm-arm/proc-armv/shmparam.h - * - * Copyright (C) 1996 Russell King - * - * 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. - * - * definitions for the shared process memory on ARM v3 or v4 - * processors - */ -#ifndef __ASM_PROC_SHMPARAM_H -#define __ASM_PROC_SHMPARAM_H - -#ifndef SHMMAX -#define SHMMAX 0x01000000 -#endif - -#endif diff --git a/include/asm-arm/proc-armv/system.h b/include/asm-arm/proc-armv/system.h deleted file mode 100644 index 2179e2a175fe..000000000000 --- a/include/asm-arm/proc-armv/system.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * linux/include/asm-arm/proc-armv/system.h - * - * Copyright (C) 1996 Russell King - * - * 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. - */ -#ifndef __ASM_PROC_SYSTEM_H -#define __ASM_PROC_SYSTEM_H - -#include <linux/config.h> - -#define set_cr(x) \ - __asm__ __volatile__( \ - "mcr p15, 0, %0, c1, c0, 0 @ set CR" \ - : : "r" (x) : "cc") - -#define get_cr() \ - ({ \ - unsigned int __val; \ - __asm__ __volatile__( \ - "mrc p15, 0, %0, c1, c0, 0 @ get CR" \ - : "=r" (__val) : : "cc"); \ - __val; \ - }) - -#define CR_M (1 << 0) /* MMU enable */ -#define CR_A (1 << 1) /* Alignment abort enable */ -#define CR_C (1 << 2) /* Dcache enable */ -#define CR_W (1 << 3) /* Write buffer enable */ -#define CR_P (1 << 4) /* 32-bit exception handler */ -#define CR_D (1 << 5) /* 32-bit data address range */ -#define CR_L (1 << 6) /* Implementation defined */ -#define CR_B (1 << 7) /* Big endian */ -#define CR_S (1 << 8) /* System MMU protection */ -#define CR_R (1 << 9) /* ROM MMU protection */ -#define CR_F (1 << 10) /* Implementation defined */ -#define CR_Z (1 << 11) /* Implementation defined */ -#define CR_I (1 << 12) /* Icache enable */ -#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */ -#define CR_RR (1 << 14) /* Round Robin cache replacement */ -#define CR_L4 (1 << 15) /* LDR pc can set T bit */ -#define CR_DT (1 << 16) -#define CR_IT (1 << 18) -#define CR_ST (1 << 19) -#define CR_FI (1 << 21) -#define CR_U (1 << 22) /* Unaligned access operation */ -#define CR_XP (1 << 23) /* Extended page tables */ -#define CR_VE (1 << 24) /* Vectored interrupts */ - -extern unsigned long cr_no_alignment; /* defined in entry-armv.S */ -extern unsigned long cr_alignment; /* defined in entry-armv.S */ - -#if __LINUX_ARM_ARCH__ >= 4 -#define vectors_base() ((cr_alignment & CR_V) ? 0xffff0000 : 0) -#else -#define vectors_base() (0) -#endif - -/* - * Save the current interrupt enable state & disable IRQs - */ -#define local_irq_save(x) \ - ({ \ - unsigned long temp; \ - (void) (&temp == &x); \ - __asm__ __volatile__( \ - "mrs %0, cpsr @ local_irq_save\n" \ -" orr %1, %0, #128\n" \ -" msr cpsr_c, %1" \ - : "=r" (x), "=r" (temp) \ - : \ - : "memory", "cc"); \ - }) - -/* - * Enable IRQs - */ -#define local_irq_enable() \ - ({ \ - unsigned long temp; \ - __asm__ __volatile__( \ - "mrs %0, cpsr @ local_irq_enable\n" \ -" bic %0, %0, #128\n" \ -" msr cpsr_c, %0" \ - : "=r" (temp) \ - : \ - : "memory", "cc"); \ - }) - -/* - * Disable IRQs - */ -#define local_irq_disable() \ - ({ \ - unsigned long temp; \ - __asm__ __volatile__( \ - "mrs %0, cpsr @ local_irq_disable\n" \ -" orr %0, %0, #128\n" \ -" msr cpsr_c, %0" \ - : "=r" (temp) \ - : \ - : "memory", "cc"); \ - }) - -/* - * Enable FIQs - */ -#define __stf() \ - ({ \ - unsigned long temp; \ - __asm__ __volatile__( \ - "mrs %0, cpsr @ stf\n" \ -" bic %0, %0, #64\n" \ -" msr cpsr_c, %0" \ - : "=r" (temp) \ - : \ - : "memory", "cc"); \ - }) - -/* - * Disable FIQs - */ -#define __clf() \ - ({ \ - unsigned long temp; \ - __asm__ __volatile__( \ - "mrs %0, cpsr @ clf\n" \ -" orr %0, %0, #64\n" \ -" msr cpsr_c, %0" \ - : "=r" (temp) \ - : \ - : "memory", "cc"); \ - }) - -/* - * Save the current interrupt enable state. - */ -#define local_save_flags(x) \ - ({ \ - __asm__ __volatile__( \ - "mrs %0, cpsr @ local_save_flags" \ - : "=r" (x) : : "memory", "cc"); \ - }) - -/* - * restore saved IRQ & FIQ state - */ -#define local_irq_restore(x) \ - __asm__ __volatile__( \ - "msr cpsr_c, %0 @ local_irq_restore\n" \ - : \ - : "r" (x) \ - : "memory", "cc") - -#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110) -/* - * On the StrongARM, "swp" is terminally broken since it bypasses the - * cache totally. This means that the cache becomes inconsistent, and, - * since we use normal loads/stores as well, this is really bad. - * Typically, this causes oopsen in filp_close, but could have other, - * more disasterous effects. There are two work-arounds: - * 1. Disable interrupts and emulate the atomic swap - * 2. Clean the cache, perform atomic swap, flush the cache - * - * We choose (1) since its the "easiest" to achieve here and is not - * dependent on the processor type. - */ -#define swp_is_buggy -#endif - -static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) -{ - extern void __bad_xchg(volatile void *, int); - unsigned long ret; -#ifdef swp_is_buggy - unsigned long flags; -#endif - - switch (size) { -#ifdef swp_is_buggy - case 1: - local_irq_save(flags); - ret = *(volatile unsigned char *)ptr; - *(volatile unsigned char *)ptr = x; - local_irq_restore(flags); - break; - - case 4: - local_irq_save(flags); - ret = *(volatile unsigned long *)ptr; - *(volatile unsigned long *)ptr = x; - local_irq_restore(flags); - break; -#else - case 1: __asm__ __volatile__ ("swpb %0, %1, [%2]" - : "=&r" (ret) - : "r" (x), "r" (ptr) - : "memory", "cc"); - break; - case 4: __asm__ __volatile__ ("swp %0, %1, [%2]" - : "=&r" (ret) - : "r" (x), "r" (ptr) - : "memory", "cc"); - break; -#endif - default: __bad_xchg(ptr, size), ret = 0; - } - - return ret; -} - -#endif diff --git a/include/asm-arm/proc-armv/tlbflush.h b/include/asm-arm/proc-armv/tlbflush.h deleted file mode 100644 index f51019309d59..000000000000 --- a/include/asm-arm/proc-armv/tlbflush.h +++ /dev/null @@ -1,410 +0,0 @@ -/* - * linux/include/asm-arm/proc-armv/tlbflush.h - * - * Copyright (C) 1999-2003 Russell King - * - * 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. - */ -#include <linux/config.h> -#include <asm/glue.h> - -#define TLB_V3_PAGE (1 << 0) -#define TLB_V4_U_PAGE (1 << 1) -#define TLB_V4_D_PAGE (1 << 2) -#define TLB_V4_I_PAGE (1 << 3) -#define TLB_V6_U_PAGE (1 << 4) -#define TLB_V6_D_PAGE (1 << 5) -#define TLB_V6_I_PAGE (1 << 6) - -#define TLB_V3_FULL (1 << 8) -#define TLB_V4_U_FULL (1 << 9) -#define TLB_V4_D_FULL (1 << 10) -#define TLB_V4_I_FULL (1 << 11) -#define TLB_V6_U_FULL (1 << 12) -#define TLB_V6_D_FULL (1 << 13) -#define TLB_V6_I_FULL (1 << 14) - -#define TLB_V6_U_ASID (1 << 16) -#define TLB_V6_D_ASID (1 << 17) -#define TLB_V6_I_ASID (1 << 18) - -#define TLB_DCLEAN (1 << 30) -#define TLB_WB (1 << 31) - -/* - * MMU TLB Model - * ============= - * - * We have the following to choose from: - * v3 - ARMv3 - * v4 - ARMv4 without write buffer - * v4wb - ARMv4 with write buffer without I TLB flush entry instruction - * v4wbi - ARMv4 with write buffer with I TLB flush entry instruction - * v6wbi - ARMv6 with write buffer with I TLB flush entry instruction - */ -#undef _TLB -#undef MULTI_TLB - -#define v3_tlb_flags (TLB_V3_FULL | TLB_V3_PAGE) - -#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) -# define v3_possible_flags v3_tlb_flags -# define v3_always_flags v3_tlb_flags -# ifdef _TLB -# define MULTI_TLB 1 -# else -# define _TLB v3 -# endif -#else -# define v3_possible_flags 0 -# define v3_always_flags (-1UL) -#endif - -#define v4_tlb_flags (TLB_V4_U_FULL | TLB_V4_U_PAGE) - -#if defined(CONFIG_CPU_ARM720T) -# define v4_possible_flags v4_tlb_flags -# define v4_always_flags v4_tlb_flags -# ifdef _TLB -# define MULTI_TLB 1 -# else -# define _TLB v4 -# endif -#else -# define v4_possible_flags 0 -# define v4_always_flags (-1UL) -#endif - -#define v4wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \ - TLB_V4_I_FULL | TLB_V4_D_FULL | \ - TLB_V4_I_PAGE | TLB_V4_D_PAGE) - -#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \ - defined(CONFIG_CPU_ARM926T) || defined(CONFIG_CPU_ARM1020) || \ - defined(CONFIG_CPU_XSCALE) -# define v4wbi_possible_flags v4wbi_tlb_flags -# define v4wbi_always_flags v4wbi_tlb_flags -# ifdef _TLB -# define MULTI_TLB 1 -# else -# define _TLB v4wbi -# endif -#else -# define v4wbi_possible_flags 0 -# define v4wbi_always_flags (-1UL) -#endif - -#define v4wb_tlb_flags (TLB_WB | TLB_DCLEAN | \ - TLB_V4_I_FULL | TLB_V4_D_FULL | \ - TLB_V4_D_PAGE) - -#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100) -# define v4wb_possible_flags v4wb_tlb_flags -# define v4wb_always_flags v4wb_tlb_flags -# ifdef _TLB -# define MULTI_TLB 1 -# else -# define _TLB v4wb -# endif -#else -# define v4wb_possible_flags 0 -# define v4wb_always_flags (-1UL) -#endif - -#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \ - TLB_V6_I_FULL | TLB_V6_D_FULL | \ - TLB_V6_I_PAGE | TLB_V6_D_PAGE | \ - TLB_V6_I_ASID | TLB_V6_D_ASID) - -#if defined(CONFIG_CPU_V6) -# define v6wbi_possible_flags v6wbi_tlb_flags -# define v6wbi_always_flags v6wbi_tlb_flags -# ifdef _TLB -# define MULTI_TLB 1 -# else -# define _TLB v6wbi -# endif -#else -# define v6wbi_possible_flags 0 -# define v6wbi_always_flags (-1UL) -#endif - -#ifndef _TLB -#error Unknown TLB model -#endif - -#ifndef __ASSEMBLY__ - -struct cpu_tlb_fns { - void (*flush_user_range)(unsigned long, unsigned long, struct vm_area_struct *); - void (*flush_kern_range)(unsigned long, unsigned long); - unsigned long tlb_flags; -}; - -/* - * Select the calling method - */ -#ifdef MULTI_TLB - -#define __cpu_flush_user_tlb_range cpu_tlb.flush_user_range -#define __cpu_flush_kern_tlb_range cpu_tlb.flush_kern_range - -#else - -#define __cpu_flush_user_tlb_range __glue(_TLB,_flush_user_tlb_range) -#define __cpu_flush_kern_tlb_range __glue(_TLB,_flush_kern_tlb_range) - -extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *); -extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long); - -#endif - -extern struct cpu_tlb_fns cpu_tlb; - -#define __cpu_tlb_flags cpu_tlb.tlb_flags - -/* - * TLB Management - * ============== - * - * The arch/arm/mm/tlb-*.S files implement these methods. - * - * The TLB specific code is expected to perform whatever tests it - * needs to determine if it should invalidate the TLB for each - * call. Start addresses are inclusive and end addresses are - * exclusive; it is safe to round these addresses down. - * - * flush_tlb_all() - * - * Invalidate the entire TLB. - * - * flush_tlb_mm(mm) - * - * Invalidate all TLB entries in a particular address - * space. - * - mm - mm_struct describing address space - * - * flush_tlb_range(mm,start,end) - * - * Invalidate a range of TLB entries in the specified - * address space. - * - mm - mm_struct describing address space - * - start - start address (may not be aligned) - * - end - end address (exclusive, may not be aligned) - * - * flush_tlb_page(vaddr,vma) - * - * Invalidate the specified page in the specified address range. - * - vaddr - virtual address (may not be aligned) - * - vma - vma_struct describing address range - * - * flush_kern_tlb_page(kaddr) - * - * Invalidate the TLB entry for the specified page. The address - * will be in the kernels virtual memory space. Current uses - * only require the D-TLB to be invalidated. - * - kaddr - Kernel virtual memory address - */ - -/* - * We optimise the code below by: - * - building a set of TLB flags that might be set in __cpu_tlb_flags - * - building a set of TLB flags that will always be set in __cpu_tlb_flags - * - if we're going to need __cpu_tlb_flags, access it once and only once - * - * This allows us to build optimal assembly for the single-CPU type case, - * and as close to optimal given the compiler constrants for multi-CPU - * case. We could do better for the multi-CPU case if the compiler - * implemented the "%?" method, but this has been discontinued due to too - * many people getting it wrong. - */ -#define possible_tlb_flags (v3_possible_flags | \ - v4_possible_flags | \ - v4wbi_possible_flags | \ - v4wb_possible_flags | \ - v6wbi_possible_flags) - -#define always_tlb_flags (v3_always_flags & \ - v4_always_flags & \ - v4wbi_always_flags & \ - v4wb_always_flags & \ - v6wbi_always_flags) - -#define tlb_flag(f) ((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f))) - -static inline void flush_tlb_all(void) -{ - const int zero = 0; - const unsigned int __tlb_flag = __cpu_tlb_flags; - - if (tlb_flag(TLB_WB)) - asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero)); - - if (tlb_flag(TLB_V3_FULL)) - asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (zero)); - if (tlb_flag(TLB_V4_U_FULL | TLB_V6_U_FULL)) - asm("mcr%? p15, 0, %0, c8, c7, 0" : : "r" (zero)); - if (tlb_flag(TLB_V4_D_FULL | TLB_V6_D_FULL)) - asm("mcr%? p15, 0, %0, c8, c6, 0" : : "r" (zero)); - if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL)) - asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero)); -} - -static inline void flush_tlb_mm(struct mm_struct *mm) -{ - const int zero = 0; - const int asid = ASID(mm); - const unsigned int __tlb_flag = __cpu_tlb_flags; - - if (tlb_flag(TLB_WB)) - asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero)); - - if (mm == current->active_mm) { - if (tlb_flag(TLB_V3_FULL)) - asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (zero)); - if (tlb_flag(TLB_V4_U_FULL)) - asm("mcr%? p15, 0, %0, c8, c7, 0" : : "r" (zero)); - if (tlb_flag(TLB_V4_D_FULL)) - asm("mcr%? p15, 0, %0, c8, c6, 0" : : "r" (zero)); - if (tlb_flag(TLB_V4_I_FULL)) - asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero)); - } - - if (tlb_flag(TLB_V6_U_ASID)) - asm("mcr%? p15, 0, %0, c8, c7, 2" : : "r" (asid)); - if (tlb_flag(TLB_V6_D_ASID)) - asm("mcr%? p15, 0, %0, c8, c6, 2" : : "r" (asid)); - if (tlb_flag(TLB_V6_I_ASID)) - asm("mcr%? p15, 0, %0, c8, c5, 2" : : "r" (asid)); -} - -static inline void -flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) -{ - const int zero = 0; - const unsigned int __tlb_flag = __cpu_tlb_flags; - - uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm); - - if (tlb_flag(TLB_WB)) - asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero)); - - if (vma->vm_mm == current->active_mm) { - if (tlb_flag(TLB_V3_PAGE)) - asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (uaddr)); - if (tlb_flag(TLB_V4_U_PAGE)) - asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (uaddr)); - if (tlb_flag(TLB_V4_D_PAGE)) - asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (uaddr)); - if (tlb_flag(TLB_V4_I_PAGE)) - asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (uaddr)); - if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL)) - asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero)); - } - - if (tlb_flag(TLB_V6_U_PAGE)) - asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (uaddr)); - if (tlb_flag(TLB_V6_D_PAGE)) - asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (uaddr)); - if (tlb_flag(TLB_V6_I_PAGE)) - asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (uaddr)); -} - -static inline void flush_tlb_kernel_page(unsigned long kaddr) -{ - const int zero = 0; - const unsigned int __tlb_flag = __cpu_tlb_flags; - - kaddr &= PAGE_MASK; - - if (tlb_flag(TLB_WB)) - asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero)); - - if (tlb_flag(TLB_V3_PAGE)) - asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (kaddr)); - if (tlb_flag(TLB_V4_U_PAGE)) - asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (kaddr)); - if (tlb_flag(TLB_V4_D_PAGE)) - asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (kaddr)); - if (tlb_flag(TLB_V4_I_PAGE)) - asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (kaddr)); - if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL)) - asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero)); - - if (tlb_flag(TLB_V6_U_PAGE)) - asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (kaddr)); - if (tlb_flag(TLB_V6_D_PAGE)) - asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (kaddr)); - if (tlb_flag(TLB_V6_I_PAGE)) - asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (kaddr)); -} - -/* - * flush_pmd_entry - * - * Flush a PMD entry (word aligned, or double-word aligned) to - * RAM if the TLB for the CPU we are running on requires this. - * This is typically used when we are creating PMD entries. - * - * clean_pmd_entry - * - * Clean (but don't drain the write buffer) if the CPU requires - * these operations. This is typically used when we are removing - * PMD entries. - */ -static inline void flush_pmd_entry(pmd_t *pmd) -{ - const unsigned int zero = 0; - const unsigned int __tlb_flag = __cpu_tlb_flags; - - if (tlb_flag(TLB_DCLEAN)) - asm("mcr%? p15, 0, %0, c7, c10, 1 @ flush_pmd" - : : "r" (pmd)); - if (tlb_flag(TLB_WB)) - asm("mcr%? p15, 0, %0, c7, c10, 4 @ flush_pmd" - : : "r" (zero)); -} - -static inline void clean_pmd_entry(pmd_t *pmd) -{ - const unsigned int __tlb_flag = __cpu_tlb_flags; - - if (tlb_flag(TLB_DCLEAN)) - asm("mcr%? p15, 0, %0, c7, c10, 1 @ flush_pmd" - : : "r" (pmd)); -} - -#undef tlb_flag -#undef always_tlb_flags -#undef possible_tlb_flags - -/* - * Convert calls to our calling convention. - */ -#define flush_tlb_range(vma,start,end) __cpu_flush_user_tlb_range(start,end,vma) -#define flush_tlb_kernel_range(s,e) __cpu_flush_kern_tlb_range(s,e) - -/* - * if PG_dcache_dirty is set for the page, we need to ensure that any - * cache entries for the kernels virtual memory range are written - * back to the page. - */ -extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte); - -/* - * ARM processors do not cache TLB tables in RAM. - */ -#define flush_tlb_pgtables(mm,start,end) do { } while (0) - -/* - * Old ARM MEMC stuff. This supports the reversed mapping handling that - * we have on the older 26-bit machines. We don't have a MEMC chip, so... - */ -#define memc_update_all() do { } while (0) -#define memc_update_mm(mm) do { } while (0) -#define memc_update_addr(mm,pte,log) do { } while (0) -#define memc_clear(mm,physaddr) do { } while (0) - -#endif diff --git a/include/asm-arm/proc-armv/uaccess.h b/include/asm-arm/proc-armv/uaccess.h deleted file mode 100644 index b871c78160b1..000000000000 --- a/include/asm-arm/proc-armv/uaccess.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * linux/include/asm-arm/proc-armv/uaccess.h - * - * 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. - */ -#include <asm/arch/memory.h> -#include <asm/proc/domain.h> - -/* - * Note that this is actually 0x1,0000,0000 - */ -#define KERNEL_DS 0x00000000 -#define USER_DS TASK_SIZE - -static inline void set_fs (mm_segment_t fs) -{ - current_thread_info()->addr_limit = fs; - modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER); -} - -/* We use 33-bit arithmetic here... */ -#define __range_ok(addr,size) ({ \ - unsigned long flag, sum; \ - __asm__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0" \ - : "=&r" (flag), "=&r" (sum) \ - : "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit) \ - : "cc"); \ - flag; }) - -#define __addr_ok(addr) ({ \ - unsigned long flag; \ - __asm__("cmp %2, %0; movlo %0, #0" \ - : "=&r" (flag) \ - : "0" (current_thread_info()->addr_limit), "r" (addr) \ - : "cc"); \ - (flag == 0); }) - -#define __put_user_asm_byte(x,__pu_addr,err) \ - __asm__ __volatile__( \ - "1: strbt %1,[%2],#0\n" \ - "2:\n" \ - " .section .fixup,\"ax\"\n" \ - " .align 2\n" \ - "3: mov %0, %3\n" \ - " b 2b\n" \ - " .previous\n" \ - " .section __ex_table,\"a\"\n" \ - " .align 3\n" \ - " .long 1b, 3b\n" \ - " .previous" \ - : "+r" (err) \ - : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \ - : "cc") - -#ifndef __ARMEB__ -#define __put_user_asm_half(x,__pu_addr,err) \ -({ \ - unsigned long __temp = (unsigned long)(x); \ - __put_user_asm_byte(__temp, __pu_addr, err); \ - __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err); \ -}) -#else -#define __put_user_asm_half(x,__pu_addr,err) \ -({ \ - unsigned long __temp = (unsigned long)(x); \ - __put_user_asm_byte(__temp >> 8, __pu_addr, err); \ - __put_user_asm_byte(__temp, __pu_addr + 1, err); \ -}) -#endif - -#define __put_user_asm_word(x,__pu_addr,err) \ - __asm__ __volatile__( \ - "1: strt %1,[%2],#0\n" \ - "2:\n" \ - " .section .fixup,\"ax\"\n" \ - " .align 2\n" \ - "3: mov %0, %3\n" \ - " b 2b\n" \ - " .previous\n" \ - " .section __ex_table,\"a\"\n" \ - " .align 3\n" \ - " .long 1b, 3b\n" \ - " .previous" \ - : "+r" (err) \ - : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \ - : "cc") - -#ifndef __ARMEB__ -#define __reg_oper0 "%R2" -#define __reg_oper1 "%Q2" -#else -#define __reg_oper0 "%Q2" -#define __reg_oper1 "%R2" -#endif - -#define __put_user_asm_dword(x,__pu_addr,err) \ - __asm__ __volatile__( \ - "1: strt " __reg_oper1 ", [%1], #4\n" \ - "2: strt " __reg_oper0 ", [%1], #0\n" \ - "3:\n" \ - " .section .fixup,\"ax\"\n" \ - " .align 2\n" \ - "4: mov %0, %3\n" \ - " b 3b\n" \ - " .previous\n" \ - " .section __ex_table,\"a\"\n" \ - " .align 3\n" \ - " .long 1b, 4b\n" \ - " .long 2b, 4b\n" \ - " .previous" \ - : "+r" (err), "+r" (__pu_addr) \ - : "r" (x), "i" (-EFAULT) \ - : "cc") - -#define __get_user_asm_byte(x,addr,err) \ - __asm__ __volatile__( \ - "1: ldrbt %1,[%2],#0\n" \ - "2:\n" \ - " .section .fixup,\"ax\"\n" \ - " .align 2\n" \ - "3: mov %0, %3\n" \ - " mov %1, #0\n" \ - " b 2b\n" \ - " .previous\n" \ - " .section __ex_table,\"a\"\n" \ - " .align 3\n" \ - " .long 1b, 3b\n" \ - " .previous" \ - : "+r" (err), "=&r" (x) \ - : "r" (addr), "i" (-EFAULT) \ - : "cc") - -#ifndef __ARMEB__ -#define __get_user_asm_half(x,__gu_addr,err) \ -({ \ - unsigned long __b1, __b2; \ - __get_user_asm_byte(__b1, __gu_addr, err); \ - __get_user_asm_byte(__b2, __gu_addr + 1, err); \ - (x) = __b1 | (__b2 << 8); \ -}) -#else -#define __get_user_asm_half(x,__gu_addr,err) \ -({ \ - unsigned long __b1, __b2; \ - __get_user_asm_byte(__b1, __gu_addr, err); \ - __get_user_asm_byte(__b2, __gu_addr + 1, err); \ - (x) = (__b1 << 8) | __b2; \ -}) -#endif - -#define __get_user_asm_word(x,addr,err) \ - __asm__ __volatile__( \ - "1: ldrt %1,[%2],#0\n" \ - "2:\n" \ - " .section .fixup,\"ax\"\n" \ - " .align 2\n" \ - "3: mov %0, %3\n" \ - " mov %1, #0\n" \ - " b 2b\n" \ - " .previous\n" \ - " .section __ex_table,\"a\"\n" \ - " .align 3\n" \ - " .long 1b, 3b\n" \ - " .previous" \ - : "+r" (err), "=&r" (x) \ - : "r" (addr), "i" (-EFAULT) \ - : "cc") - -extern unsigned long __arch_copy_from_user(void *to, const void *from, unsigned long n); -#define __do_copy_from_user(to,from,n) \ - (n) = __arch_copy_from_user(to,from,n) - -extern unsigned long __arch_copy_to_user(void *to, const void *from, unsigned long n); -#define __do_copy_to_user(to,from,n) \ - (n) = __arch_copy_to_user(to,from,n) - -extern unsigned long __arch_clear_user(void *addr, unsigned long n); -#define __do_clear_user(addr,sz) \ - (sz) = __arch_clear_user(addr,sz) - -extern unsigned long __arch_strncpy_from_user(char *to, const char *from, unsigned long count); -#define __do_strncpy_from_user(dst,src,count,res) \ - (res) = __arch_strncpy_from_user(dst,src,count) - -extern unsigned long __arch_strnlen_user(const char *s, long n); -#define __do_strnlen_user(s,n,res) \ - (res) = __arch_strnlen_user(s,n) diff --git a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h index 5b6040fc3f74..9fcc8a89080c 100644 --- a/include/asm-arm/proc-fns.h +++ b/include/asm-arm/proc-fns.h @@ -21,11 +21,6 @@ #undef MULTI_CPU #undef CPU_NAME -#ifdef CONFIG_CPU_26 -# define CPU_INCLUDE_NAME "asm/cpu-multi26.h" -# define MULTI_CPU -#endif - /* * CPU_NAME - the prefix for CPU related functions */ diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h index 181223a7329b..31c888ba601c 100644 --- a/include/asm-arm/processor.h +++ b/include/asm-arm/processor.h @@ -1,7 +1,7 @@ /* * linux/include/asm-arm/processor.h * - * Copyright (C) 1995 Russell King + * Copyright (C) 1995-1999 Russell King * * 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 @@ -27,9 +27,10 @@ #include <asm/ptrace.h> #include <asm/procinfo.h> #include <asm/arch/memory.h> -#include <asm/proc/processor.h> #include <asm/types.h> +#define KERNEL_STACK_SIZE PAGE_SIZE + union debug_insn { u32 arm; u16 thumb; @@ -56,6 +57,24 @@ struct thread_struct { #define INIT_THREAD { } +#define start_thread(regs,pc,sp) \ +({ \ + unsigned long *stack = (unsigned long *)sp; \ + set_fs(USER_DS); \ + memzero(regs->uregs, sizeof(regs->uregs)); \ + if (current->personality & ADDR_LIMIT_32BIT) \ + regs->ARM_cpsr = USR_MODE; \ + else \ + regs->ARM_cpsr = USR26_MODE; \ + if (elf_hwcap & HWCAP_THUMB && pc & 1) \ + regs->ARM_cpsr |= PSR_T_BIT; \ + regs->ARM_pc = pc & ~1; /* pc */ \ + regs->ARM_sp = sp; /* sp */ \ + regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ + regs->ARM_r1 = stack[1]; /* r1 (argv) */ \ + regs->ARM_r0 = stack[0]; /* r0 (argc) */ \ +}) + /* Forward declaration, a strange C thing */ struct task_struct; @@ -74,6 +93,9 @@ unsigned long get_wchan(struct task_struct *p); */ extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); +#define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1019]) +#define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1017]) + /* * Prefetching support - only ARMv5. */ diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h index eaf50e3bd63e..162c456638db 100644 --- a/include/asm-arm/ptrace.h +++ b/include/asm-arm/ptrace.h @@ -1,6 +1,17 @@ +/* + * linux/include/asm-arm/ptrace.h + * + * Copyright (C) 1996-2003 Russell King + * + * 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. + */ #ifndef __ASM_ARM_PTRACE_H #define __ASM_ARM_PTRACE_H +#include <linux/config.h> + #define PTRACE_GETREGS 12 #define PTRACE_SETREGS 13 #define PTRACE_GETFPREGS 14 @@ -8,9 +19,112 @@ #define PTRACE_OLDSETOPTIONS 21 -#include <asm/proc/ptrace.h> +/* + * PSR bits + */ +#define USR26_MODE 0x00000000 +#define FIQ26_MODE 0x00000001 +#define IRQ26_MODE 0x00000002 +#define SVC26_MODE 0x00000003 +#define USR_MODE 0x00000010 +#define FIQ_MODE 0x00000011 +#define IRQ_MODE 0x00000012 +#define SVC_MODE 0x00000013 +#define ABT_MODE 0x00000017 +#define UND_MODE 0x0000001b +#define SYSTEM_MODE 0x0000001f +#define MODE32_BIT 0x00000010 +#define MODE_MASK 0x0000001f +#define PSR_T_BIT 0x00000020 +#define PSR_F_BIT 0x00000040 +#define PSR_I_BIT 0x00000080 +#define PSR_J_BIT 0x01000000 +#define PSR_Q_BIT 0x08000000 +#define PSR_V_BIT 0x10000000 +#define PSR_C_BIT 0x20000000 +#define PSR_Z_BIT 0x40000000 +#define PSR_N_BIT 0x80000000 +#define PCMASK 0 + +/* + * Groups of PSR bits + */ +#define PSR_f 0xff000000 /* Flags */ +#define PSR_s 0x00ff0000 /* Status */ +#define PSR_x 0x0000ff00 /* Extension */ +#define PSR_c 0x000000ff /* Control */ #ifndef __ASSEMBLY__ + +/* this struct defines the way the registers are stored on the + stack during a system call. */ + +struct pt_regs { + long uregs[18]; +}; + +#define ARM_cpsr uregs[16] +#define ARM_pc uregs[15] +#define ARM_lr uregs[14] +#define ARM_sp uregs[13] +#define ARM_ip uregs[12] +#define ARM_fp uregs[11] +#define ARM_r10 uregs[10] +#define ARM_r9 uregs[9] +#define ARM_r8 uregs[8] +#define ARM_r7 uregs[7] +#define ARM_r6 uregs[6] +#define ARM_r5 uregs[5] +#define ARM_r4 uregs[4] +#define ARM_r3 uregs[3] +#define ARM_r2 uregs[2] +#define ARM_r1 uregs[1] +#define ARM_r0 uregs[0] +#define ARM_ORIG_r0 uregs[17] + +#ifdef __KERNEL__ + +#define user_mode(regs) \ + (((regs)->ARM_cpsr & 0xf) == 0) + +#ifdef CONFIG_ARM_THUMB +#define thumb_mode(regs) \ + (((regs)->ARM_cpsr & PSR_T_BIT)) +#else +#define thumb_mode(regs) (0) +#endif + +#define processor_mode(regs) \ + ((regs)->ARM_cpsr & MODE_MASK) + +#define interrupts_enabled(regs) \ + (!((regs)->ARM_cpsr & PSR_I_BIT)) + +#define fast_interrupts_enabled(regs) \ + (!((regs)->ARM_cpsr & PSR_F_BIT)) + +#define condition_codes(regs) \ + ((regs)->ARM_cpsr & (PSR_V_BIT|PSR_C_BIT|PSR_Z_BIT|PSR_N_BIT)) + +/* Are the current registers suitable for user mode? + * (used to maintain security in signal handlers) + */ +static inline int valid_user_regs(struct pt_regs *regs) +{ + if (user_mode(regs) && + (regs->ARM_cpsr & (PSR_F_BIT|PSR_I_BIT)) == 0) + return 1; + + /* + * Force CPSR to something logical... + */ + regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT; + + return 0; +} + +#endif /* __KERNEL__ */ + #define pc_pointer(v) \ ((v) & ~PCMASK) diff --git a/include/asm-arm/semaphore.h b/include/asm-arm/semaphore.h index 34412c203747..76284ff21f49 100644 --- a/include/asm-arm/semaphore.h +++ b/include/asm-arm/semaphore.h @@ -10,7 +10,7 @@ #include <linux/rwsem.h> #include <asm/atomic.h> -#include <asm/proc/locks.h> +#include <asm/locks.h> struct semaphore { atomic_t count; @@ -88,7 +88,7 @@ static inline void down(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif - + might_sleep(); __down_op(sem, __down_failed); } @@ -101,7 +101,7 @@ static inline int down_interruptible (struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif - + might_sleep(); return __down_op_ret(sem, __down_interruptible_failed); } diff --git a/include/asm-arm/shmparam.h b/include/asm-arm/shmparam.h index 4359852cc1ac..46d9944a7a14 100644 --- a/include/asm-arm/shmparam.h +++ b/include/asm-arm/shmparam.h @@ -1,8 +1,6 @@ #ifndef _ASMARM_SHMPARAM_H #define _ASMARM_SHMPARAM_H -#include <asm/proc/shmparam.h> - /* * This should be the size of the virtually indexed cache/ways, * or page size, whichever is greater since the cache aliases diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h index d000f45ed4e7..bb533f25fc7d 100644 --- a/include/asm-arm/system.h +++ b/include/asm-arm/system.h @@ -4,6 +4,45 @@ #ifdef __KERNEL__ #include <linux/config.h> + +#define CPU_ARCH_UNKNOWN 0 +#define CPU_ARCH_ARMv3 1 +#define CPU_ARCH_ARMv4 2 +#define CPU_ARCH_ARMv4T 3 +#define CPU_ARCH_ARMv5 4 +#define CPU_ARCH_ARMv5T 5 +#define CPU_ARCH_ARMv5TE 6 +#define CPU_ARCH_ARMv6 7 + +/* + * CR1 bits (CP#15 CR1) + */ +#define CR_M (1 << 0) /* MMU enable */ +#define CR_A (1 << 1) /* Alignment abort enable */ +#define CR_C (1 << 2) /* Dcache enable */ +#define CR_W (1 << 3) /* Write buffer enable */ +#define CR_P (1 << 4) /* 32-bit exception handler */ +#define CR_D (1 << 5) /* 32-bit data address range */ +#define CR_L (1 << 6) /* Implementation defined */ +#define CR_B (1 << 7) /* Big endian */ +#define CR_S (1 << 8) /* System MMU protection */ +#define CR_R (1 << 9) /* ROM MMU protection */ +#define CR_F (1 << 10) /* Implementation defined */ +#define CR_Z (1 << 11) /* Implementation defined */ +#define CR_I (1 << 12) /* Icache enable */ +#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */ +#define CR_RR (1 << 14) /* Round Robin cache replacement */ +#define CR_L4 (1 << 15) /* LDR pc can set T bit */ +#define CR_DT (1 << 16) +#define CR_IT (1 << 18) +#define CR_ST (1 << 19) +#define CR_FI (1 << 21) +#define CR_U (1 << 22) /* Unaligned access operation */ +#define CR_XP (1 << 23) /* Extended page tables */ +#define CR_VE (1 << 24) /* Vectored interrupts */ + +#ifndef __ASSEMBLY__ + #include <linux/kernel.h> struct thread_info; @@ -34,21 +73,30 @@ void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, extern asmlinkage void __backtrace(void); -#define CPU_ARCH_UNKNOWN 0 -#define CPU_ARCH_ARMv3 1 -#define CPU_ARCH_ARMv4 2 -#define CPU_ARCH_ARMv4T 3 -#define CPU_ARCH_ARMv5 4 -#define CPU_ARCH_ARMv5T 5 -#define CPU_ARCH_ARMv5TE 6 -#define CPU_ARCH_ARMv6 7 - extern int cpu_architecture(void); -/* - * Include processor dependent parts - */ -#include <asm/proc/system.h> +#define set_cr(x) \ + __asm__ __volatile__( \ + "mcr p15, 0, %0, c1, c0, 0 @ set CR" \ + : : "r" (x) : "cc") + +#define get_cr() \ + ({ \ + unsigned int __val; \ + __asm__ __volatile__( \ + "mrc p15, 0, %0, c1, c0, 0 @ get CR" \ + : "=r" (__val) : : "cc"); \ + __val; \ + }) + +extern unsigned long cr_no_alignment; /* defined in entry-armv.S */ +extern unsigned long cr_alignment; /* defined in entry-armv.S */ + +#if __LINUX_ARM_ARCH__ >= 4 +#define vectors_base() ((cr_alignment & CR_V) ? 0xffff0000 : 0) +#else +#define vectors_base() (0) +#endif #define mb() __asm__ __volatile__ ("" : : : "memory") #define rmb() mb() @@ -75,6 +123,102 @@ extern struct task_struct *__switch_to(struct task_struct *, struct thread_info mb(); \ } while (0) +/* + * Save the current interrupt enable state & disable IRQs + */ +#define local_irq_save(x) \ + ({ \ + unsigned long temp; \ + (void) (&temp == &x); \ + __asm__ __volatile__( \ + "mrs %0, cpsr @ local_irq_save\n" \ +" orr %1, %0, #128\n" \ +" msr cpsr_c, %1" \ + : "=r" (x), "=r" (temp) \ + : \ + : "memory", "cc"); \ + }) + +/* + * Enable IRQs + */ +#define local_irq_enable() \ + ({ \ + unsigned long temp; \ + __asm__ __volatile__( \ + "mrs %0, cpsr @ local_irq_enable\n" \ +" bic %0, %0, #128\n" \ +" msr cpsr_c, %0" \ + : "=r" (temp) \ + : \ + : "memory", "cc"); \ + }) + +/* + * Disable IRQs + */ +#define local_irq_disable() \ + ({ \ + unsigned long temp; \ + __asm__ __volatile__( \ + "mrs %0, cpsr @ local_irq_disable\n" \ +" orr %0, %0, #128\n" \ +" msr cpsr_c, %0" \ + : "=r" (temp) \ + : \ + : "memory", "cc"); \ + }) + +/* + * Enable FIQs + */ +#define __stf() \ + ({ \ + unsigned long temp; \ + __asm__ __volatile__( \ + "mrs %0, cpsr @ stf\n" \ +" bic %0, %0, #64\n" \ +" msr cpsr_c, %0" \ + : "=r" (temp) \ + : \ + : "memory", "cc"); \ + }) + +/* + * Disable FIQs + */ +#define __clf() \ + ({ \ + unsigned long temp; \ + __asm__ __volatile__( \ + "mrs %0, cpsr @ clf\n" \ +" orr %0, %0, #64\n" \ +" msr cpsr_c, %0" \ + : "=r" (temp) \ + : \ + : "memory", "cc"); \ + }) + +/* + * Save the current interrupt enable state. + */ +#define local_save_flags(x) \ + ({ \ + __asm__ __volatile__( \ + "mrs %0, cpsr @ local_save_flags" \ + : "=r" (x) : : "memory", "cc"); \ + }) + +/* + * restore saved IRQ & FIQ state + */ +#define local_irq_restore(x) \ + __asm__ __volatile__( \ + "msr cpsr_c, %0 @ local_irq_restore\n" \ + : \ + : "r" (x) \ + : "memory", "cc") + #ifdef CONFIG_SMP #error SMP not supported @@ -100,8 +244,67 @@ extern struct task_struct *__switch_to(struct task_struct *, struct thread_info flags & PSR_I_BIT; \ }) +#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110) +/* + * On the StrongARM, "swp" is terminally broken since it bypasses the + * cache totally. This means that the cache becomes inconsistent, and, + * since we use normal loads/stores as well, this is really bad. + * Typically, this causes oopsen in filp_close, but could have other, + * more disasterous effects. There are two work-arounds: + * 1. Disable interrupts and emulate the atomic swap + * 2. Clean the cache, perform atomic swap, flush the cache + * + * We choose (1) since its the "easiest" to achieve here and is not + * dependent on the processor type. + */ +#define swp_is_buggy +#endif + +static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) +{ + extern void __bad_xchg(volatile void *, int); + unsigned long ret; +#ifdef swp_is_buggy + unsigned long flags; +#endif + + switch (size) { +#ifdef swp_is_buggy + case 1: + local_irq_save(flags); + ret = *(volatile unsigned char *)ptr; + *(volatile unsigned char *)ptr = x; + local_irq_restore(flags); + break; + + case 4: + local_irq_save(flags); + ret = *(volatile unsigned long *)ptr; + *(volatile unsigned long *)ptr = x; + local_irq_restore(flags); + break; +#else + case 1: __asm__ __volatile__ ("swpb %0, %1, [%2]" + : "=&r" (ret) + : "r" (x), "r" (ptr) + : "memory", "cc"); + break; + case 4: __asm__ __volatile__ ("swp %0, %1, [%2]" + : "=&r" (ret) + : "r" (x), "r" (ptr) + : "memory", "cc"); + break; +#endif + default: __bad_xchg(ptr, size), ret = 0; + } + + return ret; +} + #endif /* CONFIG_SMP */ +#endif /* __ASSEMBLY__ */ + #endif /* __KERNEL__ */ #endif diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h index 60bec9ec8c79..642810a9ed84 100644 --- a/include/asm-arm/thread_info.h +++ b/include/asm-arm/thread_info.h @@ -18,9 +18,9 @@ struct task_struct; struct exec_domain; #include <asm/fpstate.h> -#include <asm/proc/processor.h> #include <asm/ptrace.h> #include <asm/types.h> +#include <asm/domain.h> typedef unsigned long mm_segment_t; @@ -55,17 +55,19 @@ struct thread_info { union fp_state fpstate; }; -#define INIT_THREAD_INFO(tsk) \ -{ \ - .task = &tsk, \ - .exec_domain = &default_exec_domain, \ - .flags = 0, \ - .preempt_count = 1, \ - .addr_limit = KERNEL_DS, \ - .restart_block = { \ - .fn = do_no_restart_syscall, \ - }, \ - INIT_EXTRA_THREAD_INFO, \ +#define INIT_THREAD_INFO(tsk) \ +{ \ + .task = &tsk, \ + .exec_domain = &default_exec_domain, \ + .flags = 0, \ + .preempt_count = 1, \ + .addr_limit = KERNEL_DS, \ + .cpu_domain = domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ + domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ + domain_val(DOMAIN_IO, DOMAIN_CLIENT), \ + .restart_block = { \ + .fn = do_no_restart_syscall, \ + }, \ } #define init_thread_info (init_thread_union.thread_info) diff --git a/include/asm-arm/tlbflush.h b/include/asm-arm/tlbflush.h index 9011f00fca32..6fdcc6ffeb0c 100644 --- a/include/asm-arm/tlbflush.h +++ b/include/asm-arm/tlbflush.h @@ -1,7 +1,7 @@ /* * linux/include/asm-arm/tlbflush.h * - * Copyright (C) 2000-2002 Russell King + * Copyright (C) 1999-2003 Russell King * * 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 @@ -10,6 +10,397 @@ #ifndef _ASMARM_TLBFLUSH_H #define _ASMARM_TLBFLUSH_H -#include <asm-arm/proc/tlbflush.h> +#include <linux/config.h> +#include <asm/glue.h> + +#define TLB_V3_PAGE (1 << 0) +#define TLB_V4_U_PAGE (1 << 1) +#define TLB_V4_D_PAGE (1 << 2) +#define TLB_V4_I_PAGE (1 << 3) +#define TLB_V6_U_PAGE (1 << 4) +#define TLB_V6_D_PAGE (1 << 5) +#define TLB_V6_I_PAGE (1 << 6) + +#define TLB_V3_FULL (1 << 8) +#define TLB_V4_U_FULL (1 << 9) +#define TLB_V4_D_FULL (1 << 10) +#define TLB_V4_I_FULL (1 << 11) +#define TLB_V6_U_FULL (1 << 12) +#define TLB_V6_D_FULL (1 << 13) +#define TLB_V6_I_FULL (1 << 14) + +#define TLB_V6_U_ASID (1 << 16) +#define TLB_V6_D_ASID (1 << 17) +#define TLB_V6_I_ASID (1 << 18) + +#define TLB_DCLEAN (1 << 30) +#define TLB_WB (1 << 31) + +/* + * MMU TLB Model + * ============= + * + * We have the following to choose from: + * v3 - ARMv3 + * v4 - ARMv4 without write buffer + * v4wb - ARMv4 with write buffer without I TLB flush entry instruction + * v4wbi - ARMv4 with write buffer with I TLB flush entry instruction + * v6wbi - ARMv6 with write buffer with I TLB flush entry instruction + */ +#undef _TLB +#undef MULTI_TLB + +#define v3_tlb_flags (TLB_V3_FULL | TLB_V3_PAGE) + +#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) +# define v3_possible_flags v3_tlb_flags +# define v3_always_flags v3_tlb_flags +# ifdef _TLB +# define MULTI_TLB 1 +# else +# define _TLB v3 +# endif +#else +# define v3_possible_flags 0 +# define v3_always_flags (-1UL) +#endif + +#define v4_tlb_flags (TLB_V4_U_FULL | TLB_V4_U_PAGE) + +#if defined(CONFIG_CPU_ARM720T) +# define v4_possible_flags v4_tlb_flags +# define v4_always_flags v4_tlb_flags +# ifdef _TLB +# define MULTI_TLB 1 +# else +# define _TLB v4 +# endif +#else +# define v4_possible_flags 0 +# define v4_always_flags (-1UL) +#endif + +#define v4wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \ + TLB_V4_I_FULL | TLB_V4_D_FULL | \ + TLB_V4_I_PAGE | TLB_V4_D_PAGE) + +#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \ + defined(CONFIG_CPU_ARM926T) || defined(CONFIG_CPU_ARM1020) || \ + defined(CONFIG_CPU_XSCALE) +# define v4wbi_possible_flags v4wbi_tlb_flags +# define v4wbi_always_flags v4wbi_tlb_flags +# ifdef _TLB +# define MULTI_TLB 1 +# else +# define _TLB v4wbi +# endif +#else +# define v4wbi_possible_flags 0 +# define v4wbi_always_flags (-1UL) +#endif + +#define v4wb_tlb_flags (TLB_WB | TLB_DCLEAN | \ + TLB_V4_I_FULL | TLB_V4_D_FULL | \ + TLB_V4_D_PAGE) + +#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100) +# define v4wb_possible_flags v4wb_tlb_flags +# define v4wb_always_flags v4wb_tlb_flags +# ifdef _TLB +# define MULTI_TLB 1 +# else +# define _TLB v4wb +# endif +#else +# define v4wb_possible_flags 0 +# define v4wb_always_flags (-1UL) +#endif + +#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \ + TLB_V6_I_FULL | TLB_V6_D_FULL | \ + TLB_V6_I_PAGE | TLB_V6_D_PAGE | \ + TLB_V6_I_ASID | TLB_V6_D_ASID) + +#if defined(CONFIG_CPU_V6) +# define v6wbi_possible_flags v6wbi_tlb_flags +# define v6wbi_always_flags v6wbi_tlb_flags +# ifdef _TLB +# define MULTI_TLB 1 +# else +# define _TLB v6wbi +# endif +#else +# define v6wbi_possible_flags 0 +# define v6wbi_always_flags (-1UL) +#endif + +#ifndef _TLB +#error Unknown TLB model +#endif + +#ifndef __ASSEMBLY__ + +struct cpu_tlb_fns { + void (*flush_user_range)(unsigned long, unsigned long, struct vm_area_struct *); + void (*flush_kern_range)(unsigned long, unsigned long); + unsigned long tlb_flags; +}; + +/* + * Select the calling method + */ +#ifdef MULTI_TLB + +#define __cpu_flush_user_tlb_range cpu_tlb.flush_user_range +#define __cpu_flush_kern_tlb_range cpu_tlb.flush_kern_range + +#else + +#define __cpu_flush_user_tlb_range __glue(_TLB,_flush_user_tlb_range) +#define __cpu_flush_kern_tlb_range __glue(_TLB,_flush_kern_tlb_range) + +extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *); +extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long); + +#endif + +extern struct cpu_tlb_fns cpu_tlb; + +#define __cpu_tlb_flags cpu_tlb.tlb_flags + +/* + * TLB Management + * ============== + * + * The arch/arm/mm/tlb-*.S files implement these methods. + * + * The TLB specific code is expected to perform whatever tests it + * needs to determine if it should invalidate the TLB for each + * call. Start addresses are inclusive and end addresses are + * exclusive; it is safe to round these addresses down. + * + * flush_tlb_all() + * + * Invalidate the entire TLB. + * + * flush_tlb_mm(mm) + * + * Invalidate all TLB entries in a particular address + * space. + * - mm - mm_struct describing address space + * + * flush_tlb_range(mm,start,end) + * + * Invalidate a range of TLB entries in the specified + * address space. + * - mm - mm_struct describing address space + * - start - start address (may not be aligned) + * - end - end address (exclusive, may not be aligned) + * + * flush_tlb_page(vaddr,vma) + * + * Invalidate the specified page in the specified address range. + * - vaddr - virtual address (may not be aligned) + * - vma - vma_struct describing address range + * + * flush_kern_tlb_page(kaddr) + * + * Invalidate the TLB entry for the specified page. The address + * will be in the kernels virtual memory space. Current uses + * only require the D-TLB to be invalidated. + * - kaddr - Kernel virtual memory address + */ + +/* + * We optimise the code below by: + * - building a set of TLB flags that might be set in __cpu_tlb_flags + * - building a set of TLB flags that will always be set in __cpu_tlb_flags + * - if we're going to need __cpu_tlb_flags, access it once and only once + * + * This allows us to build optimal assembly for the single-CPU type case, + * and as close to optimal given the compiler constrants for multi-CPU + * case. We could do better for the multi-CPU case if the compiler + * implemented the "%?" method, but this has been discontinued due to too + * many people getting it wrong. + */ +#define possible_tlb_flags (v3_possible_flags | \ + v4_possible_flags | \ + v4wbi_possible_flags | \ + v4wb_possible_flags | \ + v6wbi_possible_flags) + +#define always_tlb_flags (v3_always_flags & \ + v4_always_flags & \ + v4wbi_always_flags & \ + v4wb_always_flags & \ + v6wbi_always_flags) + +#define tlb_flag(f) ((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f))) + +static inline void flush_tlb_all(void) +{ + const int zero = 0; + const unsigned int __tlb_flag = __cpu_tlb_flags; + + if (tlb_flag(TLB_WB)) + asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero)); + + if (tlb_flag(TLB_V3_FULL)) + asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (zero)); + if (tlb_flag(TLB_V4_U_FULL | TLB_V6_U_FULL)) + asm("mcr%? p15, 0, %0, c8, c7, 0" : : "r" (zero)); + if (tlb_flag(TLB_V4_D_FULL | TLB_V6_D_FULL)) + asm("mcr%? p15, 0, %0, c8, c6, 0" : : "r" (zero)); + if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL)) + asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero)); +} + +static inline void flush_tlb_mm(struct mm_struct *mm) +{ + const int zero = 0; + const int asid = ASID(mm); + const unsigned int __tlb_flag = __cpu_tlb_flags; + + if (tlb_flag(TLB_WB)) + asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero)); + + if (mm == current->active_mm) { + if (tlb_flag(TLB_V3_FULL)) + asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (zero)); + if (tlb_flag(TLB_V4_U_FULL)) + asm("mcr%? p15, 0, %0, c8, c7, 0" : : "r" (zero)); + if (tlb_flag(TLB_V4_D_FULL)) + asm("mcr%? p15, 0, %0, c8, c6, 0" : : "r" (zero)); + if (tlb_flag(TLB_V4_I_FULL)) + asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero)); + } + + if (tlb_flag(TLB_V6_U_ASID)) + asm("mcr%? p15, 0, %0, c8, c7, 2" : : "r" (asid)); + if (tlb_flag(TLB_V6_D_ASID)) + asm("mcr%? p15, 0, %0, c8, c6, 2" : : "r" (asid)); + if (tlb_flag(TLB_V6_I_ASID)) + asm("mcr%? p15, 0, %0, c8, c5, 2" : : "r" (asid)); +} + +static inline void +flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) +{ + const int zero = 0; + const unsigned int __tlb_flag = __cpu_tlb_flags; + + uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm); + + if (tlb_flag(TLB_WB)) + asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero)); + + if (vma->vm_mm == current->active_mm) { + if (tlb_flag(TLB_V3_PAGE)) + asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (uaddr)); + if (tlb_flag(TLB_V4_U_PAGE)) + asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (uaddr)); + if (tlb_flag(TLB_V4_D_PAGE)) + asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (uaddr)); + if (tlb_flag(TLB_V4_I_PAGE)) + asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (uaddr)); + if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL)) + asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero)); + } + + if (tlb_flag(TLB_V6_U_PAGE)) + asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (uaddr)); + if (tlb_flag(TLB_V6_D_PAGE)) + asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (uaddr)); + if (tlb_flag(TLB_V6_I_PAGE)) + asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (uaddr)); +} + +static inline void flush_tlb_kernel_page(unsigned long kaddr) +{ + const int zero = 0; + const unsigned int __tlb_flag = __cpu_tlb_flags; + + kaddr &= PAGE_MASK; + + if (tlb_flag(TLB_WB)) + asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero)); + + if (tlb_flag(TLB_V3_PAGE)) + asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (kaddr)); + if (tlb_flag(TLB_V4_U_PAGE)) + asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (kaddr)); + if (tlb_flag(TLB_V4_D_PAGE)) + asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (kaddr)); + if (tlb_flag(TLB_V4_I_PAGE)) + asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (kaddr)); + if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL)) + asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero)); + + if (tlb_flag(TLB_V6_U_PAGE)) + asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (kaddr)); + if (tlb_flag(TLB_V6_D_PAGE)) + asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (kaddr)); + if (tlb_flag(TLB_V6_I_PAGE)) + asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (kaddr)); +} + +/* + * flush_pmd_entry + * + * Flush a PMD entry (word aligned, or double-word aligned) to + * RAM if the TLB for the CPU we are running on requires this. + * This is typically used when we are creating PMD entries. + * + * clean_pmd_entry + * + * Clean (but don't drain the write buffer) if the CPU requires + * these operations. This is typically used when we are removing + * PMD entries. + */ +static inline void flush_pmd_entry(pmd_t *pmd) +{ + const unsigned int zero = 0; + const unsigned int __tlb_flag = __cpu_tlb_flags; + + if (tlb_flag(TLB_DCLEAN)) + asm("mcr%? p15, 0, %0, c7, c10, 1 @ flush_pmd" + : : "r" (pmd)); + if (tlb_flag(TLB_WB)) + asm("mcr%? p15, 0, %0, c7, c10, 4 @ flush_pmd" + : : "r" (zero)); +} + +static inline void clean_pmd_entry(pmd_t *pmd) +{ + const unsigned int __tlb_flag = __cpu_tlb_flags; + + if (tlb_flag(TLB_DCLEAN)) + asm("mcr%? p15, 0, %0, c7, c10, 1 @ flush_pmd" + : : "r" (pmd)); +} + +#undef tlb_flag +#undef always_tlb_flags +#undef possible_tlb_flags + +/* + * Convert calls to our calling convention. + */ +#define flush_tlb_range(vma,start,end) __cpu_flush_user_tlb_range(start,end,vma) +#define flush_tlb_kernel_range(s,e) __cpu_flush_kern_tlb_range(s,e) + +/* + * if PG_dcache_dirty is set for the page, we need to ensure that any + * cache entries for the kernels virtual memory range are written + * back to the page. + */ +extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte); + +/* + * ARM processors do not cache TLB tables in RAM. + */ +#define flush_tlb_pgtables(mm,start,end) do { } while (0) + +#endif #endif diff --git a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h index 23bf0cbc1c76..634980801347 100644 --- a/include/asm-arm/uaccess.h +++ b/include/asm-arm/uaccess.h @@ -1,3 +1,10 @@ +/* + * linux/include/asm-arm/uaccess.h + * + * 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. + */ #ifndef _ASMARM_UACCESS_H #define _ASMARM_UACCESS_H @@ -6,6 +13,8 @@ */ #include <linux/sched.h> #include <asm/errno.h> +#include <asm/arch/memory.h> +#include <asm/domain.h> #define VERIFY_READ 0 #define VERIFY_WRITE 1 @@ -30,11 +39,39 @@ struct exception_table_entry extern int fixup_exception(struct pt_regs *regs); +/* + * Note that this is actually 0x1,0000,0000 + */ +#define KERNEL_DS 0x00000000 +#define USER_DS TASK_SIZE + #define get_ds() (KERNEL_DS) #define get_fs() (current_thread_info()->addr_limit) + +static inline void set_fs (mm_segment_t fs) +{ + current_thread_info()->addr_limit = fs; + modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER); +} + #define segment_eq(a,b) ((a) == (b)) -#include <asm/proc/uaccess.h> +#define __addr_ok(addr) ({ \ + unsigned long flag; \ + __asm__("cmp %2, %0; movlo %0, #0" \ + : "=&r" (flag) \ + : "0" (current_thread_info()->addr_limit), "r" (addr) \ + : "cc"); \ + (flag == 0); }) + +/* We use 33-bit arithmetic here... */ +#define __range_ok(addr,size) ({ \ + unsigned long flag, sum; \ + __asm__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0" \ + : "=&r" (flag), "=&r" (sum) \ + : "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit) \ + : "cc"); \ + flag; }) #define access_ok(type,addr,size) (__range_ok(addr,size) == 0) @@ -125,17 +162,71 @@ do { \ (x) = (__typeof__(*(ptr)))__gu_val; \ } while (0) +#define __get_user_asm_byte(x,addr,err) \ + __asm__ __volatile__( \ + "1: ldrbt %1,[%2],#0\n" \ + "2:\n" \ + " .section .fixup,\"ax\"\n" \ + " .align 2\n" \ + "3: mov %0, %3\n" \ + " mov %1, #0\n" \ + " b 2b\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .long 1b, 3b\n" \ + " .previous" \ + : "+r" (err), "=&r" (x) \ + : "r" (addr), "i" (-EFAULT) \ + : "cc") + +#ifndef __ARMEB__ +#define __get_user_asm_half(x,__gu_addr,err) \ +({ \ + unsigned long __b1, __b2; \ + __get_user_asm_byte(__b1, __gu_addr, err); \ + __get_user_asm_byte(__b2, __gu_addr + 1, err); \ + (x) = __b1 | (__b2 << 8); \ +}) +#else +#define __get_user_asm_half(x,__gu_addr,err) \ +({ \ + unsigned long __b1, __b2; \ + __get_user_asm_byte(__b1, __gu_addr, err); \ + __get_user_asm_byte(__b2, __gu_addr + 1, err); \ + (x) = (__b1 << 8) | __b2; \ +}) +#endif + +#define __get_user_asm_word(x,addr,err) \ + __asm__ __volatile__( \ + "1: ldrt %1,[%2],#0\n" \ + "2:\n" \ + " .section .fixup,\"ax\"\n" \ + " .align 2\n" \ + "3: mov %0, %3\n" \ + " mov %1, #0\n" \ + " b 2b\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .long 1b, 3b\n" \ + " .previous" \ + : "+r" (err), "=&r" (x) \ + : "r" (addr), "i" (-EFAULT) \ + : "cc") + extern int __put_user_1(void *, unsigned int); extern int __put_user_2(void *, unsigned int); extern int __put_user_4(void *, unsigned int); extern int __put_user_8(void *, unsigned long long); extern int __put_user_bad(void); -#define __put_user_x(__r1,__p,__e,__s,__i...) \ +#define __put_user_x(__r1,__p,__e,__s) \ __asm__ __volatile__ ("bl __put_user_" #__s \ : "=&r" (__e) \ : "0" (__p), "r" (__r1) \ - : __i, "cc") + : "ip", "lr", "cc") #define put_user(x,p) \ ({ \ @@ -144,16 +235,16 @@ extern int __put_user_bad(void); register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ case 1: \ - __put_user_x(__r1, __p, __e, 1, "ip", "lr"); \ + __put_user_x(__r1, __p, __e, 1); \ break; \ case 2: \ - __put_user_x(__r1, __p, __e, 2, "ip", "lr"); \ + __put_user_x(__r1, __p, __e, 2); \ break; \ case 4: \ - __put_user_x(__r1, __p, __e, 4, "ip", "lr"); \ + __put_user_x(__r1, __p, __e, 4); \ break; \ case 8: \ - __put_user_x(__r1, __p, __e, 8, "ip", "lr"); \ + __put_user_x(__r1, __p, __e, 8); \ break; \ default: __e = __put_user_bad(); break; \ } \ @@ -186,10 +277,93 @@ do { \ } \ } while (0) +#define __put_user_asm_byte(x,__pu_addr,err) \ + __asm__ __volatile__( \ + "1: strbt %1,[%2],#0\n" \ + "2:\n" \ + " .section .fixup,\"ax\"\n" \ + " .align 2\n" \ + "3: mov %0, %3\n" \ + " b 2b\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .long 1b, 3b\n" \ + " .previous" \ + : "+r" (err) \ + : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \ + : "cc") + +#ifndef __ARMEB__ +#define __put_user_asm_half(x,__pu_addr,err) \ +({ \ + unsigned long __temp = (unsigned long)(x); \ + __put_user_asm_byte(__temp, __pu_addr, err); \ + __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err); \ +}) +#else +#define __put_user_asm_half(x,__pu_addr,err) \ +({ \ + unsigned long __temp = (unsigned long)(x); \ + __put_user_asm_byte(__temp >> 8, __pu_addr, err); \ + __put_user_asm_byte(__temp, __pu_addr + 1, err); \ +}) +#endif + +#define __put_user_asm_word(x,__pu_addr,err) \ + __asm__ __volatile__( \ + "1: strt %1,[%2],#0\n" \ + "2:\n" \ + " .section .fixup,\"ax\"\n" \ + " .align 2\n" \ + "3: mov %0, %3\n" \ + " b 2b\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .long 1b, 3b\n" \ + " .previous" \ + : "+r" (err) \ + : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \ + : "cc") + +#ifndef __ARMEB__ +#define __reg_oper0 "%R2" +#define __reg_oper1 "%Q2" +#else +#define __reg_oper0 "%Q2" +#define __reg_oper1 "%R2" +#endif + +#define __put_user_asm_dword(x,__pu_addr,err) \ + __asm__ __volatile__( \ + "1: strt " __reg_oper1 ", [%1], #4\n" \ + "2: strt " __reg_oper0 ", [%1], #0\n" \ + "3:\n" \ + " .section .fixup,\"ax\"\n" \ + " .align 2\n" \ + "4: mov %0, %3\n" \ + " b 3b\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .long 1b, 4b\n" \ + " .long 2b, 4b\n" \ + " .previous" \ + : "+r" (err), "+r" (__pu_addr) \ + : "r" (x), "i" (-EFAULT) \ + : "cc") + +extern unsigned long __arch_copy_from_user(void *to, const void *from, unsigned long n); +extern unsigned long __arch_copy_to_user(void *to, const void *from, unsigned long n); +extern unsigned long __arch_clear_user(void *addr, unsigned long n); +extern unsigned long __arch_strncpy_from_user(char *to, const char *from, unsigned long count); +extern unsigned long __arch_strnlen_user(const char *s, long n); + static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n) { if (access_ok(VERIFY_READ, from, n)) - __do_copy_from_user(to, from, n); + n = __arch_copy_from_user(to, from, n); else /* security hole - plug it */ memzero(to, n); return n; @@ -197,49 +371,44 @@ static __inline__ unsigned long copy_from_user(void *to, const void *from, unsig static __inline__ unsigned long __copy_from_user(void *to, const void *from, unsigned long n) { - __do_copy_from_user(to, from, n); - return n; + return __arch_copy_from_user(to, from, n); } static __inline__ unsigned long copy_to_user(void *to, const void *from, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) - __do_copy_to_user(to, from, n); + n = __arch_copy_to_user(to, from, n); return n; } static __inline__ unsigned long __copy_to_user(void *to, const void *from, unsigned long n) { - __do_copy_to_user(to, from, n); - return n; + return __arch_copy_to_user(to, from, n); } static __inline__ unsigned long clear_user (void *to, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) - __do_clear_user(to, n); + n = __arch_clear_user(to, n); return n; } static __inline__ unsigned long __clear_user (void *to, unsigned long n) { - __do_clear_user(to, n); - return n; + return __arch_clear_user(to, n); } static __inline__ long strncpy_from_user (char *dst, const char *src, long count) { long res = -EFAULT; if (access_ok(VERIFY_READ, src, 1)) - __do_strncpy_from_user(dst, src, count, res); + res = __arch_strncpy_from_user(dst, src, count); return res; } static __inline__ long __strncpy_from_user (char *dst, const char *src, long count) { - long res; - __do_strncpy_from_user(dst, src, count, res); - return res; + return __arch_strncpy_from_user(dst, src, count); } #define strlen_user(s) strnlen_user(s, ~0UL >> 1) @@ -249,7 +418,7 @@ static inline long strnlen_user(const char *s, long n) unsigned long res = 0; if (__addr_ok(s)) - __do_strnlen_user(s, n, res); + res = __arch_strnlen_user(s, n); return res; } diff --git a/include/asm-arm26/semaphore.h b/include/asm-arm26/semaphore.h index a7d94526309d..49946274a67b 100644 --- a/include/asm-arm26/semaphore.h +++ b/include/asm-arm26/semaphore.h @@ -84,7 +84,7 @@ static inline void down(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif - + might_sleep(); __down_op(sem, __down_failed); } @@ -97,7 +97,7 @@ static inline int down_interruptible (struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif - + might_sleep(); return __down_op_ret(sem, __down_interruptible_failed); } diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h index 011a3bdc9ca7..d0821f6cef7f 100644 --- a/include/asm-cris/semaphore.h +++ b/include/asm-cris/semaphore.h @@ -79,6 +79,7 @@ extern inline void down(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif + might_sleep(); /* atomically decrement the semaphores count, and if its negative, we wait */ local_save_flags(flags); @@ -104,6 +105,7 @@ extern inline int down_interruptible(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif + might_sleep(); /* atomically decrement the semaphores count, and if its negative, we wait */ local_save_flags(flags); diff --git a/include/asm-h8300/semaphore.h b/include/asm-h8300/semaphore.h index 962f5eb32d16..62e6e9ce669e 100644 --- a/include/asm-h8300/semaphore.h +++ b/include/asm-h8300/semaphore.h @@ -90,6 +90,7 @@ static inline void down(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif + might_sleep(); count = &(sem->count); __asm__ __volatile__( @@ -117,6 +118,7 @@ static inline int down_interruptible(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif + might_sleep(); count = &(sem->count); __asm__ __volatile__( diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h index 8890ea1fdb4e..ffc472ff5418 100644 --- a/include/asm-i386/hpet.h +++ b/include/asm-i386/hpet.h @@ -102,8 +102,7 @@ extern int is_hpet_capable(void); extern int hpet_readl(unsigned long a); extern void hpet_writel(unsigned long d, unsigned long a); -#ifdef CONFIG_RTC -#define CONFIG_HPET_EMULATE_RTC 1 +#ifdef CONFIG_HPET_EMULATE_RTC extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask); extern int hpet_set_rtc_irq_bit(unsigned long bit_mask); extern int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec); @@ -111,6 +110,6 @@ extern int hpet_set_periodic_freq(unsigned long freq); extern int hpet_rtc_dropped_irq(void); extern int hpet_rtc_timer_init(void); extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs); -#endif /* CONFIG_RTC */ +#endif /* CONFIG_HPET_EMULATE_RTC */ #endif /* CONFIG_HPET_TIMER */ #endif /* _I386_HPET_H */ diff --git a/include/asm-i386/termios.h b/include/asm-i386/termios.h index c4cc5c8168aa..03f548536d6b 100644 --- a/include/asm-i386/termios.h +++ b/include/asm-i386/termios.h @@ -58,6 +58,7 @@ struct termio { #define N_HCI 15 /* Bluetooth HCI UART */ #ifdef __KERNEL__ +#include <linux/module.h> /* intr=^C quit=^\ erase=del kill=^U eof=^D vtime=\0 vmin=\1 sxtc=\0 diff --git a/include/asm-ia64/semaphore.h b/include/asm-ia64/semaphore.h index dd0eade35495..44165a637add 100644 --- a/include/asm-ia64/semaphore.h +++ b/include/asm-ia64/semaphore.h @@ -73,6 +73,7 @@ down (struct semaphore *sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif + might_sleep(); if (atomic_dec_return(&sem->count) < 0) __down(sem); } @@ -89,6 +90,7 @@ down_interruptible (struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif + might_sleep(); if (atomic_dec_return(&sem->count) < 0) ret = __down_interruptible(sem); return ret; diff --git a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h index 8581f361c52d..cc844ef36a83 100644 --- a/include/asm-m68k/semaphore.h +++ b/include/asm-m68k/semaphore.h @@ -89,7 +89,7 @@ extern inline void down(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif - + might_sleep(); __asm__ __volatile__( "| atomic down operation\n\t" "subql #1,%0@\n\t" @@ -112,7 +112,7 @@ extern inline int down_interruptible(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif - + might_sleep(); __asm__ __volatile__( "| atomic interruptible down operation\n\t" "subql #1,%1@\n\t" diff --git a/include/asm-m68knommu/semaphore.h b/include/asm-m68knommu/semaphore.h index 4720a09e6191..f85d311bc2d8 100644 --- a/include/asm-m68knommu/semaphore.h +++ b/include/asm-m68knommu/semaphore.h @@ -88,7 +88,7 @@ extern inline void down(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif - + might_sleep(); __asm__ __volatile__( "| atomic down operation\n\t" "movel %0, %%a1\n\t" @@ -108,7 +108,7 @@ extern inline int down_interruptible(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif - + might_sleep(); __asm__ __volatile__( "| atomic down operation\n\t" "movel %1, %%a1\n\t" diff --git a/include/asm-mips/semaphore.h b/include/asm-mips/semaphore.h index 34fc00d60460..a867bb1014be 100644 --- a/include/asm-mips/semaphore.h +++ b/include/asm-mips/semaphore.h @@ -88,6 +88,7 @@ static inline void down(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif + might_sleep(); if (atomic_dec_return(&sem->count) < 0) __down(sem); } @@ -103,6 +104,7 @@ static inline int down_interruptible(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif + might_sleep(); if (atomic_dec_return(&sem->count) < 0) ret = __down_interruptible(sem); return ret; diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h index 80686a7ab250..f01554398f1a 100644 --- a/include/asm-parisc/semaphore.h +++ b/include/asm-parisc/semaphore.h @@ -84,7 +84,7 @@ extern __inline__ void down(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif - + might_sleep(); spin_lock_irq(&sem->sentry); if (sem->count > 0) { sem->count--; @@ -100,7 +100,7 @@ extern __inline__ int down_interruptible(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif - + might_sleep(); spin_lock_irq(&sem->sentry); if (sem->count > 0) { sem->count--; diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h new file mode 100644 index 000000000000..ff6b72df2c10 --- /dev/null +++ b/include/asm-ppc/ibm44x.h @@ -0,0 +1,435 @@ +/* + * include/asm-ppc/ibm44x.h + * + * PPC44x definitions + * + * Matt Porter <mporter@mvista.com> + * + * Copyright 2002-2003 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 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifdef __KERNEL__ +#ifndef __ASM_IBM44x_H__ +#define __ASM_IBM44x_H__ + +#include <linux/config.h> + +#ifndef __ASSEMBLY__ +/* + * Data structure defining board information maintained by the boot + * ROM on IBM's "Ebony" evaluation board. An effort has been made to + * keep the field names consistent with the 8xx 'bd_t' board info + * structures. + * + * Ebony firmware stores MAC addresses in the F/W VPD area. The + * firmware must store the other dynamic values in NVRAM like on + * the previous 40x systems so they should be accessible if we + * really want them. + */ +typedef struct board_info { + unsigned char bi_enetaddr[2][6]; /* EMAC addresses */ + unsigned int bi_opb_busfreq; /* OPB clock in Hz */ + int bi_iic_fast[2]; /* Use fast i2c mode */ +} bd_t; +#endif /* __ASSEMBLY__ */ + +#ifndef NR_BOARD_IRQS +#define NR_BOARD_IRQS 0 +#endif + +#define _IO_BASE isa_io_base +#define _ISA_MEM_BASE isa_mem_base +#define PCI_DRAM_OFFSET pci_dram_offset + +/* TLB entry offset/size used for pinning kernel lowmem */ +#define PPC44x_PIN_SHIFT 28 +#define PPC44x_PIN_SIZE (1 << PPC44x_PIN_SHIFT) + +/* Lowest TLB slot consumed by the default pinned TLBs */ +#define PPC44x_LOW_SLOT 62 + +/* + * Standard 4GB "page" definitions + */ +#define PPC44x_IO_PAGE 0x0000000100000000ULL +#define PPC44x_PCICFG_PAGE 0x0000000200000000ULL +#define PPC44x_PCIIO_PAGE PPC44x_PCICFG_PAGE +#define PPC44x_PCIMEM_PAGE 0x0000000300000000ULL + +/* + * 36-bit trap ranges + */ +#define PPC44x_IO_LO 0x40000000 +#define PPC44x_IO_HI 0x40001000 +#define PPC44x_PCICFG_LO 0x0ec00000 +#define PPC44x_PCICFG_HI 0x0ec7ffff +#define PPC44x_PCIMEM_LO 0x80002000 +#define PPC44x_PCIMEM_HI 0xffffffff + +/* + * The "residual" board information structure the boot loader passes + * into the kernel. + */ +#ifndef __ASSEMBLY__ + +/* + * SPRN definitions + */ +#define SPRN_CPC0_GPIO 0xe5/BEARLRL + +/* + * DCRN definitions + */ + +#ifdef CONFIG_440GX +/* SDRs */ +#define DCRN_SDR_CONFIG_ADDR 0xe +#define DCRN_SDR_CONFIG_DATA 0xf +#define DCRN_SDR_PFC0 0x4100 +#define DCRN_SDR_PFC1 0x4101 +#define DCRN_SDR_MFR 0x4300 +#define DCRN_SDR_MFR_TAH0 0x80000000 /* TAHOE0 Enable */ +#define DCRN_SDR_MFR_TAH1 0x40000000 /* TAHOE1 Enable */ +#define DCRN_SDR_MFR_PCM 0x10000000 /* PPC440GP irq compat mode */ +#define DCRN_SDR_MFR_ECS 0x08000000 /* EMAC int clk */ +#define DCRN_SDR_MFR_T0TXFL 0x00080000 +#define DCRN_SDR_MFR_T0TXFH 0x00040000 +#define DCRN_SDR_MFR_T1TXFL 0x00020000 +#define DCRN_SDR_MFR_T1TXFH 0x00010000 +#define DCRN_SDR_MFR_E0TXFL 0x00008000 +#define DCRN_SDR_MFR_E0TXFH 0x00004000 +#define DCRN_SDR_MFR_E0RXFL 0x00002000 +#define DCRN_SDR_MFR_E0RXFH 0x00001000 +#define DCRN_SDR_MFR_E1TXFL 0x00000800 +#define DCRN_SDR_MFR_E1TXFH 0x00000400 +#define DCRN_SDR_MFR_E1RXFL 0x00000200 +#define DCRN_SDR_MFR_E1RXFH 0x00000100 +#define DCRN_SDR_MFR_E2TXFL 0x00000080 +#define DCRN_SDR_MFR_E2TXFH 0x00000040 +#define DCRN_SDR_MFR_E2RXFL 0x00000020 +#define DCRN_SDR_MFR_E2RXFH 0x00000010 +#define DCRN_SDR_MFR_E3TXFL 0x00000008 +#define DCRN_SDR_MFR_E3TXFH 0x00000004 +#define DCRN_SDR_MFR_E3RXFL 0x00000002 +#define DCRN_SDR_MFR_E3RXFH 0x00000001 + +/* SDR read/write helper macros */ +#define SDR_READ(offset) ({\ + mtdcr(DCRN_SDR_CONFIG_ADDR, offset); \ + mfdcr(DCRN_SDR_CONFIG_DATA);}) +#define SDR_WRITE(offset, data) ({\ + mtdcr(DCRN_SDR_CONFIG_ADDR, offset); \ + mtdcr(DCRN_SDR_CONFIG_DATA,data);}) +#endif /* CONFIG_440GX */ + +/* Base DCRNs */ +#define DCRN_DMA0_BASE 0x100 +#define DCRN_DMA1_BASE 0x108 +#define DCRN_DMA2_BASE 0x110 +#define DCRN_DMA3_BASE 0x118 +#define DCRN_DMASR_BASE 0x120 +#define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */ +#define DCRN_MAL_BASE 0x180 + +/* UIC */ +#define DCRN_UIC0_BASE 0xc0 +#define DCRN_UIC1_BASE 0xd0 +#define UIC0 DCRN_UIC0_BASE +#define UIC1 DCRN_UIC1_BASE + +#define DCRN_UIC_SR(base) (base + 0x0) +#define DCRN_UIC_ER(base) (base + 0x2) +#define DCRN_UIC_CR(base) (base + 0x3) +#define DCRN_UIC_PR(base) (base + 0x4) +#define DCRN_UIC_TR(base) (base + 0x5) +#define DCRN_UIC_MSR(base) (base + 0x6) +#define DCRN_UIC_VR(base) (base + 0x7) +#define DCRN_UIC_VCR(base) (base + 0x8) + +#define UIC0_UIC1NC 30 /* UIC1 non-critical interrupt */ +#define UIC0_UIC1CR 31 /* UIC1 critical interrupt */ + +/* 440GP MAL DCRs */ +#define DCRN_MALCR(base) (base + 0x0) /* Configuration */ +#define DCRN_MALESR(base) (base + 0x1) /* Error Status */ +#define DCRN_MALIER(base) (base + 0x2) /* Interrupt Enable */ +#define DCRN_MALTXCASR(base) (base + 0x4) /* Tx Channel Active Set */ +#define DCRN_MALTXCARR(base) (base + 0x5) /* Tx Channel Active Reset */ +#define DCRN_MALTXEOBISR(base) (base + 0x6) /* Tx End of Buffer Interrupt Status */ +#define DCRN_MALTXDEIR(base) (base + 0x7) /* Tx Descriptor Error Interrupt */ +#define DCRN_MALRXCASR(base) (base + 0x10) /* Rx Channel Active Set */ +#define DCRN_MALRXCARR(base) (base + 0x11) /* Rx Channel Active Reset */ +#define DCRN_MALRXEOBISR(base) (base + 0x12) /* Rx End of Buffer Interrupt Status */ +#define DCRN_MALRXDEIR(base) (base + 0x13) /* Rx Descriptor Error Interrupt */ +#define DCRN_MALTXCTP0R(base) (base + 0x20) /* Channel Tx 0 Channel Table Pointer */ +#define DCRN_MALTXCTP1R(base) (base + 0x21) /* Channel Tx 1 Channel Table Pointer */ +#define DCRN_MALTXCTP2R(base) (base + 0x22) /* Channel Tx 2 Channel Table Pointer */ +#define DCRN_MALTXCTP3R(base) (base + 0x23) /* Channel Tx 3 Channel Table Pointer */ +#define DCRN_MALRXCTP0R(base) (base + 0x40) /* Channel Rx 0 Channel Table Pointer */ +#define DCRN_MALRXCTP1R(base) (base + 0x41) /* Channel Rx 1 Channel Table Pointer */ +#define DCRN_MALRCBS0(base) (base + 0x60) /* Channel Rx 0 Channel Buffer Size */ +#define DCRN_MALRCBS1(base) (base + 0x61) /* Channel Rx 1 Channel Buffer Size */ + +/* Compatibility DCRN's */ +#define DCRN_MALRXCTP2R(base) ((base) + 0x42) /* Channel Rx 2 Channel Table Pointer */ +#define DCRN_MALRXCTP3R(base) ((base) + 0x43) /* Channel Rx 3 Channel Table Pointer */ +#define DCRN_MALTXCTP4R(base) ((base) + 0x24) /* Channel Tx 4 Channel Table Pointer */ +#define DCRN_MALTXCTP5R(base) ((base) + 0x25) /* Channel Tx 5 Channel Table Pointer */ +#define DCRN_MALTXCTP6R(base) ((base) + 0x26) /* Channel Tx 6 Channel Table Pointer */ +#define DCRN_MALTXCTP7R(base) ((base) + 0x27) /* Channel Tx 7 Channel Table Pointer */ +#define DCRN_MALRCBS2(base) ((base) + 0x62) /* Channel Rx 2 Channel Buffer Size */ +#define DCRN_MALRCBS3(base) ((base) + 0x63) /* Channel Rx 3 Channel Buffer Size */ + + +#define MALCR_MMSR 0x80000000 /* MAL Software reset */ +#define MALCR_PLBP_1 0x00400000 /* MAL reqest priority: */ +#define MALCR_PLBP_2 0x00800000 /* lowsest is 00 */ +#define MALCR_PLBP_3 0x00C00000 /* highest */ +#define MALCR_GA 0x00200000 /* Guarded Active Bit */ +#define MALCR_OA 0x00100000 /* Ordered Active Bit */ +#define MALCR_PLBLE 0x00080000 /* PLB Lock Error Bit */ +#define MALCR_PLBLT_1 0x00040000 /* PLB Latency Timer */ +#define MALCR_PLBLT_2 0x00020000 +#define MALCR_PLBLT_3 0x00010000 +#define MALCR_PLBLT_4 0x00008000 +#ifdef CONFIG_440GP +#define MALCR_PLBLT_DEFAULT 0x00330000 /* PLB Latency Timer default */ +#else +#define MALCR_PLBLT_DEFAULT 0x00ff0000 /* PLB Latency Timer default */ +#endif +#define MALCR_PLBB 0x00004000 /* PLB Burst Deactivation Bit */ +#define MALCR_OPBBL 0x00000080 /* OPB Lock Bit */ +#define MALCR_EOPIE 0x00000004 /* End Of Packet Interrupt Enable */ +#define MALCR_LEA 0x00000002 /* Locked Error Active */ +#define MALCR_MSD 0x00000001 /* MAL Scroll Descriptor Bit */ +/* DCRN_MALESR */ +#define MALESR_EVB 0x80000000 /* Error Valid Bit */ +#define MALESR_CIDRX 0x40000000 /* Channel ID Receive */ +#define MALESR_DE 0x00100000 /* Descriptor Error */ +#define MALESR_OEN 0x00080000 /* OPB Non-Fullword Error */ +#define MALESR_OTE 0x00040000 /* OPB Timeout Error */ +#define MALESR_OSE 0x00020000 /* OPB Slave Error */ +#define MALESR_PEIN 0x00010000 /* PLB Bus Error Indication */ +#define MALESR_DEI 0x00000010 /* Descriptor Error Interrupt */ +#define MALESR_ONEI 0x00000008 /* OPB Non-Fullword Error Interrupt */ +#define MALESR_OTEI 0x00000004 /* OPB Timeout Error Interrupt */ +#define MALESR_OSEI 0x00000002 /* OPB Slace Error Interrupt */ +#define MALESR_PBEI 0x00000001 /* PLB Bus Error Interrupt */ +/* DCRN_MALIER */ +#define MALIER_DE 0x00000010 /* Descriptor Error Interrupt Enable */ +#define MALIER_NE 0x00000008 /* OPB Non-word Transfer Int Enable */ +#define MALIER_TE 0x00000004 /* OPB Time Out Error Interrupt Enable */ +#define MALIER_OPBE 0x00000002 /* OPB Slave Error Interrupt Enable */ +#define MALIER_PLBE 0x00000001 /* PLB Error Interrupt Enable */ +/* DCRN_MALTXEOBISR */ +#define MALOBISR_CH0 0x80000000 /* EOB channel 1 bit */ +#define MALOBISR_CH2 0x40000000 /* EOB channel 2 bit */ + +/* 440GP PLB Arbiter DCRs */ +#define DCRN_PLB0_REVID 0x082 /* PLB Arbiter Revision ID */ +#define DCRN_PLB0_ACR 0x083 /* PLB Arbiter Control */ +#define DCRN_PLB0_BESR 0x084 /* PLB Error Status */ +#define DCRN_PLB0_BEARL 0x086 /* PLB Error Address Low */ +#define DCRN_PLB0_BEAR DCRN_PLB0_BEARL /* 40x compatibility */ +#define DCRN_PLB0_BEARH 0x087 /* PLB Error Address High */ + +/* 440GP Clock, PM, chip control */ +#define DCRN_CPC0_SR 0x0b0 +#define DCRN_CPC0_ER 0x0b1 +#define DCRN_CPC0_FR 0x0b2 +#define DCRN_CPC0_SYS0 0x0e0 +#define DCRN_CPC0_SYS1 0x0e1 +#define DCRN_CPC0_CUST0 0x0e2 +#define DCRN_CPC0_CUST1 0x0e3 +#define DCRN_CPC0_STRP0 0x0e4 +#define DCRN_CPC0_STRP1 0x0e5 +#define DCRN_CPC0_STRP2 0x0e6 +#define DCRN_CPC0_STRP3 0x0e7 +#define DCRN_CPC0_GPIO 0x0e8 +#define DCRN_CPC0_PLB 0x0e9 +#define DCRN_CPC0_CR1 0x0ea +#define DCRN_CPC0_CR0 0x0eb +#define DCRN_CPC0_MIRQ0 0x0ec +#define DCRN_CPC0_MIRQ1 0x0ed +#define DCRN_CPC0_JTAGID 0x0ef + +/* 440GP DMA controller DCRs */ +#define DCRN_DMACR0 (DCRN_DMA0_BASE + 0x0) /* DMA Channel Control 0 */ +#define DCRN_DMACT0 (DCRN_DMA0_BASE + 0x1) /* DMA Count 0 */ +#define DCRN_DMASAH0 (DCRN_DMA0_BASE + 0x2) /* DMA Src Addr High 0 */ +#define DCRN_DMASA0 (DCRN_DMA0_BASE + 0x3) /* DMA Src Addr Low 0 */ +#define DCRN_DMADAH0 (DCRN_DMA0_BASE + 0x4) /* DMA Dest Addr High 0 */ +#define DCRN_DMADA0 (DCRN_DMA0_BASE + 0x5) /* DMA Dest Addr Low 0 */ +#define DCRN_ASGH0 (DCRN_DMA0_BASE + 0x6) /* DMA SG Desc Addr High 0 */ +#define DCRN_ASG0 (DCRN_DMA0_BASE + 0x7) /* DMA SG Desc Addr Low 0 */ + +#define DCRN_DMACR1 (DCRN_DMA1_BASE + 0x0) /* DMA Channel Control 1 */ +#define DCRN_DMACT1 (DCRN_DMA1_BASE + 0x1) /* DMA Count 1 */ +#define DCRN_DMASAH1 (DCRN_DMA1_BASE + 0x2) /* DMA Src Addr High 1 */ +#define DCRN_DMASA1 (DCRN_DMA1_BASE + 0x3) /* DMA Src Addr Low 1 */ +#define DCRN_DMADAH1 (DCRN_DMA1_BASE + 0x4) /* DMA Dest Addr High 1 */ +#define DCRN_DMADA1 (DCRN_DMA1_BASE + 0x5) /* DMA Dest Addr Low 1 */ +#define DCRN_ASGH1 (DCRN_DMA1_BASE + 0x6) /* DMA SG Desc Addr High 1 */ +#define DCRN_ASG1 (DCRN_DMA1_BASE + 0x7) /* DMA SG Desc Addr Low 1 */ + +#define DCRN_DMACR2 (DCRN_DMA2_BASE + 0x0) /* DMA Channel Control 2 */ +#define DCRN_DMACT2 (DCRN_DMA2_BASE + 0x1) /* DMA Count 2 */ +#define DCRN_DMASAH2 (DCRN_DMA2_BASE + 0x2) /* DMA Src Addr High 2 */ +#define DCRN_DMASA2 (DCRN_DMA2_BASE + 0x3) /* DMA Src Addr Low 2 */ +#define DCRN_DMADAH2 (DCRN_DMA2_BASE + 0x4) /* DMA Dest Addr High 2 */ +#define DCRN_DMADA2 (DCRN_DMA2_BASE + 0x5) /* DMA Dest Addr Low 2 */ +#define DCRN_ASGH2 (DCRN_DMA2_BASE + 0x6) /* DMA SG Desc Addr High 2 */ +#define DCRN_ASG2 (DCRN_DMA2_BASE + 0x7) /* DMA SG Desc Addr Low 2 */ + +#define DCRN_DMACR3 (DCRN_DMA3_BASE + 0x0) /* DMA Channel Control 3 */ +#define DCRN_DMACT3 (DCRN_DMA3_BASE + 0x1) /* DMA Count 3 */ +#define DCRN_DMASAH3 (DCRN_DMA3_BASE + 0x2) /* DMA Src Addr High 3 */ +#define DCRN_DMASA3 (DCRN_DMA3_BASE + 0x3) /* DMA Src Addr Low 3 */ +#define DCRN_DMADAH3 (DCRN_DMA3_BASE + 0x4) /* DMA Dest Addr High 3 */ +#define DCRN_DMADA3 (DCRN_DMA3_BASE + 0x5) /* DMA Dest Addr Low 3 */ +#define DCRN_ASGH3 (DCRN_DMA3_BASE + 0x6) /* DMA SG Desc Addr High 3 */ +#define DCRN_ASG3 (DCRN_DMA3_BASE + 0x7) /* DMA SG Desc Addr Low 3 */ + +#define DCRN_DMASR (DCRN_DMASR_BASE + 0x0) /* DMA Status Register */ +#define DCRN_ASGC (DCRN_DMASR_BASE + 0x3) /* DMA Scatter/Gather Command */ +#define DCRN_SLP (DCRN_DMASR_BASE + 0x5) /* DMA Sleep Register */ +#define DCRN_POL (DCRN_DMASR_BASE + 0x6) /* DMA Polarity Register */ + +/* 440GP DRAM controller DCRs */ +#define DCRN_SDRAM0_CFGADDR 0x010 +#define DCRN_SDRAM0_CFGDATA 0x011 + +#define SDRAM0_B0CR 0x40 +#define SDRAM0_B1CR 0x44 +#define SDRAM0_B2CR 0x48 +#define SDRAM0_B3CR 0x4c + +#define SDRAM_CONFIG_BANK_ENABLE 0x00000001 +#define SDRAM_CONFIG_SIZE_MASK 0x000e0000 +#define SDRAM_CONFIG_BANK_SIZE(reg) ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17) +#define SDRAM_CONFIG_SIZE_8M 0x00000001 +#define SDRAM_CONFIG_SIZE_16M 0x00000002 +#define SDRAM_CONFIG_SIZE_32M 0x00000003 +#define SDRAM_CONFIG_SIZE_64M 0x00000004 +#define SDRAM_CONFIG_SIZE_128M 0x00000005 +#define SDRAM_CONFIG_SIZE_256M 0x00000006 +#define SDRAM_CONFIG_SIZE_512M 0x00000007 +#define PPC44x_MEM_SIZE_8M 0x00800000 +#define PPC44x_MEM_SIZE_16M 0x01000000 +#define PPC44x_MEM_SIZE_32M 0x02000000 +#define PPC44x_MEM_SIZE_64M 0x04000000 +#define PPC44x_MEM_SIZE_128M 0x08000000 +#define PPC44x_MEM_SIZE_256M 0x10000000 +#define PPC44x_MEM_SIZE_512M 0x20000000 + +/* + * PCI-X definitions + */ +#define PCIX0_REG_BASE 0x20ec80000ULL +#define PCIX0_REG_SIZE 0x200 + +#define PCIX0_VENDID 0x000 +#define PCIX0_DEVID 0x002 +#define PCIX0_COMMAND 0x004 +#define PCIX0_STATUS 0x006 +#define PCIX0_REVID 0x008 +#define PCIX0_CLS 0x009 +#define PCIX0_CACHELS 0x00c +#define PCIX0_LATTIM 0x00d +#define PCIX0_HDTYPE 0x00e +#define PCIX0_BIST 0x00f +#define PCIX0_BAR0L 0x010 +#define PCIX0_BAR0H 0x014 +#define PCIX0_BAR1 0x018 +#define PCIX0_BAR2L 0x01c +#define PCIX0_BAR2H 0x020 +#define PCIX0_BAR3 0x024 +#define PCIX0_CISPTR 0x028 +#define PCIX0_SBSYSVID 0x02c +#define PCIX0_SBSYSID 0x02e +#define PCIX0_EROMBA 0x030 +#define PCIX0_CAP 0x034 +#define PCIX0_RES0 0x035 +#define PCIX0_RES1 0x036 +#define PCIX0_RES2 0x038 +#define PCIX0_INTLN 0x03c +#define PCIX0_INTPN 0x03d +#define PCIX0_MINGNT 0x03e +#define PCIX0_MAXLTNCY 0x03f +#define PCIX0_BRDGOPT1 0x040 +#define PCIX0_BRDGOPT2 0x044 +#define PCIX0_ERREN 0x050 +#define PCIX0_ERRSTS 0x054 +#define PCIX0_PLBBESR 0x058 +#define PCIX0_PLBBEARL 0x05c +#define PCIX0_PLBBEARH 0x060 +#define PCIX0_POM0LAL 0x068 +#define PCIX0_POM0LAH 0x06c +#define PCIX0_POM0SA 0x070 +#define PCIX0_POM0PCIAL 0x074 +#define PCIX0_POM0PCIAH 0x078 +#define PCIX0_POM1LAL 0x07c +#define PCIX0_POM1LAH 0x080 +#define PCIX0_POM1SA 0x084 +#define PCIX0_POM1PCIAL 0x088 +#define PCIX0_POM1PCIAH 0x08c +#define PCIX0_POM2SA 0x090 +#define PCIX0_PIM0SAL 0x098 +#define PCIX0_PIM0SA PCIX0_PIM0SAL +#define PCIX0_PIM0LAL 0x09c +#define PCIX0_PIM0LAH 0x0a0 +#define PCIX0_PIM1SA 0x0a4 +#define PCIX0_PIM1LAL 0x0a8 +#define PCIX0_PIM1LAH 0x0ac +#define PCIX0_PIM2SAL 0x0b0 +#define PCIX0_PIM2SA PCIX0_PIM2SAL +#define PCIX0_PIM2LAL 0x0b4 +#define PCIX0_PIM2LAH 0x0b8 +#define PCIX0_OMCAPID 0x0c0 +#define PCIX0_OMNIPTR 0x0c1 +#define PCIX0_OMMC 0x0c2 +#define PCIX0_OMMA 0x0c4 +#define PCIX0_OMMUA 0x0c8 +#define PCIX0_OMMDATA 0x0cc +#define PCIX0_OMMEOI 0x0ce +#define PCIX0_PMCAPID 0x0d0 +#define PCIX0_PMNIPTR 0x0d1 +#define PCIX0_PMC 0x0d2 +#define PCIX0_PMCSR 0x0d4 +#define PCIX0_PMCSRBSE 0x0d6 +#define PCIX0_PMDATA 0x0d7 +#define PCIX0_PMSCRR 0x0d8 +#define PCIX0_CAPID 0x0dc +#define PCIX0_NIPTR 0x0dd +#define PCIX0_CMD 0x0de +#define PCIX0_STS 0x0e0 +#define PCIX0_IDR 0x0e4 +#define PCIX0_CID 0x0e8 +#define PCIX0_RID 0x0ec +#define PCIX0_PIM0SAH 0x0f8 +#define PCIX0_PIM2SAH 0x0fc +#define PCIX0_MSGIL 0x100 +#define PCIX0_MSGIH 0x104 +#define PCIX0_MSGOL 0x108 +#define PCIX0_MSGOH 0x10c +#define PCIX0_IM 0x1f8 + +#define IIC_OWN 0x55 +#define IIC_CLOCK 50 + +#undef NR_UICS +#define NR_UICS 2 +#define UIC_CASCADE_MASK 0x0003 /* bits 30 & 31 */ + +#define BD_EMAC_ADDR(e,i) bi_enetaddr[e][i] + +#include <asm/ibm4xx.h> + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_IBM44x_H__ */ +#endif /* __KERNEL__ */ diff --git a/include/asm-ppc/ibm4xx.h b/include/asm-ppc/ibm4xx.h index 4884067dbcd9..c8da43c8512f 100644 --- a/include/asm-ppc/ibm4xx.h +++ b/include/asm-ppc/ibm4xx.h @@ -122,7 +122,25 @@ void ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5, #define PCI_DRAM_OFFSET 0 #endif +#elif CONFIG_44x + +#if defined(CONFIG_EBONY) +#include <platforms/4xx/ebony.h> +#endif + +#if defined(CONFIG_OCOTEA) +#include <platforms/4xx/ocotea.h> +#endif #endif /* CONFIG_40x */ + +#ifndef __ASSEMBLY__ +/* + * The "residual" board information structure the boot loader passes + * into the kernel. + */ +extern bd_t __res; +#endif + #endif /* __ASM_IBM4XX_H__ */ #endif /* __KERNEL__ */ diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h index b67f27323f46..55e67291c3d2 100644 --- a/include/asm-ppc/io.h +++ b/include/asm-ppc/io.h @@ -4,9 +4,11 @@ #include <linux/config.h> #include <linux/types.h> +#include <linux/mm.h> #include <asm/page.h> #include <asm/byteorder.h> +#include <asm/mmu.h> #define SIO_CONFIG_RA 0x398 #define SIO_CONFIG_RD 0x399 @@ -22,7 +24,7 @@ #define PREP_ISA_MEM_BASE 0xc0000000 #define PREP_PCI_DRAM_OFFSET 0x80000000 -#if defined(CONFIG_40x) +#if defined(CONFIG_4xx) #include <asm/ibm4xx.h> #elif defined(CONFIG_8xx) #include <asm/mpc8xx.h> @@ -197,14 +199,17 @@ extern void _outsl_ns(volatile u32 *port, const void *buf, int nl); * Map in an area of physical address space, for accessing * I/O devices etc. */ -extern void *__ioremap(unsigned long address, unsigned long size, +extern void *__ioremap(phys_addr_t address, unsigned long size, unsigned long flags); -extern void *ioremap(unsigned long address, unsigned long size); +extern void *ioremap(phys_addr_t address, unsigned long size); +#ifdef CONFIG_44x +extern void *ioremap64(unsigned long long address, unsigned long size); +#endif #define ioremap_nocache(addr, size) ioremap((addr), (size)) extern void iounmap(void *addr); extern unsigned long iopa(unsigned long addr); extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const)); -extern void io_block_mapping(unsigned long virt, unsigned long phys, +extern void io_block_mapping(unsigned long virt, phys_addr_t phys, unsigned int size, int flags); /* diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h index 6ca586ab8f4e..02b993f6c3c7 100644 --- a/include/asm-ppc/irq.h +++ b/include/asm-ppc/irq.h @@ -71,11 +71,11 @@ irq_canonicalize(int irq) return (irq); } -#elif defined(CONFIG_440) -#include <asm/ibm440.h> +#elif defined(CONFIG_44x) +#include <asm/ibm44x.h> -#define NR_UIC_IRQS 64 -#define NR_IRQS (NR_UIC_IRQS + NR_BOARD_IRQS) +#define NR_UIC_IRQS 32 +#define NR_IRQS ((NR_UIC_IRQS * NR_UICS) + NR_BOARD_IRQS) static __inline__ int irq_canonicalize(int irq) diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h index 7b729cdf52f4..b75b24e4c056 100644 --- a/include/asm-ppc/mmu.h +++ b/include/asm-ppc/mmu.h @@ -10,6 +10,18 @@ #ifndef __ASSEMBLY__ +/* + * Define physical address type. Machines using split size + * virtual/physical addressing like 32-bit virtual / 36-bit + * physical need a larger than native word size type. -Matt + */ +#ifndef CONFIG_PTE_64BIT +typedef unsigned long phys_addr_t; +#else +typedef unsigned long long phys_addr_t; +extern phys_addr_t fixup_bigphys_addr(phys_addr_t, phys_addr_t); +#endif + /* Default "unsigned long" context */ typedef unsigned long mm_context_t; @@ -320,5 +332,55 @@ typedef struct _P601_BAT { #define TLB_M 0x00000002 /* Memory is coherent */ #define TLB_G 0x00000001 /* Memory is guarded from prefetch */ +/* + * PPC440 support + */ +#define PPC44x_MMUCR_TID 0x000000ff +#define PPC44x_MMUCR_STS 0x00010000 + +#define PPC44x_TLB_PAGEID 0 +#define PPC44x_TLB_XLAT 1 +#define PPC44x_TLB_ATTRIB 2 + +/* Page identification fields */ +#define PPC44x_TLB_EPN_MASK 0xfffffc00 /* Effective Page Number */ +#define PPC44x_TLB_VALID 0x00000200 /* Valid flag */ +#define PPC44x_TLB_TS 0x00000100 /* Translation address space */ +#define PPC44x_TLB_PAGESZ_MASK 0x000000f0 +#define PPC44x_TLB_PAGESZ(x) (x << 4) +#define PPC44x_PAGESZ_1K 0 +#define PPC44x_PAGESZ_4K 1 +#define PPC44x_PAGESZ_16K 2 +#define PPC44x_PAGESZ_64K 3 +#define PPC44x_PAGESZ_256K 4 +#define PPC44x_PAGESZ_1M 5 +#define PPC44x_PAGESZ_16M 7 +#define PPC44x_PAGESZ_256M 9 + +/* Translation fields */ +#define PPC44x_TLB_RPN_MASK 0xfffffc00 /* Real Page Number */ +#define PPC44x_TLB_ERPN_MASK 0x0000000f + +/* Storage attribute and access control fields */ +#define PPC44x_TLB_ATTR_MASK 0x0000ff80 +#define PPC44x_TLB_U0 0x00008000 /* User 0 */ +#define PPC44x_TLB_U1 0x00004000 /* User 1 */ +#define PPC44x_TLB_U2 0x00002000 /* User 2 */ +#define PPC44x_TLB_U3 0x00001000 /* User 3 */ +#define PPC44x_TLB_W 0x00000800 /* Caching is write-through */ +#define PPC44x_TLB_I 0x00000400 /* Caching is inhibited */ +#define PPC44x_TLB_M 0x00000200 /* Memory is coherent */ +#define PPC44x_TLB_G 0x00000100 /* Memory is guarded */ +#define PPC44x_TLB_E 0x00000080 /* Memory is guarded */ + +#define PPC44x_TLB_PERM_MASK 0x0000003f +#define PPC44x_TLB_UX 0x00000020 /* User execution */ +#define PPC44x_TLB_UW 0x00000010 /* User write */ +#define PPC44x_TLB_UR 0x00000008 /* User read */ +#define PPC44x_TLB_SX 0x00000004 /* Super execution */ +#define PPC44x_TLB_SW 0x00000002 /* Super write */ +#define PPC44x_TLB_SR 0x00000001 /* Super read */ + + #endif /* _PPC_MMU_H_ */ #endif /* __KERNEL__ */ diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h index b8f25854778d..6d2a8a40368f 100644 --- a/include/asm-ppc/page.h +++ b/include/asm-ppc/page.h @@ -4,7 +4,12 @@ /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT 12 #define PAGE_SIZE (1UL << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) + +/* + * Subtle: this is an int (not an unsigned long) and so it + * gets extended to 64 bits the way want (i.e. with 1s). -- paulus + */ +#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1)) #ifdef __KERNEL__ #include <linux/config.h> @@ -15,13 +20,27 @@ #ifndef __ASSEMBLY__ -#define STRICT_MM_TYPECHECKS +/* + * The basic type of a PTE - 64 bits for those CPUs with > 32 bit + * physical addressing. For now this just the IBM PPC440. + */ +#ifdef CONFIG_PTE_64BIT +typedef unsigned long long pte_basic_t; +#define PTE_SHIFT (PAGE_SHIFT - 3) /* 512 ptes per page */ +#define PTE_FMT "%16Lx" +#else +typedef unsigned long pte_basic_t; +#define PTE_SHIFT (PAGE_SHIFT - 2) /* 1024 ptes per page */ +#define PTE_FMT "%.8lx" +#endif + +#undef STRICT_MM_TYPECHECKS #ifdef STRICT_MM_TYPECHECKS /* * These are used to make use of C type-checking.. */ -typedef struct { unsigned long pte; } pte_t; +typedef struct { pte_basic_t pte; } pte_t; typedef struct { unsigned long pmd; } pmd_t; typedef struct { unsigned long pgd; } pgd_t; typedef struct { unsigned long pgprot; } pgprot_t; @@ -40,7 +59,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; /* * .. while these make it easier on the compiler */ -typedef unsigned long pte_t; +typedef pte_basic_t pte_t; typedef unsigned long pmd_t; typedef unsigned long pgd_t; typedef unsigned long pgprot_t; @@ -123,6 +142,7 @@ static inline void* ___va(unsigned long p) #define pfn_to_page(pfn) (mem_map + ((pfn) - PPC_PGSTART)) #define page_to_pfn(page) ((unsigned long)((page) - mem_map) + PPC_PGSTART) #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) +#define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT) #define pfn_valid(pfn) (((pfn) - PPC_PGSTART) < max_mapnr) #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) diff --git a/include/asm-ppc/pgalloc.h b/include/asm-ppc/pgalloc.h index 7d5d0455cc00..faf91bc03022 100644 --- a/include/asm-ppc/pgalloc.h +++ b/include/asm-ppc/pgalloc.h @@ -20,10 +20,17 @@ extern void pgd_free(pgd_t *pgd); #define __pmd_free_tlb(tlb,x) do { } while (0) #define pgd_populate(mm, pmd, pte) BUG() +#ifndef CONFIG_BOOKE #define pmd_populate_kernel(mm, pmd, pte) \ (pmd_val(*(pmd)) = __pa(pte) | _PMD_PRESENT) #define pmd_populate(mm, pmd, pte) \ (pmd_val(*(pmd)) = (page_to_pfn(pte) << PAGE_SHIFT) | _PMD_PRESENT) +#else +#define pmd_populate_kernel(mm, pmd, pte) \ + (pmd_val(*(pmd)) = (unsigned long)pte | _PMD_PRESENT) +#define pmd_populate(mm, pmd, pte) \ + (pmd_val(*(pmd)) = (unsigned long)page_to_virt(pte) | _PMD_PRESENT) +#endif extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr); diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index 73a8f18d22cf..0399c8cfbcab 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h @@ -65,13 +65,23 @@ extern unsigned long ioremap_bot, ioremap_base; * and ITLB, respectively (see "mmu.h" for definitions). */ -/* PMD_SHIFT determines the size of the area mapped by the second-level page tables */ -#define PMD_SHIFT 22 +/* + * The normal case is that PTEs are 32-bits and we have a 1-page + * 1024-entry pgdir pointing to 1-page 1024-entry PTE pages. -- paulus + * + * For any >32-bit physical address platform, we can use the following + * two level page table layout where the pgdir is 8KB and the MS 13 bits + * are an index to the second level table. The combined pgdir/pmd first + * level has 2048 entries and the second level has 512 64-bit PTE entries. + * -Matt + */ +/* PMD_SHIFT determines the size of the area mapped by the PTE pages */ +#define PMD_SHIFT (PAGE_SHIFT + PTE_SHIFT) #define PMD_SIZE (1UL << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) -/* PGDIR_SHIFT determines what a third-level page table entry can map */ -#define PGDIR_SHIFT 22 +/* PGDIR_SHIFT determines what a top-level page table entry can map */ +#define PGDIR_SHIFT PMD_SHIFT #define PGDIR_SIZE (1UL << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) @@ -79,9 +89,10 @@ extern unsigned long ioremap_bot, ioremap_base; * entries per page directory level: our page-table tree is two-level, so * we don't really have any PMD directory. */ -#define PTRS_PER_PTE 1024 +#define PTRS_PER_PTE (1 << PTE_SHIFT) #define PTRS_PER_PMD 1 -#define PTRS_PER_PGD 1024 +#define PTRS_PER_PGD (1 << (32 - PGDIR_SHIFT)) + #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) #define FIRST_USER_PGD_NR 0 @@ -89,7 +100,7 @@ extern unsigned long ioremap_bot, ioremap_base; #define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS) #define pte_ERROR(e) \ - printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) + printk("%s:%d: bad pte "PTE_FMT".\n", __FILE__, __LINE__, pte_val(e)) #define pmd_ERROR(e) \ printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) #define pgd_ERROR(e) \ @@ -113,7 +124,11 @@ extern unsigned long ioremap_bot, ioremap_base; * of RAM. -- Cort */ #define VMALLOC_OFFSET (0x1000000) /* 16M */ +#ifdef CONFIG_44x +#define VMALLOC_START (((_ALIGN((long)high_memory, PPC44x_PIN_SIZE) + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))) +#else #define VMALLOC_START ((((long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))) +#endif #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END ioremap_bot @@ -170,6 +185,44 @@ extern unsigned long ioremap_bot, ioremap_base; #define _PMD_SIZE_16M 0x0e0 #define PMD_PAGE_SIZE(pmdval) (1024 << (((pmdval) & _PMD_SIZE) >> 4)) +#elif defined(CONFIG_44x) +/* + * Definitions for PPC440 + * + * Because of the 3 word TLB entries to support 36-bit addressing, + * the attribute are difficult to map in such a fashion that they + * are easily loaded during exception processing. I decided to + * organize the entry so the ERPN is the only portion in the + * upper word of the PTE and the attribute bits below are packed + * in as sensibly as they can be in the area below a 4KB page size + * oriented RPN. This at least makes it easy to load the RPN and + * ERPN fields in the TLB. -Matt + * + * Note that these bits preclude future use of a page size + * less than 4KB. + */ +#define _PAGE_PRESENT 0x00000001 /* S: PTE valid */ +#define _PAGE_RW 0x00000002 /* S: Write permission */ +#define _PAGE_DIRTY 0x00000004 /* S: Page dirty */ +#define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */ +#define _PAGE_HWWRITE 0x00000010 /* H: Dirty & RW */ +#define _PAGE_HWEXEC 0x00000020 /* H: Execute permission */ +#define _PAGE_USER 0x00000040 /* S: User page */ +#define _PAGE_ENDIAN 0x00000080 /* H: E bit */ +#define _PAGE_GUARDED 0x00000100 /* H: G bit */ +#define _PAGE_COHERENT 0x00000200 /* H: M bit */ +#define _PAGE_FILE 0x00000400 /* S: nonlinear file mapping */ +#define _PAGE_NO_CACHE 0x00000400 /* H: I bit */ +#define _PAGE_WRITETHRU 0x00000800 /* H: W bit */ + +/* TODO: Add large page lowmem mapping support */ +#define _PMD_PRESENT 0 +#define _PMD_PRESENT_MASK (PAGE_MASK) +#define _PMD_BAD (~PAGE_MASK) + +/* ERPN in a PTE never gets cleared, ignore it */ +#define _PTE_NONE_MASK 0xffffffff00000000ULL + #elif defined(CONFIG_8xx) /* Definitions for 8xx embedded chips. */ #define _PAGE_PRESENT 0x0001 /* Page is valid */ @@ -270,7 +323,11 @@ extern unsigned long ioremap_bot, ioremap_base; #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED) #define _PAGE_WRENABLE (_PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE) +#ifndef CONFIG_44x #define _PAGE_KERNEL (_PAGE_BASE | _PAGE_SHARED | _PAGE_WRENABLE) +#else +#define _PAGE_KERNEL (_PAGE_BASE | _PAGE_SHARED | _PAGE_WRENABLE | _PAGE_GUARDED) +#endif #ifdef CONFIG_PPC_STD_MMU /* On standard PPC MMU, no user access implies kernel read/write access, @@ -283,7 +340,7 @@ extern unsigned long ioremap_bot, ioremap_base; #define _PAGE_IO (_PAGE_KERNEL | _PAGE_NO_CACHE | _PAGE_GUARDED) #define _PAGE_RAM (_PAGE_KERNEL | _PAGE_HWEXEC) -#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) +#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) /* We want the debuggers to be able to set breakpoints anywhere, so * don't write protect the kernel text */ #define _PAGE_RAM_TEXT _PAGE_RAM @@ -420,6 +477,8 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) * * pte_update clears and sets bit atomically, and returns * the old pte value. + * The ((unsigned long)(p+1) - 4) hack is to get to the least-significant + * 32 bits of the PTE regardless of whether PTEs are 32 or 64 bits. */ static inline unsigned long pte_update(pte_t *p, unsigned long clr, unsigned long set) @@ -434,7 +493,7 @@ static inline unsigned long pte_update(pte_t *p, unsigned long clr, " stwcx. %1,0,%3\n\ bne- 1b" : "=&r" (old), "=&r" (tmp), "=m" (*p) - : "r" (p), "r" (clr), "r" (set), "m" (*p) + : "r" ((unsigned long)(p+1) - 4), "r" (clr), "r" (set), "m" (*p) : "cc" ); return old; } @@ -485,11 +544,25 @@ static inline void ptep_mkdirty(pte_t *ptep) #define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0) +/* + * Note that on Book E processors, the pmd contains the kernel virtual + * (lowmem) address of the pte page. The physical address is less useful + * because everything runs with translation enabled (even the TLB miss + * handler). On everything else the pmd contains the physical address + * of the pte page. -- paulus + */ +#ifndef CONFIG_BOOKE #define pmd_page_kernel(pmd) \ ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) #define pmd_page(pmd) \ (mem_map + (pmd_val(pmd) >> PAGE_SHIFT)) - +#else +#define pmd_page_kernel(pmd) \ + ((unsigned long) (pmd_val(pmd) & PAGE_MASK)) +#define pmd_page(pmd) \ + (mem_map + (__pa(pmd_val(pmd)) >> PAGE_SHIFT)) +#endif + /* to find an entry in a kernel page-table-directory */ #define pgd_offset_k(address) pgd_offset(&init_mm, address) @@ -516,7 +589,8 @@ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) -extern pgd_t swapper_pg_dir[1024]; +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; + extern void paging_init(void); /* diff --git a/include/asm-ppc/ppc_asm.h b/include/asm-ppc/ppc_asm.h index 39049bcac7fc..afd99032491c 100644 --- a/include/asm-ppc/ppc_asm.h +++ b/include/asm-ppc/ppc_asm.h @@ -107,7 +107,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) bdnz 0b #endif -#if !defined(CONFIG_440) +#if !defined(CONFIG_44x) /* * On APUS (Amiga PowerPC cpu upgrade board), we don't know the * physical base address of RAM at compile time. @@ -125,7 +125,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) .align 1; \ .long 0b; \ .previous -#else /* CONFIG_440 */ +#else /* CONFIG_44x */ #define tophys(rd,rs) \ mr rd,rs @@ -133,7 +133,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) #define tovirt(rd,rs) \ mr rd,rs -#endif /* CONFIG_440 */ +#endif /* CONFIG_44x */ /* * On 64-bit cpus, we use the rfid instruction instead of rfi, but diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h index 21c2c819b98f..e13d0a0b1f45 100644 --- a/include/asm-ppc/processor.h +++ b/include/asm-ppc/processor.h @@ -3,6 +3,12 @@ #define __ASM_PPC_PROCESSOR_H /* + * The Book E definitions are hacked into here for 440 right + * now. This whole thing needs regorganized (maybe two files) + * so that it becomes readable. -Matt + */ + +/* * Default implementation of macro that returns current * instruction pointer ("program counter"). */ @@ -45,6 +51,11 @@ #define MSR_RI (1<<1) /* Recoverable Exception */ #define MSR_LE (1<<0) /* Little Endian */ +#ifdef CONFIG_BOOKE +#define MSR_IS MSR_IR /* Instruction Space */ +#define MSR_DS MSR_DR /* Data Space */ +#endif + #ifdef CONFIG_APUS_FAST_EXCEPT #define MSR_ (MSR_ME|MSR_IP|MSR_RI) #else @@ -93,8 +104,13 @@ #define SPRN_CDBCR 0x3D7 /* Cache Debug Control Register */ #define SPRN_CTR 0x009 /* Count Register */ #define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */ +#ifndef CONFIG_BOOKE #define SPRN_DAC1 0x3F6 /* Data Address Compare 1 */ #define SPRN_DAC2 0x3F7 /* Data Address Compare 2 */ +#else +#define SPRN_DAC1 0x13C /* Book E Data Address Compare 1 */ +#define SPRN_DAC2 0x13D /* Book E Data Address Compare 2 */ +#endif /* CONFIG_BOOKE */ #define SPRN_DAR 0x013 /* Data Address Register */ #define SPRN_DBAT0L 0x219 /* Data BAT 0 Lower Register */ #define SPRN_DBAT0U 0x218 /* Data BAT 0 Upper Register */ @@ -146,7 +162,11 @@ #define DBCR_SDA 0x00000004 /* Second DAC Enable */ #define DBCR_JOI 0x00000002 /* JTAG Serial Outbound Int. Enable */ #define DBCR_JII 0x00000001 /* JTAG Serial Inbound Int. Enable */ +#ifndef CONFIG_BOOKE #define SPRN_DBCR0 0x3F2 /* Debug Control Register 0 */ +#else +#define SPRN_DBCR0 0x134 /* Book E Debug Control Register 0 */ +#endif /* CONFIG_BOOKE */ #define DBCR0_EDM 0x80000000 /* External Debug Mode */ #define DBCR0_IDM 0x40000000 /* Internal Debug Mode */ #define DBCR0_RST 0x30000000 /* all the bits in the RST field */ @@ -169,11 +189,18 @@ #define DBCR0_IA12T 0x00008000 /* Instr Addr 1-2 range Toggle */ #define DBCR0_IA34T 0x00004000 /* Instr Addr 3-4 range Toggle */ #define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */ +#ifndef CONFIG_BOOKE #define SPRN_DBCR1 0x3BD /* Debug Control Register 1 */ #define SPRN_DBSR 0x3F0 /* Debug Status Register */ #define DBSR_IC 0x80000000 /* Instruction Completion */ #define DBSR_BT 0x40000000 /* Branch taken */ #define DBSR_TIE 0x10000000 /* Trap Instruction debug Event */ +#else +#define SPRN_DBCR1 0x135 /* Book E Debug Control Register 1 */ +#define SPRN_DBSR 0x130 /* Book E Debug Status Register */ +#define DBSR_IC 0x08000000 /* Book E Instruction Completion */ +#define DBSR_TIE 0x01000000 /* Book E Trap Instruction Event */ +#endif /* CONFIG_BOOKE */ #define SPRN_DCCR 0x3FA /* Data Cache Cacheability Register */ #define DCCR_NOCACHE 0 /* Noncacheable */ #define DCCR_CACHE 1 /* Cacheable */ @@ -181,7 +208,11 @@ #define SPRN_DCWR 0x3BA /* Data Cache Write-thru Register */ #define DCWR_COPY 0 /* Copy-back */ #define DCWR_WRITE 1 /* Write-through */ +#ifndef CONFIG_BOOKE #define SPRN_DEAR 0x3D5 /* Data Error Address Register */ +#else +#define SPRN_DEAR 0x03D /* Book E Data Error Address Register */ +#endif /* CONFIG_BOOKE */ #define SPRN_DEC 0x016 /* Decrement Register */ #define SPRN_DER 0x095 /* Debug Enable Regsiter */ #define DER_RSTE 0x40000000 /* Reset Interrupt */ @@ -206,12 +237,16 @@ #define SPRN_DMISS 0x3D0 /* Data TLB Miss Register */ #define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */ #define SPRN_EAR 0x11A /* External Address Register */ +#ifndef CONFIG_BOOKE #define SPRN_ESR 0x3D4 /* Exception Syndrome Register */ +#else +#define SPRN_ESR 0x03E /* Book E Exception Syndrome Register */ +#endif /* CONFIG_BOOKE */ #define ESR_MCI 0x80000000 /* 405 Machine Check - Instruction */ -#define ESR_IMCP 0x80000000 /* 403 Inst. Mach. Check - Protection */ -#define ESR_IMCN 0x40000000 /* 403 Inst. Mach. Check - Non-config */ -#define ESR_IMCB 0x20000000 /* 403 Inst. Mach. Check - Bus error */ -#define ESR_IMCT 0x10000000 /* 403 Inst. Mach. Check - Timeout */ +#define ESR_IMCP 0x80000000 /* Instr. Machine Check - Protection */ +#define ESR_IMCN 0x40000000 /* Instr. Machine Check - Non-config */ +#define ESR_IMCB 0x20000000 /* Instr. Machine Check - Bus error */ +#define ESR_IMCT 0x10000000 /* Instr. Machine Check - Timeout */ #define ESR_PIL 0x08000000 /* Program Exception - Illegal */ #define ESR_PPR 0x04000000 /* Program Exception - Priveleged */ #define ESR_PTR 0x02000000 /* Program Exception - Trap */ @@ -266,8 +301,13 @@ #define HID1_SYNCBE (1<<11) /* 7450 ABE for sync, eieio */ #define HID1_ABE (1<<10) /* 7450 Address Broadcast Enable */ #define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */ +#ifndef CONFIG_BOOKE #define SPRN_IAC1 0x3F4 /* Instruction Address Compare 1 */ #define SPRN_IAC2 0x3F5 /* Instruction Address Compare 2 */ +#else +#define SPRN_IAC1 0x138 /* Book E Instruction Address Compare 1 */ +#define SPRN_IAC2 0x139 /* Book E Instruction Address Compare 2 */ +#endif /* CONFIG_BOOKE */ #define SPRN_IBAT0L 0x211 /* Instruction BAT 0 Lower Register */ #define SPRN_IBAT0U 0x210 /* Instruction BAT 0 Upper Register */ #define SPRN_IBAT1L 0x213 /* Instruction BAT 1 Lower Register */ @@ -358,8 +398,13 @@ #define SPRN_PBL2 0x3FE /* Protection Bound Lower 2 */ #define SPRN_PBU1 0x3FD /* Protection Bound Upper 1 */ #define SPRN_PBU2 0x3FF /* Protection Bound Upper 2 */ +#ifndef CONFIG_BOOKE #define SPRN_PID 0x3B1 /* Process ID */ #define SPRN_PIR 0x3FF /* Processor Identification Register */ +#else +#define SPRN_PID 0x030 /* Book E Process ID */ +#define SPRN_PIR 0x11E /* Book E Processor Identification Register */ +#endif /* CONFIG_BOOKE */ #define SPRN_PIT 0x3DB /* Programmable Interval Timer */ #define SPRN_PMC1 0x3B9 /* Performance Counter Register 1 */ #define SPRN_PMC2 0x3BA /* Performance Counter Register 2 */ @@ -375,6 +420,7 @@ #define SGR_NORMAL 0 #define SGR_GUARDED 1 #define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */ +#define SPRN_SLER 0x3BB /* Little-endian real mode */ #define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */ #define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */ #define SPRN_SPRG2 0x112 /* Special Purpose Register General 2 */ @@ -387,6 +433,7 @@ #define SPRN_SRR1 0x01B /* Save/Restore Register 1 */ #define SPRN_SRR2 0x3DE /* Save/Restore Register 2 */ #define SPRN_SRR3 0x3DF /* Save/Restore Register 3 */ +#define SPRN_SU0R 0x3BC /* "User 0" real mode */ #define SPRN_TBHI 0x3DC /* Time Base High (4xx) */ #define SPRN_TBHU 0x3CC /* Time Base High User-mode (4xx) */ #define SPRN_TBLO 0x3DD /* Time Base Low (4xx) */ @@ -395,7 +442,11 @@ #define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */ #define SPRN_TBWL 0x11C /* Time Base Lower Register (super, R/W) */ #define SPRN_TBWU 0x11D /* Time Base Upper Register (super, R/W) */ +#ifndef CONFIG_BOOKE #define SPRN_TCR 0x3DA /* Timer Control Register */ +#else +#define SPRN_TCR 0x154 /* Book E Timer Control Register */ +#endif #define TCR_WP(x) (((x)&0x3)<<30) /* WDT Period */ #define TCR_WP_MASK TCR_WP(3) #define WP_2_17 0 /* 2^17 clocks */ @@ -410,6 +461,7 @@ #define WRC_SYSTEM 3 /* System reset will occur */ #define TCR_WIE 0x08000000 /* WDT Interrupt Enable */ #define TCR_PIE 0x04000000 /* PIT Interrupt Enable */ +#define TCR_DIE TCR_PIE /* DEC Interrupt Enable */ #define TCR_FP(x) (((x)&0x3)<<24) /* FIT Period */ #define TCR_FP_MASK TCR_FP(3) #define FP_2_9 0 /* 2^9 clocks */ @@ -431,7 +483,11 @@ #define SPRN_THRM3 0x3FE /* Thermal Management Register 3 */ #define THRM3_E (1<<0) #define SPRN_TLBMISS 0x3D4 /* 980 7450 TLB Miss Register */ +#ifndef CONFIG_BOOKE #define SPRN_TSR 0x3D8 /* Timer Status Register */ +#else +#define SPRN_TSR 0x150 /* Book E Timer Status Register */ +#endif /* CONFIG_BOOKE */ #define TSR_ENW 0x80000000 /* Enable Next Watchdog */ #define TSR_WIS 0x40000000 /* WDT Interrupt Status */ #define TSR_WRS(x) (((x)&0x3)<<28) /* WDT Reset Status */ @@ -440,6 +496,7 @@ #define WRS_CHIP 2 /* WDT forced chip reset */ #define WRS_SYSTEM 3 /* WDT forced system reset */ #define TSR_PIS 0x08000000 /* PIT Interrupt Status */ +#define TSR_DIS TSR_PIS /* DEC Interrupt Status */ #define TSR_FIS 0x04000000 /* FIT Interrupt Status */ #define SPRN_UMMCR0 0x3A8 /* User Monitor Mode Control Register 0 */ #define SPRN_UMMCR1 0x3AC /* User Monitor Mode Control Register 0 */ @@ -452,6 +509,45 @@ #define SPRN_XER 0x001 /* Fixed Point Exception Register */ #define SPRN_ZPR 0x3B0 /* Zone Protection Register */ +/* Book E definitions */ +#define SPRN_DECAR 0x036 /* Decrementer Auto Reload Register */ +#define SPRN_CSRR0 0x03A /* Critical Save and Restore Register 0 */ +#define SPRN_CSRR1 0x03B /* Critical Save and Restore Register 1 */ +#define SPRN_IVPR 0x03F /* Interrupt Vector Prefix Register */ +#define SPRN_USPRG0 0x100 /* User Special Purpose Register General 0 */ +#define SPRN_SPRG4R 0x104 /* Special Purpose Register General 4 Read */ +#define SPRN_SPRG5R 0x105 /* Special Purpose Register General 5 Read */ +#define SPRN_SPRG6R 0x106 /* Special Purpose Register General 6 Read */ +#define SPRN_SPRG7R 0x107 /* Special Purpose Register General 7 Read */ +#define SPRN_SPRG4W 0x114 /* Special Purpose Register General 4 Write */ +#define SPRN_SPRG5W 0x115 /* Special Purpose Register General 5 Write */ +#define SPRN_SPRG6W 0x116 /* Special Purpose Register General 6 Write */ +#define SPRN_SPRG7W 0x117 /* Special Purpose Register General 7 Write */ +#define SPRN_DBCR2 0x136 /* Debug Control Register 2 */ +#define SPRN_IAC3 0x13A /* Instruction Address Compare 3 */ +#define SPRN_IAC4 0x13B /* Instruction Address Compare 4 */ +#define SPRN_DVC1 0x13E /* */ +#define SPRN_DVC2 0x13F /* */ +#define SPRN_IVOR0 0x190 /* Interrupt Vector Offset Register 0 */ +#define SPRN_IVOR1 0x191 /* Interrupt Vector Offset Register 1 */ +#define SPRN_IVOR2 0x192 /* Interrupt Vector Offset Register 2 */ +#define SPRN_IVOR3 0x193 /* Interrupt Vector Offset Register 3 */ +#define SPRN_IVOR4 0x194 /* Interrupt Vector Offset Register 4 */ +#define SPRN_IVOR5 0x195 /* Interrupt Vector Offset Register 5 */ +#define SPRN_IVOR6 0x196 /* Interrupt Vector Offset Register 6 */ +#define SPRN_IVOR7 0x197 /* Interrupt Vector Offset Register 7 */ +#define SPRN_IVOR8 0x198 /* Interrupt Vector Offset Register 8 */ +#define SPRN_IVOR9 0x199 /* Interrupt Vector Offset Register 9 */ +#define SPRN_IVOR10 0x19a /* Interrupt Vector Offset Register 10 */ +#define SPRN_IVOR11 0x19b /* Interrupt Vector Offset Register 11 */ +#define SPRN_IVOR12 0x19c /* Interrupt Vector Offset Register 12 */ +#define SPRN_IVOR13 0x19d /* Interrupt Vector Offset Register 13 */ +#define SPRN_IVOR14 0x19e /* Interrupt Vector Offset Register 14 */ +#define SPRN_IVOR15 0x19f /* Interrupt Vector Offset Register 15 */ +#define SPRN_MMUCR 0x3b2 /* MMU Control Register */ + +#define ESR_ST 0x00800000 /* Store Operation */ + /* Short-hand versions for a number of the above SPRNs */ #define CTR SPRN_CTR /* Counter Register */ @@ -524,6 +620,16 @@ #define SPRG5 SPRN_SPRG5 #define SPRG6 SPRN_SPRG6 #define SPRG7 SPRN_SPRG7 +#define SPRG4R SPRN_SPRG4R /* Book E Supervisor Private Registers */ +#define SPRG5R SPRN_SPRG5R +#define SPRG6R SPRN_SPRG6R +#define SPRG7R SPRN_SPRG7R +#define SPRG4W SPRN_SPRG4W +#define SPRG5W SPRN_SPRG5W +#define SPRG6W SPRN_SPRG6W +#define SPRG7W SPRN_SPRG7W +#define CSRR0 SPRN_CSRR0 /* Critical Save and Restore Register 0 */ +#define CSRR1 SPRN_CSRR1 /* Critical Save and Restore Register 1 */ #define SRR0 SPRN_SRR0 /* Save and Restore Register 0 */ #define SRR1 SPRN_SRR1 /* Save and Restore Register 1 */ #define SRR2 SPRN_SRR2 /* Save and Restore Register 2 */ @@ -557,6 +663,51 @@ #define PVR_MAJ(pvr) (((pvr) >> 4) & 0xF) /* Major revision field */ #define PVR_MIN(pvr) (((pvr) >> 0) & 0xF) /* Minor revision field */ +/* Processor Version Numbers */ + +#define PVR_403GA 0x00200000 +#define PVR_403GB 0x00200100 +#define PVR_403GC 0x00200200 +#define PVR_403GCX 0x00201400 +#define PVR_405GP 0x40110000 +#define PVR_STB03XXX 0x40310000 +#define PVR_NP405H 0x41410000 +#define PVR_NP405L 0x41610000 +#define PVR_440GP_RB 0x40120440 +#define PVR_440GP_RC1 0x40120481 +#define PVR_440GP_RC2 0x40200481 +#define PVR_440GX_RC1 0x51b21850 +#define PVR_601 0x00010000 +#define PVR_602 0x00050000 +#define PVR_603 0x00030000 +#define PVR_603e 0x00060000 +#define PVR_603ev 0x00070000 +#define PVR_603r 0x00071000 +#define PVR_604 0x00040000 +#define PVR_604e 0x00090000 +#define PVR_604r 0x000A0000 +#define PVR_620 0x00140000 +#define PVR_740 0x00080000 +#define PVR_750 PVR_740 +#define PVR_740P 0x10080000 +#define PVR_750P PVR_740P +#define PVR_7400 0x000C0000 +#define PVR_7410 0x800C0000 +#define PVR_7450 0x80000000 +/* + * For the 8xx processors, all of them report the same PVR family for + * the PowerPC core. The various versions of these processors must be + * differentiated by the version number in the Communication Processor + * Module (CPM). + */ +#define PVR_821 0x00500000 +#define PVR_823 PVR_821 +#define PVR_850 PVR_821 +#define PVR_860 PVR_821 +#define PVR_8240 0x00810100 +#define PVR_8245 0x80811014 +#define PVR_8260 PVR_8240 + /* We only need to define a new _MACH_xxx for machines which are part of * a configuration which supports more than one type of different machine. * This is currently limited to CONFIG_PPC_MULTIPLATFORM and CHRP/PReP/PMac. -- Tom diff --git a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h index 5d121448d3c1..2d9e8642cc87 100644 --- a/include/asm-ppc/serial.h +++ b/include/asm-ppc/serial.h @@ -28,7 +28,7 @@ #include <platforms/sandpoint.h> #elif defined(CONFIG_SPRUCE) #include <platforms/spruce_serial.h> -#elif defined(CONFIG_40x) +#elif defined(CONFIG_4xx) #include <asm/ibm4xx.h> #else diff --git a/include/asm-ppc/tlbflush.h b/include/asm-ppc/tlbflush.h index 2ccb0b20d2af..a441eb07e0e5 100644 --- a/include/asm-ppc/tlbflush.h +++ b/include/asm-ppc/tlbflush.h @@ -19,17 +19,23 @@ extern void _tlbia(void); #if defined(CONFIG_4xx) +#ifndef CONFIG_44x +#define __tlbia() asm volatile ("sync; tlbia; isync" : : : "memory") +#else +#define __tlbia _tlbia +#endif + static inline void flush_tlb_mm(struct mm_struct *mm) - { _tlbia(); } + { __tlbia(); } static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) { _tlbie(vmaddr); } static inline void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) - { _tlbia(); } + { __tlbia(); } static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end) - { _tlbia(); } + { __tlbia(); } #elif defined(CONFIG_8xx) #define __tlbia() asm volatile ("tlbia; sync" : : : "memory") diff --git a/include/asm-s390/semaphore.h b/include/asm-s390/semaphore.h index 474abcd85b34..5720dea2459f 100644 --- a/include/asm-s390/semaphore.h +++ b/include/asm-s390/semaphore.h @@ -60,6 +60,7 @@ asmlinkage void __up(struct semaphore * sem); static inline void down(struct semaphore * sem) { + might_sleep(); if (atomic_dec_return(&sem->count) < 0) __down(sem); } @@ -68,6 +69,7 @@ static inline int down_interruptible(struct semaphore * sem) { int ret = 0; + might_sleep(); if (atomic_dec_return(&sem->count) < 0) ret = __down_interruptible(sem); return ret; diff --git a/include/asm-sh/semaphore.h b/include/asm-sh/semaphore.h index 2ba0930035f6..dc8955e3448c 100644 --- a/include/asm-sh/semaphore.h +++ b/include/asm-sh/semaphore.h @@ -107,6 +107,7 @@ static inline int down_interruptible(struct semaphore * sem) CHECK_MAGIC(sem->__magic); #endif + might_sleep(); if (atomic_dec_return(&sem->count) < 0) ret = __down_interruptible(sem); return ret; diff --git a/include/asm-sparc/semaphore.h b/include/asm-sparc/semaphore.h index cf3135b928a0..0e6122ae3058 100644 --- a/include/asm-sparc/semaphore.h +++ b/include/asm-sparc/semaphore.h @@ -71,6 +71,7 @@ static inline void down(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif + might_sleep(); ptr = &(sem->count.counter); increment = 1; @@ -107,6 +108,7 @@ static inline int down_interruptible(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif + might_sleep(); ptr = &(sem->count.counter); increment = 1; diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h index 11f174e6b3c3..0a8ad4cac125 100644 --- a/include/asm-sparc/termios.h +++ b/include/asm-sparc/termios.h @@ -73,6 +73,7 @@ struct winsize { #define N_HCI 15 /* Bluetooth HCI UART */ #ifdef __KERNEL__ +#include <linux/module.h> /* * c_cc characters in the termio structure. Oh, how I love being diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h index d29aa87ad90b..8effce0da087 100644 --- a/include/asm-sparc64/termios.h +++ b/include/asm-sparc64/termios.h @@ -73,6 +73,7 @@ struct winsize { #define N_HCI 15 /* Bluetooth HCI UART */ #ifdef __KERNEL__ +#include <linux/module.h> /* * c_cc characters in the termio structure. Oh, how I love being diff --git a/include/asm-v850/semaphore.h b/include/asm-v850/semaphore.h index 0d6560f3ba98..c514062bb69e 100644 --- a/include/asm-v850/semaphore.h +++ b/include/asm-v850/semaphore.h @@ -57,6 +57,7 @@ extern void __up (struct semaphore * sem); extern inline void down (struct semaphore * sem) { + might_sleep(); if (atomic_dec_return (&sem->count) < 0) __down (sem); } @@ -64,6 +65,7 @@ extern inline void down (struct semaphore * sem) extern inline int down_interruptible (struct semaphore * sem) { int ret = 0; + might_sleep(); if (atomic_dec_return (&sem->count) < 0) ret = __down_interruptible (sem); return ret; diff --git a/include/asm-x86_64/semaphore.h b/include/asm-x86_64/semaphore.h index 6f42c7af790b..5fe25482facc 100644 --- a/include/asm-x86_64/semaphore.h +++ b/include/asm-x86_64/semaphore.h @@ -118,6 +118,7 @@ static inline void down(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif + might_sleep(); __asm__ __volatile__( "# atomic down operation\n\t" @@ -144,6 +145,7 @@ static inline int down_interruptible(struct semaphore * sem) #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif + might_sleep(); __asm__ __volatile__( "# atomic interruptible down operation\n\t" diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 99dbf0d24eaf..285fd86e2b48 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -12,6 +12,8 @@ #include <linux/wait.h> #include <linux/mempool.h> #include <linux/bio.h> +#include <linux/module.h> +#include <linux/stringify.h> #include <asm/scatterlist.h> @@ -268,7 +270,7 @@ struct request_queue * Together with queue_head for cacheline sharing */ struct list_head queue_head; - struct list_head *last_merge; + struct request *last_merge; elevator_t elevator; /* @@ -671,6 +673,11 @@ void kblockd_flush(void); } \ ) #endif - + +#define MODULE_ALIAS_BLOCKDEV(major,minor) \ + MODULE_ALIAS("block-major-" __stringify(major) "-" __stringify(minor)) +#define MODULE_ALIAS_BLOCKDEV_MAJOR(major) \ + MODULE_ALIAS("block-major-" __stringify(major) "-*") + #endif diff --git a/include/linux/device.h b/include/linux/device.h index 8d6266f2e3c3..96043c0f46c5 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -398,4 +398,9 @@ extern void firmware_unregister(struct subsystem *); #define dev_warn(dev, format, arg...) \ dev_printk(KERN_WARNING , dev , format , ## arg) +/* Create alias, so I can be autoloaded. */ +#define MODULE_ALIAS_CHARDEV(major,minor) \ + MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor)) +#define MODULE_ALIAS_CHARDEV_MAJOR(major) \ + MODULE_ALIAS("char-major-" __stringify(major) "-*") #endif /* _DEVICE_H_ */ diff --git a/include/linux/elevator.h b/include/linux/elevator.h index ac30ae089069..e43d670c1371 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -1,7 +1,7 @@ #ifndef _LINUX_ELEVATOR_H #define _LINUX_ELEVATOR_H -typedef int (elevator_merge_fn) (request_queue_t *, struct list_head **, +typedef int (elevator_merge_fn) (request_queue_t *, struct request **, struct bio *); typedef void (elevator_merge_req_fn) (request_queue_t *, struct request *, struct request *); @@ -10,7 +10,7 @@ typedef void (elevator_merged_fn) (request_queue_t *, struct request *); typedef struct request *(elevator_next_req_fn) (request_queue_t *); -typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, struct list_head *); +typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, int); typedef int (elevator_queue_empty_fn) (request_queue_t *); typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *); typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *); @@ -62,7 +62,7 @@ struct elevator_s */ extern void elv_add_request(request_queue_t *, struct request *, int, int); extern void __elv_add_request(request_queue_t *, struct request *, int, int); -extern int elv_merge(request_queue_t *, struct list_head **, struct bio *); +extern int elv_merge(request_queue_t *, struct request **, struct bio *); extern void elv_merge_requests(request_queue_t *, struct request *, struct request *); extern void elv_merged_request(request_queue_t *, struct request *); @@ -79,9 +79,6 @@ extern void elv_completed_request(request_queue_t *, struct request *); extern int elv_set_request(request_queue_t *, struct request *, int); extern void elv_put_request(request_queue_t *, struct request *); -#define __elv_add_request_pos(q, rq, pos) \ - (q)->elevator.elevator_add_req_fn((q), (rq), (pos)) - /* * noop I/O scheduler. always merges, always inserts new request at tail */ @@ -111,4 +108,11 @@ extern inline int elv_try_last_merge(request_queue_t *, struct bio *); #define ELEVATOR_FRONT_MERGE 1 #define ELEVATOR_BACK_MERGE 2 +/* + * Insertion selection + */ +#define ELEVATOR_INSERT_FRONT 1 +#define ELEVATOR_INSERT_BACK 2 +#define ELEVATOR_INSERT_SORT 3 + #endif diff --git a/include/linux/fs.h b/include/linux/fs.h index 936f34c469dd..87ae270bf96c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1391,10 +1391,6 @@ extern int simple_fill_super(struct super_block *, int, struct tree_descr *); extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count); extern void simple_release_fs(struct vfsmount **mount, int *count); -#ifdef CONFIG_BLK_DEV_INITRD -extern unsigned int real_root_dev; -#endif - extern int inode_change_ok(struct inode *, struct iattr *); extern int inode_setattr(struct inode *, struct iattr *); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 460ef0362ab5..13e0933ccbc7 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -75,7 +75,6 @@ struct disk_stats { unsigned read_merges, write_merges; unsigned read_ticks, write_ticks; unsigned io_ticks; - int in_flight; unsigned time_in_queue; }; @@ -101,6 +100,7 @@ struct gendisk { unsigned sync_io; /* RAID */ unsigned long stamp, stamp_idle; + int in_flight; #ifdef CONFIG_SMP struct disk_stats *dkstats; #else diff --git a/include/linux/hiddev.h b/include/linux/hiddev.h index dc6d8dd843b5..9e6d27476a74 100644 --- a/include/linux/hiddev.h +++ b/include/linux/hiddev.h @@ -207,7 +207,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs); void hiddev_report_event(struct hid_device *hid, struct hid_report *report); int __init hiddev_init(void); -void __exit hiddev_exit(void); +void hiddev_exit(void); #else static inline int hiddev_connect(struct hid_device *hid) { return -1; } static inline void hiddev_disconnect(struct hid_device *hid) { } diff --git a/include/linux/ide.h b/include/linux/ide.h index 4664fd44a986..e7c50528e10e 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1218,7 +1218,6 @@ typedef struct ide_driver_s { const char *version; u8 media; unsigned busy : 1; - unsigned supports_dma : 1; unsigned supports_dsc_overlap : 1; int (*cleanup)(ide_drive_t *); int (*shutdown)(ide_drive_t *); diff --git a/include/linux/if_frad.h b/include/linux/if_frad.h index 975aad03d762..3d9fc5d43803 100644 --- a/include/linux/if_frad.h +++ b/include/linux/if_frad.h @@ -155,9 +155,11 @@ struct frhdr struct dlci_local { struct net_device_stats stats; - struct net_device *slave; + struct net_device *master; + struct net_device *slave; struct dlci_conf config; int configured; + struct list_head list; /* callback function */ void (*receive)(struct sk_buff *skb, struct net_device *); diff --git a/include/linux/initrd.h b/include/linux/initrd.h index 32452d53dac3..55289d261b4f 100644 --- a/include/linux/initrd.h +++ b/include/linux/initrd.h @@ -16,3 +16,5 @@ extern int initrd_below_start_ok; /* free_initrd_mem always gets called with the next two as arguments.. */ extern unsigned long initrd_start, initrd_end; extern void free_initrd_mem(unsigned long, unsigned long); + +extern unsigned int real_root_dev; diff --git a/include/linux/isdn.h b/include/linux/isdn.h index ecd0f5394e9e..35a2ef6e2452 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -258,13 +258,13 @@ typedef struct { * variables. Of course, we need to check skb_headroom prior to * any access. */ -typedef struct isdn_audio_skb { +typedef struct _isdnaudio_header { unsigned short dle_count; unsigned char lock; -} isdn_audio_skb; +} isdnaudio_header; -#define ISDN_AUDIO_SKB_DLECOUNT(skb) (((isdn_audio_skb*)skb->head)->dle_count) -#define ISDN_AUDIO_SKB_LOCK(skb) (((isdn_audio_skb*)skb->head)->lock) +#define ISDN_AUDIO_SKB_DLECOUNT(skb) (((isdnaudio_header*)skb->head)->dle_count) +#define ISDN_AUDIO_SKB_LOCK(skb) (((isdnaudio_header*)skb->head)->lock) #endif /* Private data of AT-command-interpreter */ @@ -291,6 +291,7 @@ typedef struct atemu { /* Private data (similar to async_struct in <linux/serial.h>) */ typedef struct modem_info { int magic; + struct module *owner; int flags; /* defined in tty.h */ int x_char; /* xon/xoff character */ int mcr; /* Modem control register */ diff --git a/include/linux/isdn/capilli.h b/include/linux/isdn/capilli.h index cf501356aba4..d4747a9cee9c 100644 --- a/include/linux/isdn/capilli.h +++ b/include/linux/isdn/capilli.h @@ -54,7 +54,7 @@ struct capi_ctr { int count, int *eof, struct capi_ctr *card); /* filled in before calling ready callback */ - u8 manu[CAPI_MANUFACTURER_LEN]; /* CAPI_GET_MANUFACTURER */ + u8 manu[CAPI_MANUFACTURER_LEN]; /* CAPI_GET_MANUFACTURER */ capi_version version; /* CAPI_GET_VERSION */ capi_profile profile; /* CAPI_GET_PROFILE */ u8 serial[CAPI_SERIAL_LEN]; /* CAPI_GET_SERIAL */ diff --git a/include/linux/kernel.h b/include/linux/kernel.h index b0aebfeda888..b2d17ea0dac0 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -52,8 +52,10 @@ struct completion; #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP void __might_sleep(char *file, int line); #define might_sleep() __might_sleep(__FILE__, __LINE__) +#define might_sleep_if(cond) do { if (unlikely(cond)) might_sleep(); } while (0) #else #define might_sleep() do {} while(0) +#define might_sleep_if(cond) do {} while (0) #endif extern struct notifier_block *panic_notifier_list; diff --git a/include/linux/kmod.h b/include/linux/kmod.h index 7fa02a737518..8412faeea0f7 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -29,7 +29,7 @@ extern int request_module(const char * name, ...) __attribute__ ((format (printf static inline int request_module(const char * name, ...) { return -ENOSYS; } #endif -#define try_then_request_module(x, mod...) ((x) ?: request_module(mod), (x)) +#define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x))) extern int call_usermodehelper(char *path, char *argv[], char *envp[], int wait); #ifdef CONFIG_HOTPLUG diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index 159f8ab3df80..23b095889111 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -1,5 +1,7 @@ #ifndef _LINUX_MISCDEVICE_H #define _LINUX_MISCDEVICE_H +#include <linux/module.h> +#include <linux/major.h> #define BUSMOUSE_MINOR 0 #define PSMOUSE_MINOR 1 @@ -48,4 +50,7 @@ struct miscdevice extern int misc_register(struct miscdevice * misc); extern int misc_deregister(struct miscdevice * misc); +#define MODULE_ALIAS_MISCDEV(minor) \ + MODULE_ALIAS("char-major-" __stringify(MISC_MAJOR) \ + "-" __stringify(minor)) #endif diff --git a/include/linux/mm.h b/include/linux/mm.h index 445fc58751c7..9f9743146b54 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -110,6 +110,7 @@ struct vm_area_struct { #define VM_RESERVED 0x00080000 /* Don't unmap it from swap_out */ #define VM_ACCOUNT 0x00100000 /* Is a VM accounted object */ #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ +#define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index dfc1aa47f35c..c99e53fed30e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -37,9 +37,6 @@ #ifdef __KERNEL__ #include <linux/config.h> -#ifdef CONFIG_NET_PROFILE -#include <net/profile.h> -#endif struct divert_blk; struct vlan_group; @@ -498,6 +495,7 @@ extern struct net_device loopback_dev; /* The loopback */ extern struct net_device *dev_base; /* All devices */ extern rwlock_t dev_base_lock; /* Device list lock */ +extern void probe_old_netdevs(void); extern int netdev_boot_setup_add(char *name, struct ifmap *map); extern int netdev_boot_setup_check(struct net_device *dev); extern struct net_device *dev_getbyhwaddr(unsigned short type, char *hwaddr); diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index d4fd6bb3ca43..006fde0295d5 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -191,6 +191,8 @@ extern void get_full_page_state(struct page_state *ret); #define PageSlab(page) test_bit(PG_slab, &(page)->flags) #define SetPageSlab(page) set_bit(PG_slab, &(page)->flags) #define ClearPageSlab(page) clear_bit(PG_slab, &(page)->flags) +#define TestClearPageSlab(page) test_and_clear_bit(PG_slab, &(page)->flags) +#define TestSetPageSlab(page) test_and_set_bit(PG_slab, &(page)->flags) #ifdef CONFIG_HIGHMEM #define PageHighMem(page) test_bit(PG_highmem, &(page)->flags) diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 27c38b240736..e1aaf1fac8e0 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -101,6 +101,7 @@ typedef struct rtc_task { int rtc_register(rtc_task_t *task); int rtc_unregister(rtc_task_t *task); int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg); +void rtc_get_rtc_time(struct rtc_time *rtc_tm); #endif /* __KERNEL__ */ diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 3e3a26916a12..fd8b35209ccc 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -3,9 +3,6 @@ #include <linux/netlink.h> -#define RTNL_DEBUG 1 - - /**** * Routing/neighbour discovery messages. ****/ diff --git a/include/linux/sctp.h b/include/linux/sctp.h index 6ebaff34570c..6131e3c9aa45 100644 --- a/include/linux/sctp.h +++ b/include/linux/sctp.h @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2002 International Business Machines, Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll @@ -42,6 +42,8 @@ * randall@sctp.chicago.il.us * kmorneau@cisco.com * qxie1@email.mot.com + * Sridhar Samudrala <sri@us.ibm.com> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -507,6 +509,11 @@ typedef struct sctp_cwr_chunk { * The ASCONF Parameter Response is used in the ASCONF-ACK to * report status of ASCONF processing. */ +typedef struct sctp_addip_param { + sctp_paramhdr_t param_hdr; + __u32 crr_id; +}sctp_addip_param_t __attribute__((packed)); + typedef struct sctp_addiphdr { __u32 serial; __u8 params[0]; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index a372186cb6d6..4b5f057f8bfb 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -389,6 +389,7 @@ static inline int skb_shared(struct sk_buff *skb) */ static inline struct sk_buff *skb_share_check(struct sk_buff *skb, int pri) { + might_sleep_if(pri & __GFP_WAIT); if (skb_shared(skb)) { struct sk_buff *nskb = skb_clone(skb, pri); kfree_skb(skb); @@ -419,6 +420,7 @@ static inline struct sk_buff *skb_share_check(struct sk_buff *skb, int pri) */ static inline struct sk_buff *skb_unshare(struct sk_buff *skb, int pri) { + might_sleep_if(pri & __GFP_WAIT); if (skb_cloned(skb)) { struct sk_buff *nskb = skb_copy(skb, pri); kfree_skb(skb); /* Free our shared copy */ diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index c48edf4a551e..38c43d95a616 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -603,7 +603,8 @@ enum { DEV_HWMON=2, DEV_PARPORT=3, DEV_RAID=4, - DEV_MAC_HID=5 + DEV_MAC_HID=5, + DEV_SCSI=6, }; /* /proc/sys/dev/cdrom */ @@ -664,6 +665,11 @@ enum { DEV_MAC_HID_ADB_MOUSE_SENDS_KEYCODES=6 }; +/* /proc/sys/dev/scsi */ +enum { + DEV_SCSI_LOGGING_LEVEL=1, +}; + /* /proc/sys/abi */ enum { diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index ac8ac46845ba..c851b7dc997e 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -138,4 +138,7 @@ struct tty_ldisc { #define LDISC_FLAG_DEFINED 0x00000001 +#define MODULE_ALIAS_LDISC(ldisc) \ + MODULE_ALIAS("tty-ldisc-" __stringify(ldisc)) + #endif /* _LINUX_TTY_LDISC_H */ diff --git a/include/linux/usb.h b/include/linux/usb.h index 471c37f5188b..a20b33d953aa 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -329,7 +329,7 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size) { int actual; actual = snprintf (buf, size, "usb-%s-%s", dev->bus->bus_name, dev->devpath); - return (actual >= size) ? -1 : actual; + return (actual >= (int)size) ? -1 : actual; } /*-------------------------------------------------------------------------*/ diff --git a/include/linux/vcache.h b/include/linux/vcache.h deleted file mode 100644 index 5708fe6a908a..000000000000 --- a/include/linux/vcache.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * virtual => physical mapping cache support. - */ -#ifndef _LINUX_VCACHE_H -#define _LINUX_VCACHE_H - -typedef struct vcache_s { - unsigned long address; - struct mm_struct *mm; - struct list_head hash_entry; - void (*callback)(struct vcache_s *data, struct page *new_page); -} vcache_t; - -extern spinlock_t vcache_lock; - -extern void __attach_vcache(vcache_t *vcache, - unsigned long address, - struct mm_struct *mm, - void (*callback)(struct vcache_s *data, struct page *new_page)); - -extern void __detach_vcache(vcache_t *vcache); - -extern void invalidate_vcache(unsigned long address, struct mm_struct *mm, - struct page *new_page); - -#endif diff --git a/include/net/profile.h b/include/net/profile.h deleted file mode 100644 index fd6a3b346990..000000000000 --- a/include/net/profile.h +++ /dev/null @@ -1,312 +0,0 @@ -#include <linux/config.h> /* for CONFIG_NET_PROFILE */ -#ifndef _NET_PROFILE_H_ -#define _NET_PROFILE_H_ 1 - -#ifdef CONFIG_NET_PROFILE - -#include <linux/types.h> -#include <linux/time.h> -#include <linux/kernel.h> -#include <asm/system.h> - -#ifdef CONFIG_X86_TSC -#include <asm/msr.h> -#endif - -struct net_profile_slot -{ - char id[16]; - struct net_profile_slot *next; - struct timeval entered; - struct timeval accumulator; - struct timeval irq; - int hits; - int active; - int underflow; -}; - -extern atomic_t net_profile_active; -extern struct timeval net_profile_adjust; -extern void net_profile_irq_adjust(struct timeval *entered, struct timeval* leaved); - -#ifdef CONFIG_X86_TSC - -static inline void net_profile_stamp(struct timeval *pstamp) -{ - rdtsc(pstamp->tv_usec, pstamp->tv_sec); -} - -static inline void net_profile_accumulate(struct timeval *entered, - struct timeval *leaved, - struct timeval *acc) -{ - __asm__ __volatile__ ("subl %2,%0\n\t" - "sbbl %3,%1\n\t" - "addl %4,%0\n\t" - "adcl %5,%1\n\t" - "subl net_profile_adjust+4,%0\n\t" - "sbbl $0,%1\n\t" - : "=r" (acc->tv_usec), "=r" (acc->tv_sec) - : "g" (entered->tv_usec), "g" (entered->tv_sec), - "g" (leaved->tv_usec), "g" (leaved->tv_sec), - "0" (acc->tv_usec), "1" (acc->tv_sec)); -} - -static inline void net_profile_sub(struct timeval *sub, - struct timeval *acc) -{ - __asm__ __volatile__ ("subl %2,%0\n\t" - "sbbl %3,%1\n\t" - : "=r" (acc->tv_usec), "=r" (acc->tv_sec) - : "g" (sub->tv_usec), "g" (sub->tv_sec), - "0" (acc->tv_usec), "1" (acc->tv_sec)); -} - -static inline void net_profile_add(struct timeval *add, - struct timeval *acc) -{ - __asm__ __volatile__ ("addl %2,%0\n\t" - "adcl %3,%1\n\t" - : "=r" (acc->tv_usec), "=r" (acc->tv_sec) - : "g" (add->tv_usec), "g" (add->tv_sec), - "0" (acc->tv_usec), "1" (acc->tv_sec)); -} - - -#elif defined (__alpha__) - -extern __u32 alpha_lo; -extern long alpha_hi; - -/* On alpha cycle counter has only 32 bits :-( :-( */ - -static inline void net_profile_stamp(struct timeval *pstamp) -{ - __u32 result; - __asm__ __volatile__ ("rpcc %0" : "r="(result)); - if (result <= alpha_lo) - alpha_hi++; - alpha_lo = result; - pstamp->tv_sec = alpha_hi; - pstamp->tv_usec = alpha_lo; -} - -static inline void net_profile_accumulate(struct timeval *entered, - struct timeval *leaved, - struct timeval *acc) -{ - time_t usecs = acc->tv_usec + leaved->tv_usec - entered->tv_usec - - net_profile_adjust.tv_usec; - time_t secs = acc->tv_sec + leaved->tv_sec - entered->tv_sec; - - if (usecs >= 0x100000000L) { - usecs -= 0x100000000L; - secs++; - } else if (usecs < -0x100000000L) { - usecs += 0x200000000L; - secs -= 2; - } else if (usecs < 0) { - usecs += 0x100000000L; - secs--; - } - acc->tv_sec = secs; - acc->tv_usec = usecs; -} - -static inline void net_profile_sub(struct timeval *entered, - struct timeval *leaved) -{ - time_t usecs = leaved->tv_usec - entered->tv_usec; - time_t secs = leaved->tv_sec - entered->tv_sec; - - if (usecs < 0) { - usecs += 0x100000000L; - secs--; - } - leaved->tv_sec = secs; - leaved->tv_usec = usecs; -} - -static inline void net_profile_add(struct timeval *entered, struct timeval *leaved) -{ - time_t usecs = leaved->tv_usec + entered->tv_usec; - time_t secs = leaved->tv_sec + entered->tv_sec; - - if (usecs >= 0x100000000L) { - usecs -= 0x100000000L; - secs++; - } - leaved->tv_sec = secs; - leaved->tv_usec = usecs; -} - - -#else - -static inline void net_profile_stamp(struct timeval *pstamp) -{ - /* Not "fast" counterpart! On architectures without - cpu clock "fast" routine is absolutely useless in this - situation. do_gettimeofday still says something on slow-slow-slow - boxes, though it eats more cpu time than the subject of - investigation :-) :-) - */ - do_gettimeofday(pstamp); -} - -static inline void net_profile_accumulate(struct timeval *entered, - struct timeval *leaved, - struct timeval *acc) -{ - time_t usecs = acc->tv_usec + leaved->tv_usec - entered->tv_usec - - net_profile_adjust.tv_usec; - time_t secs = acc->tv_sec + leaved->tv_sec - entered->tv_sec; - - if (usecs >= 1000000) { - usecs -= 1000000; - secs++; - } else if (usecs < -1000000) { - usecs += 2000000; - secs -= 2; - } else if (usecs < 0) { - usecs += 1000000; - secs--; - } - acc->tv_sec = secs; - acc->tv_usec = usecs; -} - -static inline void net_profile_sub(struct timeval *entered, - struct timeval *leaved) -{ - time_t usecs = leaved->tv_usec - entered->tv_usec; - time_t secs = leaved->tv_sec - entered->tv_sec; - - if (usecs < 0) { - usecs += 1000000; - secs--; - } - leaved->tv_sec = secs; - leaved->tv_usec = usecs; -} - -static inline void net_profile_add(struct timeval *entered, struct timeval *leaved) -{ - time_t usecs = leaved->tv_usec + entered->tv_usec; - time_t secs = leaved->tv_sec + entered->tv_sec; - - if (usecs >= 1000000) { - usecs -= 1000000; - secs++; - } - leaved->tv_sec = secs; - leaved->tv_usec = usecs; -} - - - -#endif - -static inline void net_profile_enter(struct net_profile_slot *s) -{ - unsigned long flags; - - save_flags(flags); - cli(); - if (s->active++ == 0) { - net_profile_stamp(&s->entered); - atomic_inc(&net_profile_active); - } - restore_flags(flags); -} - -static inline void net_profile_leave_irq(struct net_profile_slot *s) -{ - unsigned long flags; - - save_flags(flags); - cli(); - if (--s->active <= 0) { - if (s->active == 0) { - struct timeval curr_pstamp; - net_profile_stamp(&curr_pstamp); - net_profile_accumulate(&s->entered, &curr_pstamp, &s->accumulator); - if (!atomic_dec_and_test(&net_profile_active)) - net_profile_irq_adjust(&s->entered, &curr_pstamp); - } else { - s->underflow++; - } - } - s->hits++; - restore_flags(flags); -} - -static inline void net_profile_leave(struct net_profile_slot *s) -{ - unsigned long flags; - save_flags(flags); - cli(); - if (--s->active <= 0) { - if (s->active == 0) { - struct timeval curr_pstamp; - net_profile_stamp(&curr_pstamp); - net_profile_accumulate(&s->entered, &curr_pstamp, &s->accumulator); - atomic_dec(&net_profile_active); - } else { - s->underflow++; - } - } - s->hits++; - restore_flags(flags); -} - - -#define NET_PROFILE_ENTER(slot) net_profile_enter(&net_prof_##slot) -#define NET_PROFILE_LEAVE(slot) net_profile_leave(&net_prof_##slot) -#define NET_PROFILE_LEAVE_IRQ(slot) net_profile_leave_irq(&net_prof_##slot) - -#define NET_PROFILE_SKB_CLEAR(skb) ({ \ - skb->pstamp.tv_usec = 0; \ -}) - -#define NET_PROFILE_SKB_INIT(skb) ({ \ - net_profile_stamp(&skb->pstamp); \ -}) - -#define NET_PROFILE_SKB_PASSED(skb, slot) ({ \ - if (skb->pstamp.tv_usec) { \ - struct timeval cur_pstamp = skb->pstamp; \ - net_profile_stamp(&skb->pstamp); \ - net_profile_accumulate(&cur_pstamp, &skb->pstamp, &net_prof_##slot.accumulator); \ - net_prof_##slot.hits++; \ - }}) - -#define NET_PROFILE_DECL(slot) \ - extern struct net_profile_slot net_prof_##slot; - -#define NET_PROFILE_DEFINE(slot) \ - struct net_profile_slot net_prof_##slot = { #slot, }; - -#define NET_PROFILE_REGISTER(slot) net_profile_register(&net_prof_##slot) -#define NET_PROFILE_UNREGISTER(slot) net_profile_unregister(&net_prof_##slot) - -extern int net_profile_init(void); -extern int net_profile_register(struct net_profile_slot *); -extern int net_profile_unregister(struct net_profile_slot *); - -#else - -#define NET_PROFILE_ENTER(slot) do { /* nothing */ } while(0) -#define NET_PROFILE_LEAVE(slot) do { /* nothing */ } while(0) -#define NET_PROFILE_LEAVE_IRQ(slot) do { /* nothing */ } while(0) -#define NET_PROFILE_SKB_CLEAR(skb) do { /* nothing */ } while(0) -#define NET_PROFILE_SKB_INIT(skb) do { /* nothing */ } while(0) -#define NET_PROFILE_SKB_PASSED(skb, slot) do { /* nothing */ } while(0) -#define NET_PROFILE_DECL(slot) -#define NET_PROFILE_DEFINE(slot) -#define NET_PROFILE_REGISTER(slot) do { /* nothing */ } while(0) -#define NET_PROFILE_UNREGISTER(slot) do { /* nothing */ } while(0) - -#endif - -#endif diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 506fd2cb1305..3f21f1985699 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines, Corp. * Copyright (c) 2001-2003 Intel Corp. * * This file is part of the SCTP kernel reference Implementation @@ -40,6 +40,7 @@ * Sridhar Samudrala <sri@us.ibm.com> * Ardelle Fan <ardelle.fan@intel.com> * Ryan Layer <rmlayer@us.ibm.com> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -145,6 +146,7 @@ int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg); int sctp_primitive_ABORT(struct sctp_association *, void *arg); int sctp_primitive_SEND(struct sctp_association *, void *arg); int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg); +int sctp_primitive_ASCONF(struct sctp_association *, void *arg); /* * sctp/crc32c.c @@ -404,6 +406,12 @@ static inline struct list_head *sctp_list_dequeue(struct list_head *list) return result; } +/* Tests if the list has one and only one entry. */ +static inline int sctp_list_single_entry(struct list_head *head) +{ + return ((head->next != head) && (head->next == head->prev)); +} + /* Calculate the size (in bytes) occupied by the data of an iovec. */ static inline size_t get_user_iov_size(struct iovec *iov, int iovlen) { @@ -525,6 +533,19 @@ static inline int ipver2af(__u8 ipver) }; } +/* Convert from an address parameter type to an address family. */ +static inline int param_type2af(__u16 type) +{ + switch (type) { + case SCTP_PARAM_IPV4_ADDRESS: + return AF_INET; + case SCTP_PARAM_IPV6_ADDRESS: + return AF_INET6; + default: + return 0; + }; +} + /* Perform some sanity checks. */ static inline int sctp_sanity_check(void) { diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 28d4c6409247..3eb9c18df0c5 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -1,8 +1,8 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001 Intel Corp. - * Copyright (c) 2001-2002 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -41,6 +41,7 @@ * Sridhar Samudrala <sri@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com> * Ardelle Fan <ardelle.fan@intel.com> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -268,6 +269,9 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, struct sctp_chunk *asconf, int vparam_len); +struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, + union sctp_addr *addr); + void sctp_chunk_assign_tsn(struct sctp_chunk *); void sctp_chunk_assign_ssn(struct sctp_chunk *); @@ -330,12 +334,6 @@ void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep, __u32 sctp_generate_tag(const struct sctp_endpoint *); __u32 sctp_generate_tsn(const struct sctp_endpoint *); -/* 4th level prototypes */ -void sctp_param2sockaddr(union sctp_addr *addr, union sctp_addr_param *, - __u16 port, int iif); -int sctp_addr2sockaddr(const union sctp_params, union sctp_addr *); -int sockaddr2sctp_addr(const union sctp_addr *, union sctp_addr_param *); - /* Extern declarations for major data structures. */ const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t); extern const sctp_sm_table_entry_t diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index f77373f18e7e..7ba32701be00 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1,8 +1,8 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001 Intel Corp. - * Copyright (c) 2001-2003 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -45,6 +45,7 @@ * Ardelle Fan <ardelle.fan@intel.com> * Ryan Layer <rmlayer@us.ibm.com> * Anup Pemmaiah <pemmaiah@cc.usu.edu> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -217,86 +218,6 @@ extern struct sctp_globals { #define sctp_local_addr_list (sctp_globals.local_addr_list) #define sctp_local_addr_lock (sctp_globals.local_addr_lock) -/* - * Pointers to address related SCTP functions. - * (i.e. things that depend on the address family.) - */ -struct sctp_af { - int (*sctp_xmit) (struct sk_buff *skb, - struct sctp_transport *, - int ipfragok); - int (*setsockopt) (struct sock *sk, - int level, - int optname, - char *optval, - int optlen); - int (*getsockopt) (struct sock *sk, - int level, - int optname, - char *optval, - int *optlen); - struct dst_entry *(*get_dst) (struct sctp_association *asoc, - union sctp_addr *daddr, - union sctp_addr *saddr); - void (*get_saddr) (struct sctp_association *asoc, - struct dst_entry *dst, - union sctp_addr *daddr, - union sctp_addr *saddr); - void (*copy_addrlist) (struct list_head *, - struct net_device *); - void (*dst_saddr) (union sctp_addr *saddr, - struct dst_entry *dst, - unsigned short port); - int (*cmp_addr) (const union sctp_addr *addr1, - const union sctp_addr *addr2); - void (*addr_copy) (union sctp_addr *dst, - union sctp_addr *src); - void (*from_skb) (union sctp_addr *, - struct sk_buff *skb, - int saddr); - void (*from_sk) (union sctp_addr *, - struct sock *sk); - void (*to_sk_saddr) (union sctp_addr *, - struct sock *sk); - void (*to_sk_daddr) (union sctp_addr *, - struct sock *sk); - int (*addr_valid) (union sctp_addr *, - struct sctp_opt *); - sctp_scope_t (*scope) (union sctp_addr *); - void (*inaddr_any) (union sctp_addr *, unsigned short); - int (*is_any) (const union sctp_addr *); - int (*available) (union sctp_addr *, - struct sctp_opt *); - int (*skb_iif) (const struct sk_buff *sk); - int (*is_ce) (const struct sk_buff *sk); - void (*seq_dump_addr)(struct seq_file *seq, - union sctp_addr *addr); - __u16 net_header_len; - int sockaddr_len; - sa_family_t sa_family; - struct list_head list; -}; - -struct sctp_af *sctp_get_af_specific(sa_family_t); -int sctp_register_af(struct sctp_af *); - -/* Protocol family functions. */ -struct sctp_pf { - void (*event_msgname)(struct sctp_ulpevent *, char *, int *); - void (*skb_msgname) (struct sk_buff *, char *, int *); - int (*af_supported) (sa_family_t, struct sctp_opt *); - int (*cmp_addr) (const union sctp_addr *, - const union sctp_addr *, - struct sctp_opt *); - int (*bind_verify) (struct sctp_opt *, union sctp_addr *); - int (*send_verify) (struct sctp_opt *, union sctp_addr *); - int (*supported_addrs)(const struct sctp_opt *, __u16 *); - struct sock *(*create_accept_sk) (struct sock *sk, - struct sctp_association *asoc); - void (*addr_v4map) (struct sctp_opt *, union sctp_addr *); - struct sctp_af *af; -}; - /* SCTP Socket type: UDP or TCP style. */ typedef enum { SCTP_SOCKET_UDP = 0, @@ -488,6 +409,92 @@ static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id) return stream->ssn[id]++; } +/* + * Pointers to address related SCTP functions. + * (i.e. things that depend on the address family.) + */ +struct sctp_af { + int (*sctp_xmit) (struct sk_buff *skb, + struct sctp_transport *, + int ipfragok); + int (*setsockopt) (struct sock *sk, + int level, + int optname, + char *optval, + int optlen); + int (*getsockopt) (struct sock *sk, + int level, + int optname, + char *optval, + int *optlen); + struct dst_entry *(*get_dst) (struct sctp_association *asoc, + union sctp_addr *daddr, + union sctp_addr *saddr); + void (*get_saddr) (struct sctp_association *asoc, + struct dst_entry *dst, + union sctp_addr *daddr, + union sctp_addr *saddr); + void (*copy_addrlist) (struct list_head *, + struct net_device *); + void (*dst_saddr) (union sctp_addr *saddr, + struct dst_entry *dst, + unsigned short port); + int (*cmp_addr) (const union sctp_addr *addr1, + const union sctp_addr *addr2); + void (*addr_copy) (union sctp_addr *dst, + union sctp_addr *src); + void (*from_skb) (union sctp_addr *, + struct sk_buff *skb, + int saddr); + void (*from_sk) (union sctp_addr *, + struct sock *sk); + void (*to_sk_saddr) (union sctp_addr *, + struct sock *sk); + void (*to_sk_daddr) (union sctp_addr *, + struct sock *sk); + void (*from_addr_param) (union sctp_addr *, + union sctp_addr_param *, + __u16 port, int iif); + int (*to_addr_param) (const union sctp_addr *, + union sctp_addr_param *); + int (*addr_valid) (union sctp_addr *, + struct sctp_opt *); + sctp_scope_t (*scope) (union sctp_addr *); + void (*inaddr_any) (union sctp_addr *, unsigned short); + int (*is_any) (const union sctp_addr *); + int (*available) (union sctp_addr *, + struct sctp_opt *); + int (*skb_iif) (const struct sk_buff *sk); + int (*is_ce) (const struct sk_buff *sk); + void (*seq_dump_addr)(struct seq_file *seq, + union sctp_addr *addr); + __u16 net_header_len; + int sockaddr_len; + sa_family_t sa_family; + struct list_head list; +}; + +struct sctp_af *sctp_get_af_specific(sa_family_t); +int sctp_register_af(struct sctp_af *); + +/* Protocol family functions. */ +struct sctp_pf { + void (*event_msgname)(struct sctp_ulpevent *, char *, int *); + void (*skb_msgname) (struct sk_buff *, char *, int *); + int (*af_supported) (sa_family_t, struct sctp_opt *); + int (*cmp_addr) (const union sctp_addr *, + const union sctp_addr *, + struct sctp_opt *); + int (*bind_verify) (struct sctp_opt *, union sctp_addr *); + int (*send_verify) (struct sctp_opt *, union sctp_addr *); + int (*supported_addrs)(const struct sctp_opt *, __u16 *); + struct sock *(*create_accept_sk) (struct sock *sk, + struct sctp_association *asoc); + void (*addr_v4map) (struct sctp_opt *, union sctp_addr *); + struct sctp_af *af; +}; + + /* Structure to track chunk fragments that have been acked, but peer * fragments of the same message have not. */ @@ -1688,6 +1695,8 @@ struct sctp_transport *sctp_assoc_choose_shutdown_transport( void sctp_assoc_update_retran_path(struct sctp_association *); struct sctp_transport *sctp_assoc_lookup_paddr(const struct sctp_association *, const union sctp_addr *); +int sctp_assoc_lookup_laddr(struct sctp_association *asoc, + const union sctp_addr *laddr); struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *, const union sctp_addr *address, const int gfp); diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index da96859dba92..45f96479510f 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h @@ -551,13 +551,15 @@ struct sctp_status { }; /* - * 8.3, 8.5 get all peer/local addresses on a socket - * This parameter struct is for getsockopt + * 8.3, 8.5 get all peer/local addresses in an association. + * This parameter struct is used by SCTP_GET_PEER_ADDRS and + * SCTP_GET_LOCAL_ADDRS socket options used internally to implement + * sctp_getpaddrs() and sctp_getladdrs() API. */ struct sctp_getaddrs { sctp_assoc_t assoc_id; int addr_num; - struct sockaddr_storage *addrs; + struct sockaddr *addrs; }; /* These are bit fields for msghdr->msg_flags. See section 5.1. */ diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 04b8f47837a9..17cac6fdaa34 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -74,8 +74,6 @@ struct scsi_device { unsigned wdtr:1; /* Device supports WDTR messages */ unsigned ppr:1; /* Device supports PPR messages */ unsigned tagged_supported:1; /* Supports SCSI-II tagged queuing */ - unsigned tagged_queue:1;/* This is going away!!!! Look at simple_tags - instead!!! Please fix your driver now!! */ unsigned simple_tags:1; /* simple queue tag messages are enabled */ unsigned ordered_tags:1;/* ordered queue tag messages are enabled */ unsigned single_lun:1; /* Indicates we should only allow I/O to diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h index d591d365c983..98719407d554 100644 --- a/include/scsi/scsi_request.h +++ b/include/scsi/scsi_request.h @@ -45,7 +45,7 @@ struct scsi_request { level driver) of this request */ }; -extern struct scsi_request *scsi_allocate_request(struct scsi_device *); +extern struct scsi_request *scsi_allocate_request(struct scsi_device *, int); extern void scsi_release_request(struct scsi_request *); extern void scsi_wait_req(struct scsi_request *, const void *cmnd, void *buffer, unsigned bufflen, diff --git a/init/Kconfig b/init/Kconfig index c296f6bee03c..31871d1982f2 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -33,7 +33,7 @@ config EXPERIMENTAL drivers that are currently considered to be in the alpha-test phase. config CLEAN_COMPILE - bool "Don't select drivers known to be broken" if EXPERIMENTAL + bool "Select only drivers expected to compile cleanly" if EXPERIMENTAL default y help Select this option if you don't even want to see the option diff --git a/kernel/configs.c b/kernel/configs.c index dd7acd64b214..7faf6837bfb2 100644 --- a/kernel/configs.c +++ b/kernel/configs.c @@ -26,6 +26,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/init.h> #include <linux/compile.h> #include <linux/version.h> @@ -41,75 +42,59 @@ /**************************************************/ /* globals and useful constants */ -static char *IKCONFIG_NAME = "ikconfig"; -static char *IKCONFIG_VERSION = "0.5"; +static const char IKCONFIG_NAME[] = "ikconfig"; +static const char IKCONFIG_VERSION[] = "0.6"; -static int ikconfig_current_size = 0; -static struct proc_dir_entry *ikconfig_dir, *current_config, *built_with; - -static int -ikconfig_permission_current(struct inode *inode, int op, struct nameidata *nd) -{ - /* anyone can read the device, no one can write to it */ - return (op == MAY_READ) ? 0 : -EACCES; -} +static int ikconfig_size; +static struct proc_dir_entry *ikconfig_dir; static ssize_t -ikconfig_output_current(struct file *file, char *buf, - size_t len, loff_t * offset) -{ - int i, limit; - int cnt; - - limit = (ikconfig_current_size > len) ? len : ikconfig_current_size; - for (i = file->f_pos, cnt = 0; - i < ikconfig_current_size && cnt < limit; i++, cnt++) { - if (put_user(ikconfig_config[i], buf + cnt)) - return -EFAULT; - } - file->f_pos = i; - return cnt; -} - -static int -ikconfig_open_current(struct inode *inode, struct file *file) -{ - if (file->f_mode & FMODE_READ) { - inode->i_size = ikconfig_current_size; - file->f_pos = 0; - } - return 0; -} - -static int -ikconfig_close_current(struct inode *inode, struct file *file) +ikconfig_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) { - return 0; + loff_t pos = *offset; + ssize_t count; + + if (pos >= ikconfig_size) + return 0; + + count = min(len, (size_t)(ikconfig_size - pos)); + if(copy_to_user(buf, ikconfig_config + pos, count)) + return -EFAULT; + + *offset += count; + return count; } -static struct file_operations ikconfig_file_ops = { - .read = ikconfig_output_current, - .open = ikconfig_open_current, - .release = ikconfig_close_current, -}; - -static struct inode_operations ikconfig_inode_ops = { - .permission = ikconfig_permission_current, +static struct file_operations config_fops = { + .owner = THIS_MODULE, + .read = ikconfig_read, }; /***************************************************/ -/* proc_read_built_with: let people read the info */ +/* built_with_show: let people read the info */ /* we have on the tools used to build this kernel */ -static int -proc_read_built_with(char *page, char **start, - off_t off, int count, int *eof, void *data) +static int builtwith_show(struct seq_file *seq, void *v) +{ + seq_printf(seq, + "Kernel: %s\nCompiler: %s\nVersion_in_Makefile: %s\n", + ikconfig_built_with, LINUX_COMPILER, UTS_RELEASE); + return 0; +} + +static int built_with_open(struct inode *inode, struct file *file) { - *eof = 1; - return sprintf(page, - "Kernel: %s\nCompiler: %s\nVersion_in_Makefile: %s\n", - ikconfig_built_with, LINUX_COMPILER, UTS_RELEASE); + return single_open(file, builtwith_show, PDE(inode)->data); } + +static struct file_operations builtwith_fops = { + .owner = THIS_MODULE, + .open = built_with_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; /***************************************************/ /* ikconfig_init: start up everything we need to */ @@ -117,41 +102,33 @@ proc_read_built_with(char *page, char **start, int __init ikconfig_init(void) { - int result = 0; + struct proc_dir_entry *entry; printk(KERN_INFO "ikconfig %s with /proc/ikconfig\n", IKCONFIG_VERSION); /* create the ikconfig directory */ ikconfig_dir = proc_mkdir(IKCONFIG_NAME, NULL); - if (ikconfig_dir == NULL) { - result = -ENOMEM; + if (ikconfig_dir == NULL) goto leave; - } ikconfig_dir->owner = THIS_MODULE; /* create the current config file */ - current_config = create_proc_entry("config", S_IFREG | S_IRUGO, - ikconfig_dir); - if (current_config == NULL) { - result = -ENOMEM; + entry = create_proc_entry("config", S_IFREG | S_IRUGO, ikconfig_dir); + if (!entry) goto leave2; - } - current_config->proc_iops = &ikconfig_inode_ops; - current_config->proc_fops = &ikconfig_file_ops; - current_config->owner = THIS_MODULE; - ikconfig_current_size = strlen(ikconfig_config); - current_config->size = ikconfig_current_size; + + entry->proc_fops = &config_fops; + entry->size = ikconfig_size = strlen(ikconfig_config); /* create the "built with" file */ - built_with = create_proc_read_entry("built_with", 0444, ikconfig_dir, - proc_read_built_with, NULL); - if (built_with == NULL) { - result = -ENOMEM; + entry = create_proc_entry("built_with", S_IFREG | S_IRUGO, + ikconfig_dir); + if (!entry) goto leave3; - } - built_with->owner = THIS_MODULE; - goto leave; + entry->proc_fops = &builtwith_fops; + + return 0; leave3: /* remove the file from proc */ @@ -162,7 +139,7 @@ leave2: remove_proc_entry(IKCONFIG_NAME, NULL); leave: - return result; + return -ENOMEM; } /***************************************************/ diff --git a/kernel/futex.c b/kernel/futex.c index 4557addfc6d6..a4feceee661a 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -5,6 +5,9 @@ * Generalized futexes, futex requeueing, misc fixes by Ingo Molnar * (C) Copyright 2003 Red Hat Inc, All Rights Reserved * + * Removed page pinning, fix privately mapped COW pages and other cleanups + * (C) Copyright 2003 Jamie Lokier + * * Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly * enough at me, Linus for the original (flawed) idea, Matthew * Kirkwood for proof-of-concept implementation. @@ -33,12 +36,32 @@ #include <linux/hash.h> #include <linux/init.h> #include <linux/futex.h> -#include <linux/vcache.h> #include <linux/mount.h> +#include <linux/pagemap.h> #define FUTEX_HASHBITS 8 /* + * Futexes are matched on equal values of this key. + * The key type depends on whether it's a shared or private mapping. + */ +union futex_key { + struct { + unsigned long pgoff; + struct inode *inode; + } shared; + struct { + unsigned long uaddr; + struct mm_struct *mm; + } private; + struct { + unsigned long word; + void *ptr; + } both; + int offset; +}; + +/* * We use this hashed waitqueue instead of a normal wait_queue_t, so * we can wake only the relevant ones (hashed queues may be shared): */ @@ -46,12 +69,8 @@ struct futex_q { struct list_head list; wait_queue_head_t waiters; - /* Page struct and offset within it. */ - struct page *page; - int offset; - - /* the virtual => physical COW-safe cache */ - vcache_t vcache; + /* Key which the futex is hashed on. */ + union futex_key key; /* For fd, sigio sent using these. */ int fd; @@ -66,111 +85,149 @@ static spinlock_t futex_lock = SPIN_LOCK_UNLOCKED; static struct vfsmount *futex_mnt; /* - * These are all locks that are necessery to look up a physical - * mapping safely, and modify/search the futex hash, atomically: + * We hash on the keys returned from get_futex_key (see below). */ -static inline void lock_futex_mm(void) +static inline struct list_head *hash_futex(union futex_key *key) { - spin_lock(¤t->mm->page_table_lock); - spin_lock(&vcache_lock); - spin_lock(&futex_lock); -} - -static inline void unlock_futex_mm(void) -{ - spin_unlock(&futex_lock); - spin_unlock(&vcache_lock); - spin_unlock(¤t->mm->page_table_lock); + return &futex_queues[hash_long(key->both.word + + (unsigned long) key->both.ptr + + key->offset, FUTEX_HASHBITS)]; } /* - * The physical page is shared, so we can hash on its address: + * Return 1 if two futex_keys are equal, 0 otherwise. */ -static inline struct list_head *hash_futex(struct page *page, int offset) +static inline int match_futex(union futex_key *key1, union futex_key *key2) { - return &futex_queues[hash_long((unsigned long)page + offset, - FUTEX_HASHBITS)]; + return (key1->both.word == key2->both.word + && key1->both.ptr == key2->both.ptr + && key1->offset == key2->offset); } /* - * Get kernel address of the user page and pin it. + * Get parameters which are the keys for a futex. + * + * For shared mappings, it's (page->index, vma->vm_file->f_dentry->d_inode, + * offset_within_page). For private mappings, it's (uaddr, current->mm). + * We can usually work out the index without swapping in the page. * - * Must be called with (and returns with) all futex-MM locks held. + * Returns: 0, or negative error code. + * The key words are stored in *key on success. + * + * Should be called with ¤t->mm->mmap_sem, + * but NOT &futex_lock or ¤t->mm->page_table_lock. */ -static inline struct page *__pin_page_atomic (struct page *page) -{ - if (!PageReserved(page)) - get_page(page); - return page; -} - -static struct page *__pin_page(unsigned long addr) +static int get_futex_key(unsigned long uaddr, union futex_key *key) { struct mm_struct *mm = current->mm; - struct page *page, *tmp; + struct vm_area_struct *vma; + struct page *page; int err; /* - * Do a quick atomic lookup first - this is the fastpath. + * The futex address must be "naturally" aligned. + */ + key->offset = uaddr % PAGE_SIZE; + if (unlikely((key->offset % sizeof(u32)) != 0)) + return -EINVAL; + uaddr -= key->offset; + + /* + * The futex is hashed differently depending on whether + * it's in a shared or private mapping. So check vma first. + */ + vma = find_extend_vma(mm, uaddr); + if (unlikely(!vma)) + return -EFAULT; + + /* + * Permissions. */ - page = follow_page(mm, addr, 0); - if (likely(page != NULL)) - return __pin_page_atomic(page); + if (unlikely((vma->vm_flags & (VM_IO|VM_READ)) != VM_READ)) + return (vma->vm_flags & VM_IO) ? -EPERM : -EACCES; /* - * No luck - need to fault in the page: + * Private mappings are handled in a simple way. + * + * NOTE: When userspace waits on a MAP_SHARED mapping, even if + * it's a read-only handle, it's expected that futexes attach to + * the object not the particular process. Therefore we use + * VM_MAYSHARE here, not VM_SHARED which is restricted to shared + * mappings of _writable_ handles. */ -repeat_lookup: + if (likely(!(vma->vm_flags & VM_MAYSHARE))) { + key->private.mm = mm; + key->private.uaddr = uaddr; + return 0; + } - unlock_futex_mm(); + /* + * Linear mappings are also simple. + */ + key->shared.inode = vma->vm_file->f_dentry->d_inode; + if (likely(!(vma->vm_flags & VM_NONLINEAR))) { + key->shared.pgoff = (((uaddr - vma->vm_start) >> PAGE_SHIFT) + + vma->vm_pgoff); + return 0; + } - down_read(&mm->mmap_sem); - err = get_user_pages(current, mm, addr, 1, 0, 0, &page, NULL); - up_read(&mm->mmap_sem); + /* + * We could walk the page table to read the non-linear + * pte, and get the page index without fetching the page + * from swap. But that's a lot of code to duplicate here + * for a rare case, so we simply fetch the page. + */ - lock_futex_mm(); + /* + * Do a quick atomic lookup first - this is the fastpath. + */ + spin_lock(¤t->mm->page_table_lock); + page = follow_page(mm, uaddr, 0); + if (likely(page != NULL)) { + key->shared.pgoff = + page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); + spin_unlock(¤t->mm->page_table_lock); + return 0; + } + spin_unlock(¤t->mm->page_table_lock); - if (err < 0) - return NULL; /* - * Since the faulting happened with locks released, we have to - * check for races: + * Do it the general way. */ - tmp = follow_page(mm, addr, 0); - if (tmp != page) { + err = get_user_pages(current, mm, uaddr, 1, 0, 0, &page, NULL); + if (err >= 0) { + key->shared.pgoff = + page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); put_page(page); - goto repeat_lookup; } - - return page; + return err; } + /* * Wake up all waiters hashed on the physical page that is mapped * to this virtual address: */ -static inline int futex_wake(unsigned long uaddr, int offset, int num) +static inline int futex_wake(unsigned long uaddr, int num) { struct list_head *i, *next, *head; - struct page *page; - int ret = 0; + union futex_key key; + int ret; - lock_futex_mm(); + down_read(¤t->mm->mmap_sem); - page = __pin_page(uaddr - offset); - if (!page) { - unlock_futex_mm(); - return -EFAULT; - } + ret = get_futex_key(uaddr, &key); + if (unlikely(ret != 0)) + goto out; - head = hash_futex(page, offset); + head = hash_futex(&key); + spin_lock(&futex_lock); list_for_each_safe(i, next, head) { struct futex_q *this = list_entry(i, struct futex_q, list); - if (this->page == page && this->offset == offset) { + if (match_futex (&this->key, &key)) { list_del_init(i); - __detach_vcache(&this->vcache); wake_up_all(&this->waiters); if (this->filp) send_sigio(&this->filp->f_owner, this->fd, POLL_IN); @@ -179,113 +236,74 @@ static inline int futex_wake(unsigned long uaddr, int offset, int num) break; } } + spin_unlock(&futex_lock); - unlock_futex_mm(); - put_page(page); - +out: + up_read(¤t->mm->mmap_sem); return ret; } /* - * This gets called by the COW code, we have to rehash any - * futexes that were pending on the old physical page, and - * rehash it to the new physical page. The pagetable_lock - * and vcache_lock is already held: - */ -static void futex_vcache_callback(vcache_t *vcache, struct page *new_page) -{ - struct futex_q *q = container_of(vcache, struct futex_q, vcache); - struct list_head *head = hash_futex(new_page, q->offset); - - spin_lock(&futex_lock); - - if (!list_empty(&q->list)) { - put_page(q->page); - q->page = new_page; - __pin_page_atomic(new_page); - list_del(&q->list); - list_add_tail(&q->list, head); - } - - spin_unlock(&futex_lock); -} - -/* * Requeue all waiters hashed on one physical page to another * physical page. */ -static inline int futex_requeue(unsigned long uaddr1, int offset1, - unsigned long uaddr2, int offset2, int nr_wake, int nr_requeue) +static inline int futex_requeue(unsigned long uaddr1, unsigned long uaddr2, + int nr_wake, int nr_requeue) { struct list_head *i, *next, *head1, *head2; - struct page *page1 = NULL, *page2 = NULL; - int ret = 0; + union futex_key key1, key2; + int ret; - lock_futex_mm(); + down_read(¤t->mm->mmap_sem); - page1 = __pin_page(uaddr1 - offset1); - if (!page1) + ret = get_futex_key(uaddr1, &key1); + if (unlikely(ret != 0)) goto out; - page2 = __pin_page(uaddr2 - offset2); - if (!page2) + ret = get_futex_key(uaddr2, &key2); + if (unlikely(ret != 0)) goto out; - head1 = hash_futex(page1, offset1); - head2 = hash_futex(page2, offset2); + head1 = hash_futex(&key1); + head2 = hash_futex(&key2); + spin_lock(&futex_lock); list_for_each_safe(i, next, head1) { struct futex_q *this = list_entry(i, struct futex_q, list); - if (this->page == page1 && this->offset == offset1) { + if (match_futex (&this->key, &key1)) { list_del_init(i); - __detach_vcache(&this->vcache); if (++ret <= nr_wake) { wake_up_all(&this->waiters); if (this->filp) send_sigio(&this->filp->f_owner, this->fd, POLL_IN); } else { - put_page(this->page); - __pin_page_atomic (page2); list_add_tail(i, head2); - __attach_vcache(&this->vcache, uaddr2, - current->mm, futex_vcache_callback); - this->offset = offset2; - this->page = page2; + this->key = key2; if (ret - nr_wake >= nr_requeue) break; } } } + spin_unlock(&futex_lock); out: - unlock_futex_mm(); - - if (page1) - put_page(page1); - if (page2) - put_page(page2); - + up_read(¤t->mm->mmap_sem); return ret; } -static inline void __queue_me(struct futex_q *q, struct page *page, - unsigned long uaddr, int offset, - int fd, struct file *filp) +static inline void queue_me(struct futex_q *q, union futex_key *key, + int fd, struct file *filp) { - struct list_head *head = hash_futex(page, offset); + struct list_head *head = hash_futex(key); - q->offset = offset; + q->key = *key; q->fd = fd; q->filp = filp; - q->page = page; + spin_lock(&futex_lock); list_add_tail(&q->list, head); - /* - * We register a futex callback to this virtual address, - * to make sure a COW properly rehashes the futex-queue. - */ - __attach_vcache(&q->vcache, uaddr, current->mm, futex_vcache_callback); + spin_unlock(&futex_lock); } /* Return 1 if we were still queued (ie. 0 means we were woken) */ @@ -293,83 +311,107 @@ static inline int unqueue_me(struct futex_q *q) { int ret = 0; - spin_lock(&vcache_lock); spin_lock(&futex_lock); if (!list_empty(&q->list)) { list_del(&q->list); - __detach_vcache(&q->vcache); ret = 1; } spin_unlock(&futex_lock); - spin_unlock(&vcache_lock); return ret; } -static inline int futex_wait(unsigned long uaddr, - int offset, - int val, - unsigned long time) +static inline int futex_wait(unsigned long uaddr, int val, unsigned long time) { DECLARE_WAITQUEUE(wait, current); - int ret = 0, curval; - struct page *page; + int ret, curval; + union futex_key key; struct futex_q q; + try_again: init_waitqueue_head(&q.waiters); - lock_futex_mm(); + down_read(¤t->mm->mmap_sem); - page = __pin_page(uaddr - offset); - if (!page) { - unlock_futex_mm(); - return -EFAULT; - } - __queue_me(&q, page, uaddr, offset, -1, NULL); + ret = get_futex_key(uaddr, &key); + if (unlikely(ret != 0)) + goto out_release_sem; + + queue_me(&q, &key, -1, NULL); /* - * Page is pinned, but may no longer be in this address space. - * It cannot schedule, so we access it with the spinlock held. + * Access the page after the futex is queued. + * We hold the mmap semaphore, so the mapping cannot have changed + * since we looked it up. */ if (get_user(curval, (int *)uaddr) != 0) { - unlock_futex_mm(); ret = -EFAULT; - goto out; + goto out_unqueue; } if (curval != val) { - unlock_futex_mm(); ret = -EWOULDBLOCK; - goto out; + goto out_unqueue; } + + /* + * Now the futex is queued and we have checked the data, we + * don't want to hold mmap_sem while we sleep. + */ + up_read(¤t->mm->mmap_sem); + /* - * The get_user() above might fault and schedule so we - * cannot just set TASK_INTERRUPTIBLE state when queueing - * ourselves into the futex hash. This code thus has to + * There might have been scheduling since the queue_me(), as we + * cannot hold a spinlock across the get_user() in case it + * faults. So we cannot just set TASK_INTERRUPTIBLE state when + * queueing ourselves into the futex hash. This code thus has to * rely on the futex_wake() code doing a wakeup after removing * the waiter from the list. */ add_wait_queue(&q.waiters, &wait); + spin_lock(&futex_lock); set_current_state(TASK_INTERRUPTIBLE); - if (!list_empty(&q.list)) { - unlock_futex_mm(); - time = schedule_timeout(time); + + if (unlikely(list_empty(&q.list))) { + /* + * We were woken already. + */ + spin_unlock(&futex_lock); + set_current_state(TASK_RUNNING); + return 0; } + + spin_unlock(&futex_lock); + time = schedule_timeout(time); set_current_state(TASK_RUNNING); + /* * NOTE: we don't remove ourselves from the waitqueue because * we are the only user of it. */ - if (time == 0) { - ret = -ETIMEDOUT; - goto out; - } + + /* + * Were we woken or interrupted for a valid reason? + */ + ret = unqueue_me(&q); + if (ret == 0) + return 0; + if (time == 0) + return -ETIMEDOUT; if (signal_pending(current)) - ret = -EINTR; -out: - /* Were we woken up anyway? */ + return -EINTR; + + /* + * No, it was a spurious wakeup. Try again. Should never happen. :) + */ + goto try_again; + + out_unqueue: + /* + * Were we unqueued anyway? + */ if (!unqueue_me(&q)) ret = 0; - put_page(q.page); - + out_release_sem: + up_read(¤t->mm->mmap_sem); return ret; } @@ -378,7 +420,6 @@ static int futex_close(struct inode *inode, struct file *filp) struct futex_q *q = filp->private_data; unqueue_me(q); - put_page(q->page); kfree(filp->private_data); return 0; } @@ -406,12 +447,12 @@ static struct file_operations futex_fops = { /* Signal allows caller to avoid the race which would occur if they set the sigio stuff up afterwards. */ -static int futex_fd(unsigned long uaddr, int offset, int signal) +static int futex_fd(unsigned long uaddr, int signal) { - struct page *page = NULL; struct futex_q *q; + union futex_key key; struct file *filp; - int ret; + int ret, err; ret = -EINVAL; if (signal < 0 || signal > _NSIG) @@ -450,69 +491,47 @@ static int futex_fd(unsigned long uaddr, int offset, int signal) goto out; } - lock_futex_mm(); - - page = __pin_page(uaddr - offset); - if (!page) { - unlock_futex_mm(); + down_read(¤t->mm->mmap_sem); + err = get_futex_key(uaddr, &key); + up_read(¤t->mm->mmap_sem); + if (unlikely(err != 0)) { put_unused_fd(ret); put_filp(filp); kfree(q); - return -EFAULT; + return err; } init_waitqueue_head(&q->waiters); filp->private_data = q; - __queue_me(q, page, uaddr, offset, ret, filp); - - unlock_futex_mm(); + queue_me(q, &key, ret, filp); /* Now we map fd to filp, so userspace can access it */ fd_install(ret, filp); - page = NULL; out: - if (page) - put_page(page); return ret; } long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout, unsigned long uaddr2, int val2) { - unsigned long pos_in_page; int ret; - pos_in_page = uaddr % PAGE_SIZE; - - /* Must be "naturally" aligned */ - if (pos_in_page % sizeof(u32)) - return -EINVAL; - switch (op) { case FUTEX_WAIT: - ret = futex_wait(uaddr, pos_in_page, val, timeout); + ret = futex_wait(uaddr, val, timeout); break; case FUTEX_WAKE: - ret = futex_wake(uaddr, pos_in_page, val); + ret = futex_wake(uaddr, val); break; case FUTEX_FD: /* non-zero val means F_SETOWN(getpid()) & F_SETSIG(val) */ - ret = futex_fd(uaddr, pos_in_page, val); + ret = futex_fd(uaddr, val); break; case FUTEX_REQUEUE: - { - unsigned long pos_in_page2 = uaddr2 % PAGE_SIZE; - - /* Must be "naturally" aligned */ - if (pos_in_page2 % sizeof(u32)) - return -EINVAL; - - ret = futex_requeue(uaddr, pos_in_page, uaddr2, pos_in_page2, - val, val2); + ret = futex_requeue(uaddr, uaddr2, val, val2); break; - } default: ret = -ENOSYS; } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 142ccfcf835b..3180fa00d248 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -35,6 +35,7 @@ #include <linux/writeback.h> #include <linux/hugetlb.h> #include <linux/security.h> +#include <linux/initrd.h> #include <asm/uaccess.h> #ifdef CONFIG_ROOT_NFS diff --git a/mm/Makefile b/mm/Makefile index a8de64ff3525..c66aba5886f8 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -9,6 +9,6 @@ mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ page_alloc.o page-writeback.o pdflush.o readahead.o \ - slab.o swap.o truncate.o vcache.o vmscan.o $(mmu-y) + slab.o swap.o truncate.o vmscan.o $(mmu-y) obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o diff --git a/mm/fremap.c b/mm/fremap.c index 8f96af82b4e8..b19bdde07bb6 100644 --- a/mm/fremap.c +++ b/mm/fremap.c @@ -144,9 +144,10 @@ long sys_remap_file_pages(unsigned long start, unsigned long size, return err; #endif - down_read(&mm->mmap_sem); - + /* We need down_write() to change vma->vm_flags. */ + down_write(&mm->mmap_sem); vma = find_vma(mm, start); + /* * Make sure the vma is shared, that it supports prefaulting, * and that the remapped range is valid and fully within @@ -155,11 +156,27 @@ long sys_remap_file_pages(unsigned long start, unsigned long size, if (vma && (vma->vm_flags & VM_SHARED) && vma->vm_ops && vma->vm_ops->populate && end > start && start >= vma->vm_start && - end <= vma->vm_end) - err = vma->vm_ops->populate(vma, start, size, vma->vm_page_prot, - pgoff, flags & MAP_NONBLOCK); - - up_read(&mm->mmap_sem); + end <= vma->vm_end) { + + /* Must set VM_NONLINEAR before any pages are populated. */ + if (pgoff != ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff) + vma->vm_flags |= VM_NONLINEAR; + + /* ->populate can take a long time, so downgrade the lock. */ + downgrade_write(&mm->mmap_sem); + err = vma->vm_ops->populate(vma, start, size, + vma->vm_page_prot, + pgoff, flags & MAP_NONBLOCK); + + /* + * We can't clear VM_NONLINEAR because we'd have to do + * it after ->populate completes, and that would prevent + * downgrading the lock. (Locks can't be upgraded). + */ + up_read(&mm->mmap_sem); + } else { + up_write(&mm->mmap_sem); + } return err; } diff --git a/mm/memory.c b/mm/memory.c index 61b782f40df9..980953dbbfb4 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -43,7 +43,6 @@ #include <linux/swap.h> #include <linux/highmem.h> #include <linux/pagemap.h> -#include <linux/vcache.h> #include <linux/rmap-locking.h> #include <linux/module.h> @@ -962,7 +961,6 @@ static inline void establish_pte(struct vm_area_struct * vma, unsigned long addr static inline void break_cow(struct vm_area_struct * vma, struct page * new_page, unsigned long address, pte_t *page_table) { - invalidate_vcache(address, vma->vm_mm, new_page); flush_cache_page(vma, address); establish_pte(vma, address, page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot)))); } diff --git a/mm/mremap.c b/mm/mremap.c index d9180f18ad6c..0412a204cb69 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -420,7 +420,7 @@ unsigned long do_mremap(unsigned long addr, if (flags & MREMAP_MAYMOVE) { if (!(flags & MREMAP_FIXED)) { unsigned long map_flags = 0; - if (vma->vm_flags & VM_SHARED) + if (vma->vm_flags & VM_MAYSHARE) map_flags |= MAP_SHARED; new_addr = get_unmapped_area(vma->vm_file, 0, new_len, diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 453f291437ab..4051a19b0ab5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -220,6 +220,7 @@ static inline void free_pages_check(const char *function, struct page *page) 1 << PG_locked | 1 << PG_active | 1 << PG_reclaim | + 1 << PG_slab | 1 << PG_writeback ))) bad_page(function, page); if (PageDirty(page)) @@ -542,8 +543,7 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, int do_retry; struct reclaim_state reclaim_state; - if (wait) - might_sleep(); + might_sleep_if(wait); cold = 0; if (gfp_mask & __GFP_COLD) diff --git a/mm/rmap.c b/mm/rmap.c index 06377cb9c907..c4434f218e4d 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -503,8 +503,7 @@ struct pte_chain *pte_chain_alloc(int gfp_flags) struct pte_chain *ret; struct pte_chain **pte_chainp; - if (gfp_flags & __GFP_WAIT) - might_sleep(); + might_sleep_if(gfp_flags & __GFP_WAIT); pte_chainp = &get_cpu_var(local_pte_chain); if (*pte_chainp) { diff --git a/mm/slab.c b/mm/slab.c index 6093193d0456..34b62ca48429 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -787,7 +787,8 @@ static inline void kmem_freepages (kmem_cache_t *cachep, void *addr) * vm_scan(). Shouldn't be a worry. */ while (i--) { - ClearPageSlab(page); + if (!TestClearPageSlab(page)) + BUG(); page++; } sub_page_state(nr_slab, nr_freed); @@ -1813,8 +1814,7 @@ alloc_done: static inline void cache_alloc_debugcheck_before(kmem_cache_t *cachep, int flags) { - if (flags & __GFP_WAIT) - might_sleep(); + might_sleep_if(flags & __GFP_WAIT); #if DEBUG kmem_flagcheck(cachep, flags); #endif diff --git a/mm/vcache.c b/mm/vcache.c deleted file mode 100644 index 599e0f25490d..000000000000 --- a/mm/vcache.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * linux/mm/vcache.c - * - * virtual => physical page mapping cache. Users of this mechanism - * register callbacks for a given (virt,mm,phys) page mapping, and - * the kernel guarantees to call back when this mapping is invalidated. - * (ie. upon COW or unmap.) - * - * Started by Ingo Molnar, Copyright (C) 2002 - */ - -#include <linux/mm.h> -#include <linux/init.h> -#include <linux/hash.h> -#include <linux/vcache.h> - -#define VCACHE_HASHBITS 8 -#define VCACHE_HASHSIZE (1 << VCACHE_HASHBITS) - -spinlock_t vcache_lock = SPIN_LOCK_UNLOCKED; - -static struct list_head hash[VCACHE_HASHSIZE]; - -static struct list_head *hash_vcache(unsigned long address, - struct mm_struct *mm) -{ - return &hash[hash_long(address + (unsigned long)mm, VCACHE_HASHBITS)]; -} - -void __attach_vcache(vcache_t *vcache, - unsigned long address, - struct mm_struct *mm, - void (*callback)(struct vcache_s *data, struct page *new)) -{ - struct list_head *hash_head; - - address &= PAGE_MASK; - vcache->address = address; - vcache->mm = mm; - vcache->callback = callback; - - hash_head = hash_vcache(address, mm); - - list_add_tail(&vcache->hash_entry, hash_head); -} - -void __detach_vcache(vcache_t *vcache) -{ - list_del_init(&vcache->hash_entry); -} - -void invalidate_vcache(unsigned long address, struct mm_struct *mm, - struct page *new_page) -{ - struct list_head *l, *hash_head; - vcache_t *vcache; - - address &= PAGE_MASK; - - hash_head = hash_vcache(address, mm); - /* - * This is safe, because this path is called with the pagetable - * lock held. So while other mm's might add new entries in - * parallel, *this* mm is locked out, so if the list is empty - * now then we do not have to take the vcache lock to see it's - * really empty. - */ - if (likely(list_empty(hash_head))) - return; - - spin_lock(&vcache_lock); - list_for_each(l, hash_head) { - vcache = list_entry(l, vcache_t, hash_entry); - if (vcache->address != address || vcache->mm != mm) - continue; - vcache->callback(vcache, new_page); - } - spin_unlock(&vcache_lock); -} - -static int __init vcache_init(void) -{ - unsigned int i; - - for (i = 0; i < VCACHE_HASHSIZE; i++) - INIT_LIST_HEAD(hash + i); - return 0; -} -__initcall(vcache_init); - diff --git a/net/Kconfig b/net/Kconfig index 4c3474604a0c..7d76574a9cc3 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -676,7 +676,6 @@ config NET_SCHED source "net/sched/Kconfig" -#bool 'Network code profiler' CONFIG_NET_PROFILE endmenu menu "Network testing" diff --git a/net/README b/net/README deleted file mode 100644 index e509ec526c25..000000000000 --- a/net/README +++ /dev/null @@ -1,26 +0,0 @@ - -Maintainers and developers for networking code sections - -Code Section Bug Report Contact --------------------+------------------------------------------- -802 [other ] alan@lxorguk.ukuu.org.uk - [token ring ] p.norton@computer.org -appletalk jschlst@samba.org -ax25 g4klx@g4klx.demon.co.uk -bridge buytenh@gnu.org -core alan@lxorguk.ukuu.org.uk -decnet SteveW@ACM.org -ethernet alan@lxorguk.ukuu.org.uk -ipv4 davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se -ipv6 davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se -ipx acme@conectiva.com.br -spx jschlst@samba.org -irda dagb@cs.uit.no -lapb g4klx@g4klx.demon.co.uk -netrom g4klx@g4klx.demon.co.uk -rose g4klx@g4klx.demon.co.uk -wanrouter gene@compuserve.com, jaspreet@sangoma and dm@sangoma.com -unix alan@lxorguk.ukuu.org.uk -x25 g4klx@g4klx.demon.co.uk -bluetooth maxk@qualcomm.com -8021q greearb@candelatech.com, vlan@scry.wanfear.com diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 4d5469bd8140..217244bd611d 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1888,8 +1888,6 @@ EXPORT_SYMBOL(aarp_send_ddp); EXPORT_SYMBOL(atrtr_get_dev); EXPORT_SYMBOL(atalk_find_dev_addr); -static char atalk_banner[] __initdata = - KERN_INFO "NET4: AppleTalk 0.20 for Linux NET4.0\n"; static char atalk_err_snap[] __initdata = KERN_CRIT "Unable to register DDP with SNAP.\n"; @@ -1908,7 +1906,6 @@ static int __init atalk_init(void) aarp_proto_init(); atalk_proc_init(); atalk_register_sysctl(); - printk(atalk_banner); return 0; } module_init(atalk_init); @@ -1939,5 +1936,5 @@ module_exit(atalk_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alan Cox <Alan.Cox@linux.org>"); -MODULE_DESCRIPTION("AppleTalk 0.20 for Linux NET4.0\n"); +MODULE_DESCRIPTION("AppleTalk 0.20\n"); MODULE_ALIAS_NETPROTO(PF_APPLETALK); diff --git a/net/atm/addr.c b/net/atm/addr.c index 5974a1876116..459bdeed05f9 100644 --- a/net/atm/addr.c +++ b/net/atm/addr.c @@ -118,23 +118,24 @@ int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc *u_buf,int size) { unsigned long flags; struct atm_dev_addr *walk; - int total; + int total = 0, error; + struct sockaddr_atmsvc *tmp_buf, *tmp_bufp; + spin_lock_irqsave(&dev->lock, flags); - total = 0; - for (walk = dev->local; walk; walk = walk->next) { + for (walk = dev->local; walk; walk = walk->next) total += sizeof(struct sockaddr_atmsvc); - if (total > size) { - spin_unlock_irqrestore(&dev->lock, flags); - return -E2BIG; - } - if (copy_to_user(u_buf,&walk->addr, - sizeof(struct sockaddr_atmsvc))) { - spin_unlock_irqrestore(&dev->lock, flags); - return -EFAULT; - } - u_buf++; + tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC); + if (!tmp_buf) { + spin_unlock_irqrestore(&dev->lock, flags); + return -ENOMEM; } + for (walk = dev->local; walk; walk = walk->next) + memcpy(tmp_bufp++, &walk->addr, sizeof(struct sockaddr_atmsvc)); spin_unlock_irqrestore(&dev->lock, flags); - return total; + error = total > size ? -E2BIG : total; + if (copy_to_user(u_buf, tmp_buf, total < size ? total : size)) + error = -EFAULT; + kfree(tmp_buf); + return error; } diff --git a/net/atm/br2684.c b/net/atm/br2684.c index fa25cbdd9a80..0f9d98463a69 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -18,6 +18,7 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary #include <net/arp.h> #include <linux/atm.h> #include <linux/atmdev.h> +#include <linux/seq_file.h> #include <linux/atmbr2684.h> @@ -666,31 +667,57 @@ static int br2684_ioctl(struct atm_vcc *atmvcc, unsigned int cmd, return -ENOIOCTLCMD; } -/* Never put more than 256 bytes in at once */ -static int br2684_proc_engine(loff_t pos, char *buf) +#ifdef CONFIG_PROC_FS +static void *br2684_seq_start(struct seq_file *seq, loff_t *pos) { - struct list_head *lhd, *lhc; - struct net_device *net_dev; - struct br2684_dev *brdev; - struct br2684_vcc *brvcc; - list_for_each(lhd, &br2684_devs) { - net_dev = list_entry_brdev(lhd); - brdev = BRPRIV(net_dev); - if (pos-- == 0) - return sprintf(buf, "dev %.16s: num=%d, mac=%02X:%02X:" - "%02X:%02X:%02X:%02X (%s)\n", net_dev->name, - brdev->number, - net_dev->dev_addr[0], - net_dev->dev_addr[1], - net_dev->dev_addr[2], - net_dev->dev_addr[3], - net_dev->dev_addr[4], - net_dev->dev_addr[5], - brdev->mac_was_set ? "set" : "auto"); - list_for_each(lhc, &brdev->brvccs) { - brvcc = list_entry_brvcc(lhc); - if (pos-- == 0) - return sprintf(buf, " vcc %d.%d.%d: encaps=%s" + loff_t offs = 0; + struct br2684_dev *brd; + + read_lock(&devs_lock); + + list_for_each_entry(brd, &br2684_devs, br2684_devs) { + if (offs == *pos) + return brd; + ++offs; + } + return NULL; +} + +static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct br2684_dev *brd = v; + + ++*pos; + + brd = list_entry(brd->br2684_devs.next, + struct br2684_dev, br2684_devs); + return (&brd->br2684_devs != &br2684_devs) ? brd : NULL; +} + +static void br2684_seq_stop(struct seq_file *seq, void *v) +{ + read_unlock(&devs_lock); +} + +static int br2684_seq_show(struct seq_file *seq, void *v) +{ + const struct br2684_dev *brdev = v; + const struct net_device *net_dev = brdev->net_dev; + const struct br2684_vcc *brvcc; + + seq_printf(seq, "dev %.16s: num=%d, mac=%02X:%02X:" + "%02X:%02X:%02X:%02X (%s)\n", net_dev->name, + brdev->number, + net_dev->dev_addr[0], + net_dev->dev_addr[1], + net_dev->dev_addr[2], + net_dev->dev_addr[3], + net_dev->dev_addr[4], + net_dev->dev_addr[5], + brdev->mac_was_set ? "set" : "auto"); + + list_for_each_entry(brvcc, &brdev->brvccs, brvccs) { + seq_printf(seq, " vcc %d.%d.%d: encaps=%s" #ifndef FASTER_VERSION ", failed copies %u/%u" #endif /* FASTER_VERSION */ @@ -711,63 +738,41 @@ static int br2684_proc_engine(loff_t pos, char *buf) #undef bs #undef b1 #endif /* CONFIG_ATM_BR2684_IPFILTER */ - } } return 0; } -static ssize_t br2684_proc_read(struct file *file, char *buf, size_t count, - loff_t *pos) +static struct seq_operations br2684_seq_ops = { + .start = br2684_seq_start, + .next = br2684_seq_next, + .stop = br2684_seq_stop, + .show = br2684_seq_show, +}; + +static int br2684_proc_open(struct inode *inode, struct file *file) { - unsigned long page; - int len = 0, x, left; - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - left = PAGE_SIZE - 256; - if (count < left) - left = count; - read_lock(&devs_lock); - for (;;) { - x = br2684_proc_engine(*pos, &((char *) page)[len]); - if (x == 0) - break; - if (x > left) - /* - * This should only happen if the user passed in - * a "count" too small for even one line - */ - x = -EINVAL; - if (x < 0) { - len = x; - break; - } - len += x; - left -= x; - (*pos)++; - if (left < 256) - break; - } - read_unlock(&devs_lock); - if (len > 0 && copy_to_user(buf, (char *) page, len)) - len = -EFAULT; - free_page(page); - return len; + return seq_open(file, &br2684_seq_ops); } -static struct file_operations br2684_proc_operations = { - .owner = THIS_MODULE, - .read = br2684_proc_read, +static struct file_operations br2684_proc_ops = { + .owner = THIS_MODULE, + .open = br2684_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, }; extern struct proc_dir_entry *atm_proc_root; /* from proc.c */ +#endif static int __init br2684_init(void) { +#ifdef CONFIG_PROC_FS struct proc_dir_entry *p; if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL) return -ENOMEM; - p->proc_fops = &br2684_proc_operations; + p->proc_fops = &br2684_proc_ops; +#endif br2684_ioctl_set(br2684_ioctl); return 0; } @@ -779,7 +784,9 @@ static void __exit br2684_exit(void) struct br2684_vcc *brvcc; br2684_ioctl_set(NULL); +#ifdef CONFIG_PROC_FS remove_proc_entry("br2684", atm_proc_root); +#endif while (!list_empty(&br2684_devs)) { net_dev = list_entry_brdev(br2684_devs.next); diff --git a/net/atm/common.c b/net/atm/common.c index 6fde6b018418..62c8f0a72179 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -422,26 +422,31 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, int vpi, } if (!error) error = adjust_tp(&vcc->qos.txtp,vcc->qos.aal); if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->qos.aal); - if (error) { - vcc_remove_socket(vcc->sk); - return error; - } + if (error) + goto fail; DPRINTK("VCC %d.%d, AAL %d\n",vpi,vci,vcc->qos.aal); DPRINTK(" TX: %d, PCR %d..%d, SDU %d\n",vcc->qos.txtp.traffic_class, vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu); DPRINTK(" RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class, vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu); - if (!try_module_get(dev->ops->owner)) - return -ENODEV; + if (!try_module_get(dev->ops->owner)) { + error = -ENODEV; + goto fail; + } + if (dev->ops->open) { - error = dev->ops->open(vcc,vpi,vci); - if (error) { - module_put(dev->ops->owner); - vcc_remove_socket(vcc->sk); - return error; - } + if ((error = dev->ops->open(vcc,vpi,vci))) + goto put_module_fail; } return 0; + +put_module_fail: + module_put(dev->ops->owner); +fail: + vcc_remove_socket(vcc->sk); + /* ensure we get dev module ref count correct */ + vcc->dev = NULL; + return error; } @@ -1109,12 +1114,10 @@ static int __init atm_init(void) printk(KERN_ERR "atmsvc_init() failed with %d\n", error); goto failure; } -#ifdef CONFIG_PROC_FS if ((error = atm_proc_init()) < 0) { printk(KERN_ERR "atm_proc_init() failed with %d\n",error); goto failure; } -#endif return 0; failure: @@ -1125,9 +1128,7 @@ failure: static void __exit atm_exit(void) { -#ifdef CONFIG_PROC_FS atm_proc_exit(); -#endif atmsvc_exit(); atmpvc_exit(); } diff --git a/net/atm/common.h b/net/atm/common.h index eb98c9357431..426f1fa8bbb1 100644 --- a/net/atm/common.h +++ b/net/atm/common.h @@ -33,8 +33,21 @@ int atmpvc_init(void); void atmpvc_exit(void); int atmsvc_init(void); void atmsvc_exit(void); + +#ifdef CONFIG_PROC_FS int atm_proc_init(void); void atm_proc_exit(void); +#else +static inline int atm_proc_init(void) +{ + return 0; +} + +static inline void atm_proc_exit(void) +{ + /* nothing */ +} +#endif /* CONFIG_PROC_FS */ /* SVC */ diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c index cca22da87ae6..4a8f73b41edf 100644 --- a/net/atm/pppoatm.c +++ b/net/atm/pppoatm.c @@ -341,16 +341,13 @@ static int pppoatm_ioctl(struct atm_vcc *atmvcc, unsigned int cmd, return -ENOIOCTLCMD; } -/* the following avoids some spurious warnings from the compiler */ -#define UNUSED __attribute__((unused)) - -static int __init UNUSED pppoatm_init(void) +static int __init pppoatm_init(void) { pppoatm_ioctl_set(pppoatm_ioctl); return 0; } -static void __exit UNUSED pppoatm_exit(void) +static void __exit pppoatm_exit(void) { pppoatm_ioctl_set(NULL); } diff --git a/net/atm/proc.c b/net/atm/proc.c index 05c41491b431..d493ab2cd420 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -593,6 +593,10 @@ int atm_proc_dev_register(struct atm_dev *dev) int digits,num; int error; + /* No proc info */ + if (!dev->ops->proc_read) + return 0; + error = -ENOMEM; digits = 0; for (num = dev->number; num; num /= 10) digits++; @@ -619,6 +623,9 @@ fail1: void atm_proc_dev_deregister(struct atm_dev *dev) { + if (!dev->ops->proc_read) + return; + remove_proc_entry(dev->proc_name, atm_proc_root); kfree(dev->proc_name); } diff --git a/net/atm/pvc.c b/net/atm/pvc.c index 9dee7f22c801..c0ce4d4d20b6 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c @@ -104,6 +104,7 @@ static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr, static struct proto_ops pvc_proto_ops = { .family = PF_ATMPVC, + .owner = THIS_MODULE, .release = vcc_release, .bind = pvc_bind, @@ -134,6 +135,7 @@ static int pvc_create(struct socket *sock,int protocol) static struct net_proto_family pvc_family_ops = { .family = PF_ATMPVC, .create = pvc_create, + .owner = THIS_MODULE, }; diff --git a/net/atm/resources.c b/net/atm/resources.c index ae3009c6eb4f..bd32c0caabe4 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -110,20 +110,16 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, list_add_tail(&dev->dev_list, &atm_devs); spin_unlock(&atm_dev_lock); -#ifdef CONFIG_PROC_FS - if (ops->proc_read) { - if (atm_proc_dev_register(dev) < 0) { - printk(KERN_ERR "atm_dev_register: " - "atm_proc_dev_register failed for dev %s\n", - type); - spin_lock(&atm_dev_lock); - list_del(&dev->dev_list); - spin_unlock(&atm_dev_lock); - __free_atm_dev(dev); - return NULL; - } + if (atm_proc_dev_register(dev) < 0) { + printk(KERN_ERR "atm_dev_register: " + "atm_proc_dev_register failed for dev %s\n", + type); + spin_lock(&atm_dev_lock); + list_del(&dev->dev_list); + spin_unlock(&atm_dev_lock); + __free_atm_dev(dev); + return NULL; } -#endif return dev; } @@ -133,10 +129,8 @@ void atm_dev_deregister(struct atm_dev *dev) { unsigned long warning_time; -#ifdef CONFIG_PROC_FS - if (dev->ops->proc_read) - atm_proc_dev_deregister(dev); -#endif + atm_proc_dev_deregister(dev); + spin_lock(&atm_dev_lock); list_del(&dev->dev_list); spin_unlock(&atm_dev_lock); diff --git a/net/atm/resources.h b/net/atm/resources.h index c4ecc1be6a26..1b6bad8db9cc 100644 --- a/net/atm/resources.h +++ b/net/atm/resources.h @@ -24,6 +24,18 @@ int atm_dev_ioctl(unsigned int cmd, unsigned long arg); int atm_proc_dev_register(struct atm_dev *dev); void atm_proc_dev_deregister(struct atm_dev *dev); -#endif +#else + +static inline int atm_proc_dev_register(struct atm_dev *dev) +{ + return 0; +} + +static inline void atm_proc_dev_deregister(struct atm_dev *dev) +{ + /* nothing */ +} + +#endif /* CONFIG_PROC_FS */ #endif diff --git a/net/atm/svc.c b/net/atm/svc.c index 07c0849b37c7..aa46d6ae96d5 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c @@ -513,6 +513,7 @@ out: static struct proto_ops svc_proto_ops = { .family = PF_ATMSVC, + .owner = THIS_MODULE, .release = svc_release, .bind = svc_bind, @@ -549,6 +550,7 @@ static int svc_create(struct socket *sock,int protocol) static struct net_proto_family svc_family_ops = { .family = PF_ATMSVC, .create = svc_create, + .owner = THIS_MODULE, }; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 4bb3798a2638..43662ed9a619 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -2003,8 +2003,6 @@ EXPORT_SYMBOL(asc2ax); EXPORT_SYMBOL(null_ax25_address); EXPORT_SYMBOL(ax25_display_timer); -static char banner[] __initdata = KERN_INFO "NET4: G4KLX/GW4PTS AX.25 for Linux. Version 0.37 for Linux NET4.0\n"; - static int __init ax25_init(void) { sock_register(&ax25_family_ops); @@ -2016,7 +2014,6 @@ static int __init ax25_init(void) proc_net_fops_create("ax25", S_IRUGO, &ax25_info_fops); proc_net_fops_create("ax25_calls", S_IRUGO, &ax25_uid_fops); - printk(banner); return 0; } module_init(ax25_init); diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index b1d5fff0d872..1292e56f3ce6 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -41,7 +41,6 @@ #include <linux/poll.h> #include <linux/fcntl.h> #include <linux/init.h> -#include <linux/skbuff.h> #include <linux/interrupt.h> #include <linux/socket.h> #include <linux/skbuff.h> diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 4b7c3315ff89..f62df6a7d153 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1794,7 +1794,7 @@ static void *rfcomm_seq_next(struct seq_file *seq, void *e, loff_t *pos) if (p->next != &s->dlcs) return p->next; - for (p = s->list.next; p != &session_list; p = p->next) { + list_for_each(p, &session_list) { s = list_entry(p, struct rfcomm_session, list); __list_for_each(pp, &s->dlcs) { seq->private = s; diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 04dc0898ad1c..99aa7e32a695 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -39,7 +39,6 @@ #include <linux/poll.h> #include <linux/fcntl.h> #include <linux/init.h> -#include <linux/skbuff.h> #include <linux/interrupt.h> #include <linux/socket.h> #include <linux/skbuff.h> diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index b1ef7c76663d..f277bd75de7a 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -41,7 +41,6 @@ #include <linux/poll.h> #include <linux/fcntl.h> #include <linux/init.h> -#include <linux/skbuff.h> #include <linux/interrupt.h> #include <linux/socket.h> #include <linux/skbuff.h> diff --git a/net/bridge/br.c b/net/bridge/br.c index bf41aa2c61dd..3d90a9017bfc 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -32,8 +32,6 @@ int (*br_should_route_hook) (struct sk_buff **pskb) = NULL; static int __init br_init(void) { - printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n"); - #if defined(CONFIG_INET) && defined(CONFIG_NETFILTER) if (br_netfilter_init()) return 1; diff --git a/net/core/Makefile b/net/core/Makefile index 28ec942019e8..22e715cbdeb2 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -11,6 +11,5 @@ obj-y += flow.o dev.o ethtool.o net-sysfs.o dev_mcast.o dst.o \ obj-$(CONFIG_NETFILTER) += netfilter.o obj-$(CONFIG_NET_DIVERT) += dv.o -obj-$(CONFIG_NET_PROFILE) += profile.o obj-$(CONFIG_NET_PKTGEN) += pktgen.o obj-$(CONFIG_NET_RADIO) += wireless.o diff --git a/net/core/dev.c b/net/core/dev.c index fe8976f4e757..2cf887cee6d7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -99,7 +99,6 @@ #include <linux/divert.h> #include <net/dst.h> #include <net/pkt_sched.h> -#include <net/profile.h> #include <net/checksum.h> #include <linux/highmem.h> #include <linux/init.h> @@ -128,9 +127,6 @@ extern int plip_init(void); */ #undef OFFLINE_SAMPLE -NET_PROFILE_DEFINE(dev_queue_xmit) -NET_PROFILE_DEFINE(softnet_process) - /* * The list of packet types we will receive (as opposed to discard) * and the routines to invoke. @@ -2981,7 +2977,6 @@ int unregister_netdevice(struct net_device *dev) */ static int __init net_dev_init(void) { - struct net_device *dev, **dp; int i, rc = -ENOMEM; BUG_ON(!dev_boot_phase); @@ -3016,88 +3011,15 @@ static int __init net_dev_init(void) atomic_set(&queue->backlog_dev.refcnt, 1); } -#ifdef CONFIG_NET_PROFILE - net_profile_init(); - NET_PROFILE_REGISTER(dev_queue_xmit); - NET_PROFILE_REGISTER(softnet_process); -#endif - #ifdef OFFLINE_SAMPLE samp_timer.expires = jiffies + (10 * HZ); add_timer(&samp_timer); #endif - /* - * Add the devices. - * If the call to dev->init fails, the dev is removed - * from the chain disconnecting the device until the - * next reboot. - * - * NB At boot phase networking is dead. No locking is required. - * But we still preserve dev_base_lock for sanity. - */ - - dp = &dev_base; - while ((dev = *dp) != NULL) { - spin_lock_init(&dev->queue_lock); - spin_lock_init(&dev->xmit_lock); -#ifdef CONFIG_NET_FASTROUTE - dev->fastpath_lock = RW_LOCK_UNLOCKED; -#endif - dev->xmit_lock_owner = -1; - dev->iflink = -1; - dev_hold(dev); - - /* - * Allocate name. If the init() fails - * the name will be reissued correctly. - */ - if (strchr(dev->name, '%')) - dev_alloc_name(dev, dev->name); - - /* - * Check boot time settings for the device. - */ - netdev_boot_setup_check(dev); - - if ( (dev->init && dev->init(dev)) || - netdev_register_sysfs(dev) ) { - /* - * It failed to come up. It will be unhooked later. - * dev_alloc_name can now advance to next suitable - * name that is checked next. - */ - dp = &dev->next; - } else { - dp = &dev->next; - dev->ifindex = dev_new_index(); - dev->reg_state = NETREG_REGISTERED; - if (dev->iflink == -1) - dev->iflink = dev->ifindex; - if (!dev->rebuild_header) - dev->rebuild_header = default_rebuild_header; - dev_init_scheduler(dev); - set_bit(__LINK_STATE_PRESENT, &dev->state); - } - } - - /* - * Unhook devices that failed to come up - */ - dp = &dev_base; - while ((dev = *dp) != NULL) { - if (dev->reg_state != NETREG_REGISTERED) { - write_lock_bh(&dev_base_lock); - *dp = dev->next; - write_unlock_bh(&dev_base_lock); - dev_put(dev); - } else { - dp = &dev->next; - } - } - dev_boot_phase = 0; + probe_old_netdevs(); + open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL); open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL); diff --git a/net/core/dv.c b/net/core/dv.c index 62352d7c9bcc..e7de41f94f9c 100644 --- a/net/core/dv.c +++ b/net/core/dv.c @@ -40,7 +40,6 @@ const char sysctl_divert_version[32]="0.46"; /* Current version */ static int __init dv_init(void) { - printk(KERN_INFO "NET4: Frame Diverter %s\n", sysctl_divert_version); return 0; } module_init(dv_init); diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 958385890b79..ae21f8932e45 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -11,7 +11,6 @@ * */ -#include <linux/workqueue.h> #include <linux/config.h> #include <linux/netdevice.h> #include <linux/if.h> diff --git a/net/core/netfilter.c b/net/core/netfilter.c index ffb6a4471e85..07cbaf6b3c1e 100644 --- a/net/core/netfilter.c +++ b/net/core/netfilter.c @@ -101,7 +101,7 @@ int nf_register_sockopt(struct nf_sockopt_ops *reg) if (down_interruptible(&nf_sockopt_mutex) != 0) return -EINTR; - for (i = nf_sockopts.next; i != &nf_sockopts; i = i->next) { + list_for_each(i, &nf_sockopts) { struct nf_sockopt_ops *ops = (struct nf_sockopt_ops *)i; if (ops->pf == reg->pf && (overlap(ops->set_optmin, ops->set_optmax, @@ -296,7 +296,7 @@ static int nf_sockopt(struct sock *sk, int pf, int val, if (down_interruptible(&nf_sockopt_mutex) != 0) return -EINTR; - for (i = nf_sockopts.next; i != &nf_sockopts; i = i->next) { + list_for_each(i, &nf_sockopts) { ops = (struct nf_sockopt_ops *)i; if (ops->pf == pf) { if (get) { diff --git a/net/core/profile.c b/net/core/profile.c deleted file mode 100644 index 0caedda13842..000000000000 --- a/net/core/profile.c +++ /dev/null @@ -1,294 +0,0 @@ -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/jiffies.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/netdevice.h> -#include <linux/string.h> -#include <linux/skbuff.h> -#include <linux/proc_fs.h> -#include <linux/init.h> -#include <linux/ip.h> -#include <linux/inet.h> -#include <net/checksum.h> - -#include <asm/processor.h> -#include <asm/uaccess.h> -#include <asm/system.h> - -#include <net/profile.h> - -#ifdef CONFIG_NET_PROFILE - -atomic_t net_profile_active; -struct timeval net_profile_adjust; - -NET_PROFILE_DEFINE(total); - -struct net_profile_slot *net_profile_chain = &net_prof_total; - -#ifdef __alpha__ -__u32 alpha_lo; -long alpha_hi; - -static void alpha_tick(unsigned long); - -static struct timer_list alpha_timer = TIMER_INITIALIZER(alpha_tick, 0, 0); - -void alpha_tick(unsigned long dummy) -{ - struct timeval dummy_stamp; - net_profile_stamp(&dummy_stamp); - alpha_timer.expires = jiffies + 4*HZ; - add_timer(&alpha_timer); -} - -#endif - -void net_profile_irq_adjust(struct timeval *entered, struct timeval* leaved) -{ - struct net_profile_slot *s; - - net_profile_sub(entered, leaved); - for (s = net_profile_chain; s; s = s->next) { - if (s->active) - net_profile_add(leaved, &s->irq); - } -} - - -#ifdef CONFIG_PROC_FS -static int profile_read_proc(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) -{ - off_t pos=0; - off_t begin=0; - int len=0; - struct net_profile_slot *s; - - len+= sprintf(buffer, "Slot Hits Hi Lo OnIrqHi OnIrqLo Ufl\n"); - - if (offset == 0) { - cli(); - net_prof_total.active = 1; - atomic_inc(&net_profile_active); - NET_PROFILE_LEAVE(total); - sti(); - } - for (s = net_profile_chain; s; s = s->next) { - struct net_profile_slot tmp; - - cli(); - tmp = *s; - - /* Wrong, but pretty close to truth */ - - s->accumulator.tv_sec = 0; - s->accumulator.tv_usec = 0; - s->irq.tv_sec = 0; - s->irq.tv_usec = 0; - s->hits = 0; - s->underflow = 0; - /* Repair active count, it is possible, only if code has a bug */ - if (s->active) { - s->active = 0; - atomic_dec(&net_profile_active); - } - sti(); - - net_profile_sub(&tmp.irq, &tmp.accumulator); - - len += sprintf(buffer+len,"%-15s %-10d %-10ld %-10lu %-10lu %-10lu %d/%d", - tmp.id, - tmp.hits, - tmp.accumulator.tv_sec, - tmp.accumulator.tv_usec, - tmp.irq.tv_sec, - tmp.irq.tv_usec, - tmp.underflow, tmp.active); - - buffer[len++]='\n'; - - pos=begin+len; - if(pos<offset) { - len=0; - begin=pos; - } - if(pos>offset+length) - goto done; - } - *eof = 1; - -done: - *start=buffer+(offset-begin); - len-=(offset-begin); - if(len>length) - len=length; - if (len < 0) - len = 0; - if (offset == 0) { - cli(); - net_prof_total.active = 0; - net_prof_total.hits = 0; - net_profile_stamp(&net_prof_total.entered); - sti(); - } - return len; -} -#endif - -struct iphdr whitehole_iph; -int whitehole_count; - -static int whitehole_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct net_device_stats *stats; - - stats = (struct net_device_stats *)dev->priv; - stats->tx_packets++; - stats->tx_bytes+=skb->len; - - dev_kfree_skb(skb); - return 0; -} - -static void whitehole_inject(unsigned long); -int whitehole_init(struct net_device *dev); - -static struct timer_list whitehole_timer = - TIMER_INITIALIZER(whitehole_inject, 0, 0); - -static struct net_device whitehole_dev = { - .name = "whitehole", - .init = whitehole_init, -}; - -static int whitehole_open(struct net_device *dev) -{ - whitehole_count = 100000; - whitehole_timer.expires = jiffies + 5*HZ; - add_timer(&whitehole_timer); - return 0; -} - -static int whitehole_close(struct net_device *dev) -{ - del_timer(&whitehole_timer); - return 0; -} - -static void whitehole_inject(unsigned long dummy) -{ - struct net_device_stats *stats = (struct net_device_stats *)whitehole_dev.priv; - extern int netdev_dropping; - - do { - struct iphdr *iph; - struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC); - if (!skb) - break; - skb_reserve(skb, 32); - iph = (struct iphdr*)skb_put(skb, sizeof(*iph)); - skb->mac.raw = ((u8*)iph) - 14; - memcpy(iph, &whitehole_iph, sizeof(*iph)); - skb->protocol = __constant_htons(ETH_P_IP); - skb->dev = &whitehole_dev; - skb->pkt_type = PACKET_HOST; - stats->rx_packets++; - stats->rx_bytes += skb->len; - netif_rx(skb); - whitehole_count--; - } while (netdev_dropping == 0 && whitehole_count>0); - if (whitehole_count > 0) { - whitehole_timer.expires = jiffies + 1; - add_timer(&whitehole_timer); - } -} - -static struct net_device_stats *whitehole_get_stats(struct net_device *dev) -{ - struct net_device_stats *stats = (struct net_device_stats *) dev->priv; - return stats; -} - -int __init whitehole_init(struct net_device *dev) -{ - dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOBUFS; - memset(dev->priv, 0, sizeof(struct net_device_stats)); - dev->get_stats = whitehole_get_stats; - dev->hard_start_xmit = whitehole_xmit; - dev->open = whitehole_open; - dev->stop = whitehole_close; - ether_setup(dev); - dev->tx_queue_len = 0; - dev->flags |= IFF_NOARP; - dev->flags &= ~(IFF_BROADCAST|IFF_MULTICAST); - dev->iflink = 0; - whitehole_iph.ihl = 5; - whitehole_iph.version = 4; - whitehole_iph.ttl = 2; - whitehole_iph.saddr = in_aton("193.233.7.21"); - whitehole_iph.daddr = in_aton("193.233.7.10"); - whitehole_iph.tot_len = htons(20); - whitehole_iph.check = ip_compute_csum((void *)&whitehole_iph, 20); - return 0; -} - -int net_profile_register(struct net_profile_slot *slot) -{ - cli(); - slot->next = net_profile_chain; - net_profile_chain = slot; - sti(); - return 0; -} - -int net_profile_unregister(struct net_profile_slot *slot) -{ - struct net_profile_slot **sp, *s; - - for (sp = &net_profile_chain; (s = *sp) != NULL; sp = &s->next) { - if (s == slot) { - cli(); - *sp = s->next; - sti(); - return 0; - } - } - return -ESRCH; -} - - -int __init net_profile_init(void) -{ - int i; - -#ifdef CONFIG_PROC_FS - create_proc_read_entry("net/profile", 0, 0, profile_read_proc, NULL); -#endif - - register_netdevice(&whitehole_dev); - - printk("Evaluating net profiler cost ..."); -#ifdef __alpha__ - alpha_tick(0); -#endif - for (i=0; i<1024; i++) { - NET_PROFILE_ENTER(total); - NET_PROFILE_LEAVE(total); - } - if (net_prof_total.accumulator.tv_sec) { - printk(" too high!\n"); - } else { - net_profile_adjust.tv_usec = net_prof_total.accumulator.tv_usec>>10; - printk("%ld units\n", net_profile_adjust.tv_usec); - } - net_prof_total.hits = 0; - net_profile_stamp(&net_prof_total.entered); - return 0; -} - -#endif diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 4215e4a7dcd0..444f07e51e27 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -559,9 +559,6 @@ struct notifier_block rtnetlink_dev_notifier = { void __init rtnetlink_init(void) { -#ifdef RTNL_DEBUG - printk("Initializing RT netlink socket\n"); -#endif rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv); if (rtnl == NULL) panic("rtnetlink_init: cannot initialize rtnetlink\n"); diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 52a0c5f688ff..918505be8ea7 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -35,7 +35,6 @@ #include <linux/string.h> #include <linux/if_arp.h> #include <linux/if_ether.h> -#include <linux/init.h> #include <linux/skbuff.h> #include <linux/rtnetlink.h> #include <linux/sysctl.h> diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 8a5dbadd51f3..3879dca72b92 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1097,8 +1097,6 @@ static int __init inet_init(void) struct inet_protosw *q; struct list_head *r; - printk(KERN_INFO "NET4: Linux TCP/IP 1.0 for NET4.0\n"); - if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "%s: panic\n", __FUNCTION__); return -EINVAL; diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index c9f456eaa745..715919c77234 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -230,12 +230,18 @@ static struct icmp_control icmp_pointers[NR_ICMP_TYPES+1]; static DEFINE_PER_CPU(struct socket *, __icmp_socket) = NULL; #define icmp_socket __get_cpu_var(__icmp_socket) -static __inline__ void icmp_xmit_lock(void) +static __inline__ int icmp_xmit_lock(void) { local_bh_disable(); - if (unlikely(!spin_trylock(&icmp_socket->sk->sk_lock.slock))) - BUG(); + if (unlikely(!spin_trylock(&icmp_socket->sk->sk_lock.slock))) { + /* This can happen if the output path signals a + * dst_link_failure() for an outgoing ICMP packet. + */ + local_bh_enable(); + return 1; + } + return 0; } static void icmp_xmit_unlock(void) @@ -376,7 +382,8 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) if (ip_options_echo(&icmp_param->replyopts, skb)) goto out; - icmp_xmit_lock(); + if (icmp_xmit_lock()) + return; icmp_param->data.icmph.checksum = 0; icmp_out_count(icmp_param->data.icmph.type); @@ -488,7 +495,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info) } } - icmp_xmit_lock(); + if (icmp_xmit_lock()) + return; /* * Construct source address and options. diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 3f671efed9e6..9f5a0485e0a7 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1744,7 +1744,6 @@ static struct inet_protocol pim_protocol = { void __init ip_mr_init(void) { - printk(KERN_INFO "Linux IP multicast router 0.06 plus PIM-SM\n"); mrt_cachep = kmem_cache_create("ip_mrt_cache", sizeof(struct mfc_cache), 0, SLAB_HWCACHE_ALIGN, diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index ac3aafd9aa82..166e3be72987 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c @@ -31,7 +31,6 @@ #include <linux/proc_fs.h> #include <linux/timer.h> #include <linux/swap.h> -#include <linux/proc_fs.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index d6e5f3bcb7f4..6dc8fd2a065b 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -150,8 +150,7 @@ list_conntracks(char *buffer, char **start, off_t offset, int length) } /* Now iterate through expecteds. */ - for (e = ip_conntrack_expect_list.next; - e != &ip_conntrack_expect_list; e = e->next) { + list_for_each(e, &ip_conntrack_expect_list) { unsigned int last_len; struct ip_conntrack_expect *expect = (struct ip_conntrack_expect *)e; @@ -319,7 +318,7 @@ int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto) struct list_head *i; WRITE_LOCK(&ip_conntrack_lock); - for (i = protocol_list.next; i != &protocol_list; i = i->next) { + list_for_each(i, &protocol_list) { if (((struct ip_conntrack_protocol *)i)->proto == proto->proto) { ret = -EBUSY; diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index a9f726b10a46..249c8e66f5aa 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -157,8 +157,8 @@ in_range(const struct ip_conntrack_tuple *tuple, continue; } - if ((mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED) - && proto->in_range(&newtuple, IP_NAT_MANIP_SRC, + if (!(mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED) + || proto->in_range(&newtuple, IP_NAT_MANIP_SRC, &mr->range[i].min, &mr->range[i].max)) return 1; } diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c index 75df6c8222bb..0e3028dcb176 100644 --- a/net/ipv4/netfilter/ip_nat_snmp_basic.c +++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c @@ -50,7 +50,6 @@ #include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv4/ip_nat.h> #include <linux/netfilter_ipv4/ip_nat_helper.h> -#include <linux/types.h> #include <linux/ip.h> #include <net/udp.h> #include <asm/uaccess.h> diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 825ae9ffef36..bd014b74571f 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -271,7 +271,7 @@ int ip_nat_protocol_register(struct ip_nat_protocol *proto) struct list_head *i; WRITE_LOCK(&ip_nat_lock); - for (i = protos.next; i != &protos; i = i->next) { + list_for_each(i, &protos) { if (((struct ip_nat_protocol *)i)->protonum == proto->protonum) { ret = -EBUSY; diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index b5bfc900281b..272dab8ded25 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -141,7 +141,7 @@ static void send_reset(struct sk_buff *oldskb, int local) nskb->nf_debug = 0; #endif nskb->nfmark = 0; -#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) +#ifdef CONFIG_BRIDGE_NETFILTER nf_bridge_put(nskb->nf_bridge); nskb->nf_bridge = NULL; #endif diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 6374bdd52780..1398b8590dba 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -45,7 +45,6 @@ #include <linux/netlink.h> #include <linux/netdevice.h> #include <linux/mm.h> -#include <linux/socket.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_ULOG.h> #include <linux/netfilter_ipv4/lockhelp.h> diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 08c3a40a4bd2..1746eae040b3 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1349,64 +1349,65 @@ struct proto udp_prot = { /* ------------------------------------------------------------------------ */ #ifdef CONFIG_PROC_FS -static __inline__ struct sock *udp_get_bucket(struct seq_file *seq, loff_t *pos) +static struct sock *udp_get_first(struct seq_file *seq) { - int i; struct sock *sk; - struct hlist_node *node; - loff_t l = *pos; struct udp_iter_state *state = seq->private; - for (; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { - i = 0; + for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { + struct hlist_node *node; sk_for_each(sk, node, &udp_hash[state->bucket]) { - if (sk->sk_family != state->family) { - ++i; - continue; - } - if (l--) { - ++i; - continue; - } - *pos = i; - goto out; + if (sk->sk_family == state->family) + goto found; } } sk = NULL; -out: +found: return sk; } +static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk) +{ + struct udp_iter_state *state = seq->private; + + do { + sk = sk_next(sk); +try_again: + ; + } while (sk && sk->sk_family != state->family); + + if (!sk && ++state->bucket < UDP_HTABLE_SIZE) { + sk = sk_head(&udp_hash[state->bucket]); + goto try_again; + } + return sk; +} + +static struct sock *udp_get_idx(struct seq_file *seq, loff_t pos) +{ + struct sock *sk = udp_get_first(seq); + + if (sk) + while(pos && (sk = udp_get_next(seq, sk)) != NULL) + --pos; + return pos ? NULL : sk; +} + static void *udp_seq_start(struct seq_file *seq, loff_t *pos) { read_lock(&udp_hash_lock); - return *pos ? udp_get_bucket(seq, pos) : (void *)1; + return *pos ? udp_get_idx(seq, *pos-1) : (void *)1; } static void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct sock *sk; - struct hlist_node *node; - struct udp_iter_state *state; - - if (v == (void *)1) { - sk = udp_get_bucket(seq, pos); - goto out; - } - - state = seq->private; - - sk = v; - sk_for_each_continue(sk, node) - if (sk->sk_family == state->family) - goto out; - if (++state->bucket >= UDP_HTABLE_SIZE) - goto out; + if (v == (void *)1) + sk = udp_get_idx(seq, 0); + else + sk = udp_get_next(seq, v); - *pos = 0; - sk = udp_get_bucket(seq, pos); -out: ++*pos; return sk; } diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index c6246d0fc1d6..150089e25d2c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -57,7 +57,6 @@ #include <linux/delay.h> #include <linux/notifier.h> -#include <linux/proc_fs.h> #include <net/sock.h> #include <net/snmp.h> diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 6289170cb341..df60b4030a44 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -40,7 +40,6 @@ #include <linux/proc_fs.h> #include <linux/stat.h> #include <linux/init.h> -#include <linux/version.h> #include <linux/inet.h> #include <linux/netdevice.h> @@ -724,8 +723,6 @@ static int __init inet6_init(void) #endif #endif - printk(KERN_INFO "IPv6 v0.8 for NET4.0\n"); - if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "inet6_proto_init: size fault\n"); diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 358b3f3f3d18..a97c931c5549 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -28,7 +28,6 @@ #include <linux/module.h> #include <net/inet_ecn.h> #include <net/ip.h> -#include <net/xfrm.h> #include <net/ah.h> #include <linux/crypto.h> #include <linux/pfkeyv2.h> diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 083155a233a6..8c9091ede27d 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1940,10 +1940,6 @@ extern void destroy_8023_client(struct datalink_proto *); static unsigned char ipx_8022_type = 0xE0; static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; -static char ipx_banner[] __initdata = - KERN_INFO "NET4: Linux IPX 0.51 for NET4.0\n" - KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n" \ - KERN_INFO "IPX Portions Copyright (c) 2000-2003 Conectiva, Inc.\n"; static char ipx_EII_err_msg[] __initdata = KERN_CRIT "IPX: Unable to register with Ethernet II\n"; static char ipx_8023_err_msg[] __initdata = @@ -1980,7 +1976,6 @@ static int __init ipx_init(void) register_netdevice_notifier(&ipx_dev_notifier); ipx_register_sysctl(); ipx_proc_init(); - printk(ipx_banner); return 0; } diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c index fbb552adc243..fc71309e7e9b 100644 --- a/net/lapb/lapb_iface.c +++ b/net/lapb/lapb_iface.c @@ -435,11 +435,8 @@ EXPORT_SYMBOL(lapb_disconnect_request); EXPORT_SYMBOL(lapb_data_request); EXPORT_SYMBOL(lapb_data_received); -static char banner[] __initdata = KERN_INFO "NET4: LAPB for Linux. Version 0.01 for NET4.0\n"; - static int __init lapb_init(void) { - printk(banner); return 0; } diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 5b011b872d94..ff2710542e4b 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -1042,15 +1042,10 @@ static struct proto_ops llc_ui_ops = { .sendpage = sock_no_sendpage, }; -static char llc_ui_banner[] __initdata = - KERN_INFO "NET4.0 IEEE 802.2 BSD sockets, Jay Schulist, 2001, " - "Arnaldo C. Melo, 2002-2003\n"; - int __init llc_ui_init(void) { llc_ui_sap_last_autoport = LLC_SAP_DYN_START; sock_register(&llc_ui_family_ops); - printk(llc_ui_banner); return 0; } diff --git a/net/llc/llc_main.c b/net/llc/llc_main.c index 3ee7b0aa16ae..8f2fc4d7ec71 100644 --- a/net/llc/llc_main.c +++ b/net/llc/llc_main.c @@ -603,5 +603,5 @@ module_exit(llc_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Procom, 1997, Arnaldo C. Melo, Jay Schullist, 2001-2003"); -MODULE_DESCRIPTION("LLC 2.0, NET4.0 IEEE 802.2 extended support"); +MODULE_DESCRIPTION("LLC 2.0, IEEE 802.2 extended support"); MODULE_ALIAS_NETPROTO(PF_LLC); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index e23847781517..3347859a1665 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -40,6 +40,7 @@ #include <linux/netdevice.h> #include <linux/rtnetlink.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/smp_lock.h> #include <linux/notifier.h> #include <linux/security.h> @@ -964,62 +965,108 @@ int netlink_post(int unit, struct sk_buff *skb) #endif - #ifdef CONFIG_PROC_FS -static int netlink_read_proc(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) +static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos) { - off_t pos=0; - off_t begin=0; - int len=0; - int i; + long i; struct sock *s; struct hlist_node *node; - - len+= sprintf(buffer,"sk Eth Pid Groups " - "Rmem Wmem Dump Locks\n"); - + loff_t off = 0; + for (i=0; i<MAX_LINKS; i++) { - read_lock(&nl_table_lock); sk_for_each(s, node, &nl_table[i]) { - struct netlink_opt *nlk = nlk_sk(s); - - len+=sprintf(buffer+len,"%p %-3d %-6d %08x %-8d %-8d %p %d", - s, - s->sk_protocol, - nlk->pid, - nlk->groups, - atomic_read(&s->sk_rmem_alloc), - atomic_read(&s->sk_wmem_alloc), - nlk->cb, - atomic_read(&s->sk_refcnt) - ); - - buffer[len++]='\n'; - - pos=begin+len; - if(pos<offset) { - len=0; - begin=pos; + if (off == pos) { + seq->private = (void *) i; + return s; } - if(pos>offset+length) { - read_unlock(&nl_table_lock); - goto done; + ++off; + } + } + return NULL; +} + +static void *netlink_seq_start(struct seq_file *seq, loff_t *pos) +{ + read_lock(&nl_table_lock); + return *pos ? netlink_seq_socket_idx(seq, *pos - 1) : (void *) 1; +} + +static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct sock *s; + + ++*pos; + + if (v == (void *) 1) + return netlink_seq_socket_idx(seq, 0); + + s = sk_next(v); + if (!s) { + long i = (long)seq->private; + + while (++i < MAX_LINKS) { + s = sk_head(&nl_table[i]); + if (s) { + seq->private = (void *) i; + break; } } - read_unlock(&nl_table_lock); } - *eof = 1; - -done: - *start=buffer+(offset-begin); - len-=(offset-begin); - if(len>length) - len=length; - if(len<0) - len=0; - return len; + return s; } + +static void netlink_seq_stop(struct seq_file *seq, void *v) +{ + read_unlock(&nl_table_lock); +} + + +static int netlink_seq_show(struct seq_file *seq, void *v) +{ + if (v == (void *)1) + seq_puts(seq, + "sk Eth Pid Groups " + "Rmem Wmem Dump Locks\n"); + else { + struct sock *s = v; + struct netlink_opt *nlk = nlk_sk(s); + + seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %d\n", + s, + s->sk_protocol, + nlk->pid, + nlk->groups, + atomic_read(&s->sk_rmem_alloc), + atomic_read(&s->sk_wmem_alloc), + nlk->cb, + atomic_read(&s->sk_refcnt) + ); + + } + return 0; +} + +struct seq_operations netlink_seq_ops = { + .start = netlink_seq_start, + .next = netlink_seq_next, + .stop = netlink_seq_stop, + .show = netlink_seq_show, +}; + + +static int netlink_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &netlink_seq_ops); +} + +static struct file_operations netlink_seq_fops = { + .owner = THIS_MODULE, + .open = netlink_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + #endif int netlink_register_notifier(struct notifier_block *nb) @@ -1069,7 +1116,7 @@ static int __init netlink_proto_init(void) } sock_register(&netlink_family_ops); #ifdef CONFIG_PROC_FS - create_proc_read_entry("net/netlink", 0, 0, netlink_read_proc, NULL); + proc_net_fops_create("netlink", 0, &netlink_seq_fops); #endif /* The netlink device handler may be needed early. */ rtnetlink_init(); @@ -1079,7 +1126,7 @@ static int __init netlink_proto_init(void) static void __exit netlink_proto_exit(void) { sock_unregister(PF_NETLINK); - remove_proc_entry("net/netlink", NULL); + proc_net_remove("netlink"); } core_initcall(netlink_proto_init); diff --git a/net/rxrpc/sysctl.c b/net/rxrpc/sysctl.c index ada78e6532ba..08df88fcd643 100644 --- a/net/rxrpc/sysctl.c +++ b/net/rxrpc/sysctl.c @@ -14,7 +14,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/sysctl.h> -#include <linux/config.h> #include <rxrpc/types.h> #include <rxrpc/rxrpc.h> #include <asm/errno.h> diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 849b7a589ac0..c1323ddd5576 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 La Monte H.P. Yarroll * @@ -42,6 +42,7 @@ * Sridhar Samudrala <sri@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com> * Ryan Layer <rmlayer@us.ibm.com> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -1155,3 +1156,23 @@ int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *asoc, return sctp_raw_to_bind_addrs(&asoc->base.bind_addr, raw, var_size3, asoc->ep->base.bind_addr.port, gfp); } + +/* Lookup laddr in the bind address list of an association. */ +int sctp_assoc_lookup_laddr(struct sctp_association *asoc, + const union sctp_addr *laddr) +{ + int found; + + sctp_read_lock(&asoc->base.addr_lock); + if ((asoc->base.bind_addr.port == ntohs(laddr->v4.sin_port)) && + sctp_bind_addr_match(&asoc->base.bind_addr, laddr, + sctp_sk(asoc->base.sk))) { + found = 1; + goto out; + } + + found = 0; +out: + sctp_read_unlock(&asoc->base.addr_lock); + return found; +} diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 58d6a3bb7c3e..c2a288bcca39 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) Cisco 1999,2000 * Copyright (c) Motorola 1999,2000,2001 - * Copyright (c) International Business Machines Corp., 2001,2002 * Copyright (c) La Monte H.P. Yarroll 2001 * * This file is part of the SCTP kernel reference implementation. @@ -223,6 +223,8 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, int len; struct sctp_sockaddr_entry *addr; struct list_head *pos; + struct sctp_af *af; + addrparms_len = 0; len = 0; @@ -247,7 +249,8 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - len = sockaddr2sctp_addr(&addr->a, &rawaddr); + af = sctp_get_af_specific(addr->a.v4.sin_family); + len = af->to_addr_param(&addr->a, &rawaddr); memcpy(addrparms.v, &rawaddr, len); addrparms.v += len; addrparms_len += len; @@ -270,34 +273,31 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, union sctp_addr addr; int retval = 0; int len; + struct sctp_af *af; /* Convert the raw address to standard address format */ while (addrs_len) { param = (struct sctp_paramhdr *)raw_addr_list; rawaddr = (union sctp_addr_param *)raw_addr_list; - switch (param->type) { - case SCTP_PARAM_IPV4_ADDRESS: - case SCTP_PARAM_IPV6_ADDRESS: - sctp_param2sockaddr(&addr, rawaddr, port, 0); - retval = sctp_add_bind_addr(bp, &addr, gfp); - if (retval) { - /* Can't finish building the list, clean up. */ - sctp_bind_addr_clean(bp); - break;; - } - len = ntohs(param->length); - addrs_len -= len; - raw_addr_list += len; - break; - default: - /* Corrupted raw addr list! */ + af = sctp_get_af_specific(param_type2af(param->type)); + if (unlikely(!af)) { retval = -EINVAL; sctp_bind_addr_clean(bp); break; } - if (retval) - break; + + af->from_addr_param(&addr, rawaddr, port, 0); + retval = sctp_add_bind_addr(bp, &addr, gfp); + if (retval) { + /* Can't finish building the list, clean up. */ + sctp_bind_addr_clean(bp); + break;; + } + + len = ntohs(param->length); + addrs_len -= len; + raw_addr_list += len; } return retval; diff --git a/net/sctp/input.c b/net/sctp/input.c index 2c62c2171f6a..cc3e9314dd91 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -768,6 +768,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, union sctp_params params; sctp_init_chunk_t *init; struct sctp_transport *transport; + struct sctp_af *af; ch = (sctp_chunkhdr_t *) skb->data; @@ -802,11 +803,12 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, sctp_walk_params(params, init, init_hdr.params) { /* Note: Ignoring hostname addresses. */ - if ((SCTP_PARAM_IPV4_ADDRESS != params.p->type) && - (SCTP_PARAM_IPV6_ADDRESS != params.p->type)) + af = sctp_get_af_specific(param_type2af(params.p->type)); + if (!af) continue; - sctp_param2sockaddr(paddr, params.addr, ntohs(sh->source), 0); + af->from_addr_param(paddr, params.addr, ntohs(sh->source), 0); + asoc = __sctp_lookup_association(laddr, paddr, &transport); if (asoc) return asoc; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 3bce456b895f..32ec1d5176ff 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -399,6 +399,33 @@ static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) } } +/* Initialize a sctp_addr from an address parameter. */ +static void sctp_v6_from_addr_param(union sctp_addr *addr, + union sctp_addr_param *param, + __u16 port, int iif) +{ + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_port = port; + addr->v6.sin6_flowinfo = 0; /* BUG */ + ipv6_addr_copy(&addr->v6.sin6_addr, ¶m->v6.addr); + addr->v6.sin6_scope_id = iif; +} + +/* Initialize an address parameter from a sctp_addr and return the length + * of the address parameter. + */ +static int sctp_v6_to_addr_param(const union sctp_addr *addr, + union sctp_addr_param *param) +{ + int length = sizeof(sctp_ipv6addr_param_t); + + param->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS; + param->v6.param_hdr.length = ntohs(length); + ipv6_addr_copy(¶m->v6.addr, &addr->v6.sin6_addr); + + return length; +} + /* Initialize a sctp_addr from a dst_entry. */ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst, unsigned short port) @@ -903,6 +930,8 @@ static struct sctp_af sctp_ipv6_specific = { .from_sk = sctp_v6_from_sk, .to_sk_saddr = sctp_v6_to_sk_saddr, .to_sk_daddr = sctp_v6_to_sk_daddr, + .from_addr_param = sctp_v6_from_addr_param, + .to_addr_param = sctp_v6_to_addr_param, .dst_saddr = sctp_v6_dst_saddr, .cmp_addr = sctp_v6_cmp_addr, .scope = sctp_v6_scope, diff --git a/net/sctp/primitive.c b/net/sctp/primitive.c index 243b1d5a8657..3a7ebfcc1fdb 100644 --- a/net/sctp/primitive.c +++ b/net/sctp/primitive.c @@ -39,6 +39,7 @@ * Narasimha Budihal <narasimha@refcode.org> * Karl Knutson <karl@athena.chicago.il.us> * Ardelle Fan <ardelle.fan@intel.com> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -203,3 +204,16 @@ DECLARE_PRIMITIVE(SEND); */ DECLARE_PRIMITIVE(REQUESTHEARTBEAT); + +/* ADDIP +* 3.1.1 Address Configuration Change Chunk (ASCONF) +* +* This chunk is used to communicate to the remote endpoint one of the +* configuration change requests that MUST be acknowledged. The +* information carried in the ASCONF Chunk uses the form of a +* Type-Length-Value (TLV), as described in "3.2.1 Optional/ +* Variable-length Parameter Format" in RFC2960 [5], forall variable +* parameters. +*/ + +DECLARE_PRIMITIVE(ASCONF); diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 727f237b1475..986460afaa6b 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -295,6 +295,31 @@ static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk) inet_sk(sk)->daddr = addr->v4.sin_addr.s_addr; } +/* Initialize a sctp_addr from an address parameter. */ +static void sctp_v4_from_addr_param(union sctp_addr *addr, + union sctp_addr_param *param, + __u16 port, int iif) +{ + addr->v4.sin_family = AF_INET; + addr->v4.sin_port = port; + addr->v4.sin_addr.s_addr = param->v4.addr.s_addr; +} + +/* Initialize an address parameter from a sctp_addr and return the length + * of the address parameter. + */ +static int sctp_v4_to_addr_param(const union sctp_addr *addr, + union sctp_addr_param *param) +{ + int length = sizeof(sctp_ipv4addr_param_t); + + param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS; + param->v4.param_hdr.length = ntohs(length); + param->v4.addr.s_addr = addr->v4.sin_addr.s_addr; + + return length; +} + /* Initialize a sctp_addr from a dst_entry. */ static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst, unsigned short port) @@ -862,6 +887,8 @@ struct sctp_af sctp_ipv4_specific = { .from_sk = sctp_v4_from_sk, .to_sk_saddr = sctp_v4_to_sk_saddr, .to_sk_daddr = sctp_v4_to_sk_daddr, + .from_addr_param= sctp_v4_from_addr_param, + .to_addr_param = sctp_v4_to_addr_param, .dst_saddr = sctp_v4_dst_saddr, .cmp_addr = sctp_v4_cmp_addr, .addr_valid = sctp_v4_addr_valid, diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index bf3f373d9feb..40a7a4f7116f 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1,8 +1,8 @@ /* SCTP kernel reference Implementation + * Copyright (C) IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001-2002 Intel Corp. - * Copyright (c) 2001-2002 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -48,6 +48,7 @@ * Sridhar Samudrala <sri@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com> * Ardelle Fan <ardelle.fan@intel.com> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -1213,6 +1214,7 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, struct sctp_association *asoc; struct sk_buff *skb; sctp_scope_t scope; + struct sctp_af *af; /* Create the bare association. */ scope = sctp_scope(sctp_source(chunk)); @@ -1222,29 +1224,10 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, asoc->temp = 1; skb = chunk->skb; /* Create an entry for the source address of the packet. */ - /* FIXME: Use the af specific helpers. */ - switch (skb->nh.iph->version) { - case 4: - asoc->c.peer_addr.v4.sin_family = AF_INET; - asoc->c.peer_addr.v4.sin_port = ntohs(chunk->sctp_hdr->source); - asoc->c.peer_addr.v4.sin_addr.s_addr = skb->nh.iph->saddr; - break; - - case 6: - asoc->c.peer_addr.v6.sin6_family = AF_INET6; - asoc->c.peer_addr.v6.sin6_port - = ntohs(chunk->sctp_hdr->source); - asoc->c.peer_addr.v6.sin6_flowinfo = 0; /* BUG BUG BUG */ - asoc->c.peer_addr.v6.sin6_addr = skb->nh.ipv6h->saddr; - asoc->c.peer_addr.v6.sin6_scope_id = - ((struct inet6_skb_parm *)skb->cb)->iif; - break; - - default: - /* Yikes! I never heard of this kind of address. */ + af = sctp_get_af_specific(ipver2af(skb->nh.iph->version)); + if (unlikely(!af)) goto fail; - }; - + af->from_skb(&asoc->c.peer_addr, skb, 1); nodata: return asoc; @@ -1830,11 +1813,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, * stream sequence number shall be set to 0. */ - /* Allocate storage for the negotiated streams. */ - asoc->ssnmap = sctp_ssnmap_new(asoc->peer.i.num_outbound_streams, - asoc->c.sinit_num_ostreams, gfp); - if (!asoc->ssnmap) - goto nomem_ssnmap; + /* Allocate storage for the negotiated streams if it is not a temporary * association. + */ + if (!asoc->temp) { + asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams, + asoc->c.sinit_num_ostreams, gfp); + if (!asoc->ssnmap) + goto nomem_ssnmap; + } /* ADDIP Section 4.1 ASCONF Chunk Procedures * @@ -1882,6 +1868,7 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param, int retval = 1; sctp_scope_t scope; time_t stale; + struct sctp_af *af; /* We maintain all INIT parameters in network byte order all the * time. This allows us to not worry about whether the parameters @@ -1893,7 +1880,8 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param, break; /* Fall through. */ case SCTP_PARAM_IPV4_ADDRESS: - sctp_param2sockaddr(&addr, param.addr, asoc->peer.port, 0); + af = sctp_get_af_specific(param_type2af(param.p->type)); + af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); scope = sctp_scope(peer_addr); if (sctp_in_scope(&addr, scope)) if (!sctp_assoc_add_peer(asoc, &addr, gfp)) @@ -2005,90 +1993,6 @@ __u32 sctp_generate_tsn(const struct sctp_endpoint *ep) return retval; } -/******************************************************************** - * 4th Level Abstractions - ********************************************************************/ - -/* Convert from an SCTP IP parameter to a union sctp_addr. */ -void sctp_param2sockaddr(union sctp_addr *addr, union sctp_addr_param *param, - __u16 port, int iif) -{ - switch(param->v4.param_hdr.type) { - case SCTP_PARAM_IPV4_ADDRESS: - addr->v4.sin_family = AF_INET; - addr->v4.sin_port = port; - addr->v4.sin_addr.s_addr = param->v4.addr.s_addr; - break; - - case SCTP_PARAM_IPV6_ADDRESS: - addr->v6.sin6_family = AF_INET6; - addr->v6.sin6_port = port; - addr->v6.sin6_flowinfo = 0; /* BUG */ - addr->v6.sin6_addr = param->v6.addr; - addr->v6.sin6_scope_id = iif; - break; - - default: - SCTP_DEBUG_PRINTK("Illegal address type %d\n", - ntohs(param->v4.param_hdr.type)); - break; - }; -} - -/* Convert an IP address in an SCTP param into a sockaddr_in. */ -/* Returns true if a valid conversion was possible. */ -int sctp_addr2sockaddr(union sctp_params p, union sctp_addr *sa) -{ - switch (p.p->type) { - case SCTP_PARAM_IPV4_ADDRESS: - sa->v4.sin_addr = *((struct in_addr *)&p.v4->addr); - sa->v4.sin_family = AF_INET; - break; - - case SCTP_PARAM_IPV6_ADDRESS: - *((struct in6_addr *)&sa->v4.sin_addr) - = p.v6->addr; - sa->v4.sin_family = AF_INET6; - break; - - default: - return 0; - }; - - return 1; -} - -/* Convert a sockaddr_in to an IP address in an SCTP param. - * Returns len if a valid conversion was possible. - */ -int sockaddr2sctp_addr(const union sctp_addr *sa, union sctp_addr_param *p) -{ - int len = 0; - - switch (sa->v4.sin_family) { - case AF_INET: - p->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS; - p->v4.param_hdr.length = ntohs(sizeof(sctp_ipv4addr_param_t)); - len = sizeof(sctp_ipv4addr_param_t); - p->v4.addr.s_addr = sa->v4.sin_addr.s_addr; - break; - - case AF_INET6: - p->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS; - p->v6.param_hdr.length = ntohs(sizeof(sctp_ipv6addr_param_t)); - len = sizeof(sctp_ipv6addr_param_t); - p->v6.addr = *(&sa->v6.sin6_addr); - break; - - default: - printk(KERN_WARNING "sockaddr2sctp_addr: Illegal family %d.\n", - sa->v4.sin_family); - return 0; - }; - - return len; -} - /* * ADDIP 3.1.1 Address Configuration Change Chunk (ASCONF) * 0 1 2 3 @@ -2119,8 +2023,9 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc, int length = sizeof(asconf) + vparam_len; union sctp_params addrparam; int addrlen; + struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family); - addrlen = sockaddr2sctp_addr(addr, (union sctp_addr_param *)&addrparam); + addrlen = af->to_addr_param(addr, (union sctp_addr_param *)&addrparam); if (!addrlen) return NULL; length += addrlen; @@ -2135,7 +2040,51 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc, retval->subh.addip_hdr = sctp_addto_chunk(retval, sizeof(asconf), &asconf); retval->param_hdr.v = - sctp_addto_chunk(retval, addrlen, &addr); + sctp_addto_chunk(retval, addrlen, &addrparam); + + return retval; +} + +/* ADDIP + * 3.2.4 Set Primary IP Address + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type =0xC004 | Length = Variable | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ASCONF-Request Correlation ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Address Parameter | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Create an ASCONF chunk with Set Primary IP address parameter. + */ +struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, + union sctp_addr *addr) +{ + sctp_addip_param_t param; + struct sctp_chunk *retval; + int len = sizeof(param); + union sctp_params addrparam; + int addrlen; + struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family); + + addrlen = af->to_addr_param(addr, (union sctp_addr_param *)&addrparam); + if (!addrlen) + return NULL; + len += addrlen; + + /* Create the chunk and make asconf header. */ + retval = sctp_make_asconf(asoc, addr, len); + if (!retval) + return NULL; + + param.param_hdr.type = SCTP_PARAM_SET_PRIMARY; + param.param_hdr.length = htons(len); + param.crr_id = 0; + + sctp_addto_chunk(retval, sizeof(param), ¶m); + sctp_addto_chunk(retval, addrlen, &addrparam); return retval; } diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 531ff1606429..86208c51ba36 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -929,6 +929,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa, struct sctp_errhdr *errhdr; struct sctp_endpoint *ep; char buffer[sizeof(struct sctp_errhdr)+sizeof(union sctp_addr_param)]; + struct sctp_af *af = sctp_get_af_specific(ssa->v4.sin_family); /* Build the error on the stack. We are way to malloc crazy * throughout the code today. @@ -937,7 +938,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa, addrparm = (union sctp_addr_param *)errhdr->variable; /* Copy into a parm format. */ - len = sockaddr2sctp_addr(ssa, addrparm); + len = af->to_addr_param(ssa, addrparm); len += sizeof(sctp_errhdr_t); errhdr->cause = SCTP_ERROR_RESTART; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 722ddbc57c09..a7db6e38441a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1,6 +1,7 @@ -/* Copyright (c) 1999-2000 Cisco, Inc. +/* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 + * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines, Corp. * Copyright (c) 2001-2003 Intel Corp. * Copyright (c) 2001-2002 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll @@ -50,6 +51,7 @@ * Ardelle Fan <ardelle.fan@intel.com> * Ryan Layer <rmlayer@us.ibm.com> * Anup Pemmaiah <pemmaiah@cc.usu.edu> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -93,8 +95,8 @@ static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p); static int sctp_wait_for_accept(struct sock *sk, long timeo); static void sctp_wait_for_close(struct sock *sk, long timeo); static inline int sctp_verify_addr(struct sock *, union sctp_addr *, int); -static int sctp_bindx_add(struct sock *, struct sockaddr_storage *, int); -static int sctp_bindx_rem(struct sock *, struct sockaddr_storage *, int); +static int sctp_bindx_add(struct sock *, struct sockaddr *, int); +static int sctp_bindx_rem(struct sock *, struct sockaddr *, int); static int sctp_do_bind(struct sock *, union sctp_addr *, int); static int sctp_autobind(struct sock *sk); static void sctp_sock_migrate(struct sock *, struct sock *, @@ -170,10 +172,7 @@ struct sctp_transport *sctp_addr_id2transport(struct sock *sk, * sd - the socket descriptor returned by socket(). * addr - the address structure (struct sockaddr_in or struct * sockaddr_in6 [RFC 2553]), - * addrlen - the size of the address structure. - * - * The caller should use struct sockaddr_storage described in RFC 2553 - * to represent addr for portability reason. + * addr_len - the size of the address structure. */ int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) { @@ -298,112 +297,6 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) return ret; } -/* API 8.1 sctp_bindx() - * - * The syntax of sctp_bindx() is, - * - * ret = sctp_bindx(int sd, - * struct sockaddr_storage *addrs, - * int addrcnt, - * int flags); - * - * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. - * If the sd is an IPv6 socket, the addresses passed can either be IPv4 - * or IPv6 addresses. - * - * A single address may be specified as INADDR_ANY or IPV6_ADDR_ANY, see - * section 3.1.2 for this usage. - * - * addrs is a pointer to an array of one or more socket addresses. Each - * address is contained in a struct sockaddr_storage, so each address is - * fixed length. The caller specifies the number of addresses in the - * array with addrcnt. - * - * On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns -1, - * and sets errno to the appropriate error code. [ Editor's note: need - * to fill in all error code? ] - * - * For SCTP, the port given in each socket address must be the same, or - * sctp_bindx() will fail, setting errno to EINVAL . - * - * The flags parameter is formed from the bitwise OR of zero or - * more of the following currently defined flags: - * - * SCTP_BINDX_ADD_ADDR - * SCTP_BINDX_REM_ADDR - * - * SCTP_BIND_ADD_ADDR directs SCTP to add the given addresses to the - * association, and SCTP_BIND_REM_ADDR directs SCTP to remove the given - * addresses from the association. The two flags are mutually exclusive; - * if both are given, sctp_bindx() will fail with EINVAL. A caller may not - * remove all addresses from an association; sctp_bindx() will reject such - * an attempt with EINVAL. - * - * An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate - * additional addresses with an endpoint after calling bind(). Or use - * sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening - * socket is associated with so that no new association accepted will be - * associated with those addresses. - * - * SCTP_BIND_ADD_ADDR is defined as 0, so that it becomes the default - * behavior for sctp_bindx() when no flags are given. - * - * Adding and removing addresses from a connected association is optional - * functionality. Implementations that do not support this functionality - * should return EOPNOTSUPP. - * - * NOTE: This could be integrated into sctp_setsockopt_bindx(), - * but keeping it this way makes it easier if sometime sys_bindx is - * added. - */ - -/* Unprotected by locks. Call only with socket lock sk->sk_lock held! See - * sctp_bindx() for a lock-protected call. - */ - -static int __sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, - int addrcnt, int flags) -{ - int retval = 0; - - SCTP_DEBUG_PRINTK("__sctp_bindx(sk: %p, addrs: %p, addrcnt: %d, " - "flags: %s)\n", sk, addrs, addrcnt, - (SCTP_BINDX_ADD_ADDR == flags) ? "ADD" : - ((SCTP_BINDX_REM_ADDR == flags) ? "REM" : "BOGUS")); - - switch (flags) { - case SCTP_BINDX_ADD_ADDR: - retval = sctp_bindx_add(sk, addrs, addrcnt); - break; - - case SCTP_BINDX_REM_ADDR: - retval = sctp_bindx_rem(sk, addrs, addrcnt); - break; - - default: - retval = -EINVAL; - break; - }; - - return retval; -} - -/* BINDX with locks. - * - * NOTE: Currently unused at all ... - */ -int sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt, - int flags) -{ - int retval; - - sctp_lock_sock(sk); - retval = __sctp_bindx(sk, addrs, addrcnt, flags); - sctp_release_sock(sk); - - return retval; -} - /* Add a list of addresses as bind addresses to local endpoint or * association. * @@ -414,41 +307,39 @@ int sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt, * If any of them fails, then the operation will be reversed and the * ones that were added will be removed. * - * Only __sctp_bindx() is supposed to call this function. + * Only sctp_setsockopt_bindx() is supposed to call this function. */ -int sctp_bindx_add(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) +int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt) { int cnt; int retval = 0; - int addr_len; + void *addr_buf; + struct sockaddr *sa_addr; + struct sctp_af *af; SCTP_DEBUG_PRINTK("sctp_bindx_add (sk: %p, addrs: %p, addrcnt: %d)\n", sk, addrs, addrcnt); + addr_buf = addrs; for (cnt = 0; cnt < addrcnt; cnt++) { /* The list may contain either IPv4 or IPv6 address; * determine the address length for walking thru the list. */ - switch (((struct sockaddr *)&addrs[cnt])->sa_family) { - case AF_INET: - addr_len = sizeof(struct sockaddr_in); - break; - - case AF_INET6: - addr_len = sizeof(struct sockaddr_in6); - break; - - default: + sa_addr = (struct sockaddr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa_family); + if (!af) { retval = -EINVAL; goto err_bindx_add; - }; + } - retval = sctp_do_bind(sk, (union sctp_addr *)&addrs[cnt], - addr_len); + retval = sctp_do_bind(sk, (union sctp_addr *)sa_addr, + af->sockaddr_len); + + addr_buf += af->sockaddr_len; err_bindx_add: if (retval < 0) { - /* Failed. Cleanup the ones that has been added */ + /* Failed. Cleanup the ones that have been added */ if (cnt > 0) sctp_bindx_rem(sk, addrs, cnt); return retval; @@ -471,9 +362,9 @@ err_bindx_add: * At least one address has to be left; if only one address is * available, the operation will return -EBUSY. * - * Only __sctp_bindx() is supposed to call this function. + * Only sctp_setsockopt_bindx() is supposed to call this function. */ -int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) +int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) { struct sctp_opt *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; @@ -481,50 +372,41 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) struct sctp_bind_addr *bp = &ep->base.bind_addr; int retval = 0; union sctp_addr saveaddr; + void *addr_buf; + struct sockaddr *sa_addr; + struct sctp_af *af; SCTP_DEBUG_PRINTK("sctp_bindx_rem (sk: %p, addrs: %p, addrcnt: %d)\n", sk, addrs, addrcnt); + addr_buf = addrs; for (cnt = 0; cnt < addrcnt; cnt++) { - /* If there is only one bind address, there is nothing more - * to be removed (we need at least one address here). + /* If the bind address list is empty or if there is only one + * bind address, there is nothing more to be removed (we need + * at least one address here). */ - if (list_empty(&bp->address_list)) { + if (list_empty(&bp->address_list) || + (sctp_list_single_entry(&bp->address_list))) { retval = -EBUSY; goto err_bindx_rem; } /* The list may contain either IPv4 or IPv6 address; - * determine the address length for walking thru the list. + * determine the address length to copy the address to + * saveaddr. */ - switch (((struct sockaddr *)&addrs[cnt])->sa_family) { - case AF_INET: - saveaddr = *((union sctp_addr *) - &addrs[cnt]); - saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); - /* Verify the port. */ - if (saveaddr.v4.sin_port != bp->port) { - retval = -EINVAL; - goto err_bindx_rem; - } - break; - - case AF_INET6: - saveaddr = *((union sctp_addr *) - &addrs[cnt]); - saveaddr.v6.sin6_port = - ntohs(saveaddr.v6.sin6_port); - /* verify the port */ - if (saveaddr.v6.sin6_port != bp->port) { - retval = -EINVAL; - goto err_bindx_rem; - } - break; - - default: + sa_addr = (struct sockaddr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa_family); + if (!af) { retval = -EINVAL; goto err_bindx_rem; - }; + } + memcpy(&saveaddr, sa_addr, af->sockaddr_len); + saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); + if (saveaddr.v4.sin_port != bp->port) { + retval = -EINVAL; + goto err_bindx_rem; + } /* FIXME - There is probably a need to check if sk->sk_saddr and * sk->sk_rcv_addr are currently set to one of the addresses to @@ -541,6 +423,7 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) sctp_write_unlock(&ep->base.addr_lock); sctp_local_bh_enable(); + addr_buf += af->sockaddr_len; err_bindx_rem: if (retval < 0) { /* Failed. Add the ones that has been removed back */ @@ -553,18 +436,62 @@ err_bindx_rem: return retval; } -/* Helper for tunneling sys_bindx() requests through sctp_setsockopt() +/* Helper for tunneling sctp_bindx() requests through sctp_setsockopt() + * + * API 8.1 + * int sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt, + * int flags); + * + * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. + * If the sd is an IPv6 socket, the addresses passed can either be IPv4 + * or IPv6 addresses. + * + * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see + * Section 3.1.2 for this usage. + * + * addrs is a pointer to an array of one or more socket addresses. Each + * address is contained in its appropriate structure (i.e. struct + * sockaddr_in or struct sockaddr_in6) the family of the address type + * must be used to distengish the address length (note that this + * representation is termed a "packed array" of addresses). The caller + * specifies the number of addresses in the array with addrcnt. + * + * On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns + * -1, and sets errno to the appropriate error code. + * + * For SCTP, the port given in each socket address must be the same, or + * sctp_bindx() will fail, setting errno to EINVAL. + * + * The flags parameter is formed from the bitwise OR of zero or more of + * the following currently defined flags: + * + * SCTP_BINDX_ADD_ADDR + * + * SCTP_BINDX_REM_ADDR + * + * SCTP_BINDX_ADD_ADDR directs SCTP to add the given addresses to the + * association, and SCTP_BINDX_REM_ADDR directs SCTP to remove the given + * addresses from the association. The two flags are mutually exclusive; + * if both are given, sctp_bindx() will fail with EINVAL. A caller may + * not remove all addresses from an association; sctp_bindx() will + * reject such an attempt with EINVAL. + * + * An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate + * additional addresses with an endpoint after calling bind(). Or use + * sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening + * socket is associated with so that no new association accepted will be + * associated with those addresses. If the endpoint supports dynamic + * address a SCTP_BINDX_REM_ADDR or SCTP_BINDX_ADD_ADDR may cause a + * endpoint to send the appropriate message to the peer to change the + * peers address lists. + * + * Adding and removing addresses from a connected association is + * optional functionality. Implementations that do not support this + * functionality should return EOPNOTSUPP. * * Basically do nothing but copying the addresses from user to kernel - * land and invoking sctp_bindx on the sk. This is used for tunneling - * the sctp_bindx() [sys_bindx()] request through sctp_setsockopt() - * from userspace. - * - * Note I don't use move_addr_to_kernel(): the reason is we would be - * iterating over an array of struct sockaddr_storage passing always - * what we know is a good size (sizeof (struct sock...)), so it is - * pointless. Instead check the whole area for read access and copy - * it. + * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. + * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace. * * We don't use copy_from_user() for optimization: we first do the * sanity checks (buffer size -fast- and access check-healthy @@ -584,38 +511,70 @@ err_bindx_rem: * * Returns 0 if ok, <0 errno code on error. */ -SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, - struct sockaddr_storage *addrs, - int addrssize, int op) +SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr *addrs, + int addrs_size, int op) { - struct sockaddr_storage *kaddrs; + struct sockaddr *kaddrs; int err; - size_t addrcnt; + int addrcnt = 0; + int walk_size = 0; + struct sockaddr *sa_addr; + void *addr_buf; + struct sctp_af *af; - SCTP_DEBUG_PRINTK("sctp_do_setsocktopt_bindx: sk %p addrs %p" - " addrssize %d opt %d\n", sk, addrs, addrssize, op); + SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p" + " addrs_size %d opt %d\n", sk, addrs, addrs_size, op); - /* Do we have an integer number of structs sockaddr_storage? */ - if (unlikely(addrssize <= 0 || - addrssize % sizeof(struct sockaddr_storage) != 0)) + if (unlikely(addrs_size <= 0)) return -EINVAL; /* Check the user passed a healthy pointer. */ - if (unlikely(!access_ok(VERIFY_READ, addrs, addrssize))) + if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size))) return -EFAULT; /* Alloc space for the address array in kernel memory. */ - kaddrs = (struct sockaddr_storage *) kmalloc(addrssize, GFP_KERNEL); + kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL); if (unlikely(!kaddrs)) return -ENOMEM; - if (copy_from_user(kaddrs, addrs, addrssize)) { + if (__copy_from_user(kaddrs, addrs, addrs_size)) { kfree(kaddrs); return -EFAULT; } - addrcnt = addrssize / sizeof(struct sockaddr_storage); - err = __sctp_bindx(sk, kaddrs, addrcnt, op); /* Do the work. */ + /* Walk through the addrs buffer and count the number of addresses. */ + addr_buf = kaddrs; + while (walk_size < addrs_size) { + sa_addr = (struct sockaddr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa_family); + + /* If the address family is not supported or if this address + * causes the address buffer to overflow return EINVAL. + */ + if (!af || (walk_size + af->sockaddr_len) > addrs_size) { + kfree(kaddrs); + return -EINVAL; + } + addrcnt++; + addr_buf += af->sockaddr_len; + walk_size += af->sockaddr_len; + } + + /* Do the work. */ + switch (op) { + case SCTP_BINDX_ADD_ADDR: + err = sctp_bindx_add(sk, kaddrs, addrcnt); + break; + + case SCTP_BINDX_REM_ADDR: + err = sctp_bindx_rem(sk, kaddrs, addrcnt); + break; + + default: + err = -EINVAL; + break; + }; + kfree(kaddrs); return err; @@ -1476,7 +1435,7 @@ static int sctp_setsockopt_initmsg(struct sock *sk, char *optval, int optlen) } /* - * 7.1.14 Set default send parameters (SET_DEFAULT_SEND_PARAM) + * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM) * * Applications that wish to use the sendto() system call may wish to * specify a default set of parameters that would normally be supplied @@ -1522,7 +1481,7 @@ static int sctp_setsockopt_default_send_param(struct sock *sk, return 0; } -/* 7.1.10 Set Peer Primary Address (SCTP_PRIMARY_ADDR) +/* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) * * Requests that the local SCTP stack use the enclosed peer address as * the association primary. The enclosed address must be one of the @@ -1727,6 +1686,62 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char *optval, int optlen) return 0; } + +/* + * 7.1.9 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR) + * + * Requests that the peer mark the enclosed address as the association + * primary. The enclosed address must be one of the association's + * locally bound addresses. The following structure is used to make a + * set primary request: + */ +static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval, + int optlen) +{ + struct sctp_opt *sp; + struct sctp_endpoint *ep; + struct sctp_association *asoc = NULL; + struct sctp_setpeerprim prim; + struct sctp_chunk *chunk; + int err; + + sp = sctp_sk(sk); + ep = sp->ep; + + if (optlen != sizeof(struct sctp_setpeerprim)) + return -EINVAL; + + if (copy_from_user(&prim, optval, optlen)) + return -EFAULT; + + asoc = sctp_id2assoc(sk, prim.sspp_assoc_id); + if (!asoc) + return -EINVAL; + + if (!sctp_state(asoc, ESTABLISHED)) + return -ENOTCONN; + + if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr)) + return -EADDRNOTAVAIL; + + /* Create an ASCONF chunk with SET_PRIMARY parameter */ + chunk = sctp_make_asconf_set_prim(asoc, + (union sctp_addr *)&prim.sspp_addr); + if (!chunk) + return -ENOMEM; + + err = sctp_primitive_ASCONF(asoc, chunk); + if (err) { + sctp_chunk_free(chunk); + return err; + } + + SCTP_DEBUG_PRINTK("We set peer primary addr primitively.\n"); + + return 0; +} + + /* API 6.2 setsockopt(), getsockopt() * * Applications use setsockopt() and getsockopt() to set or retrieve @@ -1771,16 +1786,14 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, switch (optname) { case SCTP_SOCKOPT_BINDX_ADD: /* 'optlen' is the size of the addresses buffer. */ - retval = sctp_setsockopt_bindx(sk, (struct sockaddr_storage *) - optval, optlen, - SCTP_BINDX_ADD_ADDR); + retval = sctp_setsockopt_bindx(sk, (struct sockaddr *)optval, + optlen, SCTP_BINDX_ADD_ADDR); break; case SCTP_SOCKOPT_BINDX_REM: /* 'optlen' is the size of the addresses buffer. */ - retval = sctp_setsockopt_bindx(sk, (struct sockaddr_storage *) - optval, optlen, - SCTP_BINDX_REM_ADDR); + retval = sctp_setsockopt_bindx(sk, (struct sockaddr *)optval, + optlen, SCTP_BINDX_REM_ADDR); break; case SCTP_DISABLE_FRAGMENTS: @@ -1809,6 +1822,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, case SCTP_PRIMARY_ADDR: retval = sctp_setsockopt_primary_addr(sk, optval, optlen); break; + case SCTP_SET_PEER_PRIMARY_ADDR: + retval = sctp_setsockopt_peer_primary_addr(sk, optval, optlen); + break; case SCTP_NODELAY: retval = sctp_setsockopt_nodelay(sk, optval, optlen); break; @@ -2056,9 +2072,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) return -ESOCKTNOSUPPORT; } - /* FIXME: The next draft (04) of the SCTP Sockets Extensions - * should include a socket option for manipulating these - * message parameters (and a few others). + /* Initialize default send parameters. These parameters can be + * modified with the SCTP_DEFAULT_SEND_PARAM socket option. */ sp->default_stream = 0; sp->default_ppid = 0; @@ -2077,7 +2092,6 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) /* Initialize default RTO related parameters. These parameters can * be modified for with the SCTP_RTOINFO socket option. - * FIXME: These are not used yet. */ sp->rtoinfo.srto_initial = (sctp_rto_initial / HZ) * 1000; sp->rtoinfo.srto_max = (sctp_rto_max / HZ) * 1000; @@ -2093,15 +2107,10 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) sp->assocparams.sasoc_cookie_life = (sctp_valid_cookie_life / HZ) * 1000; - /* Initialize default event subscriptions. - * the struct sock is initialized to zero, so only - * enable the events needed. By default, UDP-style - * sockets enable io and association change notifications. + /* Initialize default event subscriptions. By default, all the + * options are off. */ - if (sctp_style(sk, UDP)) { - sp->subscribe.sctp_data_io_event = 1; - sp->subscribe.sctp_association_event = 1; - } + memset(&sp->subscribe, 0, sizeof(struct sctp_event_subscribe)); /* Default Peer Address Parameters. These defaults can * be modified via SCTP_PEER_ADDR_PARAMS @@ -2552,7 +2561,7 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval, int * } static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, - char *optval, int *optlen) + char *optval, int *optlen) { sctp_assoc_t id; struct sctp_association *asoc; @@ -2565,9 +2574,7 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) return -EFAULT; - /* - * For UDP-style sockets, id specifies the association to query. - */ + /* For UDP-style sockets, id specifies the association to query. */ asoc = sctp_id2assoc(sk, id); if (!asoc) return -EINVAL; @@ -2582,16 +2589,17 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, } static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, - char *optval, int *optlen) + char *optval, int *optlen) { struct sctp_association *asoc; struct list_head *pos; int cnt = 0; struct sctp_getaddrs getaddrs; struct sctp_transport *from; - struct sockaddr_storage *to; + void *to; union sctp_addr temp; struct sctp_opt *sp = sctp_sk(sk); + int addrlen; if (len != sizeof(struct sctp_getaddrs)) return -EINVAL; @@ -2600,21 +2608,21 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, return -EFAULT; if (getaddrs.addr_num <= 0) return -EINVAL; - /* - * For UDP-style sockets, id specifies the association to query. - */ + + /* For UDP-style sockets, id specifies the association to query. */ asoc = sctp_id2assoc(sk, getaddrs.assoc_id); if (!asoc) return -EINVAL; - to = getaddrs.addrs; + to = (void *)getaddrs.addrs; list_for_each(pos, &asoc->peer.transport_addr_list) { from = list_entry(pos, struct sctp_transport, transports); memcpy(&temp, &from->ipaddr, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); - if (copy_to_user(to, &temp, sizeof(temp))) + addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; + if (copy_to_user(to, &temp, addrlen)) return -EFAULT; - to ++; + to += addrlen ; cnt ++; if (cnt >= getaddrs.addr_num) break; } @@ -2673,9 +2681,10 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, int cnt = 0; struct sctp_getaddrs getaddrs; struct sctp_sockaddr_entry *from; - struct sockaddr_storage *to; + void *to; union sctp_addr temp; struct sctp_opt *sp = sctp_sk(sk); + int addrlen; if (len != sizeof(struct sctp_getaddrs)) return -EINVAL; @@ -2699,16 +2708,17 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, bp = &asoc->base.bind_addr; } - to = getaddrs.addrs; + to = (void *)getaddrs.addrs; list_for_each(pos, &bp->address_list) { from = list_entry(pos, struct sctp_sockaddr_entry, list); memcpy(&temp, &from->a, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); - if (copy_to_user(to, &temp, sizeof(temp))) + addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; + if (copy_to_user(to, &temp, addrlen)) return -EFAULT; - to ++; + to += addrlen; cnt ++; if (cnt >= getaddrs.addr_num) break; } @@ -2759,7 +2769,7 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, /* * - * 7.1.14 Set default send parameters (SET_DEFAULT_SEND_PARAM) + * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM) * * Applications that wish to use the sendto() system call may wish to * specify a default set of parameters that would normally be supplied @@ -3331,9 +3341,19 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) if (!sctp_style(sk, UDP)) return -EINVAL; + /* If backlog is zero, disable listening. */ + if (!backlog) { + if (sctp_sstate(sk, CLOSED)) + return 0; + + sctp_unhash_endpoint(ep); + sk->sk_state = SCTP_SS_CLOSED; + } + + /* Return if we are already listening. */ if (sctp_sstate(sk, LISTENING)) return 0; - + /* * If a bind() or sctp_bindx() is not called prior to a listen() * call that allows new associations to be accepted, the system @@ -3364,6 +3384,15 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog) struct sctp_opt *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; + /* If backlog is zero, disable listening. */ + if (!backlog) { + if (sctp_sstate(sk, CLOSED)) + return 0; + + sctp_unhash_endpoint(ep); + sk->sk_state = SCTP_SS_CLOSED; + } + if (sctp_sstate(sk, LISTENING)) return 0; diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index cdcf6d09d24f..edffe9cc8f21 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -214,7 +214,7 @@ static int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen, if (olen != sizeof (int)) return -EINVAL; } - if (put_user((*(int *)(table->data) / HZ) * 1000, + if (put_user((*(int *)(table->data) * 1000) / HZ, (int *)oldval) || (oldlenp && put_user(sizeof (int), oldlenp))) return -EFAULT; @@ -228,7 +228,7 @@ static int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen, if (get_user(new, (int *)newval)) return -EFAULT; - *(int *)(table->data) = (new * HZ) * 1000; + *(int *)(table->data) = (new * HZ) / 1000; } return 1; } diff --git a/net/socket.c b/net/socket.c index 74fd11fdd7a8..f0a1a3da7500 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1894,6 +1894,8 @@ int sock_register(struct net_proto_family *ops) err = 0; } net_family_write_unlock(); + printk(KERN_INFO "NET: Registered protocol family %d\n", + ops->family); return err; } @@ -1911,6 +1913,8 @@ int sock_unregister(int family) net_family_write_lock(); net_families[family]=NULL; net_family_write_unlock(); + printk(KERN_INFO "NET: Unregistered protocol family %d\n", + family); return 0; } diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 4ba7f3d5c2e4..67a13170c6d7 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c @@ -20,7 +20,6 @@ #include <linux/proc_fs.h> #include <linux/sunrpc/clnt.h> #include <linux/sunrpc/svcsock.h> -#include <linux/init.h> #define RPCDBG_FACILITY RPCDBG_MISC diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index d9dd8a2f3914..549c7e303144 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -111,6 +111,7 @@ #include <linux/tcp.h> #include <net/af_unix.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <net/scm.h> #include <linux/init.h> #include <linux/poll.h> @@ -1805,25 +1806,52 @@ static unsigned int unix_poll(struct file * file, struct socket *sock, poll_tabl #ifdef CONFIG_PROC_FS -static int unix_read_proc(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) +static struct sock *unix_seq_idx(int *iter, loff_t pos) { - off_t pos=0; - off_t begin=0; - int len=0; - int i; + loff_t off = 0; struct sock *s; - - len+= sprintf(buffer,"Num RefCount Protocol Flags Type St " - "Inode Path\n"); + for (s = first_unix_socket(iter); s; s = next_unix_socket(iter, s)) { + if (off == pos) + return s; + ++off; + } + return NULL; +} + + +static void *unix_seq_start(struct seq_file *seq, loff_t *pos) +{ read_lock(&unix_table_lock); - forall_unix_sockets (i,s) - { + return *pos ? unix_seq_idx(seq->private, *pos - 1) : ((void *) 1); +} + +static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + ++*pos; + + if (v == (void *)1) + return first_unix_socket(seq->private); + return next_unix_socket(seq->private, v); +} + +static void unix_seq_stop(struct seq_file *seq, void *v) +{ + read_unlock(&unix_table_lock); +} + +static int unix_seq_show(struct seq_file *seq, void *v) +{ + + if (v == (void *)1) + seq_puts(seq, "Num RefCount Protocol Flags Type St " + "Inode Path\n"); + else { + struct sock *s = v; struct unix_sock *u = unix_sk(s); unix_state_rlock(s); - len+=sprintf(buffer+len,"%p: %08X %08X %08X %04X %02X %5lu", + seq_printf(seq, "%p: %08X %08X %08X %04X %02X %5lu", s, atomic_read(&s->sk_refcnt), 0, @@ -1835,39 +1863,61 @@ static int unix_read_proc(char *buffer, char **start, off_t offset, sock_i_ino(s)); if (u->addr) { - buffer[len++] = ' '; - memcpy(buffer+len, u->addr->name->sun_path, - u->addr->len-sizeof(short)); - if (!UNIX_ABSTRACT(s)) - len--; - else - buffer[len] = '@'; - len += u->addr->len - sizeof(short); - } - unix_state_runlock(s); + int i; + seq_putc(seq, ' '); + + for (i = 0; i < u->addr->len-sizeof(short); i++) + seq_putc(seq, u->addr->name->sun_path[i]); - buffer[len++]='\n'; - - pos = begin + len; - if(pos<offset) - { - len=0; - begin=pos; + if (UNIX_ABSTRACT(s)) + seq_putc(seq, '@'); } - if(pos>offset+length) - goto done; + unix_state_runlock(s); + seq_putc(seq, '\n'); } - *eof = 1; -done: - read_unlock(&unix_table_lock); - *start=buffer+(offset-begin); - len-=(offset-begin); - if(len>length) - len=length; - if (len < 0) - len = 0; - return len; + + return 0; } + +struct seq_operations unix_seq_ops = { + .start = unix_seq_start, + .next = unix_seq_next, + .stop = unix_seq_stop, + .show = unix_seq_show, +}; + + +static int unix_seq_open(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + int rc = -ENOMEM; + int *iter = kmalloc(sizeof(int), GFP_KERNEL); + + if (!iter) + goto out; + + rc = seq_open(file, &unix_seq_ops); + if (rc) + goto out_kfree; + + seq = file->private_data; + seq->private = iter; + *iter = 0; +out: + return rc; +out_kfree: + kfree(iter); + goto out; +} + +static struct file_operations unix_seq_fops = { + .owner = THIS_MODULE, + .open = unix_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + #endif struct proto_ops unix_stream_ops = { @@ -1926,13 +1976,10 @@ static inline void unix_sysctl_register(void) {} static inline void unix_sysctl_unregister(void) {} #endif -static char banner[] __initdata = KERN_INFO "NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.\n"; - static int __init af_unix_init(void) { struct sk_buff *dummy_skb; - printk(banner); if (sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "%s: panic\n", __FUNCTION__); return -1; @@ -1947,7 +1994,7 @@ static int __init af_unix_init(void) sock_register(&unix_family_ops); #ifdef CONFIG_PROC_FS - create_proc_read_entry("net/unix", 0, 0, unix_read_proc, NULL); + proc_net_fops_create("unix", 0, &unix_seq_fops); #endif unix_sysctl_register(); return 0; @@ -1957,7 +2004,7 @@ static void __exit af_unix_exit(void) { sock_unregister(PF_UNIX); unix_sysctl_unregister(); - remove_proc_entry("net/unix", 0); + proc_net_remove("unix"); kmem_cache_destroy(unix_sk_cachep); } diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 3bc431d4617f..ac4d772d77ad 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -3,11 +3,14 @@ config SECURITY_SELINUX depends on SECURITY default n help - This enables NSA Security-Enhanced Linux (SELinux). + This selects NSA Security-Enhanced Linux (SELinux). You will also need a policy configuration and a labeled filesystem. You can obtain the policy compiler (checkpolicy), the utility for labeling filesystems (setfiles), and an example policy configuration from http://www.nsa.gov/selinux. + SELinux needs to be explicitly enabled on the kernel command line with + selinux=1. If you specify selinux=0 or do not use this parameter, + SELinux will not be enabled. If you are unsure how to answer this question, answer N. config SECURITY_SELINUX_DEVELOP diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index fc514f4517e9..d8c724a9ec7c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -73,6 +73,15 @@ static int __init enforcing_setup(char *str) __setup("enforcing=", enforcing_setup); #endif +int selinux_enabled = 0; + +static int __init selinux_enabled_setup(char *str) +{ + selinux_enabled = simple_strtol(str, NULL, 0); + return 1; +} +__setup("selinux=", selinux_enabled_setup); + /* Original (dummy) security module. */ static struct security_operations *original_ops = NULL; @@ -3347,6 +3356,11 @@ __init int selinux_init(void) { struct task_security_struct *tsec; + if (!selinux_enabled) { + printk(KERN_INFO "SELinux: Not enabled at boot.\n"); + return 0; + } + printk(KERN_INFO "SELinux: Initializing.\n"); /* Set the security state for the initial task. */ diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 1b3aa3f62782..8fa2533b0042 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -17,6 +17,8 @@ #include "security.h" #include "objsec.h" +extern int selinux_enabled; + /* Check whether a task is allowed to use a security operation. */ int task_has_security(struct task_struct *tsk, u32 perms) @@ -587,7 +589,7 @@ static struct file_system_type sel_fs_type = { static int __init init_sel_fs(void) { - return register_filesystem(&sel_fs_type); + return selinux_enabled ? register_filesystem(&sel_fs_type) : 0; } __initcall(init_sel_fs); diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig index 2fd75db6ea71..6f5956b25f0b 100644 --- a/sound/oss/Kconfig +++ b/sound/oss/Kconfig @@ -1145,10 +1145,18 @@ config SOUND_ALI5455 config SOUND_FORTE tristate "ForteMedia FM801 driver" depends on SOUND_PRIME!=n && PCI + help + Say Y or M if you want driver support for the ForteMedia FM801 PCI + audio controller (Abit AU10, Genius Sound Maker, HP Workstation + zx2000, and others). config SOUND_RME96XX tristate "RME Hammerfall (RME96XX) support" depends on SOUND_PRIME!=n && PCI + help + Say Y or M if you have a Hammerfall or Hammerfall light + multichannel card from RME. If you want to acess advanced + features of the card, read Documentation/sound/rme96xx. config SOUND_AD1980 tristate "AD1980 front/back switch plugin" |
