diff -Nru a/CREDITS b/CREDITS --- a/CREDITS Thu Aug 1 14:17:36 2002 +++ b/CREDITS Thu Aug 1 14:17:36 2002 @@ -1337,6 +1337,12 @@ S: Provo, Utah 84606-5607 S: USA +N: Marcel Holtmann +E: marcel@holtmann.org +W: http://www.holtmann.org +D: Author of the Linux Bluetooth Subsystem PC Card drivers +S: Germany + N: Rob W. W. Hooft E: hooft@EMBL-Heidelberg.DE D: Shared libs for graphics-tools and for the f2c compiler diff -Nru a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile --- a/Documentation/DocBook/Makefile Thu Aug 1 14:17:40 2002 +++ b/Documentation/DocBook/Makefile Thu Aug 1 14:17:40 2002 @@ -88,9 +88,9 @@ IMG-parportbook2 := $(addprefix Documentation/DocBook/,$(IMG-parportbook)) EPS-parportbook := $(patsubst %.fig,%.eps, $(IMG-parportbook2)) PNG-parportbook := $(patsubst %.fig,%.png, $(IMG-parportbook2)) -Documentation/DocBook/parportbook.ps: $(EPS-parportbook) -Documentation/DocBook/parportbook.html Documentation/DocBook/parportbook.pdf:\ - $(PNG-parportbook) +Documentation/DocBook/parportbook.html: $(PNG-parportbook) +Documentation/DocBook/parportbook.ps Documentation/DocBook/parportbook.pdf:\ + $(EPS-parportbook) ### # Rules to generate postscript, PDF and HTML @@ -99,48 +99,44 @@ @(which db2ps > /dev/null 2>&1) || \ (echo "*** You need to install DocBook stylesheets ***"; \ exit 1) - @echo ' DB2PS $@' - @db2ps -o $(dir $@) $< + $(call do_cmd,DB2PS $@,db2ps -o $(dir $@) $<) %.pdf : %.sgml @(which db2pdf > /dev/null 2>&1) || \ (echo "*** You need to install DocBook stylesheets ***"; \ exit 1) - @echo ' DB2PDF $@' - @db2pdf -o $(dir $@) $< + $(call do_cmd,DB2PDF $@,db2pdf -o $(dir $@) $<) %.html: %.sgml @(which db2html > /dev/null 2>&1) || \ (echo "*** You need to install DocBook stylesheets ***"; \ exit 1) @rm -rf $@ $(patsubst %.html,%,$@) - @echo ' DB2HTML $@' - @db2html -o $(patsubst %.html,%,$@) $< && \ + $(call do_cmd,DB2HTML $@,db2html -o $(patsubst %.html,%,$@) $< && \ echo '\ - Goto $(patsubst %.html,%,$(notdir $@))

' > $@ + Goto $(patsubst %.html,%,$(notdir $@))

' > $@) @if [ ! -z "$(PNG-$(basename $(notdir $@)))" ]; then \ cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi ### # Rules to generate postscripts and PNG imgages from .fig format files %.eps: %.fig - @echo ' FIG2DEV -Leps $@' - @fig2dev -Leps $< $@ + $(call do_cmd,FIG2DEV -Leps $@,fig2dev -Leps $< $@) %.png: %.fig - @echo ' FIG2DEV -Lpng $@' - fig2dev -Lpng $< $@ + $(call do_cmd,FIG2DEV -Lpng $@,fig2dev -Lpng $< $@) ### # Rule to convert a .c file to inline SGML documentation %.sgml: %.c @echo ' Generating $@' - @echo "" > $@ - @expand --tabs=8 < $< | \ - sed -e "s/&/\\&/g" \ - -e "s//\\>/g" >> $@ - @echo "" >> $@ + @( \ + echo ""; \ + expand --tabs=8 < $< | \ + sed -e "s/&/\\&/g" \ + -e "s//\\>/g"; \ + echo "") > $@ ### # Help targets as used by the top-level makefile diff -Nru a/Documentation/filesystems/devfs/ChangeLog b/Documentation/filesystems/devfs/ChangeLog --- a/Documentation/filesystems/devfs/ChangeLog Thu Aug 1 14:17:36 2002 +++ b/Documentation/filesystems/devfs/ChangeLog Thu Aug 1 14:17:36 2002 @@ -1941,3 +1941,19 @@ - Updated README from master HTML file - Fixed devfs entry leak in when *readdir fails +=============================================================================== +Changes for patch v215 + +- Created + +- Switched many functions from to + + +- Switched many functions from to +=============================================================================== +Changes for patch v216 + +- Switched arch/ia64/sn/io/hcl.c from to + + +- Removed deprecated diff -Nru a/Documentation/ide.txt b/Documentation/ide.txt --- a/Documentation/ide.txt Thu Aug 1 14:17:36 2002 +++ b/Documentation/ide.txt Thu Aug 1 14:17:36 2002 @@ -1,9 +1,6 @@ - - Information regarding the Enhanced IDE drive in Linux 2.5 - ============================================================================== @@ -49,7 +46,7 @@ - If you mix devices on the same cable, please consider using similar devices in respect of the data transfer mode they support. -- Even better tru to stick to the same vendor and device type on the same +- Even better try to stick to the same vendor and device type on the same cable. ================================================================================ @@ -69,7 +66,8 @@ To access devices on interfaces > ide0, device entries please make sure that device files for them are present in /dev. If not, please create such entries, by simply running the included shell script: -/usr/src/linux/scripts/MAKEDEV.ide + + /usr/src/linux/scripts/MAKEDEV.ide This driver automatically probes for most IDE interfaces (including all PCI ones), for the drives/geometries attached to those interfaces, and for the IRQ @@ -195,11 +193,10 @@ under control of ide.c. To have ide.c also "take over" the primary IDE port in this situation, use the "command line" parameter: ide0=0x1f0 -The IDE driver is partly modularized. The high level disk/cdrom/tape/floppy +The IDE driver is modularized. The high level disk/CD-ROM/tape/floppy drivers can always be compiled as loadable modules, the chipset drivers can only be compiled into the kernel, and the core code (ide.c) can be -compiled as a loadable module provided no chipset support and no special -partition table translations are needed. +compiled as a loadable module provided no chipset support is needed. When using ide.c/ide-tape.c as modules in combination with kerneld, add: @@ -217,8 +214,9 @@ ================================================================================ -Summary of ide driver parameters for kernel "command line": ----------------------------------------------------------- +Summary of ide driver parameters for kernel command line +-------------------------------------------------------- + "hdx=" is recognized for all "x" from "a" to "h", such as "hdc". "idex=" is recognized for all "x" from "0" to "3", such as "ide1". @@ -300,6 +298,53 @@ There may be more options than shown -- use the source, Luke! Everything else is rejected with a "BAD OPTION" message. + +================================================================================ + +IDE ATAPI streaming tape driver +------------------------------- + +This driver is a part of the Linux ide driver and works in co-operation +with linux/drivers/block/ide.c. + +The driver, in co-operation with ide.c, basically traverses the +request-list for the block device interface. The character device +interface, on the other hand, creates new requests, adds them +to the request-list of the block device, and waits for their completion. + +Pipelined operation mode is now supported on both reads and writes. + +The block device major and minor numbers are determined from the +tape's relative position in the ide interfaces, as explained in ide.c. + +The character device interface consists of the following devices: + + ht0 major 37, minor 0 first IDE tape, rewind on close. + ht1 major 37, minor 1 second IDE tape, rewind on close. + ... + nht0 major 37, minor 128 first IDE tape, no rewind on close. + nht1 major 37, minor 129 second IDE tape, no rewind on close. + ... + +Run linux/scripts/MAKEDEV.ide to create the above entries. + +The general magnetic tape commands compatible interface, as defined by +include/linux/mtio.h, is accessible through the character device. + +General ide driver configuration options, such as the interrupt-unmask +flag, can be configured by issuing an ioctl to the block device interface, +as any other ide device. + +Our own ide-tape ioctl's can be issued to either the block device or +the character device interface. + +Maximal throughput with minimal bus load will usually be achieved in the +following scenario: + + 1. ide-tape is operating in the pipelined operation mode. + 2. No buffering is performed by the user backup program. + + ================================================================================ diff -Nru a/Documentation/serial/driver b/Documentation/serial/driver --- a/Documentation/serial/driver Thu Aug 1 14:17:36 2002 +++ b/Documentation/serial/driver Thu Aug 1 14:17:36 2002 @@ -138,15 +138,16 @@ Stop receiving characters; the port is in the process of being closed. - Locking: none. - Interrupts: caller dependent. + Locking: port->lock taken. + Interrupts: locally disabled. This call must not sleep enable_ms(port) Enable the modem status interrupts. - Locking: none. - Interrupts: caller dependent. + Locking: port->lock taken. + Interrupts: locally disabled. + This call must not sleep break_ctl(port,ctl) Control the transmission of a break signal. If ctl is diff -Nru a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt --- a/Documentation/sysctl/vm.txt Thu Aug 1 14:17:41 2002 +++ b/Documentation/sysctl/vm.txt Thu Aug 1 14:17:41 2002 @@ -16,7 +16,6 @@ files can be found in mm/swap.c. Currently, these files are in /proc/sys/vm: -- kswapd - overcommit_memory - page-cluster - dirty_async_ratio @@ -34,39 +33,6 @@ ============================================================== -kswapd: - -Kswapd is the kernel swapout daemon. That is, kswapd is that -piece of the kernel that frees memory when it gets fragmented -or full. Since every system is different, you'll probably want -some control over this piece of the system. - -The numbers in this page correspond to the numbers in the -struct pager_daemon {tries_base, tries_min, swap_cluster -}; The tries_base and swap_cluster probably have the -largest influence on system performance. - -tries_base The maximum number of pages kswapd tries to - free in one round is calculated from this - number. Usually this number will be divided - by 4 or 8 (see mm/vmscan.c), so it isn't as - big as it looks. - When you need to increase the bandwidth to/from - swap, you'll want to increase this number. -tries_min This is the minimum number of times kswapd - tries to free a page each time it is called. - Basically it's just there to make sure that - kswapd frees some pages even when it's being - called with minimum priority. -swap_cluster This is the number of pages kswapd writes in - one turn. You want this large so that kswapd - does it's I/O in large chunks and the disk - doesn't have to seek often, but you don't want - it to be too large since that would flood the - request queue. - -============================================================== - overcommit_memory: This value contains a flag that enables memory overcommitment. @@ -78,7 +44,21 @@ programs that malloc() huge amounts of memory "just-in-case" and don't use much of it. -Look at: mm/mmap.c::vm_enough_memory() for more information. +A value of 2 introduces a new "strict overcommit" policy +that attempts to prevent any overcommit of memory. + +The default value is 0. + +See Documentation/vm/overcommit-accounting and +mm/mmap.c::vm_enough_memory() for more information. + +============================================================== + +overcommit_ratio: + +When overcommit_memory is set to 2, the committed address +space is not permitted to exceed swap plus this percentage +of physical RAM. See above. ============================================================== diff -Nru a/Documentation/vm/overcommit-accounting b/Documentation/vm/overcommit-accounting --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/vm/overcommit-accounting Thu Aug 1 14:17:41 2002 @@ -0,0 +1,68 @@ +The Linux kernel supports four overcommit handling modes + +0 - Heuristic overcommit handling. Obvious overcommits of + address space are refused. Used for a typical system. It + ensures a seriously wild allocation fails while allowing + overcommit to reduce swap usage. This is the default. + +1 - No overcommit handling. Appropriate for some scientific + applications. + +2 - (NEW) strict overcommit. The total address space commit + for the system is not permitted to exceed swap + a + configurable percentage (default is 50) of physical RAM. + Depending on the percentage you use, in most situations + this means a process will not be killed while accessing + pages but will receive errors on memory allocation as + appropriate. + +The overcommit policy is set via the sysctl `vm.overcommit_memory'. + +The overcommit percentage is set via `vm.overcommit_ratio'. + +Gotchas +------- + +The C language stack growth does an implicit mremap. If you want absolute +guarantees and run close to the edge you MUST mmap your stack for the +largest size you think you will need. For typical stack usage is does +not matter much but its a corner case if you really really care + +In mode 2 the MAP_NORESERVE flag is ignored. + + +How It Works +------------ + +The overcommit is based on the following rules + +For a file backed map + SHARED or READ-only - 0 cost (the file is the map not swap) + PRIVATE WRITABLE - size of mapping per instance + +For an anonymous or /dev/zero map + SHARED - size of mapping + PRIVATE READ-only - 0 cost (but of little use) + PRIVATE WRITABLE - size of mapping per instance + +Additional accounting + Pages made writable copies by mmap + shmfs memory drawn from the same pool + +Status +------ + +o We account mmap memory mappings +o We account mprotect changes in commit +o We account mremap changes in size +o We account brk +o We account munmap +o We report the commit status in /proc +o Account and check on fork +o Review stack handling/building on exec +o SHMfs accounting +o Implement actual limit enforcement + +To Do +----- +o Account ptrace pages (this is hard) diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Thu Aug 1 14:17:40 2002 +++ b/MAINTAINERS Thu Aug 1 14:17:40 2002 @@ -270,6 +270,12 @@ W: http://bluez.sf.net S: Maintained +BLUETOOTH SUBSYSTEM (PC Card Drivers) +P: Marcel Holtmann +M: marcel@holtmann.org +W: http://www.holtmann.org/linux/bluetooth/ +S: Maintained + BTTV VIDEO4LINUX DRIVER P: Gerd Knorr M: kraxel@bytesex.org @@ -1487,7 +1493,7 @@ L: alsa-devel@alsa-project.org S: Maintained -SPARC: +UltraSPARC (sparc64): P: David S. Miller M: davem@redhat.com P: Eddie C. Dost @@ -1499,6 +1505,9 @@ L: sparclinux@vger.kernel.org L: ultralinux@vger.kernel.org S: Maintained + +SPARC (sparc32): +S: Unmaintained SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER P: Roger Wolff diff -Nru a/Makefile b/Makefile --- a/Makefile Thu Aug 1 14:17:36 2002 +++ b/Makefile Thu Aug 1 14:17:36 2002 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 5 -SUBLEVEL = 29 +SUBLEVEL = 30 EXTRAVERSION = # *DOCUMENTATION* @@ -279,7 +279,6 @@ mv -f .tmpversion .version +$(MAKE) -C init $(call cmd,link_vmlinux) - $(cmd_link_vmlinux) echo 'cmd_$@ := $(cmd_link_vmlinux)' > $(@D)/.$(@F).cmd $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map endef diff -Nru a/Rules.make b/Rules.make --- a/Rules.make Thu Aug 1 14:17:40 2002 +++ b/Rules.make Thu Aug 1 14:17:40 2002 @@ -553,3 +553,22 @@ # If quiet is set, only print short version of command cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1)) + +# do_cmd is a shorthand used to support both compressed, verbose +# and silent output in a single line. +# Compared to cmd described avobe, do_cmd does no rely on any variables +# previously assigned a value. +# +# Usage $(call do_cmd,CMD $@,cmd_to_execute bla bla) +# Example: +# $(call do_cmd,CP $@,cp -b $< $@) +# make -s => nothing will be printed +# make KBUILD_VERBOSE=1 => cp -b path/to/src.file path/to/dest.file +# make KBUILD_VERBOSE=0 => CP path/to/dest.file +define do_cmd + @$(if $(filter quiet_,$(quiet)), echo ' $(1)' &&, + $(if $(filter silent_,$(quiet)),, + echo "$(2)" &&)) \ + $(2) +endef + diff -Nru a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S --- a/arch/alpha/kernel/entry.S Thu Aug 1 14:17:36 2002 +++ b/arch/alpha/kernel/entry.S Thu Aug 1 14:17:36 2002 @@ -1081,8 +1081,8 @@ .quad sys_pciconfig_write .quad sys_query_module .quad sys_prctl - .quad sys_pread - .quad sys_pwrite /* 350 */ + .quad sys_pread64 + .quad sys_pwrite64 /* 350 */ .quad sys_rt_sigreturn .quad sys_rt_sigaction .quad sys_rt_sigprocmask diff -Nru a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c --- a/arch/alpha/kernel/osf_sys.c Thu Aug 1 14:17:36 2002 +++ b/arch/alpha/kernel/osf_sys.c Thu Aug 1 14:17:36 2002 @@ -221,8 +221,8 @@ * isn't actually going to matter, as if the parent happens * to change we can happily return either of the pids. */ - (®s)->r20 = tsk->real_parent->pid; - return tsk->pid; + (®s)->r20 = tsk->real_parent->tgid; + return tsk->tgid; } asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len, diff -Nru a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S --- a/arch/arm/kernel/calls.S Thu Aug 1 14:17:40 2002 +++ b/arch/arm/kernel/calls.S Thu Aug 1 14:17:40 2002 @@ -194,8 +194,8 @@ .long sys_rt_sigtimedwait .long sys_rt_sigqueueinfo .long sys_rt_sigsuspend_wrapper -/* 180 */ .long sys_pread - .long sys_pwrite +/* 180 */ .long sys_pread64 + .long sys_pwrite64 .long sys_chown16 .long sys_getcwd .long sys_capget @@ -237,7 +237,7 @@ /* 220 */ .long sys_madvise .long sys_fcntl64 .long sys_ni_syscall /* TUX */ - .long sys_ni_syscall /* Security */ + .long sys_security .long sys_gettid /* 225 */ .long sys_readahead .long sys_setxattr diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S --- a/arch/arm/kernel/entry-armv.S Thu Aug 1 14:17:39 2002 +++ b/arch/arm/kernel/entry-armv.S Thu Aug 1 14:17:39 2002 @@ -725,7 +725,7 @@ msr cpsr_c, r9 mov r2, sp bl do_DataAbort - set_cpsr_c r0, #PSR_I_BIT | MODE_SVC + disable_irq r0 ldr r0, [sp, #S_PSR] msr spsr, r0 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr @@ -776,9 +776,9 @@ movne pc, lr mov r7, #PREEMPT_ACTIVE str r7, [r8, #TI_PREEMPT] @ set PREEMPT_ACTIVE -1: set_cpsr_c r2, #MODE_SVC @ enable IRQs +1: enable_irq r2 @ enable IRQs bl schedule - set_cpsr_c r0, #PSR_I_BIT | MODE_SVC @ disable IRQs + disable_irq r0 @ disable IRQs ldr r0, [r8, #TI_FLAGS] @ get new tasks TI_FLAGS tst r0, #_TIF_NEED_RESCHED beq preempt_return @ go again @@ -801,7 +801,7 @@ mov r0, sp @ struct pt_regs *regs bl do_undefinstr -1: set_cpsr_c r0, #PSR_I_BIT | MODE_SVC +1: disable_irq r0 ldr lr, [sp, #S_PSR] @ Get SVC cpsr msr spsr, lr ldmia sp, {r0 - pc}^ @ Restore SVC registers @@ -822,7 +822,7 @@ mov r0, r2 @ address (pc) mov r1, sp @ regs bl do_PrefetchAbort @ call abort handler - set_cpsr_c r0, #PSR_I_BIT | MODE_SVC + disable_irq r0 ldr r0, [sp, #S_PSR] msr spsr, r0 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr @@ -861,7 +861,7 @@ #else bl CPU_ABORT_HANDLER #endif - set_cpsr_c r2, #MODE_SVC @ Enable interrupts + enable_irq r2 @ Enable interrupts mov r2, sp adrsvc al, lr, ret_from_exception b do_DataAbort @@ -916,7 +916,7 @@ adrsvc al, r9, ret_from_exception @ r9 = normal FP return adrsvc al, lr, fpundefinstr @ lr = undefined instr return -call_fpe: set_cpsr_c r0, #MODE_SVC @ Enable interrupts +call_fpe: enable_irq r0 @ Enable interrupts get_thread_info r10 @ get current thread ldr r4, [r10, #TI_TASK] @ get current task mov r8, #1 @@ -939,7 +939,7 @@ stmdb r8, {sp, lr}^ @ Save sp_usr lr_usr alignment_trap r4, r7, __temp_abt zero_fp - set_cpsr_c r0, #MODE_SVC @ Enable interrupts + enable_irq r0 @ Enable interrupts mov r0, r5 @ address (pc) mov r1, sp @ regs bl do_PrefetchAbort @ call abort handler diff -Nru a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S --- a/arch/arm/kernel/entry-common.S Thu Aug 1 14:17:36 2002 +++ b/arch/arm/kernel/entry-common.S Thu Aug 1 14:17:36 2002 @@ -35,18 +35,27 @@ * stack. */ ret_fast_syscall: - set_cpsr_c r1, #PSR_I_BIT | MODE_SVC @ disable interrupts + disable_irq r1 @ disable interrupts ldr r1, [tsk, #TI_FLAGS] tst r1, #_TIF_WORK_MASK - bne ret_fast_work + bne fast_work_pending fast_restore_user_regs /* * Ok, we need to do extra processing, enter the slow path. */ -ret_fast_work: - str r0, [sp, #S_R0+S_OFF]! @ returned r0 - b work_pending +fast_work_pending: + str r0, [sp, #S_R0+S_OFF]! @ returned r0 +work_pending: + tst r1, #_TIF_NEED_RESCHED + bne work_resched + tst r1, #_TIF_NOTIFY_RESUME | _TIF_SIGPENDING + beq no_work_pending + mov r0, sp @ 'regs' + mov r2, why @ 'syscall' + bl do_notify_resume + disable_irq r1 @ disable interrupts + b no_work_pending work_resched: bl schedule @@ -55,22 +64,12 @@ */ ENTRY(ret_to_user) ret_slow_syscall: - set_cpsr_c r1, #PSR_I_BIT | MODE_SVC @ disable interrupts + disable_irq r1 @ disable interrupts ldr r1, [tsk, #TI_FLAGS] tst r1, #_TIF_WORK_MASK - beq no_work_pending -work_pending: - tst r1, #_TIF_NEED_RESCHED - bne work_resched - tst r1, #_TIF_NOTIFY_RESUME | _TIF_SIGPENDING - blne __do_notify_resume + bne work_pending no_work_pending: - restore_user_regs - -__do_notify_resume: - mov r0, sp @ 'regs' - mov r2, why @ 'syscall' - b do_notify_resume @ note the bl above sets lr + slow_restore_user_regs /* * This is how we return from a fork. @@ -80,9 +79,9 @@ bl schedule_tail #endif get_thread_info tsk - ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing + ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing mov why, #1 - tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? + tst r1, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? beq ret_slow_syscall mov r1, sp mov r0, #1 @ trace exit [IP = 1] @@ -134,7 +133,7 @@ ldr ip, [ip] mcr p15, 0, ip, c1, c0 @ update control register #endif - enable_irqs ip + enable_irq ip str r4, [sp, #-S_OFF]! @ push fifth arg diff -Nru a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S --- a/arch/arm/kernel/entry-header.S Thu Aug 1 14:17:40 2002 +++ b/arch/arm/kernel/entry-header.S Thu Aug 1 14:17:40 2002 @@ -11,13 +11,13 @@ #define MODE_SVC 0x13 #endif - .macro zero_fp + .macro zero_fp #ifndef CONFIG_NO_FRAME_POINTER - mov fp, #0 + mov fp, #0 #endif - .endm + .endm - .text + .text @ Bad Abort numbers @ ----------------- @@ -69,119 +69,146 @@ #define S_OFF 8 #ifdef CONFIG_CPU_32 - .macro save_user_regs - sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - r12} @ Calling r0 - r12 - add r8, sp, #S_PC - stmdb r8, {sp, lr}^ @ Calling sp, lr - mrs r8, spsr @ called from non-FIQ mode, so ok. - str lr, [sp, #S_PC] @ Save calling PC - str r8, [sp, #S_PSR] @ Save CPSR - str r0, [sp, #S_OLD_R0] @ Save OLD_R0 - .endm - - .macro restore_user_regs - ldr r0, [sp, #S_PSR] @ Get calling cpsr - mov ip, #PSR_I_BIT | MODE_SVC - msr cpsr_c, ip @ disable IRQs - msr spsr, r0 @ save in spsr_svc - ldr lr, [sp, #S_PC] @ Get PC - ldmia sp, {r0 - lr}^ @ Get calling r0 - lr - mov r0, r0 - add sp, sp, #S_FRAME_SIZE - movs pc, lr @ return & move spsr_svc into cpsr - .endm - - .macro fast_restore_user_regs - mov ip, #PSR_I_BIT | MODE_SVC - msr cpsr_c, ip @ disable IRQs - ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr - ldr lr, [sp, #S_OFF + S_PC]! @ get pc - msr spsr, r1 @ save in spsr_svc - ldmdb sp, {r1 - lr}^ @ get calling r1 - lr - mov r0, r0 - add sp, sp, #S_FRAME_SIZE - S_PC - movs pc, lr @ return & move spsr_svc into cpsr - .endm - - .macro mask_pc, rd, rm - .endm - - .macro enable_irqs, temp - mov \temp, #MODE_SVC - msr cpsr_c, \temp - .endm - - .macro get_thread_info, rd - mov \rd, sp, lsr #13 - mov \rd, \rd, lsl #13 - .endm - - /* - * Like adr, but force SVC mode (if required) - */ - .macro adrsvc, cond, reg, label - adr\cond \reg, \label - .endm - .macro alignment_trap, rbase, rtemp, sym + .macro set_cpsr_c, reg, mode +#if 1 + /* broken binutils */ + mov \reg, \mode + msr cpsr_c, \reg +#else + msr cpsr_c, \mode +#endif + .endm + + .macro disable_irq, temp + set_cpsr_c \temp, #PSR_I_BIT | MODE_SVC + .endm + + .macro enable_irq, temp + set_cpsr_c \temp, #MODE_SVC + .endm + + .macro save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0 - r12 + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Calling sp, lr + mrs r8, spsr @ called from non-FIQ mode, so ok. + str lr, [sp, #S_PC] @ Save calling PC + str r8, [sp, #S_PSR] @ Save CPSR + str r0, [sp, #S_OLD_R0] @ Save OLD_R0 + .endm + + .macro restore_user_regs + ldr r1, [sp, #S_PSR] @ Get calling cpsr + disable_irq ip @ disable IRQs + ldr lr, [sp, #S_PC]! @ Get PC + msr spsr, r1 @ save in spsr_svc + ldmdb sp, {r0 - lr}^ @ Get calling r0 - lr + mov r0, r0 + add sp, sp, #S_FRAME_SIZE - S_PC + movs pc, lr @ return & move spsr_svc into cpsr + .endm + +/* + * Must be called with IRQs already disabled. + */ + .macro fast_restore_user_regs + ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr + ldr lr, [sp, #S_OFF + S_PC]! @ get pc + msr spsr, r1 @ save in spsr_svc + ldmdb sp, {r1 - lr}^ @ get calling r1 - lr + mov r0, r0 + add sp, sp, #S_FRAME_SIZE - S_PC + movs pc, lr @ return & move spsr_svc into cpsr + .endm + +/* + * Must be called with IRQs already disabled. + */ + .macro slow_restore_user_regs + ldr r1, [sp, #S_PSR] @ get calling cpsr + ldr lr, [sp, #S_PC]! @ get pc + msr spsr, r1 @ save in spsr_svc + ldmdb sp, {r0 - lr}^ @ get calling r1 - lr + mov r0, r0 + add sp, sp, #S_FRAME_SIZE - S_PC + movs pc, lr @ return & move spsr_svc into cpsr + .endm + + .macro mask_pc, rd, rm + .endm + + .macro get_thread_info, rd + mov \rd, sp, lsr #13 + mov \rd, \rd, lsl #13 + .endm + +/* + * Like adr, but force SVC mode (if required) + */ + .macro adrsvc, cond, reg, label + adr\cond \reg, \label + .endm + + .macro alignment_trap, rbase, rtemp, sym #ifdef CONFIG_ALIGNMENT_TRAP #define OFF_CR_ALIGNMENT(x) cr_alignment - x - ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)] - mcr p15, 0, \rtemp, c1, c0 + ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)] + mcr p15, 0, \rtemp, c1, c0 #endif - .endm + .endm #else - .macro save_user_regs - str r0, [sp, #-4]! - str lr, [sp, #-4]! - sub sp, sp, #15*4 - stmia sp, {r0 - lr}^ - mov r0, r0 - .endm - - .macro restore_user_regs - ldmia sp, {r0 - lr}^ - mov r0, r0 - ldr lr, [sp, #15*4] - add sp, sp, #15*4+8 - movs pc, lr - .endm - - .macro fast_restore_user_regs - add sp, sp, #S_OFF - ldmib sp, {r1 - lr}^ - mov r0, r0 - ldr lr, [sp, #15*4] - add sp, sp, #15*4+8 - movs pc, lr - .endm - - .macro mask_pc, rd, rm - bic \rd, \rm, #PCMASK - .endm - - .macro enable_irqs, temp - teqp pc, #0x00000003 - .endm - - .macro initialise_traps_extra - .endm - - .macro get_thread_info, rd - mov \rd, sp, lsr #13 - mov \rd, \rd, lsl #13 - .endm - - /* - * Like adr, but force SVC mode (if required) - */ - .macro adrsvc, cond, reg, label - adr\cond \reg, \label - orr\cond \reg, \reg, #0x08000003 - .endm + .macro save_user_regs + str r0, [sp, #-4]! + str lr, [sp, #-4]! + sub sp, sp, #15*4 + stmia sp, {r0 - lr}^ + mov r0, r0 + .endm + + .macro restore_user_regs + ldmia sp, {r0 - lr}^ + mov r0, r0 + ldr lr, [sp, #15*4] + add sp, sp, #15*4+8 + movs pc, lr + .endm + + .macro fast_restore_user_regs + add sp, sp, #S_OFF + ldmib sp, {r1 - lr}^ + mov r0, r0 + ldr lr, [sp, #15*4] + add sp, sp, #15*4+8 + movs pc, lr + .endm + + .macro mask_pc, rd, rm + bic \rd, \rm, #PCMASK + .endm + + .macro enable_irqs, temp + teqp pc, #0x00000003 + .endm + + .macro initialise_traps_extra + .endm + + .macro get_thread_info, rd + mov \rd, sp, lsr #13 + mov \rd, \rd, lsl #13 + .endm + + /* + * Like adr, but force SVC mode (if required) + */ + .macro adrsvc, cond, reg, label + adr\cond \reg, \label + orr\cond \reg, \reg, #0x08000003 + .endm #endif @@ -215,13 +242,3 @@ ldr scno, [lr, #-4] @ get SWI instruction #endif .endm - - .macro set_cpsr_c, reg, mode -#if 1 - mov \reg, \mode - msr cpsr_c, \reg -#else - msr cpsr_c, \mode -#endif - .endm - diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c --- a/arch/arm/kernel/irq.c Thu Aug 1 14:17:36 2002 +++ b/arch/arm/kernel/irq.c Thu Aug 1 14:17:36 2002 @@ -217,14 +217,14 @@ desc->triggered = 1; - irq_enter(cpu, irq); + irq_enter(); kstat.irqs[cpu][irq]++; action = desc->action; if (action) __do_irq(irq, desc->action, regs); - irq_exit(cpu, irq); + irq_exit(); } /* @@ -256,7 +256,7 @@ */ desc->running = 1; - irq_enter(cpu, irq); + irq_enter(); kstat.irqs[cpu][irq]++; do { @@ -274,7 +274,7 @@ __do_irq(irq, action, regs); } while (desc->pending); - irq_exit(cpu, irq); + irq_exit(); desc->running = 0; @@ -311,7 +311,7 @@ desc->chip->ack(irq); if (likely(desc->enabled)) { - irq_enter(cpu, irq); + irq_enter(); kstat.irqs[cpu][irq]++; /* @@ -325,7 +325,7 @@ !check_irq_lock(desc, irq, regs))) desc->chip->unmask(irq); } - irq_exit(cpu, irq); + irq_exit(); } } diff -Nru a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c --- a/arch/arm/kernel/ptrace.c Thu Aug 1 14:17:36 2002 +++ b/arch/arm/kernel/ptrace.c Thu Aug 1 14:17:36 2002 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -654,6 +655,9 @@ if (request == PTRACE_TRACEME) { /* are we already being traced? */ if (current->ptrace & PT_PTRACED) + goto out; + ret = security_ops->ptrace(current->parent, current); + if (ret) goto out; /* set the ptrace bit in the process flags. */ current->ptrace |= PT_PTRACED; diff -Nru a/arch/arm/lib/kbd.c b/arch/arm/lib/kbd.c --- a/arch/arm/lib/kbd.c Thu Aug 1 14:17:40 2002 +++ b/arch/arm/lib/kbd.c Thu Aug 1 14:17:40 2002 @@ -1,13 +1,279 @@ #include #include +#include +#include -int (*k_setkeycode)(unsigned int, unsigned int); -int (*k_getkeycode)(unsigned int); -int (*k_translate)(unsigned char, unsigned char *, char); -char (*k_unexpected_up)(unsigned char); +/* + * Translation of escaped scancodes to keycodes. + * This is now user-settable. + * The keycodes 1-88,96-111,119 are fairly standard, and + * should probably not be changed - changing might confuse X. + * X also interprets scancode 0x5d (KEY_Begin). + * + * For 1-88 keycode equals scancode. + */ + +#define E0_KPENTER 96 +#define E0_RCTRL 97 +#define E0_KPSLASH 98 +#define E0_PRSCR 99 +#define E0_RALT 100 +#define E0_BREAK 101 /* (control-pause) */ +#define E0_HOME 102 +#define E0_UP 103 +#define E0_PGUP 104 +#define E0_LEFT 105 +#define E0_RIGHT 106 +#define E0_END 107 +#define E0_DOWN 108 +#define E0_PGDN 109 +#define E0_INS 110 +#define E0_DEL 111 + +/* for USB 106 keyboard */ +#define E0_YEN 124 +#define E0_BACKSLASH 89 + + +#define E1_PAUSE 119 + +/* + * The keycodes below are randomly located in 89-95,112-118,120-127. + * They could be thrown away (and all occurrences below replaced by 0), + * but that would force many users to use the `setkeycodes' utility, where + * they needed not before. It does not matter that there are duplicates, as + * long as no duplication occurs for any single keyboard. + */ +#define SC_LIM 89 + +#define FOCUS_PF1 85 /* actual code! */ +#define FOCUS_PF2 89 +#define FOCUS_PF3 90 +#define FOCUS_PF4 91 +#define FOCUS_PF5 92 +#define FOCUS_PF6 93 +#define FOCUS_PF7 94 +#define FOCUS_PF8 95 +#define FOCUS_PF9 120 +#define FOCUS_PF10 121 +#define FOCUS_PF11 122 +#define FOCUS_PF12 123 + +#define JAP_86 124 +/* tfj@olivia.ping.dk: + * The four keys are located over the numeric keypad, and are + * labelled A1-A4. It's an rc930 keyboard, from + * Regnecentralen/RC International, Now ICL. + * Scancodes: 59, 5a, 5b, 5c. + */ +#define RGN1 124 +#define RGN2 125 +#define RGN3 126 +#define RGN4 127 + +static unsigned char high_keys[128 - SC_LIM] = { + RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ + 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */ + 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */ + FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */ + FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */ +}; + +/* BTC */ +#define E0_MACRO 112 +/* LK450 */ +#define E0_F13 113 +#define E0_F14 114 +#define E0_HELP 115 +#define E0_DO 116 +#define E0_F17 117 +#define E0_KPMINPLUS 118 +/* + * My OmniKey generates e0 4c for the "OMNI" key and the + * right alt key does nada. [kkoller@nyx10.cs.du.edu] + */ +#define E0_OK 124 +/* + * New microsoft keyboard is rumoured to have + * e0 5b (left window button), e0 5c (right window button), + * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU] + * [or: Windows_L, Windows_R, TaskMan] + */ +#define E0_MSLW 125 +#define E0_MSRW 126 +#define E0_MSTM 127 + +static unsigned char e0_keys[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */ + 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */ + 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */ + E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */ + E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */ + E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END, /* 0x48-0x4f */ + E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */ + 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ + 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */ + //0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ + 0, 0, 0, 0, 0, E0_BACKSLASH, 0, 0, /* 0x70-0x77 */ + 0, 0, 0, E0_YEN, 0, 0, 0, 0 /* 0x78-0x7f */ +}; + +static int gen_setkeycode(unsigned int scancode, unsigned int keycode) +{ + if (scancode < SC_LIM || scancode > 255 || keycode > 127) + return -EINVAL; + if (scancode < 128) + high_keys[scancode - SC_LIM] = keycode; + else + e0_keys[scancode - 128] = keycode; + return 0; +} + +static int gen_getkeycode(unsigned int scancode) +{ + return + (scancode < SC_LIM || scancode > 255) ? -EINVAL : + (scancode < + 128) ? high_keys[scancode - SC_LIM] : e0_keys[scancode - 128]; +} + +static int +gen_translate(unsigned char scancode, unsigned char *keycode, char raw_mode) +{ + static int prev_scancode = 0; + + /* special prefix scancodes.. */ + if (scancode == 0xe0 || scancode == 0xe1) { + prev_scancode = scancode; + return 0; + } + + /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */ + if (scancode == 0x00 || scancode == 0xff) { + prev_scancode = 0; + return 0; + } + + scancode &= 0x7f; + + if (prev_scancode) { + /* + * usually it will be 0xe0, but a Pause key generates + * e1 1d 45 e1 9d c5 when pressed, and nothing when released + */ + if (prev_scancode != 0xe0) { + if (prev_scancode == 0xe1 && scancode == 0x1d) { + prev_scancode = 0x100; + return 0; + } + else if (prev_scancode == 0x100 + && scancode == 0x45) { + *keycode = E1_PAUSE; + prev_scancode = 0; + } else { +#ifdef KBD_REPORT_UNKN + if (!raw_mode) + printk(KERN_INFO + "keyboard: unknown e1 escape sequence\n"); +#endif + prev_scancode = 0; + return 0; + } + } else { + prev_scancode = 0; + /* + * The keyboard maintains its own internal caps lock and + * num lock statuses. In caps lock mode E0 AA precedes make + * code and E0 2A follows break code. In num lock mode, + * E0 2A precedes make code and E0 AA follows break code. + * We do our own book-keeping, so we will just ignore these. + */ + /* + * For my keyboard there is no caps lock mode, but there are + * both Shift-L and Shift-R modes. The former mode generates + * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs. + * So, we should also ignore the latter. - aeb@cwi.nl + */ + if (scancode == 0x2a || scancode == 0x36) + return 0; + + if (e0_keys[scancode]) + *keycode = e0_keys[scancode]; + else { +#ifdef KBD_REPORT_UNKN + if (!raw_mode) + printk(KERN_INFO + "keyboard: unknown scancode e0 %02x\n", + scancode); +#endif + return 0; + } + } + } else if (scancode >= SC_LIM) { + /* This happens with the FOCUS 9000 keyboard + Its keys PF1..PF12 are reported to generate + 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f + Moreover, unless repeated, they do not generate + key-down events, so we have to zero up_flag below */ + /* Also, Japanese 86/106 keyboards are reported to + generate 0x73 and 0x7d for \ - and \ | respectively. */ + /* Also, some Brazilian keyboard is reported to produce + 0x73 and 0x7e for \ ? and KP-dot, respectively. */ + + *keycode = high_keys[scancode - SC_LIM]; + + if (!*keycode) { + if (!raw_mode) { +#ifdef KBD_REPORT_UNKN + printk(KERN_INFO + "keyboard: unrecognized scancode (%02x)" + " - ignored\n", scancode); +#endif + } + return 0; + } + } else + *keycode = scancode; + return 1; +} + +static char gen_unexpected_up(unsigned char keycode) +{ + /* unexpected, but this can happen: maybe this was a key release for a + FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */ + if (keycode >= SC_LIM || keycode == 85) + return 0; + else + return 0200; +} + +/* + * These are the default mappings + */ +int (*k_setkeycode)(unsigned int, unsigned int) = gen_setkeycode; +int (*k_getkeycode)(unsigned int) = gen_getkeycode; +int (*k_translate)(unsigned char, unsigned char *, char) = gen_translate; +char (*k_unexpected_up)(unsigned char) = gen_unexpected_up; void (*k_leds)(unsigned char); +/* Simple translation table for the SysRq keys */ + #ifdef CONFIG_MAGIC_SYSRQ -int k_sysrq_key; -unsigned char *k_sysrq_xlate; +static unsigned char gen_sysrq_xlate[128] = + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ + "\r\000/"; /* 0x60 - 0x6f */ + +unsigned char *k_sysrq_xlate = gen_sysrq_xlate; +int k_sysrq_key = 0x54; #endif diff -Nru a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c --- a/arch/arm/mach-integrator/cpu.c Thu Aug 1 14:17:40 2002 +++ b/arch/arm/mach-integrator/cpu.c Thu Aug 1 14:17:40 2002 @@ -1,9 +1,9 @@ /* * linux/arch/arm/mach-integrator/cpu.c * - * Copyright (C) 2001 Deep Blue Solutions Ltd. + * Copyright (C) 2001-2002 Deep Blue Solutions Ltd. * - * $Id: cpu.c,v 1.5 2002/07/06 16:53:17 rmk Exp $ + * $Id: cpu.c,v 1.6 2002/07/18 13:58:51 rmk Exp $ * * 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 @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include #include #include @@ -42,7 +45,7 @@ #ifdef CONFIG_CPU_FREQ /* - * Divisor indexes for in ascending divisor order + * Divisor indexes in ascending divisor order */ static unsigned char s2od[] = { 1, 3, 4, 7, 5, 2, 6, 0 }; @@ -70,7 +73,8 @@ * Validate the speed in khz. If it is outside our * range, then return the lowest. */ -unsigned int integrator_validatespeed(unsigned int freq_khz) +static unsigned int +integrator_validatespeed(unsigned int cpu, unsigned int freq_khz) { struct vco vco; @@ -87,11 +91,21 @@ return vco_to_freq(vco, 1); } -void integrator_setspeed(unsigned int freq_khz) +static void integrator_setspeed(unsigned int cpu, unsigned int freq_khz) { struct vco vco = freq_to_vco(freq_khz, 1); + unsigned long cpus_allowed; u_int cm_osc; + /* + * Save this threads cpus_allowed mask, and bind to the + * specified CPU. When this call returns, we should be + * running on the right CPU. + */ + cpus_allowed = current->cpus_allowed; + set_cpus_allowed(current, 1 << cpu); + BUG_ON(cpu != smp_processor_id()); + cm_osc = __raw_readl(CM_OSC); cm_osc &= 0xfffff800; cm_osc |= vco.vdw | vco.od << 8; @@ -99,44 +113,72 @@ __raw_writel(0xa05f, CM_LOCK); __raw_writel(cm_osc, CM_OSC); __raw_writel(0, CM_LOCK); + + /* + * Restore the CPUs allowed mask. + */ + set_cpus_allowed(current, cpus_allowed); } + +static struct cpufreq_driver integrator_driver = { + .validate = integrator_validatespeed, + .setspeed = integrator_setspeed, + .sync = 1, +}; #endif -static int __init cpu_init(void) +static int __init integrator_cpu_init(void) { - u_int cm_osc, cm_stat, cpu_freq_khz, mem_freq_khz; - struct vco vco; + struct cpufreq_freqs *freqs; + unsigned long cpus_allowed; + int cpu; + + freqs = kmalloc(sizeof(struct cpufreq_freqs) * NR_CPUS, + GFP_KERNEL); + if (!freqs) { + printk(KERN_ERR "CPU: unable to allocate cpufreqs structure\n"); + return -ENOMEM; + } - cm_osc = __raw_readl(CM_OSC); + cpus_allowed = current->cpus_allowed; + for (cpu = 0; cpu < NR_CPUS; cpu++) { + u_int cm_osc, cm_stat, mem_freq_khz; + struct vco vco; + + if (!cpu_online(cpu)) + continue; + + set_cpus_allowed(current, 1 << cpu); + BUG_ON(cpu != smp_processor_id()); + + cm_stat = __raw_readl(CM_STAT); + cm_osc = __raw_readl(CM_OSC); + vco.od = (cm_osc >> 20) & 7; + vco.vdw = (cm_osc >> 12) & 255; + mem_freq_khz = vco_to_freq(vco, 2); + + printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255); + printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n", + cpu, mem_freq_khz / 1000, mem_freq_khz % 1000); + + vco.od = (cm_osc >> 8) & 7; + vco.vdw = cm_osc & 255; + + freqs[cpu].min = 12000; + freqs[cpu].max = 160000; + freqs[cpu].cur = vco_to_freq(vco, 1); + } - vco.od = (cm_osc >> 20) & 7; - vco.vdw = (cm_osc >> 12) & 255; - mem_freq_khz = vco_to_freq(vco, 2); - - printk(KERN_INFO "Memory clock = %d.%03d MHz\n", - mem_freq_khz / 1000, mem_freq_khz % 1000); - - vco.od = (cm_osc >> 8) & 7; - vco.vdw = cm_osc & 255; - cpu_freq_khz = vco_to_freq(vco, 1); + set_cpus_allowed(current, cpus_allowed); #ifdef CONFIG_CPU_FREQ - { - struct cpufreq_driver cpufreq_driver; - - cpufreq_driver.freq.min = 12000; - cpufreq_driver.freq.max = 160000; - cpufreq_driver.freq.cur = cpu_freq_khz; - cpufreq_driver.validate = &integrator_validatespeed; - cpufreq_driver.setspeed = &integrator_setspeed; - cpufreq_register(cpufreq_driver); - } + integrator_driver.freq = freqs; + cpufreq_register(&integrator_driver); +#else + kfree(freqs); #endif - cm_stat = __raw_readl(CM_STAT); - printk("Module id: %d\n", cm_stat & 255); - return 0; } -__initcall(cpu_init); +__initcall(integrator_cpu_init); diff -Nru a/arch/arm/mach-sa1100/adsbitsy.c b/arch/arm/mach-sa1100/adsbitsy.c --- a/arch/arm/mach-sa1100/adsbitsy.c Thu Aug 1 14:17:36 2002 +++ b/arch/arm/mach-sa1100/adsbitsy.c Thu Aug 1 14:17:36 2002 @@ -18,6 +18,7 @@ #include #include +#include #include #include diff -Nru a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c --- a/arch/arm/mach-sa1100/assabet.c Thu Aug 1 14:17:36 2002 +++ b/arch/arm/mach-sa1100/assabet.c Thu Aug 1 14:17:36 2002 @@ -20,6 +20,7 @@ #include #include +#include #include #include #include diff -Nru a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c --- a/arch/arm/mach-sa1100/badge4.c Thu Aug 1 14:17:36 2002 +++ b/arch/arm/mach-sa1100/badge4.c Thu Aug 1 14:17:36 2002 @@ -22,6 +22,7 @@ #include #include +#include #include #include diff -Nru a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c --- a/arch/arm/mach-sa1100/cpu-sa1100.c Thu Aug 1 14:17:36 2002 +++ b/arch/arm/mach-sa1100/cpu-sa1100.c Thu Aug 1 14:17:36 2002 @@ -91,7 +91,7 @@ #include extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); -extern unsigned int sa11x0_validatespeed(unsigned int khz); +extern unsigned int sa11x0_validatespeed(unsigned int cpu, unsigned int khz); extern unsigned int sa11x0_getspeed(void); typedef struct { @@ -220,29 +220,35 @@ }; -static void sa1100_setspeed(unsigned int khz) +static void sa1100_setspeed(unsigned int cpu, unsigned int khz) { PPCR = sa11x0_freq_to_ppcr(khz); } +static struct cpufreq_freqs sa1100_freqs = { + .min = 59000, + .max = 287000, +}; + +static struct cpufreq_driver sa1100_driver = { + .freq = &sa1100_freqs, + .validate = sa11x0_validatespeed, + .setspeed = sa1100_setspeed, + .sync = 1, +}; + static int __init sa1100_dram_init(void) { int ret = -ENODEV; if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) { - cpufreq_driver_t cpufreq_driver; - ret = cpufreq_register_notifier(&sa1100_dram_block); if (ret) return ret; - cpufreq_driver.freq.min = 59000; - cpufreq_driver.freq.max = 287000; - cpufreq_driver.freq.cur = sa11x0_getspeed(); - cpufreq_driver.validate = &sa11x0_validatespeed; - cpufreq_driver.setspeed = &sa1100_setspeed; + sa1100_freqs.cur = sa11x0_getspeed(); - ret = cpufreq_register(cpufreq_driver);< + ret = cpufreq_register(&sa1100_driver); } return ret; diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c --- a/arch/arm/mach-sa1100/cpu-sa1110.c Thu Aug 1 14:17:36 2002 +++ b/arch/arm/mach-sa1100/cpu-sa1110.c Thu Aug 1 14:17:36 2002 @@ -24,13 +24,14 @@ #include #include +#include #include #include #undef DEBUG extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); -extern unsigned int sa11x0_validatespeed(unsigned int khz); +extern unsigned int sa11x0_validatespeed(unsigned int cpu, unsigned int khz); extern unsigned int sa11x0_getspeed(void); struct sdram_params { @@ -213,7 +214,7 @@ * above, we can match for an exact frequency. If we don't find * an exact match, we will to set the lowest frequency to be safe. */ -static void sa1110_setspeed(unsigned int khz) +static void sa1110_setspeed(unsigned int cpu, unsigned int khz) { struct sdram_params *sdram = &sdram_params; struct sdram_info sd; @@ -284,6 +285,18 @@ sdram_update_refresh(khz, sdram); } +static struct cpufreq_freqs sa1110_freqs = { + .min = 59000, + .max = 287000, +}; + +static struct cpufreq_driver sa1110_driver = { + .freq = &sa1110_freqs, + .validate = sa11x0_validatespeed, + .setspeed = sa1110_setspeed, + .sync = 1, +}; + static int __init sa1110_clk_init(void) { struct sdram_params *sdram = NULL; @@ -298,8 +311,6 @@ sdram = &samsung_km416s4030ct; if (sdram) { - struct cpufreq_driver cpufreq_driver; - printk(KERN_DEBUG "SDRAM: tck: %d trcd: %d trp: %d" " twr: %d refresh: %d cas_latency: %d\n", sdram->tck, sdram->trcd, sdram->trp, @@ -307,15 +318,10 @@ memcpy(&sdram_params, sdram, sizeof(sdram_params)); - sa1110_setspeed(sa11x0_getspeed()); - - cpufreq_driver.freq.min = 59000; - cpufreq_driver.freq.max = 287000; - cpufreq_driver.freq.cur = sa11x0_getspeed(); - cpufreq_driver.validate = &sa11x0_validatespeed; - cpufreq_driver.setspeed = &sa1110_setspeed; + sa1110_freqs.cur = sa11x0_getspeed(); + sa1110_setspeed(0, sa1110_freqs.cur); - return cpufreq_register(cpufreq_driver); + return cpufreq_register(&sa1110_driver); } return 0; diff -Nru a/arch/arm/mach-sa1100/freebird.c b/arch/arm/mach-sa1100/freebird.c --- a/arch/arm/mach-sa1100/freebird.c Thu Aug 1 14:17:36 2002 +++ b/arch/arm/mach-sa1100/freebird.c Thu Aug 1 14:17:36 2002 @@ -9,6 +9,7 @@ #include #include +#include #include #include diff -Nru a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c --- a/arch/arm/mach-sa1100/generic.c Thu Aug 1 14:17:39 2002 +++ b/arch/arm/mach-sa1100/generic.c Thu Aug 1 14:17:39 2002 @@ -71,7 +71,7 @@ * Validate the speed in khz. If we can't generate the precise * frequency requested, round it down (to be on the safe side). */ -unsigned int sa11x0_validatespeed(unsigned int khz) +unsigned int sa11x0_validatespeed(unsigned int cpu, unsigned int khz) { return cclk_frequency_100khz[sa11x0_freq_to_ppcr(khz)] * 100; } diff -Nru a/arch/arm/mach-sa1100/graphicsmaster.c b/arch/arm/mach-sa1100/graphicsmaster.c --- a/arch/arm/mach-sa1100/graphicsmaster.c Thu Aug 1 14:17:40 2002 +++ b/arch/arm/mach-sa1100/graphicsmaster.c Thu Aug 1 14:17:40 2002 @@ -15,6 +15,7 @@ #include #include +#include #include #include diff -Nru a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c --- a/arch/arm/mach-sa1100/h3600.c Thu Aug 1 14:17:37 2002 +++ b/arch/arm/mach-sa1100/h3600.c Thu Aug 1 14:17:37 2002 @@ -27,6 +27,7 @@ #include #include +#include #include #include diff -Nru a/arch/arm/mach-sa1100/huw_webpanel.c b/arch/arm/mach-sa1100/huw_webpanel.c --- a/arch/arm/mach-sa1100/huw_webpanel.c Thu Aug 1 14:17:40 2002 +++ b/arch/arm/mach-sa1100/huw_webpanel.c Thu Aug 1 14:17:40 2002 @@ -8,6 +8,7 @@ #include #include +#include #include #include diff -Nru a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c --- a/arch/arm/mach-sa1100/neponset.c Thu Aug 1 14:17:40 2002 +++ b/arch/arm/mach-sa1100/neponset.c Thu Aug 1 14:17:40 2002 @@ -13,6 +13,7 @@ #include #include +#include #include #include #include diff -Nru a/arch/arm/mach-sa1100/omnimeter.c b/arch/arm/mach-sa1100/omnimeter.c --- a/arch/arm/mach-sa1100/omnimeter.c Thu Aug 1 14:17:36 2002 +++ b/arch/arm/mach-sa1100/omnimeter.c Thu Aug 1 14:17:36 2002 @@ -7,6 +7,7 @@ #include #include +#include #include #include diff -Nru a/arch/arm/mach-sa1100/pfs168.c b/arch/arm/mach-sa1100/pfs168.c --- a/arch/arm/mach-sa1100/pfs168.c Thu Aug 1 14:17:36 2002 +++ b/arch/arm/mach-sa1100/pfs168.c Thu Aug 1 14:17:36 2002 @@ -9,6 +9,7 @@ #include #include +#include #include #include diff -Nru a/arch/arm/mach-sa1100/sa1111.c b/arch/arm/mach-sa1100/sa1111.c --- a/arch/arm/mach-sa1100/sa1111.c Thu Aug 1 14:17:40 2002 +++ b/arch/arm/mach-sa1100/sa1111.c Thu Aug 1 14:17:40 2002 @@ -27,6 +27,7 @@ #include #include +#include #include #include #include diff -Nru a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c --- a/arch/arm/mach-sa1100/system3.c Thu Aug 1 14:17:41 2002 +++ b/arch/arm/mach-sa1100/system3.c Thu Aug 1 14:17:41 2002 @@ -44,9 +44,8 @@ #include #include +#include #include -#include -#include #include #include diff -Nru a/arch/arm/mach-sa1100/yopy.c b/arch/arm/mach-sa1100/yopy.c --- a/arch/arm/mach-sa1100/yopy.c Thu Aug 1 14:17:36 2002 +++ b/arch/arm/mach-sa1100/yopy.c Thu Aug 1 14:17:36 2002 @@ -7,6 +7,7 @@ #include #include +#include #include #include diff -Nru a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c --- a/arch/arm/mm/alignment.c Thu Aug 1 14:17:36 2002 +++ b/arch/arm/mm/alignment.c Thu Aug 1 14:17:36 2002 @@ -399,13 +399,13 @@ eaddr += 4; /* - * For alignment faults on the ARM922T the MMU makes + * For alignment faults on the ARM922T/ARM920T the MMU makes * the FSR (and hence addr) equal to the updated base address * of the multiple access rather than the restored value. - * Switch this messsage off if we've got a ARM922, otherwise + * Switch this messsage off if we've got a ARM92[02], otherwise * [ls]dm alignment faults are noisy! */ -#if !(defined CONFIG_CPU_ARM922T) +#if !(defined CONFIG_CPU_ARM922T) && !(defined CONFIG_CPU_ARM920T) /* * This is a "hint" - we already have eaddr worked out by the * processor for us. diff -Nru a/arch/arm/mm/init.c b/arch/arm/mm/init.c --- a/arch/arm/mm/init.c Thu Aug 1 14:17:36 2002 +++ b/arch/arm/mm/init.c Thu Aug 1 14:17:36 2002 @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c --- a/arch/arm/mm/mm-armv.c Thu Aug 1 14:17:41 2002 +++ b/arch/arm/mm/mm-armv.c Thu Aug 1 14:17:41 2002 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -149,6 +150,7 @@ pte = pmd_page(*pmd); pmd_clear(pmd); + pgtable_remove_rmap(pte); pte_free(pte); pmd_free(pmd); free: diff -Nru a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types --- a/arch/arm/tools/mach-types Thu Aug 1 14:17:40 2002 +++ b/arch/arm/tools/mach-types Thu Aug 1 14:17:40 2002 @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Fri Jul 5 21:32:20 2002 +# Last update: Sat Jul 27 09:56:53 2002 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -175,7 +175,7 @@ iam SA1100_IAM IAM 164 tt530 SA1100_TT530 TT530 165 sam2400 ARCH_SAM2400 SAM2400 166 -jornada56x ARCH_JORNADA56X JORNADA56X 167 +jornada56x SA1100_JORNADA56X JORNADA56X 167 active SA1100_ACTIVE ACTIVE 168 iq80321 ARCH_IQ80321 IQ80321 169 wid SA1100_WID WID 170 @@ -207,3 +207,10 @@ bitbox SA1100_BITBOX BITBOX 196 g200 SA1100_G200 G200 197 gill SA1100_GILL GILL 198 +pxa_mercury ARCH_PXA_MERCURY PXA_MERCURY 199 +ceiva ARCH_CEIVA CEIVA 200 +fret SA1100_FRET FRET 201 +emailphone SA1100_EMAILPHONE EMAILPHONE 202 +h3900 ARCH_H3900 H3900 203 +pxa1 ARCH_PXA1 PXA1 204 +koan369 SA1100_KOAN369 KOAN369 205 diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile --- a/arch/i386/kernel/Makefile Thu Aug 1 14:17:36 2002 +++ b/arch/i386/kernel/Makefile Thu Aug 1 14:17:36 2002 @@ -6,7 +6,7 @@ O_TARGET := kernel.o -export-objs := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o time.o +export-objs := mca.o mtrr.o i386_ksyms.o time.o obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \ diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c --- a/arch/i386/kernel/apic.c Thu Aug 1 14:17:41 2002 +++ b/arch/i386/kernel/apic.c Thu Aug 1 14:17:41 2002 @@ -1140,7 +1140,7 @@ 6: Received illegal vector 7: Illegal register address */ - printk (KERN_ERR "APIC error on CPU%d: %02lx(%02lx)\n", + printk (KERN_INFO "APIC error on CPU%d: %02lx(%02lx)\n", smp_processor_id(), v , v1); irq_exit(); } diff -Nru a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c --- a/arch/i386/kernel/apm.c Thu Aug 1 14:17:36 2002 +++ b/arch/i386/kernel/apm.c Thu Aug 1 14:17:36 2002 @@ -1589,7 +1589,7 @@ p = buf; - if ((num_possible_cpus() == 1) && + if ((num_online_cpus() == 1) && !(error = apm_get_power_status(&bx, &cx, &dx))) { ac_line_status = (bx >> 8) & 0xff; battery_status = bx & 0xff; @@ -1720,7 +1720,7 @@ } } - if (debug && (num_possible_cpus() == 1)) { + if (debug && (num_online_cpus() == 1)) { error = apm_get_power_status(&bx, &cx, &dx); if (error) printk(KERN_INFO "apm: power status not available\n"); @@ -1764,7 +1764,7 @@ pm_power_off = apm_power_off; register_sysrq_key('o', &sysrq_poweroff_op); - if (num_possible_cpus() == 1) { + if (num_online_cpus() == 1) { #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT) console_blank_hook = apm_console_blank; #endif @@ -1853,6 +1853,7 @@ static int __init apm_init(void) { struct proc_dir_entry *apm_proc; + int i; if (apm_info.bios.version == 0) { printk(KERN_INFO "apm: BIOS not found.\n"); @@ -1907,7 +1908,7 @@ printk(KERN_NOTICE "apm: disabled on user request.\n"); return -ENODEV; } - if ((num_possible_cpus() > 1) && !power_off) { + if ((num_online_cpus() > 1) && !power_off) { printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n"); return -ENODEV; } @@ -1926,37 +1927,39 @@ * NOTE: on SMP we call into the APM BIOS only on CPU#0, so it's * enough to modify CPU#0's GDT. */ - set_base(cpu_gdt_table[0][APM_40 >> 3], - __va((unsigned long)0x40 << 4)); - _set_limit((char *)&cpu_gdt_table[0][APM_40 >> 3], 4095 - (0x40 << 4)); - - apm_bios_entry.offset = apm_info.bios.offset; - apm_bios_entry.segment = APM_CS; - set_base(cpu_gdt_table[0][APM_CS >> 3], - __va((unsigned long)apm_info.bios.cseg << 4)); - set_base(cpu_gdt_table[0][APM_CS_16 >> 3], - __va((unsigned long)apm_info.bios.cseg_16 << 4)); - set_base(cpu_gdt_table[0][APM_DS >> 3], - __va((unsigned long)apm_info.bios.dseg << 4)); + for (i = 0; i < NR_CPUS; i++) { + set_base(cpu_gdt_table[i][APM_40 >> 3], + __va((unsigned long)0x40 << 4)); + _set_limit((char *)&cpu_gdt_table[i][APM_40 >> 3], 4095 - (0x40 << 4)); + + apm_bios_entry.offset = apm_info.bios.offset; + apm_bios_entry.segment = APM_CS; + set_base(cpu_gdt_table[i][APM_CS >> 3], + __va((unsigned long)apm_info.bios.cseg << 4)); + set_base(cpu_gdt_table[i][APM_CS_16 >> 3], + __va((unsigned long)apm_info.bios.cseg_16 << 4)); + set_base(cpu_gdt_table[i][APM_DS >> 3], + __va((unsigned long)apm_info.bios.dseg << 4)); #ifndef APM_RELAX_SEGMENTS - if (apm_info.bios.version == 0x100) { + if (apm_info.bios.version == 0x100) { #endif - /* For ASUS motherboard, Award BIOS rev 110 (and others?) */ - _set_limit((char *)&cpu_gdt_table[0][APM_CS >> 3], 64 * 1024 - 1); - /* For some unknown machine. */ - _set_limit((char *)&cpu_gdt_table[0][APM_CS_16 >> 3], 64 * 1024 - 1); - /* For the DEC Hinote Ultra CT475 (and others?) */ - _set_limit((char *)&cpu_gdt_table[0][APM_DS >> 3], 64 * 1024 - 1); + /* For ASUS motherboard, Award BIOS rev 110 (and others?) */ + _set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], 64 * 1024 - 1); + /* For some unknown machine. */ + _set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3], 64 * 1024 - 1); + /* For the DEC Hinote Ultra CT475 (and others?) */ + _set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3], 64 * 1024 - 1); #ifndef APM_RELAX_SEGMENTS - } else { - _set_limit((char *)&cpu_gdt_table[0][APM_CS >> 3], - (apm_info.bios.cseg_len - 1) & 0xffff); - _set_limit((char *)&cpu_gdt_table[0][APM_CS_16 >> 3], - (apm_info.bios.cseg_16_len - 1) & 0xffff); - _set_limit((char *)&cpu_gdt_table[0][APM_DS >> 3], - (apm_info.bios.dseg_len - 1) & 0xffff); - } + } else { + _set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], + (apm_info.bios.cseg_len - 1) & 0xffff); + _set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3], + (apm_info.bios.cseg_16_len - 1) & 0xffff); + _set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3], + (apm_info.bios.dseg_len - 1) & 0xffff); + } #endif + } apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info); if (apm_proc) @@ -1964,7 +1967,7 @@ kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD); - if (num_possible_cpus() > 1) { + if (num_online_cpus() > 1) { printk(KERN_NOTICE "apm: disabled - APM is not SMP safe (power off active).\n"); return 0; diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S --- a/arch/i386/kernel/entry.S Thu Aug 1 14:17:39 2002 +++ b/arch/i386/kernel/entry.S Thu Aug 1 14:17:39 2002 @@ -689,8 +689,8 @@ .long sys_rt_sigtimedwait .long sys_rt_sigqueueinfo .long sys_rt_sigsuspend - .long sys_pread /* 180 */ - .long sys_pwrite + .long sys_pread64 /* 180 */ + .long sys_pwrite64 .long sys_chown16 .long sys_getcwd .long sys_capget diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c --- a/arch/i386/kernel/i386_ksyms.c Thu Aug 1 14:17:40 2002 +++ b/arch/i386/kernel/i386_ksyms.c Thu Aug 1 14:17:40 2002 @@ -132,6 +132,7 @@ EXPORT_SYMBOL_NOVERS(__read_lock_failed); /* Global SMP stuff */ +EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL(smp_call_function); /* TLB flushing */ diff -Nru a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c --- a/arch/i386/kernel/i8259.c Thu Aug 1 14:17:41 2002 +++ b/arch/i386/kernel/i8259.c Thu Aug 1 14:17:41 2002 @@ -38,7 +38,8 @@ static void end_8259A_irq (unsigned int irq) { - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && + irq_desc[irq].action) enable_8259A_irq(irq); } diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Thu Aug 1 14:17:40 2002 +++ b/arch/i386/kernel/io_apic.c Thu Aug 1 14:17:40 2002 @@ -791,7 +791,7 @@ entry.vector = vector; /* - * The timer IRQ doesnt have to know that behind the + * The timer IRQ doesn't have to know that behind the * scene we have a 8259A-master in AEOI mode ... */ irq_desc[0].handler = &ioapic_edge_irq_type; @@ -1654,7 +1654,7 @@ printk(" failed.\n"); if (nmi_watchdog) { - printk(KERN_WARNING "timer doesnt work through the IO-APIC - disabling NMI Watchdog!\n"); + printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); nmi_watchdog = 0; } diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c --- a/arch/i386/kernel/irq.c Thu Aug 1 14:17:36 2002 +++ b/arch/i386/kernel/irq.c Thu Aug 1 14:17:36 2002 @@ -187,10 +187,6 @@ #if CONFIG_SMP inline void synchronize_irq(unsigned int irq) { - /* is there anything to synchronize with? */ - if (!irq_desc[irq].action) - return; - while (irq_desc[irq].status & IRQ_INPROGRESS) cpu_relax(); } @@ -350,7 +346,7 @@ * use the action we have. */ action = NULL; - if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { action = desc->action; status &= ~IRQ_PENDING; /* we commit to handling */ status |= IRQ_INPROGRESS; /* we are handling it */ @@ -363,7 +359,7 @@ a different instance of this same irq, the other processor will take care of it. */ - if (!action) + if (unlikely(!action)) goto out; /* @@ -381,12 +377,12 @@ handle_IRQ_event(irq, ®s, action); spin_lock(&desc->lock); - if (!(desc->status & IRQ_PENDING)) + if (likely(!(desc->status & IRQ_PENDING))) break; desc->status &= ~IRQ_PENDING; } - desc->status &= ~IRQ_INPROGRESS; out: + desc->status &= ~IRQ_INPROGRESS; /* * The ->end() handler has to deal with interrupts which got * disabled while the handler was running. diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c --- a/arch/i386/kernel/process.c Thu Aug 1 14:17:36 2002 +++ b/arch/i386/kernel/process.c Thu Aug 1 14:17:36 2002 @@ -476,32 +476,42 @@ } /* + * This gets run with %ebx containing the + * function to call, and %edx containing + * the "args". + */ +extern void kernel_thread_helper(void); +__asm__(".align 4\n" + "kernel_thread_helper:\n\t" + "movl %edx,%eax\n\t" + "pushl %edx\n\t" + "call *%ebx\n\t" + "pushl %eax\n\t" + "call do_exit"); + +/* * Create a kernel thread */ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { - long retval, d0; + struct task_struct *p; + struct pt_regs regs; - __asm__ __volatile__( - "movl %%esp,%%esi\n\t" - "int $0x80\n\t" /* Linux/i386 system call */ - "cmpl %%esp,%%esi\n\t" /* child or parent? */ - "je 1f\n\t" /* parent - jump */ - /* Load the argument into eax, and push it. That way, it does - * not matter whether the called function is compiled with - * -mregparm or not. */ - "movl %4,%%eax\n\t" - "pushl %%eax\n\t" - "call *%5\n\t" /* call fn */ - "movl %3,%0\n\t" /* exit */ - "int $0x80\n" - "1:\t" - :"=&a" (retval), "=&S" (d0) - :"0" (__NR_clone), "i" (__NR_exit), - "r" (arg), "r" (fn), - "b" (flags | CLONE_VM) - : "memory"); - return retval; + memset(®s, 0, sizeof(regs)); + + regs.ebx = (unsigned long) fn; + regs.edx = (unsigned long) arg; + + regs.xds = __KERNEL_DS; + regs.xes = __KERNEL_DS; + regs.orig_eax = -1; + regs.eip = (unsigned long) kernel_thread_helper; + regs.xcs = __KERNEL_CS; + regs.eflags = 0x286; + + /* Ok, create the new process.. */ + p = do_fork(flags | CLONE_VM, 0, ®s, 0); + return IS_ERR(p) ? PTR_ERR(p) : p->pid; } /* @@ -675,6 +685,14 @@ tss->esp0 = next->esp0; /* + * Load the per-thread Thread-Local Storage descriptor. + * + * NOTE: it's faster to do the two stores unconditionally + * than to branch away. + */ + load_TLS_desc(next, cpu); + + /* * Save away %fs and %gs. No need to save %es and %ds, as * those are always kernel segments while inside the kernel. */ @@ -690,14 +708,6 @@ } /* - * Load the per-thread Thread-Local Storage descriptor. - * - * NOTE: it's faster to do the two stores unconditionally - * than to branch away. - */ - load_TLS_desc(next, cpu); - - /* * Now maybe reload the debug registers */ if (unlikely(next->debugreg[7])) { @@ -831,34 +841,16 @@ /* * Set the Thread-Local Storage area: */ -asmlinkage int sys_set_thread_area(unsigned int base, unsigned int limit, unsigned int flags) +asmlinkage int sys_set_thread_area(unsigned long base, unsigned long flags) { struct thread_struct *t = ¤t->thread; - int limit_in_pages = 0, writable = 0; + int writable = 0; int cpu; /* do not allow unused flags */ if (flags & ~TLS_FLAGS_MASK) return -EINVAL; - /* check limit */ - if (limit & 0xfff00000) - return -EINVAL; - - /* - * Clear the TLS? - */ - if (flags & TLS_FLAG_CLEAR) { - cpu = get_cpu(); - t->tls_base = t->tls_limit = t->tls_flags = 0; - t->tls_desc.a = t->tls_desc.b = 0; - load_TLS_desc(t, cpu); - put_cpu(); - return 0; - } - - if (flags & TLS_FLAG_LIMIT_IN_PAGES) - limit_in_pages = 1; if (flags & TLS_FLAG_WRITABLE) writable = 1; @@ -866,15 +858,12 @@ * We must not get preempted while modifying the TLS. */ cpu = get_cpu(); - t->tls_base = base; - t->tls_limit = limit; - t->tls_flags = flags; - t->tls_desc.a = ((base & 0x0000ffff) << 16) | (limit & 0x0ffff); + t->tls_desc.a = ((base & 0x0000ffff) << 16) | 0xffff; t->tls_desc.b = (base & 0xff000000) | ((base & 0x00ff0000) >> 16) | - (limit & 0xf0000) | (writable << 9) | (1 << 15) | - (1 << 22) | (limit_in_pages << 23) | 0x7000; + 0xf0000 | (writable << 9) | (1 << 15) | + (1 << 22) | (1 << 23) | 0x7000; load_TLS_desc(t, cpu); put_cpu(); diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c --- a/arch/i386/mm/init.c Thu Aug 1 14:17:37 2002 +++ b/arch/i386/mm/init.c Thu Aug 1 14:17:37 2002 @@ -54,7 +54,7 @@ #if CONFIG_X86_PAE pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); - set_pgd(pgd, __pgd(__pa(md_table) | _PAGE_PRESENT)); + set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); if (pmd_table != pmd_offset(pgd, 0)) BUG(); #else diff -Nru a/arch/ia64/config.in b/arch/ia64/config.in --- a/arch/ia64/config.in Thu Aug 1 14:17:41 2002 +++ b/arch/ia64/config.in Thu Aug 1 14:17:41 2002 @@ -71,15 +71,15 @@ if [ "$CONFIG_IA64_SGI_SN1" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ]; then define_bool CONFIG_IA64_SGI_SN y - bool ' Enable extra debugging code' CONFIG_IA64_SGI_SN_DEBUG n + bool ' Enable extra debugging code' CONFIG_IA64_SGI_SN_DEBUG bool ' Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN_SIM bool ' Enable autotest (llsc). Option to run cache test instead of booting' \ - CONFIG_IA64_SGI_AUTOTEST n + CONFIG_IA64_SGI_AUTOTEST define_bool CONFIG_DEVFS_FS y if [ "$CONFIG_DEVFS_FS" = "y" ]; then - bool ' Enable DEVFS Debug Code' CONFIG_DEVFS_DEBUG n + bool ' Enable DEVFS Debug Code' CONFIG_DEVFS_DEBUG fi - bool ' Enable protocol mode for the L1 console' CONFIG_SERIAL_SGI_L1_PROTOCOL y + bool ' Enable protocol mode for the L1 console' CONFIG_SERIAL_SGI_L1_PROTOCOL define_bool CONFIG_DISCONTIGMEM y define_bool CONFIG_IA64_MCA y define_bool CONFIG_NUMA y diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c --- a/arch/ia64/ia32/sys_ia32.c Thu Aug 1 14:17:41 2002 +++ b/arch/ia64/ia32/sys_ia32.c Thu Aug 1 14:17:41 2002 @@ -3648,15 +3648,15 @@ asmlinkage long sys32_pread (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi) { - extern asmlinkage long sys_pread (unsigned int, char *, size_t, loff_t); - return sys_pread(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo); + extern asmlinkage long sys_pread64 (unsigned int, char *, size_t, loff_t); + return sys_pread64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo); } asmlinkage long sys32_pwrite (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi) { - extern asmlinkage long sys_pwrite (unsigned int, const char *, size_t, loff_t); - return sys_pwrite(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo); + extern asmlinkage long sys_pwrite64 (unsigned int, const char *, size_t, loff_t); + return sys_pwrite64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo); } asmlinkage long diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S --- a/arch/ia64/kernel/entry.S Thu Aug 1 14:17:39 2002 +++ b/arch/ia64/kernel/entry.S Thu Aug 1 14:17:39 2002 @@ -1134,8 +1134,8 @@ data8 sys_flock // 1145 data8 sys_readv data8 sys_writev - data8 sys_pread - data8 sys_pwrite + data8 sys_pread64 + data8 sys_pwrite64 data8 sys_sysctl // 1150 data8 sys_mmap data8 sys_munmap diff -Nru a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile --- a/arch/ia64/lib/Makefile Thu Aug 1 14:17:41 2002 +++ b/arch/ia64/lib/Makefile Thu Aug 1 14:17:41 2002 @@ -4,7 +4,7 @@ L_TARGET = lib.a -export-objs := io.o swiotlb.o +export-objs := swiotlb.o obj-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \ __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o \ diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c --- a/arch/ia64/mm/init.c Thu Aug 1 14:17:40 2002 +++ b/arch/ia64/mm/init.c Thu Aug 1 14:17:40 2002 @@ -167,10 +167,10 @@ #ifdef CONFIG_DISCONTIGMEM { - pg_data_t *pgdat = pgdat_list; + pg_data_t *pgdat; printk("Free swap: %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); - do { + for_each_pgdat(pgdat) { printk("Node ID: %d\n", pgdat->node_id); for(i = 0; i < pgdat->node_size; i++) { if (PageReserved(pgdat->node_mem_map+i)) @@ -184,8 +184,7 @@ printk("\t%d reserved pages\n", reserved); printk("\t%d pages shared\n", shared); printk("\t%d pages swap cached\n", cached); - pgdat = pgdat->node_next; - } while (pgdat); + } printk("Total of %ld pages in page table cache\n", pgtable_cache_size); printk("%d free buffer pages\n", nr_free_buffer_pages()); } diff -Nru a/arch/ia64/sn/io/Makefile b/arch/ia64/sn/io/Makefile --- a/arch/ia64/sn/io/Makefile Thu Aug 1 14:17:39 2002 +++ b/arch/ia64/sn/io/Makefile Thu Aug 1 14:17:39 2002 @@ -18,7 +18,7 @@ O_TARGET := sgiio.o ifeq ($(CONFIG_MODULES),y) -export-objs = pciio.o hcl.o pci_dma.o +export-objs = pciio.o hcl.o endif obj-y := stubs.o sgi_if.o pciio.o xtalk.o xbow.o xswitch.o klgraph_hack.o \ diff -Nru a/arch/ia64/sn/io/hcl.c b/arch/ia64/sn/io/hcl.c --- a/arch/ia64/sn/io/hcl.c Thu Aug 1 14:17:39 2002 +++ b/arch/ia64/sn/io/hcl.c Thu Aug 1 14:17:39 2002 @@ -673,8 +673,9 @@ * Call devfs to get the devfs entry. */ namelen = (int) strlen(name); - target_handle = devfs_find_handle (from, name, 0, 0, + target_handle = devfs_get_handle(from, name, 0, 0, 0, 1); /* Yes traverse symbolic links */ + devfs_put(target_handle); /* Assume we're the owner */ if (target_handle == NULL) return(-1); else @@ -952,12 +953,13 @@ devfs_handle_t *vertex_handle_ptr, char **remainder) { - *vertex_handle_ptr = devfs_find_handle(start_vertex_handle, /* start dir */ + *vertex_handle_ptr = devfs_get_handle(start_vertex_handle, /* start dir */ lookup_path, /* path */ 0, /* major */ 0, /* minor */ 0, /* char | block */ 1); /* traverse symlinks */ + devfs_put(*vertex_handle_ptr); /* Assume we're the owner */ if (*vertex_handle_ptr == NULL) return(-1); else @@ -965,22 +967,23 @@ } /* - * hwgraph_traverse - Find and return the devfs handle starting from de. + * hwgraph_traverse - Find and return the devfs handle starting from dir. * */ graph_error_t -hwgraph_traverse(devfs_handle_t de, char *path, devfs_handle_t *found) +hwgraph_traverse(devfs_handle_t dir, char *path, devfs_handle_t *found) { /* * get the directory entry (path should end in a directory) */ - *found = devfs_find_handle(de, /* start dir */ + *found = devfs_get_handle(dir, /* start dir */ path, /* path */ 0, /* major */ 0, /* minor */ 0, /* char | block */ 1); /* traverse symlinks */ + devfs_put(*found); /* Assume we're the owner */ if (*found == NULL) return(GRAPH_NOT_FOUND); else @@ -994,12 +997,16 @@ devfs_handle_t hwgraph_path_to_vertex(char *path) { - return(devfs_find_handle(NULL, /* start dir */ + devfs_handle_t de; + + de = devfs_get_handle(NULL, /* start dir */ path, /* path */ 0, /* major */ 0, /* minor */ 0, /* char | block */ - 1)); /* traverse symlinks */ + 1); + devfs_put(de); /* Assume we're the owner */ + return(de); } /* @@ -1017,32 +1024,40 @@ /* * hwgraph_block_device_get - return the handle of the block device file. - * The assumption here is that de is a directory. + * The assumption here is that dir is a directory. */ devfs_handle_t -hwgraph_block_device_get(devfs_handle_t de) +hwgraph_block_device_get(devfs_handle_t dir) { - return(devfs_find_handle(de, /* start dir */ + devfs_handle_t de; + + de = devfs_get_handle(dir, /* start dir */ "block", /* path */ 0, /* major */ 0, /* minor */ DEVFS_SPECIAL_BLK, /* char | block */ - 1)); /* traverse symlinks */ + 1); /* traverse symlinks */ + devfs_put(de); /* Assume we're the owner */ + return(de); } /* * hwgraph_char_device_get - return the handle of the char device file. - * The assumption here is that de is a directory. + * The assumption here is that dir is a directory. */ devfs_handle_t -hwgraph_char_device_get(devfs_handle_t de) +hwgraph_char_device_get(devfs_handle_t dir) { - return(devfs_find_handle(de, /* start dir */ + devfs_handle_t de; + + de = devfs_get_handle(dir, /* start dir */ "char", /* path */ 0, /* major */ 0, /* minor */ DEVFS_SPECIAL_CHR, /* char | block */ - 1)); /* traverse symlinks */ + 1); /* traverse symlinks */ + devfs_put(de); /* Assume we're the owner */ + return(de); } /* diff -Nru a/arch/m68k/atari/joystick.c b/arch/m68k/atari/joystick.c --- a/arch/m68k/atari/joystick.c Thu Aug 1 14:17:36 2002 +++ b/arch/m68k/atari/joystick.c Thu Aug 1 14:17:36 2002 @@ -134,7 +134,7 @@ init_waitqueue_head(&joystick[0].wait); init_waitqueue_head(&joystick[1].wait); - if (devfs_register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops)) + if (register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops)) printk("unable to get major %d for joystick devices\n", MAJOR_NR); devfs_register_series (NULL, "joysticks/digital%u", 2, DEVFS_FL_DEFAULT, MAJOR_NR, 128, S_IFCHR | S_IRUSR | S_IWUSR, diff -Nru a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S --- a/arch/m68k/kernel/entry.S Thu Aug 1 14:17:36 2002 +++ b/arch/m68k/kernel/entry.S Thu Aug 1 14:17:36 2002 @@ -608,8 +608,8 @@ .long sys_rt_sigtimedwait .long sys_rt_sigqueueinfo .long sys_rt_sigsuspend - .long sys_pread /* 180 */ - .long sys_pwrite + .long sys_pread64 /* 180 */ + .long sys_pwrite64 .long sys_lchown16; .long sys_getcwd .long sys_capget diff -Nru a/arch/mips/baget/Makefile b/arch/mips/baget/Makefile --- a/arch/mips/baget/Makefile Thu Aug 1 14:17:41 2002 +++ b/arch/mips/baget/Makefile Thu Aug 1 14:17:41 2002 @@ -5,7 +5,7 @@ O_TARGET := baget.a -export-objs := vacserial.o vacrtc.o +export-objs := vacserial.o obj-y := baget.o print.o setup.o time.o irq.o bagetIRQ.o \ reset.o wbflush.o obj-$(CONFIG_SERIAL) += vacserial.o diff -Nru a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile --- a/arch/mips/kernel/Makefile Thu Aug 1 14:17:40 2002 +++ b/arch/mips/kernel/Makefile Thu Aug 1 14:17:40 2002 @@ -6,6 +6,7 @@ O_TARGET := kernel.o EXTRA_TARGETS := head.o init_task.o +export-objs := mips_ksyms.o obj-y += branch.o process.o signal.o entry.o \ traps.o ptrace.o vm86.o ioport.o reset.o \ @@ -27,14 +28,12 @@ obj-$(CONFIG_SMP) += smp.o # Old style irq support, going to die in 2.5. -export-objs += old-irq.o obj-$(CONFIG_NEW_IRQ) += irq.o obj-$(CONFIG_ROTTEN_IRQ) += old-irq.o obj-$(CONFIG_I8259) += i8259.o # transition from old time.c to new time.c # some boards uses old-time.c, some use time.c, and some use their own ones -export-objs += old-time.o time.o obj-$(CONFIG_OLD_TIME_C) += old-time.o obj-$(CONFIG_NEW_TIME_C) += time.o diff -Nru a/arch/mips/mm/init.c b/arch/mips/mm/init.c --- a/arch/mips/mm/init.c Thu Aug 1 14:17:41 2002 +++ b/arch/mips/mm/init.c Thu Aug 1 14:17:41 2002 @@ -24,7 +24,6 @@ #include #include #include -#include #ifdef CONFIG_BLK_DEV_INITRD #include #endif diff -Nru a/arch/mips64/kernel/scall_64.S b/arch/mips64/kernel/scall_64.S --- a/arch/mips64/kernel/scall_64.S Thu Aug 1 14:17:36 2002 +++ b/arch/mips64/kernel/scall_64.S Thu Aug 1 14:17:36 2002 @@ -333,8 +333,8 @@ PTR sys_rt_sigtimedwait PTR sys_rt_sigqueueinfo PTR sys_rt_sigsuspend - PTR sys_pread /* 5200 */ - PTR sys_pwrite + PTR sys_pread64 /* 5200 */ + PTR sys_pwrite64 PTR sys_chown PTR sys_getcwd PTR sys_capget diff -Nru a/arch/mips64/mm/init.c b/arch/mips64/mm/init.c --- a/arch/mips64/mm/init.c Thu Aug 1 14:17:36 2002 +++ b/arch/mips64/mm/init.c Thu Aug 1 14:17:36 2002 @@ -21,7 +21,6 @@ #include #include #include -#include #ifdef CONFIG_BLK_DEV_INITRD #include #endif diff -Nru a/arch/ppc/8260_io/Config.in b/arch/ppc/8260_io/Config.in --- a/arch/ppc/8260_io/Config.in Thu Aug 1 14:17:36 2002 +++ b/arch/ppc/8260_io/Config.in Thu Aug 1 14:17:36 2002 @@ -26,7 +26,7 @@ choice 'Type of PHY' \ "LXT970 CONFIG_FCC_LXT970 \ LXT971 CONFIG_FCC_LXT971 \ - QS6612 CONFIG_FCC_QS6612" CONFIG_FCC_LXT971 + QS6612 CONFIG_FCC_QS6612" LXT971 fi fi fi diff -Nru a/arch/ppc/8xx_io/Makefile b/arch/ppc/8xx_io/Makefile --- a/arch/ppc/8xx_io/Makefile Thu Aug 1 14:17:40 2002 +++ b/arch/ppc/8xx_io/Makefile Thu Aug 1 14:17:40 2002 @@ -11,6 +11,8 @@ O_TARGET := 8xx_io.o +export-objs := fec.o + obj-y := commproc.o uart.o obj-$(CONFIG_FEC_ENET) += fec.o diff -Nru a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c --- a/arch/ppc/boot/common/misc-common.c Thu Aug 1 14:17:40 2002 +++ b/arch/ppc/boot/common/misc-common.c Thu Aug 1 14:17:40 2002 @@ -75,7 +75,7 @@ void _vprintk(void(*putc)(const char), const char *fmt0, va_list ap); unsigned char *ISA_io = NULL; -#if defined(CONFIG_SERIAL_CONSOLE) +#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) extern unsigned long com_port; extern int serial_tstc(unsigned long com_port); @@ -96,7 +96,7 @@ int tstc(void) { -#if defined(CONFIG_SERIAL_CONSOLE) +#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) if(keyb_present) return (CRT_tstc() || serial_tstc(com_port)); else @@ -109,10 +109,10 @@ int getc(void) { while (1) { -#if defined(CONFIG_SERIAL_CONSOLE) +#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) if (serial_tstc(com_port)) return (serial_getc(com_port)); -#endif /* CONFIG_SERIAL_CONSOLE */ +#endif /* serial console */ if (keyb_present) if(CRT_tstc()) return (CRT_getc()); @@ -124,11 +124,11 @@ { int x,y; -#if defined(CONFIG_SERIAL_CONSOLE) +#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) serial_putc(com_port, c); if ( c == '\n' ) serial_putc(com_port, '\r'); -#endif /* CONFIG_SERIAL_CONSOLE */ +#endif /* serial console */ x = orig_x; y = orig_y; @@ -171,10 +171,10 @@ y = orig_y; while ( ( c = *s++ ) != '\0' ) { -#if defined(CONFIG_SERIAL_CONSOLE) +#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) serial_putc(com_port, c); if ( c == '\n' ) serial_putc(com_port, '\r'); -#endif /* CONFIG_SERIAL_CONSOLE */ +#endif /* serial console */ if ( c == '\n' ) { x = 0; diff -Nru a/arch/ppc/boot/prep/Makefile b/arch/ppc/boot/prep/Makefile --- a/arch/ppc/boot/prep/Makefile Thu Aug 1 14:17:41 2002 +++ b/arch/ppc/boot/prep/Makefile Thu Aug 1 14:17:41 2002 @@ -27,7 +27,7 @@ OBJCOPY_ARGS = -O elf32-powerpc LIBS = ../lib/zlib.a -boot-$(CONFIG_SERIAL_CONSOLE) += ../common/ns16550.o +boot-$($CONFIG_SERIAL_8250_CONSOLE) += ../common/ns16550.o boot-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o EXTRA_TARGETS := $(boot-y) diff -Nru a/arch/ppc/boot/prep/misc.c b/arch/ppc/boot/prep/misc.c --- a/arch/ppc/boot/prep/misc.c Thu Aug 1 14:17:36 2002 +++ b/arch/ppc/boot/prep/misc.c Thu Aug 1 14:17:36 2002 @@ -56,9 +56,9 @@ char *zimage_start; int zimage_size; -#if defined(CONFIG_SERIAL_CONSOLE) +#if defined(CONFIG_SERIAL_8250_CONSOLE) unsigned long com_port; -#endif /* CONFIG_SERIAL_CONSOLE */ +#endif /* CONFIG_SERIAL_8250_CONSOLE */ #ifdef CONFIG_VGA_CONSOLE char *vidmem = (char *)0xC00B8000; int lines = 25, cols = 80; @@ -135,9 +135,9 @@ unsigned int pci_viddid, pci_did, tulip_pci_base, tulip_base; serial_fixups(); -#if defined(CONFIG_SERIAL_CONSOLE) +#if defined(CONFIG_SERIAL_8250_CONSOLE) com_port = serial_init(0, NULL); -#endif /* CONFIG_SERIAL_CONSOLE */ +#endif /* CONFIG_SERIAL_8250_CONSOLE */ #if defined(CONFIG_VGA_CONSOLE) vga_init((unsigned char *)0xC0000000); #endif /* CONFIG_VGA_CONSOLE */ diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile --- a/arch/ppc/boot/simple/Makefile Thu Aug 1 14:17:36 2002 +++ b/arch/ppc/boot/simple/Makefile Thu Aug 1 14:17:36 2002 @@ -136,9 +136,9 @@ ifeq ($(CONFIG_SERIAL_CONSOLE),y) boot-$(CONFIG_8xx) += m8xx_tty.o boot-$(CONFIG_8260) += m8260_tty.o -boot-$(CONFIG_GT64260_CONSOLE) += gt64260_tty.o -boot-$(CONFIG_SERIAL) += ../common/ns16550.o +boot-$(CONFIG_GT64260_CONSOLE) += gt64260_tty.o endif +boot-$(CONFIG_SERIAL_8250_CONSOLE) += ../common/ns16550.o EXTRA_TARGETS := $(boot-y) LIBS := ../lib/zlib.a diff -Nru a/arch/ppc/boot/simple/misc-spruce.c b/arch/ppc/boot/simple/misc-spruce.c --- a/arch/ppc/boot/simple/misc-spruce.c Thu Aug 1 14:17:40 2002 +++ b/arch/ppc/boot/simple/misc-spruce.c Thu Aug 1 14:17:40 2002 @@ -189,7 +189,7 @@ unsigned char header_type; unsigned int bar0; -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_SERIAL_8250_CONSOLE /* Initialize the serial console port */ com_port = serial_init(0, NULL); #endif diff -Nru a/arch/ppc/config.in b/arch/ppc/config.in --- a/arch/ppc/config.in Thu Aug 1 14:17:36 2002 +++ b/arch/ppc/config.in Thu Aug 1 14:17:36 2002 @@ -365,6 +365,10 @@ bool 'Support for RTAS (RunTime Abstraction Services) in /proc' CONFIG_PPC_RTAS bool 'Support for PReP Residual Data' CONFIG_PREP_RESIDUAL dep_bool ' Support for reading of PReP Residual Data in /proc' CONFIG_PROC_PREPRESIDUAL $CONFIG_PREP_RESIDUAL + define_bool CONFIG_PPCBUG_NVRAM y +fi +if [ "$CONFIG_PPLUS" = "y" -o "$CONFIG_LOPEC" = "y" ]; then + bool 'Enable reading PPCBUG NVRAM during boot' CONFIG_PPCBUG_NVRAM fi bool 'Default bootloader kernel arguments' CONFIG_CMDLINE_BOOL diff -Nru a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile --- a/arch/ppc/kernel/Makefile Thu Aug 1 14:17:40 2002 +++ b/arch/ppc/kernel/Makefile Thu Aug 1 14:17:40 2002 @@ -35,6 +35,7 @@ ifneq ($(CONFIG_PPC_ISERIES),y) obj-$(CONFIG_PCI) += pci-dma.o endif +obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o obj-$(CONFIG_KGDB) += ppc-stub.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_TAU) += temp.o diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c --- a/arch/ppc/kernel/irq.c Thu Aug 1 14:17:39 2002 +++ b/arch/ppc/kernel/irq.c Thu Aug 1 14:17:39 2002 @@ -178,15 +178,6 @@ return 0; } -#if (defined(CONFIG_8xx) || defined(CONFIG_8260)) -/* Name change so we can catch standard drivers that potentially mess up - * the internal interrupt controller on 8xx and 8260. Just bear with me, - * I don't like this either and I am searching a better solution. For - * now, this is what I need. -- Dan - */ -#define request_irq request_8xxirq -#endif - void free_irq(unsigned int irq, void* dev_id) { irq_desc_t *desc; @@ -212,11 +203,7 @@ } spin_unlock_irqrestore(&desc->lock,flags); -#ifdef CONFIG_SMP - /* Wait to make sure it's not being used on another CPU */ - while (desc->status & IRQ_INPROGRESS) - barrier(); -#endif + synchronize_irq(irq); irq_kfree(action); return; } @@ -289,8 +276,8 @@ * * This function may be called from IRQ context. */ - - void disable_irq_nosync(unsigned int irq) + +void disable_irq_nosync(unsigned int irq) { irq_desc_t *desc = irq_desc + irq; unsigned long flags; @@ -320,12 +307,7 @@ void disable_irq(unsigned int irq) { disable_irq_nosync(irq); - - if (!local_irq_count(smp_processor_id())) { - do { - barrier(); - } while (irq_desc[irq].status & IRQ_INPROGRESS); - } + synchronize_irq(irq); } /** @@ -525,11 +507,10 @@ } #ifndef CONFIG_PPC_ISERIES /* iSeries version is in iSeries_pic.c */ -int do_IRQ(struct pt_regs *regs) +void do_IRQ(struct pt_regs *regs) { - int cpu = smp_processor_id(); int irq, first = 1; - hardirq_enter( cpu ); + irq_enter(); /* * Every platform is required to implement ppc_md.get_irq. @@ -546,11 +527,7 @@ if (irq != -2 && first) /* That's not SMP safe ... but who cares ? */ ppc_spurious_interrupts++; - hardirq_exit( cpu ); - - if (softirq_pending(cpu)) - do_softirq(); - return 1; /* lets ret_from_int know we can do checks */ + irq_exit(); } #endif /* CONFIG_PPC_ISERIES */ @@ -582,262 +559,14 @@ } #ifdef CONFIG_SMP -unsigned char global_irq_holder = NO_PROC_ID; -unsigned volatile long global_irq_lock; /* pendantic :long for set_bit--RR*/ - -atomic_t global_bh_count; - -static void show(char * str) +void synchronize_irq(unsigned int irq) { - int cpu = smp_processor_id(); - - printk("\n%s, CPU %d:\n", str, cpu); - printk("irq: [%d %d]\n", - local_irq_count(0), - local_irq_count(1)); - printk("bh: %d [%d %d]\n", - atomic_read(&global_bh_count), - local_bh_count(0), - local_bh_count(1)); -} - -static inline void wait_on_bh(void) -{ - int count = MAXCOUNT; - do { - if (!--count) { - show("wait_on_bh"); - count = ~0; - } - /* nothing .. wait for the other bh's to go away */ - } while (atomic_read(&global_bh_count) != 0); -} - - -static inline void wait_on_irq(int cpu) -{ - int count = MAXCOUNT; - - for (;;) { - - /* - * Wait until all interrupts are gone. Wait - * for bottom half handlers unless we're - * already executing in one.. - */ - if (!irqs_running()) - if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock)) - break; - - /* Duh, we have to loop. Release the lock to avoid deadlocks */ - clear_bit(0,&global_irq_lock); - - for (;;) { - if (!--count) { - show("wait_on_irq"); - count = ~0; - } - local_irq_enable(); - /* - * We have to allow irqs to arrive between local_irq_enable and local_irq_disable - * Some cpus apparently won't cause the interrupt - * for several instructions. We hope that isync will - * catch this --Troy - */ - __asm__ __volatile__ ("isync"); - local_irq_disable(); - if (irqs_running()) - continue; - if (global_irq_lock) - continue; - if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock)) - continue; - if (!test_and_set_bit(0,&global_irq_lock)) - break; - } - } -} - -/* - * This is called when we want to synchronize with - * bottom half handlers. We need to wait until - * no other CPU is executing any bottom half handler. - * - * Don't wait if we're already running in an interrupt - * context or are inside a bh handler. - */ -void synchronize_bh(void) -{ - if (atomic_read(&global_bh_count) && !in_interrupt()) - wait_on_bh(); -} - -/* - * This is called when we want to synchronize with - * interrupts. We may for example tell a device to - * stop sending interrupts: but to make sure there - * are no interrupts that are executing on another - * CPU we need to call this function. - */ -void synchronize_irq(void) -{ - if (irqs_running()) { - /* Stupid approach */ - cli(); - sti(); - } -} - -static inline void get_irqlock(int cpu) -{ - unsigned int loops = MAXCOUNT; - - if (test_and_set_bit(0,&global_irq_lock)) { - /* do we already hold the lock? */ - if ((unsigned char) cpu == global_irq_holder) - return; - /* Uhhuh.. Somebody else got it. Wait.. */ - do { - do { - if (loops-- == 0) { - printk("get_irqlock(%d) waiting, global_irq_holder=%d\n", cpu, global_irq_holder); -#ifdef CONFIG_XMON - xmon(0); -#endif - } - } while (test_bit(0,&global_irq_lock)); - } while (test_and_set_bit(0,&global_irq_lock)); - } - /* - * We also need to make sure that nobody else is running - * in an interrupt context. - */ - wait_on_irq(cpu); - - /* - * Ok, finally.. - */ - global_irq_holder = cpu; -} - -/* - * A global "cli()" while in an interrupt context - * turns into just a local cli(). Interrupts - * should use spinlocks for the (very unlikely) - * case that they ever want to protect against - * each other. - * - * If we already have local interrupts disabled, - * this will not turn a local disable into a - * global one (problems with spinlocks: this makes - * save_flags+cli+sti usable inside a spinlock). - */ -void __global_cli(void) -{ - unsigned long flags; - - local_save_flags(flags); - if (flags & (1 << 15)) { - int cpu = smp_processor_id(); - local_irq_disable(); - if (!local_irq_count(cpu)) - get_irqlock(cpu); - } -} - -void __global_sti(void) -{ - int cpu = smp_processor_id(); - - if (!local_irq_count(cpu)) - release_irqlock(cpu); - local_irq_enable(); -} - -/* - * SMP flags value to restore to: - * 0 - global cli - * 1 - global sti - * 2 - local cli - * 3 - local sti - */ -unsigned long __global_save_flags(void) -{ - int retval; - int local_enabled; - unsigned long flags; - - local_save_flags(flags); - local_enabled = (flags >> 15) & 1; - /* default to local */ - retval = 2 + local_enabled; - - /* check for global flags if we're not in an interrupt */ - if (!local_irq_count(smp_processor_id())) { - if (local_enabled) - retval = 1; - if (global_irq_holder == (unsigned char) smp_processor_id()) - retval = 0; - } - return retval; -} - -int -tb(long vals[], - int max_size) -{ - register unsigned long *orig_sp __asm__ ("r1"); - register unsigned long lr __asm__ ("r3"); - unsigned long *sp; - int i; - - asm volatile ("mflr 3"); - vals[0] = lr; - sp = (unsigned long *) *orig_sp; - sp = (unsigned long *) *sp; - for (i=1; i= Hash_size>>10 ) - return -EINVAL; - - /* minimum size of htab */ - if ( size < 64 ) - return -EINVAL; - - /* make sure it's a multiple of 64k */ - if ( size % 64 ) - return -EINVAL; - - printk("Hash table resize to %luk\n", size); - /* - * We need to rehash all kernel entries for the new htab size. - * Kernel only since we do a flush_tlb_all(). Since it's kernel - * we only need to bother with vsids 0-15. To avoid problems of - * clobbering un-rehashed values we put the htab at a new spot - * and put everything there. - * -- Cort - */ - Hash_size = size<<10; - Hash_mask = (Hash_size >> 6) - 1; - _SDR1 = __pa(Hash) | (Hash_mask >> 10); - flush_tlb_all(); - - reset_SDR1(); -#endif return count; #else /* CONFIG_PPC_STD_MMU */ return 0; diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c --- a/arch/ppc/kernel/ppc_ksyms.c Thu Aug 1 14:17:41 2002 +++ b/arch/ppc/kernel/ppc_ksyms.c Thu Aug 1 14:17:41 2002 @@ -207,12 +207,6 @@ EXPORT_SYMBOL(giveup_altivec); #endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_SMP -EXPORT_SYMBOL(global_irq_lock); -EXPORT_SYMBOL(global_irq_holder); -EXPORT_SYMBOL(__global_cli); -EXPORT_SYMBOL(__global_sti); -EXPORT_SYMBOL(__global_save_flags); -EXPORT_SYMBOL(__global_restore_flags); #ifdef CONFIG_DEBUG_SPINLOCK EXPORT_SYMBOL(_raw_spin_lock); EXPORT_SYMBOL(_raw_spin_unlock); diff -Nru a/arch/ppc/kernel/prep_nvram.c b/arch/ppc/kernel/prep_nvram.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc/kernel/prep_nvram.c Thu Aug 1 14:17:40 2002 @@ -0,0 +1,148 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * arch/ppc/kernel/prep_nvram.c + * + * Copyright (C) 1998 Corey Minyard + * + * This reads the NvRAM on PReP compliant machines (generally from IBM or + * Motorola). Motorola kept the format of NvRAM in their ROM, PPCBUG, the + * same, long after they had stopped producing PReP compliant machines. So + * this code is useful in those cases as well. + * + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static char nvramData[MAX_PREP_NVRAM]; +static NVRAM_MAP *nvram=(NVRAM_MAP *)&nvramData[0]; + +unsigned char __prep prep_nvram_read_val(int addr) +{ + outb(addr, PREP_NVRAM_AS0); + outb(addr>>8, PREP_NVRAM_AS1); + return inb(PREP_NVRAM_DATA); +} + +void __prep prep_nvram_write_val(int addr, + unsigned char val) +{ + outb(addr, PREP_NVRAM_AS0); + outb(addr>>8, PREP_NVRAM_AS1); + outb(val, PREP_NVRAM_DATA); +} + +void __init init_prep_nvram(void) +{ + unsigned char *nvp; + int i; + int nvramSize; + + /* + * The following could fail if the NvRAM were corrupt but + * we expect the boot firmware to have checked its checksum + * before boot + */ + nvp = (char *) &nvram->Header; + for (i=0; iHeader.GEAddress+nvram->Header.GELength; + if(nvramSize>MAX_PREP_NVRAM) + { + /* + * NvRAM is too large + */ + nvram->Header.GELength=0; + return; + } + + /* + * Read the remainder of the PReP NvRAM + */ + nvp = (char *) &nvram->GEArea[0]; + for (i=sizeof(HEADER); iGEArea)) < nvram->Header.GELength) + && (*cp == '\0')) + { + cp++; + } + + if ((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength) { + return cp; + } else { + return NULL; + } +} + + + diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c --- a/arch/ppc/kernel/process.c Thu Aug 1 14:17:40 2002 +++ b/arch/ppc/kernel/process.c Thu Aug 1 14:17:40 2002 @@ -202,8 +202,7 @@ struct thread_struct *new_thread, *old_thread; unsigned long s; - local_save_flags(s); - local_irq_disable(); + local_irq_save(s); #if CHECK_STACK check_stack(prev); check_stack(new); diff -Nru a/arch/ppc/kernel/temp.c b/arch/ppc/kernel/temp.c --- a/arch/ppc/kernel/temp.c Thu Aug 1 14:17:36 2002 +++ b/arch/ppc/kernel/temp.c Thu Aug 1 14:17:36 2002 @@ -124,27 +124,27 @@ void TAUException(struct pt_regs * regs) { - unsigned long cpu = smp_processor_id(); + int cpu = smp_processor_id(); - hardirq_enter(cpu); + irq_enter(); tau[cpu].interrupts++; TAUupdate(cpu); - hardirq_exit(cpu); - return; + irq_exit(); } #endif /* CONFIG_TAU_INT */ static void tau_timeout(void * info) { - unsigned long cpu = smp_processor_id(); + int cpu; unsigned long flags; int size; int shrink; /* disabling interrupts *should* be okay */ - save_flags(flags); cli(); + local_irq_save(flags); + cpu = smp_processor_id(); #ifndef CONFIG_TAU_INT TAUupdate(cpu); @@ -186,7 +186,7 @@ */ mtspr(SPRN_THRM3, THRM3_SITV(500*60) | THRM3_E); - restore_flags(flags); + local_irq_restore(flags); } static void tau_timeout_smp(unsigned long unused) diff -Nru a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c --- a/arch/ppc/kernel/time.c Thu Aug 1 14:17:37 2002 +++ b/arch/ppc/kernel/time.c Thu Aug 1 14:17:37 2002 @@ -75,7 +75,7 @@ unsigned long disarm_decr[NR_CPUS]; -extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); +extern struct timezone sys_tz; /* keep track of when we need to update the rtc */ time_t last_rtc_update; @@ -151,7 +151,7 @@ * with interrupts disabled. * We set it up to overflow again in 1/HZ seconds. */ -int timer_interrupt(struct pt_regs * regs) +void timer_interrupt(struct pt_regs * regs) { int next_dec; unsigned long cpu = smp_processor_id(); @@ -161,7 +161,7 @@ if (atomic_read(&ppc_n_lost_interrupts) != 0) do_IRQ(regs); - hardirq_enter(cpu); + irq_enter(); while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0) { jiffy_stamp += tb_ticks_per_jiffy; @@ -214,12 +214,7 @@ if (ppc_md.heartbeat && !ppc_md.heartbeat_count--) ppc_md.heartbeat(); - hardirq_exit(cpu); - - if (softirq_pending(cpu)) - do_softirq(); - - return 1; /* lets ret_from_int know we can do checks */ + irq_exit(); } #endif /* CONFIG_PPC_ISERIES */ @@ -358,14 +353,11 @@ /* Not exact, but the timer interrupt takes care of this */ set_dec(tb_ticks_per_jiffy); - /* If platform provided a timezone (pmac), we correct the time - * using do_sys_settimeofday() which in turn calls warp_clock() - */ + /* If platform provided a timezone (pmac), we correct the time */ if (time_offset) { - struct timezone tz; - tz.tz_minuteswest = -time_offset / 60; - tz.tz_dsttime = 0; - do_sys_settimeofday(NULL, &tz); + sys_tz.tz_minuteswest = -time_offset / 60; + sys_tz.tz_dsttime = 0; + xtime.tv_sec -= time_offset; } } @@ -373,6 +365,11 @@ #define STARTOFTIME 1970 #define SECDAY 86400L #define SECYR (SECDAY * 365) + +/* + * Note: this is wrong for 2100, but our signed 32-bit time_t will + * have overflowed long before that, so who cares. -- paulus + */ #define leapyear(year) ((year) % 4 == 0) #define days_in_year(a) (leapyear(a) ? 366 : 365) #define days_in_month(a) (month_days[(a) - 1]) diff -Nru a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c --- a/arch/ppc/mm/fault.c Thu Aug 1 14:17:39 2002 +++ b/arch/ppc/mm/fault.c Thu Aug 1 14:17:39 2002 @@ -189,16 +189,18 @@ */ survive: switch (handle_mm_fault(mm, vma, address, is_write)) { - case 1: + case VM_FAULT_MINOR: current->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: current->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; - default: + case VM_FAULT_OOM: goto out_of_memory; + default: + BUG(); } up_read(&mm->mmap_sem); diff -Nru a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h --- a/arch/ppc/mm/mmu_decl.h Thu Aug 1 14:17:40 2002 +++ b/arch/ppc/mm/mmu_decl.h Thu Aug 1 14:17:40 2002 @@ -25,7 +25,6 @@ #include extern void mapin_ram(void); -extern void bat_mapin_ram(void); extern int map_page(unsigned long va, unsigned long pa, int flags); extern void setbat(int index, unsigned long virt, unsigned long phys, unsigned int size, int flags); @@ -49,14 +48,17 @@ #if defined(CONFIG_8xx) #define flush_HPTE(X, va, pg) _tlbie(va) #define MMU_init_hw() do { } while(0) +#define mmu_mapin_ram() (0UL) #elif defined(CONFIG_4xx) #define flush_HPTE(X, va, pg) _tlbie(va) extern void MMU_init_hw(void); +#define mmu_mapin_ram() (0UL) #else /* anything except 4xx or 8xx */ extern void MMU_init_hw(void); +extern unsigned long mmu_mapin_ram(void); /* Be careful....this needs to be updated if we ever encounter 603 SMPs, * which includes all new 82xx processors. We need tlbie/tlbsync here diff -Nru a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c --- a/arch/ppc/mm/pgtable.c Thu Aug 1 14:17:36 2002 +++ b/arch/ppc/mm/pgtable.c Thu Aug 1 14:17:36 2002 @@ -252,31 +252,14 @@ { unsigned long v, p, s, f; -#ifdef HAVE_BATS - if (!__map_without_bats) - bat_mapin_ram(); -#endif /* HAVE_BATS */ - - v = KERNELBASE; - p = PPC_MEMSTART; - for (s = 0; s < total_lowmem; s += PAGE_SIZE) { - /* On the MPC8xx, we want the page shared so we - * don't get ASID compares on kernel space. - */ - f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED | _PAGE_HWEXEC; -#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) - /* Allows stub to set breakpoints everywhere */ - f |= _PAGE_WRENABLE; -#else /* !CONFIG_KGDB && !CONFIG_XMON */ - if ((char *) v < _stext || (char *) v >= etext) - f |= _PAGE_WRENABLE; -#ifdef CONFIG_PPC_STD_MMU + s = mmu_mapin_ram(); + v = KERNELBASE + s; + p = PPC_MEMSTART + s; + for (; s < total_lowmem; s += PAGE_SIZE) { + if ((char *) v >= _stext && (char *) v < etext) + f = _PAGE_RAM_TEXT; else - /* On the powerpc (not all), no user access - forces R/W kernel access */ - f |= _PAGE_USER; -#endif /* CONFIG_PPC_STD_MMU */ -#endif /* CONFIG_KGDB || CONFIG_XMON */ + f = _PAGE_RAM; map_page(v, p, f); v += PAGE_SIZE; p += PAGE_SIZE; diff -Nru a/arch/ppc/mm/ppc_mmu.c b/arch/ppc/mm/ppc_mmu.c --- a/arch/ppc/mm/ppc_mmu.c Thu Aug 1 14:17:36 2002 +++ b/arch/ppc/mm/ppc_mmu.c Thu Aug 1 14:17:36 2002 @@ -87,12 +87,15 @@ return 0; } -void __init bat_mapin_ram(void) +unsigned long __init mmu_mapin_ram(void) { unsigned long tot, bl, done; unsigned long max_size = (256<<20); unsigned long align; + if (__map_without_bats) + return 0; + /* Set up BAT2 and if necessary BAT3 to cover RAM. */ /* Make sure we don't map a block larger than the @@ -119,7 +122,10 @@ break; setbat(3, KERNELBASE+done, PPC_MEMSTART+done, bl, _PAGE_KERNEL); + done = (unsigned long)bat_addrs[3].limit - KERNELBASE + 1; } + + return done; } /* diff -Nru a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c --- a/arch/ppc/mm/tlb.c Thu Aug 1 14:17:41 2002 +++ b/arch/ppc/mm/tlb.c Thu Aug 1 14:17:41 2002 @@ -31,13 +31,42 @@ #include #include #include +#include +#include #include "mmu_decl.h" /* + * Called when unmapping pages to flush entries from the TLB/hash table. + */ +void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr) +{ + unsigned long ptephys; + + if (Hash != 0) { + ptephys = __pa(ptep) & PAGE_MASK; + flush_hash_pages(mm->context, addr, ptephys, 1); + } +} + +/* + * Called at the end of a mmu_gather operation to make sure the + * TLB flush is completely done. + */ +void tlb_flush(mmu_gather_t *tlb) +{ + if (Hash == 0) { + /* + * 603 needs to flush the whole TLB here since + * it doesn't use a hash table. + */ + _tlbia(); + } +} + +/* * 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 @@ -92,29 +121,6 @@ } /* - * Flush all tlb/hash table entries (except perhaps for those - * mapping RAM starting at PAGE_OFFSET, since they never change). - */ -void -flush_tlb_all(void) -{ - /* - * Just flush the kernel part of the address space, that's - * all that the current callers of this require. - * Eventually I hope to persuade the powers that be that - * we can and should dispense with flush_tlb_all(). - * -- paulus. - * - * In fact this should never get called now that we - * have flush_tlb_kernel_range. -- paulus - */ - printk(KERN_ERR "flush_tlb_all called from %p\n", - __builtin_return_address(0)); - flush_range(&init_mm, TASK_SIZE, ~0UL); - FINISH_FLUSH; -} - -/* * Flush kernel TLB entries in the given range */ void flush_tlb_kernel_range(unsigned long start, unsigned long end) @@ -124,24 +130,19 @@ } /* - * Flush all the (user) entries for the address space described - * by mm. We can't rely on mm->mmap describing all the entries - * that might be in the hash table. + * Flush all the (user) entries for the address space described by mm. */ void flush_tlb_mm(struct mm_struct *mm) { + struct vm_area_struct *mp; + if (Hash == 0) { _tlbia(); return; } - if (mm->map_count) { - struct vm_area_struct *mp; - for (mp = mm->mmap; mp != NULL; mp = mp->vm_next) - flush_range(mp->vm_mm, mp->vm_start, mp->vm_end); - } else { - flush_range(mm, 0, TASK_SIZE); - } + for (mp = mm->mmap; mp != NULL; mp = mp->vm_next) + flush_range(mp->vm_mm, mp->vm_start, mp->vm_end); FINISH_FLUSH; } @@ -160,7 +161,6 @@ flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1); FINISH_FLUSH; } - /* * For each address in the range, find the pte for the address diff -Nru a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile --- a/arch/ppc/platforms/Makefile Thu Aug 1 14:17:40 2002 +++ b/arch/ppc/platforms/Makefile Thu Aug 1 14:17:40 2002 @@ -32,7 +32,7 @@ obj-$(CONFIG_ALL_PPC) += pmac_pic.o pmac_setup.o pmac_time.o \ pmac_feature.o pmac_pci.o chrp_setup.o\ chrp_time.o chrp_pci.o prep_pci.o \ - prep_time.o prep_nvram.o prep_setup.o + prep_time.o prep_setup.o ifeq ($(CONFIG_ALL_PPC),y) obj-$(CONFIG_NVRAM) += pmac_nvram.o endif @@ -50,7 +50,7 @@ obj-$(CONFIG_MVME5100) += mvme5100_setup.o mvme5100_pci.o obj-$(CONFIG_PCORE) += pcore_setup.o pcore_pci.o obj-$(CONFIG_POWERPMC250) += powerpmc250.o -obj-$(CONFIG_PPLUS) += pplus_pci.o pplus_setup.o prep_nvram.o +obj-$(CONFIG_PPLUS) += pplus_pci.o pplus_setup.o obj-$(CONFIG_PRPMC750) += prpmc750_setup.o prpmc750_pci.o obj-$(CONFIG_PRPMC800) += prpmc800_setup.o prpmc800_pci.o obj-$(CONFIG_SANDPOINT) += sandpoint_setup.o sandpoint_pci.o diff -Nru a/arch/ppc/platforms/cpc700.h b/arch/ppc/platforms/cpc700.h --- a/arch/ppc/platforms/cpc700.h Thu Aug 1 14:17:40 2002 +++ b/arch/ppc/platforms/cpc700.h Thu Aug 1 14:17:40 2002 @@ -6,7 +6,7 @@ * Author: Mark A. Greer * mgreer@mvista.com * - * Copyright 2000 MontaVista Software Inc. + * Copyright 2000-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 @@ -101,7 +101,7 @@ * UIC Exports... */ extern struct hw_interrupt_type cpc700_pic; -extern unsigned int cpc700_irq_assigns[27][2]; +extern unsigned int cpc700_irq_assigns[32][2]; extern void __init cpc700_init_IRQ(void); extern int cpc700_get_irq(struct pt_regs *); diff -Nru a/arch/ppc/platforms/cpc700_pic.c b/arch/ppc/platforms/cpc700_pic.c --- a/arch/ppc/platforms/cpc700_pic.c Thu Aug 1 14:17:37 2002 +++ b/arch/ppc/platforms/cpc700_pic.c Thu Aug 1 14:17:37 2002 @@ -8,7 +8,7 @@ * mporter@mvista.com * jpeters@mvista.com * - * Copyright 2001 MontaVista Software Inc. + * Copyright 2001-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 @@ -168,7 +168,7 @@ cpc700_pic_init_irq(i); } - for (i = 20; i < 27; i++) { + for (i = 20; i < 32; i++) { irq_desc[i].handler = &cpc700_pic; cpc700_pic_init_irq(i); } diff -Nru a/arch/ppc/platforms/iSeries_pic.c b/arch/ppc/platforms/iSeries_pic.c --- a/arch/ppc/platforms/iSeries_pic.c Thu Aug 1 14:17:40 2002 +++ b/arch/ppc/platforms/iSeries_pic.c Thu Aug 1 14:17:40 2002 @@ -42,7 +42,7 @@ extern void iSeries_smp_message_recv( struct pt_regs * ); unsigned lpEvent_count = 0; -int do_IRQ(struct pt_regs *regs) +void do_IRQ(struct pt_regs *regs) { int cpu = smp_processor_id(); unsigned long flags; @@ -52,7 +52,7 @@ if ( is_soft_enabled() ) BUG(); - hardirq_enter( cpu ); + irq_enter(); paca = (struct Paca *)mfspr(SPRG1); @@ -65,21 +65,16 @@ lpq = paca->lpQueuePtr; if ( lpq ) { - local_save_flags( flags ); - local_irq_disable(); + local_irq_save(flags); lpEvent_count += ItLpQueue_process( lpq, regs ); local_irq_restore( flags ); } - hardirq_exit( cpu ); + irq_exit(); if ( paca->xLpPacaPtr->xDecrInt ) { paca->xLpPacaPtr->xDecrInt = 0; /* Signal a fake decrementer interrupt */ timer_interrupt( regs ); } - - if (softirq_pending(cpu)) - do_softirq(); - return 1; /* lets ret_from_int know we can do checks */ } diff -Nru a/arch/ppc/platforms/iSeries_time.c b/arch/ppc/platforms/iSeries_time.c --- a/arch/ppc/platforms/iSeries_time.c Thu Aug 1 14:17:40 2002 +++ b/arch/ppc/platforms/iSeries_time.c Thu Aug 1 14:17:40 2002 @@ -102,7 +102,7 @@ int timerRetDisabled = 0; extern unsigned long iSeries_dec_value; -int timer_interrupt(struct pt_regs * regs) +void timer_interrupt(struct pt_regs * regs) { long next_dec; struct Paca * paca; @@ -117,7 +117,7 @@ else timerRetDisabled++; - hardirq_enter(cpu); + irq_enter(); if (!user_mode(regs)) ppc_do_profile(instruction_pointer(regs)); @@ -149,9 +149,5 @@ paca->xLpPacaPtr->xDecrInt = 0; set_dec( (unsigned)next_dec ); - hardirq_exit(cpu); - - if (softirq_pending(cpu)) - do_softirq(); - return 1; + irq_exit(); } diff -Nru a/arch/ppc/platforms/lopec_setup.c b/arch/ppc/platforms/lopec_setup.c --- a/arch/ppc/platforms/lopec_setup.c Thu Aug 1 14:17:36 2002 +++ b/arch/ppc/platforms/lopec_setup.c Thu Aug 1 14:17:36 2002 @@ -33,7 +33,9 @@ #include #include #include +#include +extern char saved_command_line[]; extern void lopec_find_bridges(void); /* @@ -332,6 +334,21 @@ #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; +#endif +#ifdef CONFIG_PPCBUG_NVRAM + /* Read in NVRAM data */ + init_prep_nvram(); + + /* if no bootargs, look in NVRAM */ + if ( cmd_line[0] == '\0' ) { + char *bootargs; + bootargs = prep_nvram_get_var("bootargs"); + if (bootargs != NULL) { + strcpy(cmd_line, bootargs); + /* again.. */ + strcpy(saved_command_line, cmd_line); + } + } #endif } diff -Nru a/arch/ppc/platforms/pplus_setup.c b/arch/ppc/platforms/pplus_setup.c --- a/arch/ppc/platforms/pplus_setup.c Thu Aug 1 14:17:41 2002 +++ b/arch/ppc/platforms/pplus_setup.c Thu Aug 1 14:17:41 2002 @@ -9,7 +9,7 @@ * Cort Dougan, Johnnie Peters, Matt Porter, and * Troy Benjegerdes. * - * Copyright 2001 MontaVista Software Inc. + * Copyright 2001-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 @@ -76,8 +76,9 @@ TODC_ALLOC(); -extern void pplus_setup_hose(void); +extern char saved_command_line[]; +extern void pplus_setup_hose(void); extern void pplus_set_VIA_IDE_native(void); extern unsigned long loops_per_jiffy; @@ -131,7 +132,8 @@ ROOT_DEV = Root_SDA2; #endif - printk("PowerPlus port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n"); + printk(KERN_INFO "Motorola PowerPlus Platform\n"); + printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); if ( ppc_md.progress ) ppc_md.progress("pplus_setup_arch: raven_init\n", 0); @@ -144,6 +146,21 @@ conswitchp = &vga_con; #elif defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con; +#endif +#ifdef CONFIG_PPCBUG_NVRAM + /* Read in NVRAM data */ + init_prep_nvram(); + + /* if no bootargs, look in NVRAM */ + if ( cmd_line[0] == '\0' ) { + char *bootargs; + bootargs = prep_nvram_get_var("bootargs"); + if (bootargs != NULL) { + strcpy(cmd_line, bootargs); + /* again.. */ + strcpy(saved_command_line, cmd_line); + } + } #endif if ( ppc_md.progress ) ppc_md.progress("pplus_setup_arch: exit\n", 0); diff -Nru a/arch/ppc/platforms/prep_nvram.c b/arch/ppc/platforms/prep_nvram.c --- a/arch/ppc/platforms/prep_nvram.c Thu Aug 1 14:17:40 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,143 +0,0 @@ -/* - * BK Id: %F% %I% %G% %U% %#% - */ -/* - * arch/ppc/platforms/prep_nvram.c - * - * Copyright (C) 1998 Corey Minyard - * - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -static char nvramData[MAX_PREP_NVRAM]; -static NVRAM_MAP *nvram=(NVRAM_MAP *)&nvramData[0]; - -unsigned char __prep prep_nvram_read_val(int addr) -{ - outb(addr, PREP_NVRAM_AS0); - outb(addr>>8, PREP_NVRAM_AS1); - return inb(PREP_NVRAM_DATA); -} - -void __prep prep_nvram_write_val(int addr, - unsigned char val) -{ - outb(addr, PREP_NVRAM_AS0); - outb(addr>>8, PREP_NVRAM_AS1); - outb(val, PREP_NVRAM_DATA); -} - -void __init init_prep_nvram(void) -{ - unsigned char *nvp; - int i; - int nvramSize; - - /* - * The following could fail if the NvRAM were corrupt but - * we expect the boot firmware to have checked its checksum - * before boot - */ - nvp = (char *) &nvram->Header; - for (i=0; iHeader.GEAddress+nvram->Header.GELength; - if(nvramSize>MAX_PREP_NVRAM) - { - /* - * NvRAM is too large - */ - nvram->Header.GELength=0; - return; - } - - /* - * Read the remainder of the PReP NvRAM - */ - nvp = (char *) &nvram->GEArea[0]; - for (i=sizeof(HEADER); iGEArea)) < nvram->Header.GELength) - && (*cp == '\0')) - { - cp++; - } - - if ((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength) { - return cp; - } else { - return NULL; - } -} - - - diff -Nru a/arch/ppc/platforms/spruce_setup.c b/arch/ppc/platforms/spruce_setup.c --- a/arch/ppc/platforms/spruce_setup.c Thu Aug 1 14:17:36 2002 +++ b/arch/ppc/platforms/spruce_setup.c Thu Aug 1 14:17:36 2002 @@ -6,7 +6,7 @@ * Authors: Johnnie Peters * Matt Porter * - * Copyright 2001 MontaVista Software Inc. + * Copyright 2001-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 @@ -70,7 +70,7 @@ * * First entry is the sensitivity (level/edge), second is the polarity. */ -unsigned int cpc700_irq_assigns[27][2] = { +unsigned int cpc700_irq_assigns[32][2] = { { 1, 1 }, /* IRQ 0: ECC Correctable Error - rising edge */ { 1, 1 }, /* IRQ 1: PCI Write Mem Range - rising edge */ { 0, 1 }, /* IRQ 2: PCI Write Command Reg - active high */ diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile Thu Aug 1 14:17:41 2002 +++ b/arch/ppc64/kernel/Makefile Thu Aug 1 14:17:41 2002 @@ -9,7 +9,7 @@ O_TARGET := kernel.o EXTRA_TARGETS := $(KHEAD) -export-objs := ppc_ksyms.o setup.o +export-objs := ppc_ksyms.o obj-y := ppc_ksyms.o setup.o entry.o traps.o irq.o idle.o \ time.o process.o signal.o syscalls.o misc.o ptrace.o \ diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Thu Aug 1 14:17:40 2002 +++ b/arch/ppc64/kernel/misc.S Thu Aug 1 14:17:40 2002 @@ -916,8 +916,8 @@ .llong .sys_rt_sigtimedwait .llong .sys_rt_sigqueueinfo .llong .sys_rt_sigsuspend - .llong .sys_pread - .llong .sys_pwrite /* 180 */ + .llong .sys_pread64 + .llong .sys_pwrite64 /* 180 */ .llong .sys_chown .llong .sys_getcwd .llong .sys_capget diff -Nru a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S --- a/arch/s390/kernel/entry.S Thu Aug 1 14:17:36 2002 +++ b/arch/s390/kernel/entry.S Thu Aug 1 14:17:36 2002 @@ -520,8 +520,8 @@ .long sys_rt_sigtimedwait .long sys_rt_sigqueueinfo .long sys_rt_sigsuspend_glue - .long sys_pread /* 180 */ - .long sys_pwrite + .long sys_pread64 /* 180 */ + .long sys_pwrite64 .long sys_chown16 .long sys_getcwd .long sys_capget diff -Nru a/arch/s390/mm/init.c b/arch/s390/mm/init.c --- a/arch/s390/mm/init.c Thu Aug 1 14:17:36 2002 +++ b/arch/s390/mm/init.c Thu Aug 1 14:17:36 2002 @@ -189,7 +189,7 @@ totalram_pages++; } printk ("Freeing unused kernel memory: %dk freed\n", - (&__init_end - &__init_begin) >> 10); + ((unsigned long)&__init_end - (unsigned long)&__init_begin) >> 10); } #ifdef CONFIG_BLK_DEV_INITRD diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c --- a/arch/s390x/kernel/linux32.c Thu Aug 1 14:17:36 2002 +++ b/arch/s390x/kernel/linux32.c Thu Aug 1 14:17:36 2002 @@ -3980,10 +3980,10 @@ } -extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf, +extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf, size_t count, loff_t pos); -extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf, +extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf, size_t count, loff_t pos); typedef __kernel_ssize_t32 ssize_t32; @@ -3991,13 +3991,13 @@ asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf, __kernel_size_t32 count, u32 poshi, u32 poslo) { - return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); + return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf, __kernel_size_t32 count, u32 poshi, u32 poslo) { - return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); + return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count); diff -Nru a/arch/s390x/mm/init.c b/arch/s390x/mm/init.c --- a/arch/s390x/mm/init.c Thu Aug 1 14:17:40 2002 +++ b/arch/s390x/mm/init.c Thu Aug 1 14:17:40 2002 @@ -201,7 +201,7 @@ totalram_pages++; } printk ("Freeing unused kernel memory: %ldk freed\n", - (&__init_end - &__init_begin) >> 10); + ((unsigned long)&__init_end - (unsigned long)&__init_begin) >> 10); } #ifdef CONFIG_BLK_DEV_INITRD diff -Nru a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile --- a/arch/sh/kernel/Makefile Thu Aug 1 14:17:40 2002 +++ b/arch/sh/kernel/Makefile Thu Aug 1 14:17:40 2002 @@ -5,7 +5,8 @@ O_TARGET := kernel.o EXTRA_TARGETS := head.o init_task.o -export-objs := io.o io_generic.o io_hd64461.o setup_hd64461.o sh_ksyms.o +export-objs := io.o io_generic.o io_hd64465.o setup_hd64465.o sh_ksyms.o \ + io_adx.o io_bigsur.o io_cat68701.o hd64465_gpio.o obj-y := process.o signal.o entry.o traps.o irq.o irq_ipr.o \ ptrace.o setup.o time.o sys_sh.o semaphore.o \ diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S --- a/arch/sparc/kernel/systbls.S Thu Aug 1 14:17:40 2002 +++ b/arch/sparc/kernel/systbls.S Thu Aug 1 14:17:40 2002 @@ -31,7 +31,7 @@ /*50*/ .long sys_getegid16, sys_acct, sys_nis_syscall, sys_getgid, sys_ioctl /*55*/ .long sys_reboot, sys_mmap2, sys_symlink, sys_readlink, sys_execve /*60*/ .long sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize -/*65*/ .long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_geteuid +/*65*/ .long sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_geteuid /*70*/ .long sys_getegid, sys_mmap, sys_setreuid, sys_munmap, sys_mprotect /*75*/ .long sys_madvise, sys_vhangup, sys_truncate64, sys_mincore, sys_getgroups16 /*80*/ .long sys_setgroups16, sys_getpgrp, sys_setgroups, sys_setitimer, sys_ftruncate64 diff -Nru a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c --- a/arch/sparc/mm/init.c Thu Aug 1 14:17:40 2002 +++ b/arch/sparc/mm/init.c Thu Aug 1 14:17:40 2002 @@ -18,7 +18,6 @@ #include #include #include -#include #ifdef CONFIG_BLK_DEV_INITRD #include #endif diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c --- a/arch/sparc64/kernel/sys_sparc32.c Thu Aug 1 14:17:41 2002 +++ b/arch/sparc64/kernel/sys_sparc32.c Thu Aug 1 14:17:41 2002 @@ -3878,10 +3878,10 @@ } -extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf, +extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf, size_t count, loff_t pos); -extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf, +extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf, size_t count, loff_t pos); typedef __kernel_ssize_t32 ssize_t32; @@ -3889,13 +3889,13 @@ asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf, __kernel_size_t32 count, u32 poshi, u32 poslo) { - return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); + return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf, __kernel_size_t32 count, u32 poshi, u32 poslo) { - return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); + return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count); diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S --- a/arch/sparc64/kernel/systbls.S Thu Aug 1 14:17:40 2002 +++ b/arch/sparc64/kernel/systbls.S Thu Aug 1 14:17:40 2002 @@ -32,7 +32,7 @@ /*50*/ .word sys32_getegid16, sys_acct, sys_nis_syscall, sys_getgid, sys32_ioctl .word sys_reboot, sys32_mmap2, sys_symlink, sys_readlink, sys32_execve /*60*/ .word sys_umask, sys_chroot, sys32_newfstat, sys_fstat64, sys_getpagesize - .word sys_msync, sys_vfork, sys32_pread, sys32_pwrite, sys_geteuid + .word sys_msync, sys_vfork, sys32_pread64, sys32_pwrite64, sys_geteuid /*70*/ .word sys_getegid, sys32_mmap, sys_setreuid, sys_munmap, sys_mprotect .word sys_madvise, sys_vhangup, sys32_truncate64, sys_mincore, sys32_getgroups16 /*80*/ .word sys32_setgroups16, sys_getpgrp, sys_setgroups, sys32_setitimer, sys32_ftruncate64 diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c --- a/arch/sparc64/mm/init.c Thu Aug 1 14:17:40 2002 +++ b/arch/sparc64/mm/init.c Thu Aug 1 14:17:40 2002 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c --- a/arch/sparc64/solaris/socksys.c Thu Aug 1 14:17:40 2002 +++ b/arch/sparc64/solaris/socksys.c Thu Aug 1 14:17:40 2002 @@ -181,7 +181,7 @@ int (*sys_close)(unsigned int) = (int (*)(unsigned int))SYS(close); - ret = devfs_register_chrdev (30, "socksys", &socksys_fops); + ret = register_chrdev (30, "socksys", &socksys_fops); if (ret < 0) { printk ("Couldn't register socksys character device\n"); return ret; @@ -208,7 +208,7 @@ void cleanup_socksys(void) { - if (devfs_unregister_chrdev(30, "socksys")) + if (unregister_chrdev(30, "socksys")) printk ("Couldn't unregister socksys character device\n"); devfs_unregister (devfs_handle); } diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c --- a/arch/x86_64/ia32/sys_ia32.c Thu Aug 1 14:17:40 2002 +++ b/arch/x86_64/ia32/sys_ia32.c Thu Aug 1 14:17:40 2002 @@ -1948,10 +1948,10 @@ return ret; } -extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf, +extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf, size_t count, loff_t pos); -extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf, +extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf, size_t count, loff_t pos); typedef __kernel_ssize_t32 ssize_t32; @@ -1961,7 +1961,7 @@ sys32_pread(unsigned int fd, char *ubuf, __kernel_size_t32 count, u32 poslo, u32 poshi) { - return sys_pread(fd, ubuf, count, + return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } @@ -1969,7 +1969,7 @@ sys32_pwrite(unsigned int fd, char *ubuf, __kernel_size_t32 count, u32 poslo, u32 poshi) { - return sys_pwrite(fd, ubuf, count, + return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } diff -Nru a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile --- a/arch/x86_64/kernel/Makefile Thu Aug 1 14:17:37 2002 +++ b/arch/x86_64/kernel/Makefile Thu Aug 1 14:17:37 2002 @@ -5,7 +5,7 @@ O_TARGET := kernel.o EXTRA_TARGETS := head.o head64.o init_task.o -export-objs := mtrr.o msr.o cpuid.o x8664_ksyms.o +export-objs := mtrr.o x8664_ksyms.o obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \ diff -Nru a/drivers/Makefile b/drivers/Makefile --- a/drivers/Makefile Thu Aug 1 14:17:41 2002 +++ b/drivers/Makefile Thu Aug 1 14:17:41 2002 @@ -7,8 +7,9 @@ obj-$(CONFIG_PCI) += pci/ obj-$(CONFIG_ACPI) += acpi/ +obj-y += serial/ obj-$(CONFIG_PARPORT) += parport/ -obj-y += base/ serial/ char/ block/ misc/ net/ media/ +obj-y += base/ char/ block/ misc/ net/ media/ obj-$(CONFIG_NUBUS) += nubus/ obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_IDE) += ide/ diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c --- a/drivers/acorn/block/mfmhd.c Thu Aug 1 14:17:37 2002 +++ b/drivers/acorn/block/mfmhd.c Thu Aug 1 14:17:37 2002 @@ -194,7 +194,6 @@ #define MFM_DRV_INFO mfm_info[raw_cmd.dev] static struct hd_struct mfm[MFM_MAXDRIVES << 6]; -static int mfm_sizes[MFM_MAXDRIVES << 6]; /* Stuff from the assembly routines */ extern unsigned int hdc63463_baseaddress; /* Controller base address */ @@ -1254,12 +1253,20 @@ } } -static struct gendisk mfm_gendisk = { +static struct gendisk mfm_gendisk[2] = { +{ major: MAJOR_NR, + first_minor: 0, major_name: "mfm", minor_shift: 6, part: mfm, - sizes: mfm_sizes, +}, +{ + major: MAJOR_NR, + first_minor: 64, + major_name: "mfm", + minor_shift: 6, + part: mfm + 64, }; static struct block_device_operations mfm_fops = @@ -1277,8 +1284,6 @@ printk("mfm: detected %d hard drive%s\n", mfm_drives, mfm_drives == 1 ? "" : "s"); - mfm_gendisk.nr_real = mfm_drives; - if (request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL)) printk("mfm: unable to get IRQ%d\n", mfm_irq); @@ -1286,8 +1291,10 @@ outw(0x80, mfm_irqenable); /* Required to enable IRQs from MFM podule */ for (i = 0; i < mfm_drives; i++) { + mfm_gendisk[i].nr_real = 1; + add_gendisk(mfm_gendisk + i); mfm_geometry (i); - register_disk(&mfm_gendisk, mk_kdev(MAJOR_NR,i<<6), 1<<6, + register_disk(mfm_gendisk + i, mk_kdev(MAJOR_NR,i<<6), 1<<6, &mfm_fops, mfm_info[i].cylinders * mfm_info[i].heads * mfm_info[i].sectors / 2); @@ -1382,8 +1389,6 @@ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mfm_request); - add_gendisk(&mfm_gendisk); - Busy = 0; lastspecifieddrive = -1; @@ -1421,11 +1426,13 @@ void cleanup_module(void) { + int i; if (ecs && mfm_irqenable) outw (0, mfm_irqenable); /* Required to enable IRQs from MFM podule */ free_irq(mfm_irq, NULL); unregister_blkdev(MAJOR_NR, "mfm"); - del_gendisk(&mfm_gendisk); + for (i = 0; i < mfm_drives; i++) + del_gendisk(mfm_gendisk + i); if (ecs) ecard_release(ecs); if (mfm_addr) diff -Nru a/drivers/acorn/char/Makefile b/drivers/acorn/char/Makefile --- a/drivers/acorn/char/Makefile Thu Aug 1 14:17:36 2002 +++ b/drivers/acorn/char/Makefile Thu Aug 1 14:17:36 2002 @@ -3,8 +3,6 @@ # # All the objects that export symbols. -export-objs := mouse_rpc.o - obj-arc := keyb_arc.o obj-rpc := keyb_ps2.o obj-clps7500 := keyb_ps2.o defkeymap-acorn.o diff -Nru a/drivers/base/base.h b/drivers/base/base.h --- a/drivers/base/base.h Thu Aug 1 14:17:40 2002 +++ b/drivers/base/base.h Thu Aug 1 14:17:40 2002 @@ -17,6 +17,7 @@ extern void device_remove_dir(struct device * dev); extern int device_bus_link(struct device * dev); +extern void device_remove_symlink(struct driver_dir_entry * dir, const char * name); extern int driver_attach(struct device_driver * drv); extern void driver_detach(struct device_driver * drv); diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c --- a/drivers/base/bus.c Thu Aug 1 14:17:39 2002 +++ b/drivers/base/bus.c Thu Aug 1 14:17:39 2002 @@ -140,7 +140,7 @@ void bus_remove_device(struct device * dev) { if (dev->bus) { - driverfs_remove_file(&dev->bus->device_dir,dev->bus_id); + device_remove_symlink(&dev->bus->device_dir,dev->bus_id); write_lock(&dev->bus->lock); list_del_init(&dev->bus_list); write_unlock(&dev->bus->lock); diff -Nru a/drivers/base/fs.c b/drivers/base/fs.c --- a/drivers/base/fs.c Thu Aug 1 14:17:40 2002 +++ b/drivers/base/fs.c Thu Aug 1 14:17:40 2002 @@ -15,7 +15,63 @@ #include #include -extern struct driver_file_entry * device_default_files[]; +extern struct device_attribute * device_default_files[]; + +#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr) + +#define to_device(d) container_of(d, struct device, dir) + + +/* driverfs ops for device attribute files */ + +static int +dev_attr_open(struct driver_dir_entry * dir) +{ + struct device * dev = to_device(dir); + get_device(dev); + return 0; +} + +static int +dev_attr_close(struct driver_dir_entry * dir) +{ + struct device * dev = to_device(dir); + put_device(dev); + return 0; +} + +static ssize_t +dev_attr_show(struct driver_dir_entry * dir, struct attribute * attr, + char * buf, size_t count, loff_t off) +{ + struct device_attribute * dev_attr = to_dev_attr(attr); + struct device * dev = to_device(dir); + ssize_t ret = 0; + + if (dev_attr->show) + ret = dev_attr->show(dev,buf,count,off); + return ret; +} + +static ssize_t +dev_attr_store(struct driver_dir_entry * dir, struct attribute * attr, + const char * buf, size_t count, loff_t off) +{ + struct device_attribute * dev_attr = to_dev_attr(attr); + struct device * dev = to_device(dir); + ssize_t ret = 0; + + if (dev_attr->store) + ret = dev_attr->store(dev,buf,count,off); + return ret; +} + +static struct driverfs_ops dev_attr_ops = { + open: dev_attr_open, + close: dev_attr_close, + show: dev_attr_show, + store: dev_attr_store, +}; /** * device_create_file - create a driverfs file for a device @@ -24,25 +80,15 @@ * * Allocate space for file entry, copy descriptor, and create. */ -int device_create_file(struct device * dev, struct driver_file_entry * entry) +int device_create_file(struct device * dev, struct device_attribute * entry) { - struct driver_file_entry * new_entry; - int error = -ENOMEM; - - if (!dev) - return -EINVAL; - get_device(dev); + int error = -EINVAL; - new_entry = kmalloc(sizeof(*new_entry),GFP_KERNEL); - if (!new_entry) - goto done; - - memcpy(new_entry,entry,sizeof(*entry)); - error = driverfs_create_file(new_entry,&dev->dir); - if (error) - kfree(new_entry); - done: - put_device(dev); + if (dev) { + get_device(dev); + error = driverfs_create_file(&entry->attr,&dev->dir); + put_device(dev); + } return error; } @@ -52,11 +98,11 @@ * @name: name of the file * */ -void device_remove_file(struct device * dev, const char * name) +void device_remove_file(struct device * dev, struct device_attribute * attr) { if (dev) { get_device(dev); - driverfs_remove_file(&dev->dir,name); + driverfs_remove_file(&dev->dir,attr->attr.name); put_device(dev); } } @@ -71,7 +117,6 @@ driverfs_remove_dir(&dev->dir); } - static int get_devpath_length(struct device * dev) { int length = 1; @@ -103,22 +148,6 @@ pr_debug("%s: path = '%s'\n",__FUNCTION__,path); } -static int create_symlink(struct driver_dir_entry * parent, char * name, char * path) -{ - struct driver_file_entry * entry; - int error; - - entry = kmalloc(sizeof(struct driver_file_entry),GFP_KERNEL); - if (!entry) - return -ENOMEM; - entry->name = name; - entry->mode = S_IRUGO; - error = driverfs_create_symlink(parent,entry,path); - if (error) - kfree(entry); - return error; -} - int device_bus_link(struct device * dev) { char * path; @@ -148,15 +177,18 @@ strcpy(path,"../../.."); fill_devpath(dev,path,length); - error = create_symlink(&dev->bus->device_dir,dev->bus_id,path); - + error = driverfs_create_symlink(&dev->bus->device_dir,dev->bus_id,path); kfree(path); return error; } +void device_remove_symlink(struct driver_dir_entry * dir, const char * name) +{ + driverfs_remove_file(dir,name); +} + int device_create_dir(struct driver_dir_entry * dir, struct driver_dir_entry * parent) { - INIT_LIST_HEAD(&dir->files); dir->mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO); return driverfs_create_dir(dir,parent); } @@ -176,13 +208,14 @@ int device_make_dir(struct device * dev) { struct driver_dir_entry * parent = NULL; - struct driver_file_entry * entry; + struct device_attribute * entry; int error; int i; if (dev->parent) parent = &dev->parent->dir; dev->dir.name = dev->bus_id; + dev->dir.ops = &dev_attr_ops; if ((error = device_create_dir(&dev->dir,parent))) return error; diff -Nru a/drivers/base/interface.c b/drivers/base/interface.c --- a/drivers/base/interface.c Thu Aug 1 14:17:36 2002 +++ b/drivers/base/interface.c Thu Aug 1 14:17:36 2002 @@ -14,11 +14,7 @@ return off ? 0 : sprintf(buf,"%s\n",dev->name); } -static struct driver_file_entry device_name_entry = { - name: "name", - mode: S_IRUGO, - show: device_read_name, -}; +static DEVICE_ATTR(name,"name",S_IRUGO,device_read_name,NULL); static ssize_t device_read_power(struct device * dev, char * page, size_t count, loff_t off) @@ -89,15 +85,11 @@ return error < 0 ? error : count; } -static struct driver_file_entry device_power_entry = { - name: "power", - mode: S_IWUSR | S_IRUGO, - show: device_read_power, - store: device_write_power, -}; - -struct driver_file_entry * device_default_files[] = { - &device_name_entry, - &device_power_entry, +static DEVICE_ATTR(power,"power",S_IWUSR | S_IRUGO, + device_read_power,device_write_power); + +struct device_attribute * device_default_files[] = { + &dev_attr_name, + &dev_attr_power, NULL, }; diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c --- a/drivers/block/DAC960.c Thu Aug 1 14:17:41 2002 +++ b/drivers/block/DAC960.c Thu Aug 1 14:17:41 2002 @@ -1934,7 +1934,7 @@ /* Register the Block Device Major Number for this DAC960 Controller. */ - if (devfs_register_blkdev(MajorNumber, "dac960", + if (register_blkdev(MajorNumber, "dac960", &DAC960_BlockDeviceOperations) < 0) { DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n", @@ -1961,7 +1961,6 @@ Controller->MaxSectorsPerRequest[MinorNumber] = Controller->MaxBlocksPerCommand; Controller->GenericDiskInfo.part = Controller->DiskPartitions; - Controller->GenericDiskInfo.sizes = Controller->PartitionSizes; /* Complete initialization of the Generic Disk Information structure. */ @@ -1993,7 +1992,7 @@ /* Unregister the Block Device Major Number for this DAC960 Controller. */ - devfs_unregister_blkdev(MajorNumber, "dac960"); + unregister_blkdev(MajorNumber, "dac960"); /* Remove the I/O Request Queue. */ @@ -2003,7 +2002,6 @@ array, Max Sectors per Request array, and Max Segments per Request array. */ Controller->GenericDiskInfo.part = NULL; - Controller->GenericDiskInfo.sizes = NULL; blk_clear(MajorNumber); /* Remove the Generic Disk Information structure from the list. @@ -5295,7 +5293,7 @@ DAC960_ComputeGenericDiskInfo(Controller); DAC960_RegisterDisk(Controller, LogicalDriveNumber); } - if (Controller->GenericDiskInfo.sizes[minor(Inode->i_rdev)] == 0) + if (Controller->GenericDiskInfo.part[minor(Inode->i_rdev)].nr_sects == 0) return -ENXIO; /* Increment Controller and Logical Drive Usage Counts. diff -Nru a/drivers/block/DAC960.h b/drivers/block/DAC960.h --- a/drivers/block/DAC960.h Thu Aug 1 14:17:41 2002 +++ b/drivers/block/DAC960.h Thu Aug 1 14:17:41 2002 @@ -2473,7 +2473,6 @@ } V2; } FW; DiskPartition_T DiskPartitions[DAC960_MinorCount]; - int PartitionSizes[DAC960_MinorCount]; unsigned char ProgressBuffer[DAC960_ProgressBufferSize]; unsigned char UserStatusBuffer[DAC960_UserMessageSize]; } diff -Nru a/drivers/block/Makefile b/drivers/block/Makefile --- a/drivers/block/Makefile Thu Aug 1 14:17:41 2002 +++ b/drivers/block/Makefile Thu Aug 1 14:17:41 2002 @@ -8,7 +8,8 @@ # In the future, some of these should be built conditionally. # -export-objs := elevator.o ll_rw_blk.o blkpg.o loop.o DAC960.o genhd.o block_ioctl.o +export-objs := elevator.o ll_rw_blk.o blkpg.o loop.o genhd.o \ + block_ioctl.o acsi.o obj-y := elevator.o ll_rw_blk.o blkpg.o genhd.o block_ioctl.o diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c --- a/drivers/block/acsi.c Thu Aug 1 14:17:40 2002 +++ b/drivers/block/acsi.c Thu Aug 1 14:17:40 2002 @@ -56,7 +56,6 @@ #include #include #include -#include #include #include #include @@ -246,7 +245,6 @@ unsigned long phys_acsi_buffer; static int NDevices = 0; -static int acsi_sizes[MAX_DEV<<4] = { 0, }; static struct hd_struct acsi_part[MAX_DEV<<4] = { {0,0}, }; static int access_count[MAX_DEV] = { 0, }; @@ -1360,7 +1358,6 @@ major_name: "ad", minor_shift: 4, part: acsi_part, - sizes: acsi_sizes, fops: &acsi_fops, }; @@ -1741,14 +1738,14 @@ int err = 0; if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI)) return 0; - if (devfs_register_blkdev( MAJOR_NR, "ad", &acsi_fops )) { + if (register_blkdev( MAJOR_NR, "ad", &acsi_fops )) { printk( KERN_ERR "Unable to get major %d for ACSI\n", MAJOR_NR ); return -EBUSY; } if (!(acsi_buffer = (char *)atari_stram_alloc(ACSI_BUFFER_SIZE, "acsi"))) { printk( KERN_ERR "Unable to get ACSI ST-Ram buffer.\n" ); - devfs_unregister_blkdev( MAJOR_NR, "ad" ); + unregister_blkdev( MAJOR_NR, "ad" ); return -ENOMEM; } phys_acsi_buffer = virt_to_phys( acsi_buffer ); @@ -1786,7 +1783,7 @@ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); atari_stram_free( acsi_buffer ); - if (devfs_unregister_blkdev( MAJOR_NR, "ad" ) != 0) + if (unregister_blkdev( MAJOR_NR, "ad" ) != 0) printk( KERN_ERR "acsi: cleanup_module failed\n"); del_gendisk(&acsi_gendisk); diff -Nru a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c --- a/drivers/block/acsi_slm.c Thu Aug 1 14:17:36 2002 +++ b/drivers/block/acsi_slm.c Thu Aug 1 14:17:36 2002 @@ -998,14 +998,14 @@ int slm_init( void ) { - if (devfs_register_chrdev( MAJOR_NR, "slm", &slm_fops )) { + if (register_chrdev( MAJOR_NR, "slm", &slm_fops )) { printk( KERN_ERR "Unable to get major %d for ACSI SLM\n", MAJOR_NR ); return -EBUSY; } if (!(SLMBuffer = atari_stram_alloc( SLM_BUFFER_SIZE, NULL, "SLM" ))) { printk( KERN_ERR "Unable to get SLM ST-Ram buffer.\n" ); - devfs_unregister_chrdev( MAJOR_NR, "slm" ); + unregister_chrdev( MAJOR_NR, "slm" ); return -ENOMEM; } BufferP = SLMBuffer; @@ -1038,7 +1038,7 @@ void cleanup_module(void) { devfs_unregister (devfs_handle); - if (devfs_unregister_chrdev( MAJOR_NR, "slm" ) != 0) + if (unregister_chrdev( MAJOR_NR, "slm" ) != 0) printk( KERN_ERR "acsi_slm: cleanup_module failed\n"); atari_stram_free( SLMBuffer ); } diff -Nru a/drivers/block/blkpg.c b/drivers/block/blkpg.c --- a/drivers/block/blkpg.c Thu Aug 1 14:17:36 2002 +++ b/drivers/block/blkpg.c Thu Aug 1 14:17:36 2002 @@ -86,7 +86,7 @@ g = get_gendisk(dev); if (!g) return -ENXIO; - part = g->part + minor(dev); + part = g->part + minor(dev) - g->first_minor; /* existing drive? */ @@ -109,8 +109,6 @@ /* all seems OK */ part[p->pno].start_sect = pstart; part[p->pno].nr_sects = plength; - if (g->sizes) - g->sizes[minor(dev)+p->pno] = (plength >> (BLOCK_SIZE_BITS-9)); devfs_register_partitions (g, minor(dev), 0); return 0; } @@ -137,7 +135,7 @@ g = get_gendisk(dev); if (!g) return -ENXIO; - part = g->part + minor(dev); + part = g->part + minor(dev) - g->first_minor; if (bdev != bdev->bd_contains) return -EINVAL; @@ -163,8 +161,6 @@ part[p->pno].start_sect = 0; part[p->pno].nr_sects = 0; - if (g->sizes) - g->sizes[minor(dev) + p->pno] = 0; devfs_register_partitions (g, minor(dev), 0); bd_release(bdevp); bdput(bdevp); diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c --- a/drivers/block/cciss.c Thu Aug 1 14:17:41 2002 +++ b/drivers/block/cciss.c Thu Aug 1 14:17:41 2002 @@ -348,8 +348,7 @@ drv = &(hba[ctlr]->drv[i]); if( !(drv->nr_blocks)) continue; - hba[ctlr]->hd[i << NWD_SHIFT].nr_sects = - hba[ctlr]->sizes[i << NWD_SHIFT] = drv->nr_blocks; + hba[ctlr]->hd[i << NWD_SHIFT].nr_sects = drv->nr_blocks; //hba[ctlr]->gendisk.nr_real++; (BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->block_size; } @@ -375,7 +374,7 @@ * but I'm already using way to many device nodes to claim another one * for "raw controller". */ - if (hba[ctlr]->sizes[minor(inode->i_rdev)] == 0) { + if (inode->i_bdev->bd_inode->i_size == 0) { if (minor(inode->i_rdev) != 0) return -ENXIO; if (!capable(CAP_SYS_ADMIN)) @@ -806,7 +805,6 @@ * on this controller to zero. We will reread all of this data */ memset(hba[ctlr]->hd, 0, sizeof(struct hd_struct) * 256); - memset(hba[ctlr]->sizes, 0, sizeof(int) * 256); memset(hba[ctlr]->drv, 0, sizeof(drive_info_struct) * CISS_MAX_LUN); hba[ctlr]->gendisk.nr_real = 0; @@ -823,7 +821,7 @@ cciss_geninit(ctlr); for(i=0; isizes[ i<gendisk.part[ i<gendisk); ctlr_info_t *h = hba[ctlr]; - int start, max_p, i; + int start, max_p; if (!capable(CAP_SYS_RAWIO)) @@ -856,8 +854,6 @@ max_p = 1 << gdev->minor_shift; start = logvol << gdev->minor_shift; wipe_partitions(mk_kdev(MAJOR_NR+ctlr, start)); - for (i=max_p-1; i>=0; i--) - h->sizes[start + i] = 0; /* check to see if it was the last disk */ if (logvol == h->highest_lun) { @@ -866,7 +862,7 @@ for(i=0; ihighest_lun; i++) { /* if the disk has size > 0, it is available */ - if (h->sizes[i << gdev->minor_shift] != 0) + if (h->gendisk.part[i << gdev->minor_shift].nr_sects) newhighest = i; } h->highest_lun = newhighest; @@ -2498,7 +2494,6 @@ hba[i]->gendisk.major_name = "cciss"; hba[i]->gendisk.minor_shift = NWD_SHIFT; hba[i]->gendisk.part = hba[i]->hd; - hba[i]->gendisk.sizes = hba[i]->sizes; hba[i]->gendisk.nr_real = hba[i]->highest_lun+1; /* Get on the disk list */ diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c --- a/drivers/block/cpqarray.c Thu Aug 1 14:17:36 2002 +++ b/drivers/block/cpqarray.c Thu Aug 1 14:17:36 2002 @@ -104,7 +104,6 @@ }; static struct hd_struct * ida; -static int * ida_sizes; static struct gendisk ida_gendisk[MAX_CTLR]; static struct proc_dir_entry *proc_array; @@ -176,9 +175,7 @@ drv = &hba[ctlr]->drv[i]; if (!drv->nr_blks) continue; - ida[(ctlr<nr_blks; + ida[(ctlr<nr_blks; (BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->blk_size; ida_gendisk[ctlr].nr_real++; @@ -336,10 +333,9 @@ del_gendisk(&ida_gendisk[i]); } - devfs_unregister(devfs_find_handle(NULL, "ida", 0, 0, 0, 0)); + devfs_find_and_unregister(NULL, "ida", 0, 0, 0, 0); remove_proc_entry("cpqarray", proc_root_driver); kfree(ida); - kfree(ida_sizes); } #endif /* MODULE */ @@ -372,16 +368,7 @@ return(num_cntlrs_reg); } - ida_sizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL); - if(ida_sizes==NULL) - { - kfree(ida); - printk( KERN_ERR "cpqarray: out of memory"); - return(num_cntlrs_reg); - } - memset(ida, 0, sizeof(struct hd_struct)*nr_ctlr*NWD*16); - memset(ida_sizes, 0, sizeof(int)*nr_ctlr*NWD*16); memset(ida_gendisk, 0, sizeof(struct gendisk)*MAX_CTLR); /* @@ -437,7 +424,6 @@ if (num_cntlrs_reg == 0) { kfree(ida); - kfree(ida_sizes); } return(num_cntlrs_reg); @@ -469,7 +455,6 @@ ida_gendisk[i].major_name = "ida"; ida_gendisk[i].minor_shift = NWD_SHIFT; ida_gendisk[i].part = ida + (i*256); - ida_gendisk[i].sizes = ida_sizes + (i*256); ida_gendisk[i].nr_real = 0; ida_gendisk[i].de_arr = de_arr[i]; ida_gendisk[i].fops = &ida_fops; @@ -770,8 +755,7 @@ if (ctlr > MAX_CTLR || hba[ctlr] == NULL) return -ENXIO; - if (!capable(CAP_SYS_RAWIO) && ida_sizes[(ctlr << CTLR_SHIFT) + - minor(inode->i_rdev)] == 0) + if (!capable(CAP_SYS_RAWIO) && inode->i_bdev->bd_inode->i_size == 0) return -ENXIO; /* @@ -781,7 +765,7 @@ * for "raw controller". */ if (capable(CAP_SYS_ADMIN) - && ida_sizes[(ctlr << CTLR_SHIFT) + minor(inode->i_rdev)] == 0 + && inode->i_bdev->bd_inode->i_size == 0 && minor(inode->i_rdev) != 0) return -ENXIO; @@ -1498,7 +1482,6 @@ * on this controller to zero. We will reread all of this data */ memset(ida+(ctlr*256), 0, sizeof(struct hd_struct)*NWD*16); - memset(ida_sizes+(ctlr*256), 0, sizeof(int)*NWD*16); memset(hba[ctlr]->drv, 0, sizeof(drv_info_t)*NWD); ida_gendisk[ctlr].nr_real = 0; @@ -1514,7 +1497,7 @@ ida_geninit(ctlr); for(i=0; ielevator; int lat = 0, *latency = e->elevator_data; + if (!insert_here) + insert_here = q->queue_head.prev; + if (!(rq->flags & REQ_BARRIER)) lat = latency[rq_data_dir(rq)]; @@ -318,7 +322,7 @@ struct request *elevator_noop_next_request(request_queue_t *q) { - if (!blk_queue_empty(q)) + if (!list_empty(&q->queue_head)) return list_entry_rq(q->queue_head.next); return NULL; @@ -376,7 +380,7 @@ elevator_t *e = &q->elevator; if (e->elevator_merge_req_fn) - e->elevator_merge_req_fn(rq, next); + e->elevator_merge_req_fn(q, rq, next); } /* @@ -431,6 +435,27 @@ if (e->elevator_remove_req_fn) e->elevator_remove_req_fn(q, rq); +} + +int elv_queue_empty(request_queue_t *q) +{ + elevator_t *e = &q->elevator; + + if (e->elevator_queue_empty_fn) + return e->elevator_queue_empty_fn(q); + + return list_empty(&q->queue_head); +} + +inline struct list_head *elv_get_sort_head(request_queue_t *q, + struct request *rq) +{ + elevator_t *e = &q->elevator; + + if (e->elevator_get_sort_head_fn) + return e->elevator_get_sort_head_fn(q, rq); + + return &q->queue_head; } elevator_t elevator_linus = { diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c --- a/drivers/block/floppy.c Thu Aug 1 14:17:36 2002 +++ b/drivers/block/floppy.c Thu Aug 1 14:17:36 2002 @@ -4233,7 +4233,7 @@ raw_cmd = NULL; devfs_handle = devfs_mk_dir (NULL, "floppy", NULL); - if (devfs_register_blkdev(MAJOR_NR,"fd",&floppy_fops)) { + if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) { printk("Unable to get major %d for floppy\n",MAJOR_NR); return -EBUSY; } @@ -4266,7 +4266,7 @@ use_virtual_dma = can_use_virtual_dma & 1; fdc_state[0].address = FDC1; if (fdc_state[0].address == -1) { - devfs_unregister_blkdev(MAJOR_NR,"fd"); + unregister_blkdev(MAJOR_NR,"fd"); del_timer(&fd_timeout); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); return -ENODEV; @@ -4279,7 +4279,7 @@ if (floppy_grab_irq_and_dma()){ del_timer(&fd_timeout); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - devfs_unregister_blkdev(MAJOR_NR,"fd"); + unregister_blkdev(MAJOR_NR,"fd"); return -EBUSY; } @@ -4342,7 +4342,7 @@ if (usage_count) floppy_release_irq_and_dma(); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - devfs_unregister_blkdev(MAJOR_NR,"fd"); + unregister_blkdev(MAJOR_NR,"fd"); } for (drive = 0; drive < N_DRIVE; drive++) { @@ -4539,7 +4539,7 @@ int dummy; devfs_unregister (devfs_handle); - devfs_unregister_blkdev(MAJOR_NR, "fd"); + unregister_blkdev(MAJOR_NR, "fd"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); /* eject disk, if any */ diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c --- a/drivers/block/genhd.c Thu Aug 1 14:17:40 2002 +++ b/drivers/block/genhd.c Thu Aug 1 14:17:40 2002 @@ -55,8 +55,8 @@ { if (sgp == gp) { -// printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n", -// sgp->major) + printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n", + sgp->major); goto out; } } @@ -104,15 +104,22 @@ get_gendisk(kdev_t dev) { struct gendisk *gp = NULL; - int maj = major(dev); + int major = major(dev); + int minor = minor(dev); read_lock(&gendisk_lock); - for (gp = gendisk_head; gp; gp = gp->next) - if (gp->major == maj) - break; + for (gp = gendisk_head; gp; gp = gp->next) { + if (gp->major != major) + continue; + if (gp->first_minor > minor) + continue; + if (gp->first_minor + (1<minor_shift) <= minor) + continue; + read_unlock(&gendisk_lock); + return gp; + } read_unlock(&gendisk_lock); - - return gp; + return NULL; } EXPORT_SYMBOL(get_gendisk); @@ -157,9 +164,10 @@ int minormask = (1<minor_shift) - 1; if ((n & minormask) && sgp->part[n].nr_sects == 0) continue; - seq_printf(part, "%4d %4d %10d %s\n", - sgp->major, n, sgp->sizes[n], - disk_name(sgp, n, buf)); + seq_printf(part, "%4d %4d %10ld %s\n", + sgp->major, n + sgp->first_minor, + sgp->part[n].nr_sects << 1, + disk_name(sgp, n + sgp->first_minor, buf)); } return 0; diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Thu Aug 1 14:17:36 2002 +++ b/drivers/block/ll_rw_blk.c Thu Aug 1 14:17:36 2002 @@ -1253,7 +1253,7 @@ * host that is unable to accept a particular command. */ void blk_insert_request(request_queue_t *q, struct request *rq, - int at_head, void *data) + int at_head, void *data) { unsigned long flags; @@ -1262,15 +1262,18 @@ * must not attempt merges on this) and that it acts as a soft * barrier */ - rq->flags &= REQ_QUEUED; rq->flags |= REQ_SPECIAL | REQ_BARRIER; rq->special = data; spin_lock_irqsave(q->queue_lock, flags); - /* If command is tagged, release the tag */ - if(blk_rq_tagged(rq)) + + /* + * If command is tagged, release the tag + */ + if (blk_rq_tagged(rq)) blk_queue_end_tag(q, rq); + _elv_add_request(q, rq, !at_head, 0); q->request_fn(q); spin_unlock_irqrestore(q->queue_lock, flags); @@ -1388,7 +1391,6 @@ if (rq_data_dir(req) != rq_data_dir(next) || !kdev_same(req->rq_dev, next->rq_dev) - || req->nr_sectors + next->nr_sectors > q->max_sectors || next->waiting || next->special) return; @@ -1399,15 +1401,14 @@ * counts here. */ if (q->merge_requests_fn(q, req, next)) { - elv_merge_requests(q, req, next); - - blkdev_dequeue_request(next); - req->biotail->bi_next = next->bio; req->biotail = next->biotail; req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors; + elv_merge_requests(q, req, next); + + blkdev_dequeue_request(next); blk_put_request(next); } } @@ -1415,16 +1416,18 @@ static inline void attempt_back_merge(request_queue_t *q, struct request *rq) { struct list_head *next = rq->queuelist.next; + struct list_head *sort_head = elv_get_sort_head(q, rq); - if (next != &q->queue_head) + if (next != sort_head) attempt_merge(q, rq, list_entry_rq(next)); } static inline void attempt_front_merge(request_queue_t *q, struct request *rq) { struct list_head *prev = rq->queuelist.prev; + struct list_head *sort_head = elv_get_sort_head(q, rq); - if (prev != &q->queue_head) + if (prev != sort_head) attempt_merge(q, list_entry_rq(prev), rq); } @@ -1484,7 +1487,7 @@ spin_lock_irq(q->queue_lock); again: req = NULL; - insert_here = q->queue_head.prev; + insert_here = NULL; if (blk_queue_empty(q)) { blk_plug_device(q); @@ -1502,11 +1505,10 @@ break; } - elv_merge_cleanup(q, req, nr_sectors); - req->biotail->bi_next = bio; req->biotail = bio; req->nr_sectors = req->hard_nr_sectors += nr_sectors; + elv_merge_cleanup(q, req, nr_sectors); drive_stat_acct(req, nr_sectors, 0); attempt_back_merge(q, req); goto out; @@ -1518,8 +1520,6 @@ break; } - elv_merge_cleanup(q, req, nr_sectors); - bio->bi_next = req->bio; req->bio = bio; /* @@ -1532,6 +1532,7 @@ req->hard_cur_sectors = cur_nr_sectors; req->sector = req->hard_sector = sector; req->nr_sectors = req->hard_nr_sectors += nr_sectors; + elv_merge_cleanup(q, req, nr_sectors); drive_stat_acct(req, nr_sectors, 0); attempt_front_merge(q, req); goto out; @@ -1600,9 +1601,7 @@ req->buffer = bio_data(bio); /* see ->buffer comment above */ req->waiting = NULL; req->bio = req->biotail = bio; - if (bio->bi_bdev) - req->rq_dev = to_kdev_t(bio->bi_bdev->bd_dev); - else req->rq_dev = NODEV; + req->rq_dev = to_kdev_t(bio->bi_bdev->bd_dev); add_request(q, req, insert_here); out: if (freereq) diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c --- a/drivers/block/loop.c Thu Aug 1 14:17:36 2002 +++ b/drivers/block/loop.c Thu Aug 1 14:17:36 2002 @@ -1027,7 +1027,7 @@ max_loop = 8; } - if (devfs_register_blkdev(MAJOR_NR, "loop", &lo_fops)) { + if (register_blkdev(MAJOR_NR, "loop", &lo_fops)) { printk(KERN_WARNING "Unable to get major number %d for loop" " device\n", MAJOR_NR); return -EIO; @@ -1078,7 +1078,7 @@ void loop_exit(void) { devfs_unregister(devfs_handle); - if (devfs_unregister_blkdev(MAJOR_NR, "loop")) + if (unregister_blkdev(MAJOR_NR, "loop")) printk(KERN_WARNING "loop: cannot unregister blkdev\n"); kfree(loop_dev); diff -Nru a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c --- a/drivers/block/paride/pd.c Thu Aug 1 14:17:41 2002 +++ b/drivers/block/paride/pd.c Thu Aug 1 14:17:41 2002 @@ -272,7 +272,6 @@ static void pd_eject( int unit); static struct hd_struct pd_hd[PD_DEVS]; -static int pd_sizes[PD_DEVS]; #define PD_NAMELEN 8 @@ -292,6 +291,7 @@ int alt_geom; int present; char name[PD_NAMELEN]; /* pda, pdb, etc ... */ + struct gendisk gd; }; struct pd_unit pd[PD_UNITS]; @@ -331,9 +331,8 @@ major: PD_MAJOR, major_name: PD_NAME, minor_shift: PD_BITS, - part: pd_hd, - sizes: pd_sizes, fops: &pd_fops, + nr_real: 1, }; static struct block_device_operations pd_fops = { @@ -682,8 +681,8 @@ } static int pd_detect( void ) - -{ int k, unit; +{ + int k, unit; k = 0; if (pd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */ @@ -705,18 +704,19 @@ k = unit+1; } else pi_release(PI); } - for (unit=0;unit #include #include -#include #include #include #include @@ -111,7 +110,6 @@ static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int); static int no_int_yet; -static int ps2esdi_sizes[MAX_HD << 6]; static int ps2esdi_drives; static struct hd_struct ps2esdi[MAX_HD << 6]; static u_short io_base; @@ -156,7 +154,6 @@ major_name: "ed", minor_shift: 6, part: ps2esdi, - sizes: ps2esdi_sizes, fops: &ps2esdi_fops, }; @@ -168,7 +165,7 @@ /* register the device - pass the name, major number and operations vector . */ - if (devfs_register_blkdev(MAJOR_NR, "ed", &ps2esdi_fops)) { + if (register_blkdev(MAJOR_NR, "ed", &ps2esdi_fops)) { printk("%s: Unable to get major number %d\n", DEVICE_NAME, MAJOR_NR); return -1; } @@ -182,7 +179,7 @@ if (error) { printk(KERN_WARNING "PS2ESDI: error initialising" " device, releasing resources\n"); - devfs_unregister_blkdev(MAJOR_NR, "ed"); + unregister_blkdev(MAJOR_NR, "ed"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); del_gendisk(&ps2esdi_gendisk); blk_clear(MAJOR_NR); @@ -233,7 +230,7 @@ release_region(io_base, 4); free_dma(dma_arb_level); free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); - devfs_unregister_blkdev(MAJOR_NR, "ed"); + unregister_blkdev(MAJOR_NR, "ed"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); del_gendisk(&ps2esdi_gendisk); blk_clear(MAJOR_NR); diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c --- a/drivers/block/rd.c Thu Aug 1 14:17:41 2002 +++ b/drivers/block/rd.c Thu Aug 1 14:17:41 2002 @@ -379,6 +379,7 @@ rd_bdev[unit]->bd_openers++; rd_bdev[unit]->bd_block_size = rd_blocksize; rd_bdev[unit]->bd_inode->i_mapping->a_ops = &ramdisk_aops; + rd_bdev[unit]->bd_inode->i_size = rd_length[unit]; rd_bdev[unit]->bd_queue = &blk_dev[MAJOR_NR].request_queue; } diff -Nru a/drivers/block/swim3.c b/drivers/block/swim3.c --- a/drivers/block/swim3.c Thu Aug 1 14:17:40 2002 +++ b/drivers/block/swim3.c Thu Aug 1 14:17:40 2002 @@ -1034,7 +1034,7 @@ if (floppy_count > 0) { - if (devfs_register_blkdev(MAJOR_NR, "fd", &floppy_fops)) { + if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) { printk(KERN_ERR "Unable to get major %d for floppy\n", MAJOR_NR); return -EBUSY; diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c --- a/drivers/block/umem.c Thu Aug 1 14:17:41 2002 +++ b/drivers/block/umem.c Thu Aug 1 14:17:41 2002 @@ -160,7 +160,6 @@ static struct timer_list battery_timer; -static int mm_sizes[MM_MAXCARDS << MM_SHIFT]; static struct hd_struct mm_partitions[MM_MAXCARDS << MM_SHIFT]; static int num_cards = 0; @@ -1206,7 +1205,6 @@ printk(KERN_INFO DRIVER_VERSION " : " DRIVER_DESC "\n"); memset (cards, 0, MM_MAXCARDS * sizeof(struct cardinfo)); - memset (mm_sizes, 0, (MM_MAXCARDS << MM_SHIFT) * sizeof (int)); memset (mm_partitions, 0, (MM_MAXCARDS << MM_SHIFT) * sizeof(struct hd_struct)); @@ -1224,11 +1222,6 @@ /* Initialize partition size: partion 0 of each card is the entire card */ for (i = 0; i < num_cards; i++) { - mm_sizes[i << MM_SHIFT] = cards[i].mm_size; - } - mm_gendisk.sizes = mm_sizes; - - for (i = 0; i < num_cards; i++) { spin_lock_init(&cards[i].lock); mm_partitions[i << MM_SHIFT].nr_sects = cards[i].mm_size * (1024 / MM_HARDSECT); @@ -1270,8 +1263,6 @@ pci_unregister_driver(&mm_pci_driver); unregister_blkdev(MAJOR_NR, "umem"); - - blk_size [MAJOR_NR] = NULL; /* * Get our gendisk structure off the list. diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c --- a/drivers/block/xd.c Thu Aug 1 14:17:39 2002 +++ b/drivers/block/xd.c Thu Aug 1 14:17:39 2002 @@ -122,7 +122,6 @@ }; static struct hd_struct xd_struct[XD_MAXDRIVES << 6]; -static int xd_sizes[XD_MAXDRIVES << 6]; static spinlock_t xd_lock = SPIN_LOCK_UNLOCKED; @@ -133,7 +132,6 @@ major_name: "xd", minor_shift: 6, part: xd_struct, - sizes: xd_sizes, fops: &xd_fops, }; @@ -164,7 +162,7 @@ init_timer (&xd_timer); xd_timer.function = xd_wakeup; init_timer (&xd_watchdog_int); xd_watchdog_int.function = xd_watchdog; - if (devfs_register_blkdev(MAJOR_NR,"xd",&xd_fops)) { + if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) { printk("xd: Unable to get major number %d\n",MAJOR_NR); return -1; } @@ -1085,7 +1083,7 @@ printk(KERN_INFO "XD: Loaded as a module.\n"); if (!xd_drives) { /* no drives detected - unload module */ - devfs_unregister_blkdev(MAJOR_NR, "xd"); + unregister_blkdev(MAJOR_NR, "xd"); xd_done(); return (-1); } @@ -1095,7 +1093,7 @@ void cleanup_module(void) { - devfs_unregister_blkdev(MAJOR_NR, "xd"); + unregister_blkdev(MAJOR_NR, "xd"); xd_done(); devfs_unregister (devfs_handle); if (xd_drives) { diff -Nru a/drivers/bluetooth/Config.help b/drivers/bluetooth/Config.help --- a/drivers/bluetooth/Config.help Thu Aug 1 14:17:40 2002 +++ b/drivers/bluetooth/Config.help Thu Aug 1 14:17:40 2002 @@ -62,6 +62,20 @@ Say Y here to compile support for HCI DTL1 devices into the kernel or say M to compile it as module (dtl1_cs.o). +HCI BT3C (PC Card) device driver +CONFIG_BLUEZ_HCIBT3C + Bluetooth HCI BT3C (PC Card) driver. + This driver provides support for Bluetooth PCMCIA devices with + 3Com BT3C interface: + 3Com Bluetooth Card (3CRWB6096) + HP Bluetooth Card + + The HCI BT3C driver uses external firmware loader program provided in + the BlueFW package. For more information, see . + + Say Y here to compile support for HCI BT3C devices into the + kernel or say M to compile it as module (bt3c_cs.o). + HCI BlueCard (PC Card) device driver CONFIG_BLUEZ_HCIBLUECARD Bluetooth HCI BlueCard (PC Card) driver. diff -Nru a/drivers/bluetooth/Config.in b/drivers/bluetooth/Config.in --- a/drivers/bluetooth/Config.in Thu Aug 1 14:17:40 2002 +++ b/drivers/bluetooth/Config.in Thu Aug 1 14:17:40 2002 @@ -14,6 +14,8 @@ dep_tristate 'HCI DTL1 (PC Card) driver' CONFIG_BLUEZ_HCIDTL1 $CONFIG_PCMCIA $CONFIG_BLUEZ +dep_tristate 'HCI BT3C (PC Card) driver' CONFIG_BLUEZ_HCIBT3C $CONFIG_PCMCIA $CONFIG_BLUEZ + dep_tristate 'HCI BlueCard (PC Card) driver' CONFIG_BLUEZ_HCIBLUECARD $CONFIG_PCMCIA $CONFIG_BLUEZ dep_tristate 'HCI VHCI (Virtual HCI device) driver' CONFIG_BLUEZ_HCIVHCI $CONFIG_BLUEZ diff -Nru a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile --- a/drivers/bluetooth/Makefile Thu Aug 1 14:17:41 2002 +++ b/drivers/bluetooth/Makefile Thu Aug 1 14:17:41 2002 @@ -6,6 +6,7 @@ obj-$(CONFIG_BLUEZ_HCIVHCI) += hci_vhci.o obj-$(CONFIG_BLUEZ_HCIUART) += hci_uart.o obj-$(CONFIG_BLUEZ_HCIDTL1) += dtl1_cs.o +obj-$(CONFIG_BLUEZ_HCIBT3C) += bt3c_cs.o obj-$(CONFIG_BLUEZ_HCIBLUECARD) += bluecard_cs.o hci_uart-y := hci_ldisc.o diff -Nru a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c --- a/drivers/bluetooth/bluecard_cs.c Thu Aug 1 14:17:40 2002 +++ b/drivers/bluetooth/bluecard_cs.c Thu Aug 1 14:17:40 2002 @@ -89,16 +89,16 @@ } bluecard_info_t; -void bluecard_config(dev_link_t * link); +void bluecard_config(dev_link_t *link); void bluecard_release(u_long arg); -int bluecard_event(event_t event, int priority, event_callback_args_t * args); +int bluecard_event(event_t event, int priority, event_callback_args_t *args); static dev_info_t dev_info = "bluecard_cs"; dev_link_t *bluecard_attach(void); void bluecard_detach(dev_link_t *); -dev_link_t *dev_list = NULL; +static dev_link_t *dev_list = NULL; /* Default baud rate: 57600, 115200, 230400 or 460800 */ @@ -171,7 +171,7 @@ void bluecard_activity_led_timeout(u_long arg) { - bluecard_info_t *info = (bluecard_info_t *) arg; + bluecard_info_t *info = (bluecard_info_t *)arg; unsigned int iobase = info->link.io.BasePort1; if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) { @@ -184,7 +184,7 @@ } -static void bluecard_enable_activity_led(bluecard_info_t * info) +static void bluecard_enable_activity_led(bluecard_info_t *info) { unsigned int iobase = info->link.io.BasePort1; @@ -208,8 +208,7 @@ /* ======================== Interrupt handling ======================== */ -static int bluecard_write(unsigned int iobase, unsigned int offset, - __u8 * buf, int len) +static int bluecard_write(unsigned int iobase, unsigned int offset, __u8 *buf, int len) { int i, actual; @@ -224,7 +223,7 @@ } -static void bluecard_write_wakeup(bluecard_info_t * info) +static void bluecard_write_wakeup(bluecard_info_t *info) { if (!info) { printk(KERN_WARNING "bluecard_cs: Call of write_wakeup for unknown device.\n"); @@ -253,15 +252,13 @@ return; if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) { - if (!test_bit - (XMIT_BUF_TWO_READY, &(info->tx_state))) + if (!test_bit(XMIT_BUF_TWO_READY, &(info->tx_state))) break; offset = 0x10; command = REG_COMMAND_TX_BUF_TWO; ready_bit = XMIT_BUF_TWO_READY; } else { - if (!test_bit - (XMIT_BUF_ONE_READY, &(info->tx_state))) + if (!test_bit(XMIT_BUF_ONE_READY, &(info->tx_state))) break; offset = 0x00; command = REG_COMMAND_TX_BUF_ONE; @@ -272,11 +269,9 @@ break; if (skb->pkt_type & 0x80) { - /* Disable RTS */ info->ctrl_reg |= REG_CONTROL_RTS; outb(info->ctrl_reg, iobase + REG_CONTROL); - } /* Activate LED */ @@ -349,8 +344,7 @@ } -static int bluecard_read(unsigned int iobase, unsigned int offset, - __u8 * buf, int size) +static int bluecard_read(unsigned int iobase, unsigned int offset, __u8 *buf, int size) { int i, n, len; @@ -378,7 +372,7 @@ } -static void bluecard_receive(bluecard_info_t * info, unsigned int offset) +static void bluecard_receive(bluecard_info_t *info, unsigned int offset) { unsigned int iobase; unsigned char buf[31]; @@ -410,7 +404,7 @@ if (info->rx_state == RECV_WAIT_PACKET_TYPE) { - info->rx_skb->dev = (void *) &(info->hdev); + info->rx_skb->dev = (void *)&(info->hdev); info->rx_skb->pkt_type = buf[i]; switch (info->rx_skb->pkt_type) { @@ -469,20 +463,20 @@ switch (info->rx_state) { case RECV_WAIT_EVENT_HEADER: - eh = (hci_event_hdr *) (info->rx_skb->data); + eh = (hci_event_hdr *)(info->rx_skb->data); info->rx_state = RECV_WAIT_DATA; info->rx_count = eh->plen; break; case RECV_WAIT_ACL_HEADER: - ah = (hci_acl_hdr *) (info->rx_skb->data); + ah = (hci_acl_hdr *)(info->rx_skb->data); dlen = __le16_to_cpu(ah->dlen); info->rx_state = RECV_WAIT_DATA; info->rx_count = dlen; break; case RECV_WAIT_SCO_HEADER: - sh = (hci_sco_hdr *) (info->rx_skb->data); + sh = (hci_sco_hdr *)(info->rx_skb->data); info->rx_state = RECV_WAIT_DATA; info->rx_count = sh->dlen; break; @@ -571,9 +565,8 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud) { - bluecard_info_t *info = (bluecard_info_t *) (hdev->driver_data); + bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); struct sk_buff *skb; - int i; /* Ericsson baud rate command */ unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 }; @@ -604,8 +597,7 @@ break; } - for (i = 0; i < sizeof(cmd); i++) - *skb_put(skb, 1) = cmd[i]; + memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd)); skb_queue_tail(&(info->txq), skb); @@ -621,7 +613,7 @@ static int bluecard_hci_flush(struct hci_dev *hdev) { - bluecard_info_t *info = (bluecard_info_t *) (hdev->driver_data); + bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); /* Drop TX queue */ skb_queue_purge(&(info->txq)); @@ -632,7 +624,7 @@ static int bluecard_hci_open(struct hci_dev *hdev) { - bluecard_info_t *info = (bluecard_info_t *) (hdev->driver_data); + bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); unsigned int iobase = info->link.io.BasePort1; bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE); @@ -649,7 +641,7 @@ static int bluecard_hci_close(struct hci_dev *hdev) { - bluecard_info_t *info = (bluecard_info_t *) (hdev->driver_data); + bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); unsigned int iobase = info->link.io.BasePort1; if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) @@ -667,14 +659,14 @@ static int bluecard_hci_send_frame(struct sk_buff *skb) { bluecard_info_t *info; - struct hci_dev *hdev = (struct hci_dev *) (skb->dev); + struct hci_dev *hdev = (struct hci_dev *)(skb->dev); if (!hdev) { printk(KERN_WARNING "bluecard_cs: Frame for unknown HCI device (hdev=NULL)."); return -ENODEV; } - info = (bluecard_info_t *) (hdev->driver_data); + info = (bluecard_info_t *)(hdev->driver_data); switch (skb->pkt_type) { case HCI_COMMAND_PKT: @@ -703,8 +695,7 @@ } -static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, - unsigned long arg) +static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) { return -ENOIOCTLCMD; } @@ -714,7 +705,7 @@ /* ======================== Card services HCI interaction ======================== */ -int bluecard_open(bluecard_info_t * info) +int bluecard_open(bluecard_info_t *info) { unsigned int iobase = info->link.io.BasePort1; struct hci_dev *hdev; @@ -724,7 +715,7 @@ init_timer(&(info->timer)); info->timer.function = &bluecard_activity_led_timeout; - info->timer.data = (u_long) info; + info->timer.data = (u_long)info; skb_queue_head_init(&(info->txq)); @@ -781,7 +772,8 @@ /* Timeout before it is safe to send the first HCI packet */ set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((HZ * 5) / 4); // or set it to 3/2 + schedule_timeout((HZ * 5) / 4); // or set it to 3/2 + /* Initialize and register HCI device */ @@ -806,7 +798,7 @@ } -int bluecard_close(bluecard_info_t * info) +int bluecard_close(bluecard_info_t *info) { unsigned int iobase = info->link.io.BasePort1; struct hci_dev *hdev = &(info->hdev); @@ -858,7 +850,7 @@ link->priv = info; link->release.function = &bluecard_release; - link->release.data = (u_long) link; + link->release.data = (u_long)link; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts1 = 8; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; @@ -883,9 +875,9 @@ client_reg.dev_info = &dev_info; client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; client_reg.event_handler = &bluecard_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; @@ -901,7 +893,7 @@ } -void bluecard_detach(dev_link_t * link) +void bluecard_detach(dev_link_t *link) { bluecard_info_t *info = link->priv; dev_link_t **linkp; @@ -917,7 +909,7 @@ del_timer(&link->release); if (link->state & DEV_CONFIG) - bluecard_release((u_long) link); + bluecard_release((u_long)link); if (link->handle) { ret = CardServices(DeregisterClient, link->handle); @@ -932,8 +924,7 @@ } -static int get_tuple(int fn, client_handle_t handle, tuple_t * tuple, - cisparse_t * parse) +static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse) { int i; @@ -952,7 +943,7 @@ #define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) #define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) -void bluecard_config(dev_link_t * link) +void bluecard_config(dev_link_t *link) { client_handle_t handle = link->handle; bluecard_info_t *info = link->priv; @@ -962,7 +953,7 @@ config_info_t config; int i, n, last_ret, last_fn; - tuple.TupleData = (cisdata_t *) buf; + tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; @@ -1010,12 +1001,12 @@ goto failed; } - MOD_INC_USE_COUNT; if (bluecard_open(info) != 0) goto failed; + strcpy(info->node.dev_name, info->hdev.name); link->dev = &info->node; link->state &= ~DEV_CONFIG_PENDING; @@ -1025,13 +1016,13 @@ cs_error(link->handle, last_fn, last_ret); failed: - bluecard_release((u_long) link); + bluecard_release((u_long)link); } void bluecard_release(u_long arg) { - dev_link_t *link = (dev_link_t *) arg; + dev_link_t *link = (dev_link_t *)arg; bluecard_info_t *info = link->priv; if (link->state & DEV_PRESENT) @@ -1049,8 +1040,7 @@ } -int bluecard_event(event_t event, int priority, - event_callback_args_t * args) +int bluecard_event(event_t event, int priority, event_callback_args_t *args) { dev_link_t *link = args->client_data; bluecard_info_t *info = link->priv; @@ -1079,8 +1069,7 @@ /* Fall through... */ case CS_EVENT_CARD_RESET: if (DEV_OK(link)) - CardServices(RequestConfiguration, link->handle, - &link->conf); + CardServices(RequestConfiguration, link->handle, &link->conf); break; } diff -Nru a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/bluetooth/bt3c_cs.c Thu Aug 1 14:17:41 2002 @@ -0,0 +1,944 @@ +/* + * + * Driver for the 3Com Bluetooth PCMCIA card + * + * Copyright (C) 2001-2002 Marcel Holtmann + * Jose Orlando Pereira + * + * + * 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; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + */ + +#include +#include + +#define __KERNEL_SYSCALLS__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + + +/* ======================== Module parameters ======================== */ + + +/* Bit map of interrupts to choose from */ +static u_int irq_mask = 0xffff; +static int irq_list[4] = { -1 }; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); + +MODULE_AUTHOR("Marcel Holtmann , Jose Orlando Pereira "); +MODULE_DESCRIPTION("BlueZ driver for the 3Com Bluetooth PCMCIA card"); +MODULE_LICENSE("GPL"); + + + +/* ======================== Local structures ======================== */ + + +typedef struct bt3c_info_t { + dev_link_t link; + dev_node_t node; + + struct hci_dev hdev; + + spinlock_t lock; /* For serializing operations */ + + struct sk_buff_head txq; + unsigned long tx_state; + + unsigned long rx_state; + unsigned long rx_count; + struct sk_buff *rx_skb; +} bt3c_info_t; + + +void bt3c_config(dev_link_t *link); +void bt3c_release(u_long arg); +int bt3c_event(event_t event, int priority, event_callback_args_t *args); + +static dev_info_t dev_info = "bt3c_cs"; + +dev_link_t *bt3c_attach(void); +void bt3c_detach(dev_link_t *); + +static dev_link_t *dev_list = NULL; + + +/* Transmit states */ +#define XMIT_SENDING 1 +#define XMIT_WAKEUP 2 +#define XMIT_WAITING 8 + +/* Receiver states */ +#define RECV_WAIT_PACKET_TYPE 0 +#define RECV_WAIT_EVENT_HEADER 1 +#define RECV_WAIT_ACL_HEADER 2 +#define RECV_WAIT_SCO_HEADER 3 +#define RECV_WAIT_DATA 4 + + + +/* ======================== Special I/O functions ======================== */ + + +#define DATA_L 0 +#define DATA_H 1 +#define ADDR_L 2 +#define ADDR_H 3 +#define CONTROL 4 + + +inline void bt3c_address(unsigned int iobase, unsigned short addr) +{ + outb(addr & 0xff, iobase + ADDR_L); + outb((addr >> 8) & 0xff, iobase + ADDR_H); +} + + +inline void bt3c_put(unsigned int iobase, unsigned short value) +{ + outb(value & 0xff, iobase + DATA_L); + outb((value >> 8) & 0xff, iobase + DATA_H); +} + + +inline void bt3c_io_write(unsigned int iobase, unsigned short addr, unsigned short value) +{ + bt3c_address(iobase, addr); + bt3c_put(iobase, value); +} + + +inline unsigned short bt3c_get(unsigned int iobase) +{ + unsigned short value = inb(iobase + DATA_L); + + value |= inb(iobase + DATA_H) << 8; + + return value; +} + + +inline unsigned short bt3c_read(unsigned int iobase, unsigned short addr) +{ + bt3c_address(iobase, addr); + + return bt3c_get(iobase); +} + + + +/* ======================== Interrupt handling ======================== */ + + +static int bt3c_write(unsigned int iobase, int fifo_size, __u8 *buf, int len) +{ + int actual = 0; + + bt3c_address(iobase, 0x7080); + + /* Fill FIFO with current frame */ + while (actual < len) { + /* Transmit next byte */ + bt3c_put(iobase, buf[actual]); + actual++; + } + + bt3c_io_write(iobase, 0x7005, actual); + + return actual; +} + + +static void bt3c_write_wakeup(bt3c_info_t *info, int from) +{ + unsigned long flags; + + if (!info) { + printk(KERN_WARNING "bt3c_cs: Call of write_wakeup for unknown device.\n"); + return; + } + + if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) + return; + + spin_lock_irqsave(&(info->lock), flags); + + do { + register unsigned int iobase = info->link.io.BasePort1; + register struct sk_buff *skb; + register int len; + + if (!(info->link.state & DEV_PRESENT)) + break; + + + if (!(skb = skb_dequeue(&(info->txq)))) { + clear_bit(XMIT_SENDING, &(info->tx_state)); + break; + } + + /* Send frame */ + len = bt3c_write(iobase, 256, skb->data, skb->len); + + if (len != skb->len) { + printk(KERN_WARNING "bt3c_cs: very strange\n"); + } + + kfree_skb(skb); + + info->hdev.stat.byte_tx += len; + + } while (0); + + spin_unlock_irqrestore(&(info->lock), flags); +} + + +static void bt3c_receive(bt3c_info_t *info) +{ + unsigned int iobase; + int size = 0, avail; + + if (!info) { + printk(KERN_WARNING "bt3c_cs: Call of receive for unknown device.\n"); + return; + } + + iobase = info->link.io.BasePort1; + + avail = bt3c_read(iobase, 0x7006); + //printk("bt3c_cs: receiving %d bytes\n", avail); + + bt3c_address(iobase, 0x7480); + while (size < avail) { + size++; + info->hdev.stat.byte_rx++; + + /* Allocate packet */ + if (info->rx_skb == NULL) { + info->rx_state = RECV_WAIT_PACKET_TYPE; + info->rx_count = 0; + if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { + printk(KERN_WARNING "bt3c_cs: Can't allocate mem for new packet.\n"); + return; + } + } + + + if (info->rx_state == RECV_WAIT_PACKET_TYPE) { + + info->rx_skb->dev = (void *)&(info->hdev); + info->rx_skb->pkt_type = inb(iobase + DATA_L); + inb(iobase + DATA_H); + //printk("bt3c: PACKET_TYPE=%02x\n", info->rx_skb->pkt_type); + + switch (info->rx_skb->pkt_type) { + + case HCI_EVENT_PKT: + info->rx_state = RECV_WAIT_EVENT_HEADER; + info->rx_count = HCI_EVENT_HDR_SIZE; + break; + + case HCI_ACLDATA_PKT: + info->rx_state = RECV_WAIT_ACL_HEADER; + info->rx_count = HCI_ACL_HDR_SIZE; + break; + + case HCI_SCODATA_PKT: + info->rx_state = RECV_WAIT_SCO_HEADER; + info->rx_count = HCI_SCO_HDR_SIZE; + break; + + default: + /* Unknown packet */ + printk(KERN_WARNING "bt3c_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type); + info->hdev.stat.err_rx++; + clear_bit(HCI_RUNNING, &(info->hdev.flags)); + + kfree_skb(info->rx_skb); + info->rx_skb = NULL; + break; + + } + + } else { + + __u8 x = inb(iobase + DATA_L); + + *skb_put(info->rx_skb, 1) = x; + inb(iobase + DATA_H); + info->rx_count--; + + if (info->rx_count == 0) { + + int dlen; + hci_event_hdr *eh; + hci_acl_hdr *ah; + hci_sco_hdr *sh; + + switch (info->rx_state) { + + case RECV_WAIT_EVENT_HEADER: + eh = (hci_event_hdr *)(info->rx_skb->data); + info->rx_state = RECV_WAIT_DATA; + info->rx_count = eh->plen; + break; + + case RECV_WAIT_ACL_HEADER: + ah = (hci_acl_hdr *)(info->rx_skb->data); + dlen = __le16_to_cpu(ah->dlen); + info->rx_state = RECV_WAIT_DATA; + info->rx_count = dlen; + break; + + case RECV_WAIT_SCO_HEADER: + sh = (hci_sco_hdr *)(info->rx_skb->data); + info->rx_state = RECV_WAIT_DATA; + info->rx_count = sh->dlen; + break; + + case RECV_WAIT_DATA: + hci_recv_frame(info->rx_skb); + info->rx_skb = NULL; + break; + + } + + } + + } + + } + + bt3c_io_write(iobase, 0x7006, 0x0000); +} + + +void bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs) +{ + bt3c_info_t *info = dev_inst; + unsigned int iobase; + int iir; + + if (!info) { + printk(KERN_WARNING "bt3c_cs: Call of irq %d for unknown device.\n", irq); + return; + } + + iobase = info->link.io.BasePort1; + + spin_lock(&(info->lock)); + + iir = inb(iobase + CONTROL); + if (iir & 0x80) { + int stat = bt3c_read(iobase, 0x7001); + + if ((stat & 0xff) == 0x7f) { + printk(KERN_WARNING "bt3c_cs: STRANGE stat=%04x\n", stat); + } else if ((stat & 0xff) != 0xff) { + if (stat & 0x0020) { + int stat = bt3c_read(iobase, 0x7002) & 0x10; + printk(KERN_WARNING "bt3c_cs: antena %s\n", stat ? "OUT" : "IN"); + } + if (stat & 0x0001) + bt3c_receive(info); + if (stat & 0x0002) { + //printk("bt3c_cs: ACK %04x\n", stat); + clear_bit(XMIT_SENDING, &(info->tx_state)); + bt3c_write_wakeup(info, 1); + } + + bt3c_io_write(iobase, 0x7001, 0x0000); + + outb(iir, iobase + CONTROL); + } + } + + spin_unlock(&(info->lock)); +} + + + + +/* ======================== HCI interface ======================== */ + + +static int bt3c_hci_flush(struct hci_dev *hdev) +{ + bt3c_info_t *info = (bt3c_info_t *)(hdev->driver_data); + + /* Drop TX queue */ + skb_queue_purge(&(info->txq)); + + return 0; +} + + +static int bt3c_hci_open(struct hci_dev *hdev) +{ + set_bit(HCI_RUNNING, &(hdev->flags)); + + return 0; +} + + +static int bt3c_hci_close(struct hci_dev *hdev) +{ + if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) + return 0; + + bt3c_hci_flush(hdev); + + return 0; +} + + +static int bt3c_hci_send_frame(struct sk_buff *skb) +{ + bt3c_info_t *info; + struct hci_dev *hdev = (struct hci_dev *)(skb->dev); + + if (!hdev) { + printk(KERN_WARNING "bt3c_cs: Frame for unknown HCI device (hdev=NULL)."); + return -ENODEV; + } + + info = (bt3c_info_t *) (hdev->driver_data); + + switch (skb->pkt_type) { + case HCI_COMMAND_PKT: + hdev->stat.cmd_tx++; + break; + case HCI_ACLDATA_PKT: + hdev->stat.acl_tx++; + break; + case HCI_SCODATA_PKT: + hdev->stat.sco_tx++; + break; + }; + + /* Prepend skb with frame type */ + memcpy(skb_push(skb, 1), &(skb->pkt_type), 1); + skb_queue_tail(&(info->txq), skb); + + bt3c_write_wakeup(info, 0); + + return 0; +} + + +static void bt3c_hci_destruct(struct hci_dev *hdev) +{ +} + + +static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) +{ + return -ENOIOCTLCMD; +} + + + +/* ======================== User mode firmware loader ======================== */ + + +#define FW_LOADER "/sbin/bluefw" +static int errno; + + +static int bt3c_fw_loader_exec(void *dev) +{ + char *argv[] = { FW_LOADER, "pccard", dev, NULL }; + char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; + int err; + + err = exec_usermodehelper(FW_LOADER, argv, envp); + if (err) + printk(KERN_WARNING "bt3c_cs: Failed to exec \"%s pccard %s\".\n", FW_LOADER, (char *)dev); + + return err; +} + + +static int bt3c_firmware_load(bt3c_info_t *info) +{ + sigset_t tmpsig; + char dev[16]; + pid_t pid; + int result; + + /* Check if root fs is mounted */ + if (!current->fs->root) { + printk(KERN_WARNING "bt3c_cs: Root filesystem is not mounted.\n"); + return -EPERM; + } + + sprintf(dev, "%04x", info->link.io.BasePort1); + + pid = kernel_thread(bt3c_fw_loader_exec, (void *)dev, 0); + if (pid < 0) { + printk(KERN_WARNING "bt3c_cs: Forking of kernel thread failed (errno=%d).\n", -pid); + return pid; + } + + /* Block signals, everything but SIGKILL/SIGSTOP */ + spin_lock_irq(¤t->sigmask_lock); + tmpsig = current->blocked; + siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP)); + recalc_sigpending(); + spin_unlock_irq(¤t->sigmask_lock); + + result = waitpid(pid, NULL, __WCLONE); + + /* Allow signals again */ + spin_lock_irq(¤t->sigmask_lock); + current->blocked = tmpsig; + recalc_sigpending(); + spin_unlock_irq(¤t->sigmask_lock); + + if (result != pid) { + printk(KERN_WARNING "bt3c_cs: Waiting for pid %d failed (errno=%d).\n", pid, -result); + return -result; + } + + return 0; +} + + + +/* ======================== Card services HCI interaction ======================== */ + + +int bt3c_open(bt3c_info_t *info) +{ + struct hci_dev *hdev; + int err; + + spin_lock_init(&(info->lock)); + + skb_queue_head_init(&(info->txq)); + + info->rx_state = RECV_WAIT_PACKET_TYPE; + info->rx_count = 0; + info->rx_skb = NULL; + + /* Load firmware */ + + if ((err = bt3c_firmware_load(info)) < 0) + return err; + + /* Timeout before it is safe to send the first HCI packet */ + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ); + + + /* Initialize and register HCI device */ + + hdev = &(info->hdev); + + hdev->type = HCI_PCCARD; + hdev->driver_data = info; + + hdev->open = bt3c_hci_open; + hdev->close = bt3c_hci_close; + hdev->flush = bt3c_hci_flush; + hdev->send = bt3c_hci_send_frame; + hdev->destruct = bt3c_hci_destruct; + hdev->ioctl = bt3c_hci_ioctl; + + if (hci_register_dev(hdev) < 0) { + printk(KERN_WARNING "bt3c_cs: Can't register HCI device %s.\n", hdev->name); + return -ENODEV; + } + + return 0; +} + + +int bt3c_close(bt3c_info_t *info) +{ + struct hci_dev *hdev = &(info->hdev); + + bt3c_hci_close(hdev); + + if (hci_unregister_dev(hdev) < 0) + printk(KERN_WARNING "bt3c_cs: Can't unregister HCI device %s.\n", hdev->name); + + return 0; +} + + + +/* ======================== Card services ======================== */ + + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + + CardServices(ReportError, handle, &err); +} + + +dev_link_t *bt3c_attach(void) +{ + bt3c_info_t *info; + client_reg_t client_reg; + dev_link_t *link; + int i, ret; + + /* Create new info device */ + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return NULL; + memset(info, 0, sizeof(*info)); + + link = &info->link; + link->priv = info; + + link->release.function = &bt3c_release; + link->release.data = (u_long)link; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.NumPorts1 = 8; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; + + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + + link->irq.Handler = bt3c_interrupt; + link->irq.Instance = info; + + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &bt3c_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + bt3c_detach(link); + return NULL; + } + + return link; +} + + +void bt3c_detach(dev_link_t *link) +{ + bt3c_info_t *info = link->priv; + dev_link_t **linkp; + int ret; + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) + break; + + if (*linkp == NULL) + return; + + del_timer(&link->release); + + if (link->state & DEV_CONFIG) + bt3c_release((u_long)link); + + if (link->handle) { + ret = CardServices(DeregisterClient, link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + + /* Unlink device structure, free bits */ + *linkp = link->next; + + kfree(info); +} + + +static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +{ + int i; + + i = CardServices(fn, handle, tuple); + if (i != CS_SUCCESS) + return CS_NO_MORE_ITEMS; + + i = CardServices(GetTupleData, handle, tuple); + if (i != CS_SUCCESS) + return i; + + return CardServices(ParseTuple, handle, tuple, parse); +} + + +#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) +#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) + +void bt3c_config(dev_link_t *link) +{ + static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; + client_handle_t handle = link->handle; + bt3c_info_t *info = link->priv; + tuple_t tuple; + u_short buf[256]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + config_info_t config; + int i, j, try, last_ret, last_fn; + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + + /* Get configuration register information */ + tuple.DesiredTuple = CISTPL_CONFIG; + last_ret = first_tuple(handle, &tuple, &parse); + if (last_ret != CS_SUCCESS) { + last_fn = ParseTuple; + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + i = CardServices(GetConfigurationInfo, handle, &config); + link->conf.Vcc = config.Vcc; + + /* First pass: look for a config entry that looks normal. */ + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + /* Two tries: without IO aliases, then with aliases */ + for (try = 0; try < 2; try++) { + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if (i != CS_SUCCESS) + goto next_entry; + if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) + link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; + if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; + i = CardServices(RequestIO, link->handle, &link->io); + if (i == CS_SUCCESS) + goto found_port; + } +next_entry: + i = next_tuple(handle, &tuple, &parse); + } + } + + /* Second pass: try to find an entry that isn't picky about + its base address, then try to grab any standard serial port + address, and finally try to get any free port. */ + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { + link->conf.ConfigIndex = cf->index; + for (j = 0; j < 5; j++) { + link->io.BasePort1 = base[j]; + link->io.IOAddrLines = base[j] ? 16 : 3; + i = CardServices(RequestIO, link->handle, &link->io); + if (i == CS_SUCCESS) + goto found_port; + } + } + i = next_tuple(handle, &tuple, &parse); + } + +found_port: + if (i != CS_SUCCESS) { + printk(KERN_NOTICE "bt3c_cs: No usable port range found. Giving up.\n"); + cs_error(link->handle, RequestIO, i); + goto failed; + } + + i = CardServices(RequestIRQ, link->handle, &link->irq); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIRQ, i); + link->irq.AssignedIRQ = 0; + } + + i = CardServices(RequestConfiguration, link->handle, &link->conf); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestConfiguration, i); + goto failed; + } + + MOD_INC_USE_COUNT; + + if (bt3c_open(info) != 0) + goto failed; + + strcpy(info->node.dev_name, info->hdev.name); + link->dev = &info->node; + link->state &= ~DEV_CONFIG_PENDING; + + return; + +cs_failed: + cs_error(link->handle, last_fn, last_ret); + +failed: + bt3c_release((u_long)link); +} + + +void bt3c_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + bt3c_info_t *info = link->priv; + + if (link->state & DEV_PRESENT) + bt3c_close(info); + + MOD_DEC_USE_COUNT; + + link->dev = NULL; + + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + CardServices(ReleaseIRQ, link->handle, &link->irq); + + link->state &= ~DEV_CONFIG; +} + + +int bt3c_event(event_t event, int priority, event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + bt3c_info_t *info = link->priv; + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + bt3c_close(info); + mod_timer(&link->release, jiffies + HZ / 20); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + bt3c_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (DEV_OK(link)) + CardServices(RequestConfiguration, link->handle, &link->conf); + break; + } + + return 0; +} + + + +/* ======================== Module initialization ======================== */ + + +int __init init_bt3c_cs(void) +{ + servinfo_t serv; + int err; + + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "bt3c_cs: Card Services release does not match!\n"); + return -1; + } + + err = register_pccard_driver(&dev_info, &bt3c_attach, &bt3c_detach); + + return err; +} + + +void __exit exit_bt3c_cs(void) +{ + unregister_pccard_driver(&dev_info); + + while (dev_list != NULL) + bt3c_detach(dev_list); +} + + +module_init(init_bt3c_cs); +module_exit(exit_bt3c_cs); diff -Nru a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c --- a/drivers/bluetooth/dtl1_cs.c Thu Aug 1 14:17:40 2002 +++ b/drivers/bluetooth/dtl1_cs.c Thu Aug 1 14:17:40 2002 @@ -75,23 +75,22 @@ typedef struct dtl1_info_t { - dev_link_t link; - dev_node_t node; + dev_link_t link; + dev_node_t node; - struct hci_dev hdev; + struct hci_dev hdev; - spinlock_t lock; /* For serializing operations */ + spinlock_t lock; /* For serializing operations */ - unsigned long flowmask; /* HCI flow mask */ - int ri_latch; + unsigned long flowmask; /* HCI flow mask */ + int ri_latch; - struct sk_buff_head txq; - unsigned long tx_state; - - unsigned long rx_state; - unsigned long rx_count; - struct sk_buff *rx_skb; + struct sk_buff_head txq; + unsigned long tx_state; + unsigned long rx_state; + unsigned long rx_count; + struct sk_buff *rx_skb; } dtl1_info_t; @@ -104,7 +103,7 @@ dev_link_t *dtl1_attach(void); void dtl1_detach(dev_link_t *); -dev_link_t *dev_list = NULL; +static dev_link_t *dev_list = NULL; /* Transmit states */ @@ -118,282 +117,253 @@ typedef struct { - u8 type; - u8 zero; - u16 len; -} __attribute__ ((packed)) nsh_t; /* Nokia Specific Header */ + u8 type; + u8 zero; + u16 len; +} __attribute__ ((packed)) nsh_t; /* Nokia Specific Header */ -#define NSHL 4 /* Nokia Specific Header Length */ +#define NSHL 4 /* Nokia Specific Header Length */ /* ======================== Interrupt handling ======================== */ -static int dtl1_write(unsigned int iobase, int fifo_size, __u8 *buf, int len) { - - int actual = 0; - - - /* Tx FIFO should be empty */ - if (!(inb(iobase + UART_LSR) & UART_LSR_THRE)) - return 0; - - - /* Fill FIFO with current frame */ - while ((fifo_size-- > 0) && (actual < len)) { - /* Transmit next byte */ - outb(buf[actual], iobase + UART_TX); - actual++; - } - - - return actual; - -} - - -static void dtl1_write_wakeup(dtl1_info_t *info) { - - if (!info) { - printk(KERN_WARNING "dtl1_cs: Call of write_wakeup for unknown device.\n"); - return; - } - - - if (test_bit(XMIT_WAITING, &(info->tx_state))) { - set_bit(XMIT_WAKEUP, &(info->tx_state)); - return; - } - - if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) { - set_bit(XMIT_WAKEUP, &(info->tx_state)); - return; - } - - - do { - register unsigned int iobase = info->link.io.BasePort1; - register struct sk_buff *skb; - register int len; - - clear_bit(XMIT_WAKEUP, &(info->tx_state)); - - if (!(info->link.state & DEV_PRESENT)) - return; - - - if (!(skb = skb_dequeue(&(info->txq)))) - break; - - - /* Send frame */ - len = dtl1_write(iobase, 32, skb->data, skb->len); - - if (len == skb->len) { - set_bit(XMIT_WAITING, &(info->tx_state)); - kfree_skb(skb); - } - else { - skb_pull(skb, len); - skb_queue_head(&(info->txq), skb); - } - - info->hdev.stat.byte_tx += len; - - } while (test_bit(XMIT_WAKEUP, &(info->tx_state))); - - - clear_bit(XMIT_SENDING, &(info->tx_state)); - -} - - -static void dtl1_control(dtl1_info_t *info, struct sk_buff *skb) { - - u8 flowmask = *(u8 *)skb->data; - int i; - - - printk(KERN_INFO "dtl1_cs: Nokia control data = "); - for (i = 0; i < skb->len; i++) { - printk("%02x ", skb->data[i]); - } - printk("\n"); - - - /* transition to active state */ - if (((info->flowmask & 0x07) == 0) && ((flowmask & 0x07) != 0)) { - clear_bit(XMIT_WAITING, &(info->tx_state)); - dtl1_write_wakeup(info); - } - - info->flowmask = flowmask; - - - kfree_skb(skb); - -} - - -static void dtl1_receive(dtl1_info_t *info) { - - unsigned int iobase; - nsh_t *nsh; - int boguscount = 0; - - - if (!info) { - printk(KERN_WARNING "dtl1_cs: Call of receive for unknown device.\n"); - return; - } - - - iobase = info->link.io.BasePort1; - - do { - info->hdev.stat.byte_rx++; - - /* Allocate packet */ - if (info->rx_skb == NULL) - if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { - printk(KERN_WARNING "dtl1_cs: Can't allocate mem for new packet.\n"); - info->rx_state = RECV_WAIT_NSH; - info->rx_count = NSHL; - return; - } - - - *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX); - nsh = (nsh_t *)info->rx_skb->data; - - info->rx_count--; - - - if (info->rx_count == 0) { - - switch (info->rx_state) { - case RECV_WAIT_NSH: - info->rx_state = RECV_WAIT_DATA; - info->rx_count = nsh->len + (nsh->len & 0x0001); - break; - case RECV_WAIT_DATA: - info->rx_skb->pkt_type = nsh->type; - - /* remove PAD byte if it exists */ - if (nsh->len & 0x0001) { - info->rx_skb->tail--; - info->rx_skb->len--; - } - - /* remove NSH */ - skb_pull(info->rx_skb, NSHL); - - - switch (info->rx_skb->pkt_type) { - case 0x80: - /* control data for the Nokia Card */ - dtl1_control(info, info->rx_skb); - break; - case 0x82: - case 0x83: - case 0x84: - /* send frame to the HCI layer */ - info->rx_skb->dev = (void *)&(info->hdev); - info->rx_skb->pkt_type &= 0x0f; - hci_recv_frame(info->rx_skb); - break; - default: - /* unknown packet */ - printk(KERN_WARNING "dtl1_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type); - kfree_skb(info->rx_skb); - break; - } - - - info->rx_state = RECV_WAIT_NSH; - info->rx_count = NSHL; - info->rx_skb = NULL; - break; - } - - } - - - /* Make sure we don't stay here to long */ - if (boguscount++ > 32) - break; - - } while (inb(iobase + UART_LSR) & UART_LSR_DR); - - -} - - -void dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs) { - - dtl1_info_t *info = dev_inst; - unsigned int iobase; - unsigned char msr; - int boguscount = 0; - int iir, lsr; - - - if (!info) { - printk(KERN_WARNING "dtl1_cs: Call of irq %d for unknown device.\n", irq); - return; - } - - - iobase = info->link.io.BasePort1; - - - spin_lock(&(info->lock)); - - iir = inb(iobase + UART_IIR) & UART_IIR_ID; - while (iir) { - - /* Clear interrupt */ - lsr = inb(iobase + UART_LSR); - - switch (iir) { - case UART_IIR_RLSI: - printk(KERN_NOTICE "dtl1_cs: RLSI\n"); - break; - case UART_IIR_RDI: - /* Receive interrupt */ - dtl1_receive(info); - break; - case UART_IIR_THRI: - if (lsr & UART_LSR_THRE) { - /* Transmitter ready for data */ - dtl1_write_wakeup(info); - } - break; - default: - printk(KERN_NOTICE "dtl1_cs: Unhandled IIR=%#x\n", iir); - break; - } - - /* Make sure we don't stay here to long */ - if (boguscount++ > 100) - break; - - iir = inb(iobase + UART_IIR) & UART_IIR_ID; - - } - - - msr = inb(iobase + UART_MSR); - - if (info->ri_latch ^ (msr & UART_MSR_RI)) { - info->ri_latch = msr & UART_MSR_RI; - clear_bit(XMIT_WAITING, &(info->tx_state)); - dtl1_write_wakeup(info); - } - - spin_unlock(&(info->lock)); +static int dtl1_write(unsigned int iobase, int fifo_size, __u8 *buf, int len) +{ + int actual = 0; + + /* Tx FIFO should be empty */ + if (!(inb(iobase + UART_LSR) & UART_LSR_THRE)) + return 0; + + /* Fill FIFO with current frame */ + while ((fifo_size-- > 0) && (actual < len)) { + /* Transmit next byte */ + outb(buf[actual], iobase + UART_TX); + actual++; + } + + return actual; +} + + +static void dtl1_write_wakeup(dtl1_info_t *info) +{ + if (!info) { + printk(KERN_WARNING "dtl1_cs: Call of write_wakeup for unknown device.\n"); + return; + } + + if (test_bit(XMIT_WAITING, &(info->tx_state))) { + set_bit(XMIT_WAKEUP, &(info->tx_state)); + return; + } + + if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) { + set_bit(XMIT_WAKEUP, &(info->tx_state)); + return; + } + + do { + register unsigned int iobase = info->link.io.BasePort1; + register struct sk_buff *skb; + register int len; + + clear_bit(XMIT_WAKEUP, &(info->tx_state)); + + if (!(info->link.state & DEV_PRESENT)) + return; + + if (!(skb = skb_dequeue(&(info->txq)))) + break; + + /* Send frame */ + len = dtl1_write(iobase, 32, skb->data, skb->len); + + if (len == skb->len) { + set_bit(XMIT_WAITING, &(info->tx_state)); + kfree_skb(skb); + } else { + skb_pull(skb, len); + skb_queue_head(&(info->txq), skb); + } + + info->hdev.stat.byte_tx += len; + + } while (test_bit(XMIT_WAKEUP, &(info->tx_state))); + + clear_bit(XMIT_SENDING, &(info->tx_state)); +} + + +static void dtl1_control(dtl1_info_t *info, struct sk_buff *skb) +{ + u8 flowmask = *(u8 *)skb->data; + int i; + + printk(KERN_INFO "dtl1_cs: Nokia control data = "); + for (i = 0; i < skb->len; i++) { + printk("%02x ", skb->data[i]); + } + printk("\n"); + + /* transition to active state */ + if (((info->flowmask & 0x07) == 0) && ((flowmask & 0x07) != 0)) { + clear_bit(XMIT_WAITING, &(info->tx_state)); + dtl1_write_wakeup(info); + } + + info->flowmask = flowmask; + + kfree_skb(skb); +} + + +static void dtl1_receive(dtl1_info_t *info) +{ + unsigned int iobase; + nsh_t *nsh; + int boguscount = 0; + + if (!info) { + printk(KERN_WARNING "dtl1_cs: Call of receive for unknown device.\n"); + return; + } + + iobase = info->link.io.BasePort1; + + do { + info->hdev.stat.byte_rx++; + + /* Allocate packet */ + if (info->rx_skb == NULL) + if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { + printk(KERN_WARNING "dtl1_cs: Can't allocate mem for new packet.\n"); + info->rx_state = RECV_WAIT_NSH; + info->rx_count = NSHL; + return; + } + + *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX); + nsh = (nsh_t *)info->rx_skb->data; + + info->rx_count--; + + if (info->rx_count == 0) { + + switch (info->rx_state) { + case RECV_WAIT_NSH: + info->rx_state = RECV_WAIT_DATA; + info->rx_count = nsh->len + (nsh->len & 0x0001); + break; + case RECV_WAIT_DATA: + info->rx_skb->pkt_type = nsh->type; + + /* remove PAD byte if it exists */ + if (nsh->len & 0x0001) { + info->rx_skb->tail--; + info->rx_skb->len--; + } + + /* remove NSH */ + skb_pull(info->rx_skb, NSHL); + + switch (info->rx_skb->pkt_type) { + case 0x80: + /* control data for the Nokia Card */ + dtl1_control(info, info->rx_skb); + break; + case 0x82: + case 0x83: + case 0x84: + /* send frame to the HCI layer */ + info->rx_skb->dev = (void *)&(info->hdev); + info->rx_skb->pkt_type &= 0x0f; + hci_recv_frame(info->rx_skb); + break; + default: + /* unknown packet */ + printk(KERN_WARNING "dtl1_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type); + kfree_skb(info->rx_skb); + break; + } + + info->rx_state = RECV_WAIT_NSH; + info->rx_count = NSHL; + info->rx_skb = NULL; + break; + } + + } + + /* Make sure we don't stay here to long */ + if (boguscount++ > 32) + break; + + } while (inb(iobase + UART_LSR) & UART_LSR_DR); +} + + +void dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs) +{ + dtl1_info_t *info = dev_inst; + unsigned int iobase; + unsigned char msr; + int boguscount = 0; + int iir, lsr; + + if (!info) { + printk(KERN_WARNING "dtl1_cs: Call of irq %d for unknown device.\n", irq); + return; + } + + iobase = info->link.io.BasePort1; + + spin_lock(&(info->lock)); + + iir = inb(iobase + UART_IIR) & UART_IIR_ID; + while (iir) { + + /* Clear interrupt */ + lsr = inb(iobase + UART_LSR); + + switch (iir) { + case UART_IIR_RLSI: + printk(KERN_NOTICE "dtl1_cs: RLSI\n"); + break; + case UART_IIR_RDI: + /* Receive interrupt */ + dtl1_receive(info); + break; + case UART_IIR_THRI: + if (lsr & UART_LSR_THRE) { + /* Transmitter ready for data */ + dtl1_write_wakeup(info); + } + break; + default: + printk(KERN_NOTICE "dtl1_cs: Unhandled IIR=%#x\n", iir); + break; + } + + /* Make sure we don't stay here to long */ + if (boguscount++ > 100) + break; + + iir = inb(iobase + UART_IIR) & UART_IIR_ID; + + } + + msr = inb(iobase + UART_MSR); + + if (info->ri_latch ^ (msr & UART_MSR_RI)) { + info->ri_latch = msr & UART_MSR_RI; + clear_bit(XMIT_WAITING, &(info->tx_state)); + dtl1_write_wakeup(info); + } + spin_unlock(&(info->lock)); } @@ -401,107 +371,94 @@ /* ======================== HCI interface ======================== */ -static int dtl1_hci_open(struct hci_dev *hdev) { - - set_bit(HCI_RUNNING, &(hdev->flags)); - - - return 0; +static int dtl1_hci_open(struct hci_dev *hdev) +{ + set_bit(HCI_RUNNING, &(hdev->flags)); + return 0; } -static int dtl1_hci_flush(struct hci_dev *hdev) { - - dtl1_info_t *info = (dtl1_info_t *)(hdev->driver_data); - - - /* Drop TX queue */ - skb_queue_purge(&(info->txq)); - +static int dtl1_hci_flush(struct hci_dev *hdev) +{ + dtl1_info_t *info = (dtl1_info_t *)(hdev->driver_data); - return 0; + /* Drop TX queue */ + skb_queue_purge(&(info->txq)); + return 0; } -static int dtl1_hci_close(struct hci_dev *hdev) { +static int dtl1_hci_close(struct hci_dev *hdev) +{ + if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) + return 0; - if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) - return 0; - - - dtl1_hci_flush(hdev); - - - return 0; + dtl1_hci_flush(hdev); + return 0; } -static int dtl1_hci_send_frame(struct sk_buff *skb) { - - dtl1_info_t *info; - struct hci_dev* hdev = (struct hci_dev *)(skb->dev); - struct sk_buff *s; - nsh_t nsh; - +static int dtl1_hci_send_frame(struct sk_buff *skb) +{ + dtl1_info_t *info; + struct hci_dev *hdev = (struct hci_dev *)(skb->dev); + struct sk_buff *s; + nsh_t nsh; - if (!hdev) { - printk(KERN_WARNING "dtl1_cs: Frame for unknown HCI device (hdev=NULL)."); - return -ENODEV; - } + if (!hdev) { + printk(KERN_WARNING "dtl1_cs: Frame for unknown HCI device (hdev=NULL)."); + return -ENODEV; + } - info = (dtl1_info_t *)(hdev->driver_data); + info = (dtl1_info_t *)(hdev->driver_data); + switch (skb->pkt_type) { + case HCI_COMMAND_PKT: + hdev->stat.cmd_tx++; + nsh.type = 0x81; + break; + case HCI_ACLDATA_PKT: + hdev->stat.acl_tx++; + nsh.type = 0x82; + break; + case HCI_SCODATA_PKT: + hdev->stat.sco_tx++; + nsh.type = 0x83; + break; + }; - switch (skb->pkt_type) { - case HCI_COMMAND_PKT: - hdev->stat.cmd_tx++; - nsh.type = 0x81; - break; - case HCI_ACLDATA_PKT: - hdev->stat.acl_tx++; - nsh.type = 0x82; - break; - case HCI_SCODATA_PKT: - hdev->stat.sco_tx++; - nsh.type = 0x83; - break; - }; + nsh.zero = 0; + nsh.len = skb->len; - nsh.zero = 0; - nsh.len = skb->len; + s = bluez_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC); + skb_reserve(s, NSHL); + memcpy(skb_put(s, skb->len), skb->data, skb->len); + if (skb->len & 0x0001) + *skb_put(s, 1) = 0; /* PAD */ - s = bluez_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC); - skb_reserve(s, NSHL); - memcpy(skb_put(s, skb->len), skb->data, skb->len); - if (skb->len & 0x0001) - *skb_put(s, 1) = 0; /* PAD */ + /* Prepend skb with Nokia frame header and queue */ + memcpy(skb_push(s, NSHL), &nsh, NSHL); + skb_queue_tail(&(info->txq), s); - /* Prepend skb with Nokia frame header and queue */ - memcpy(skb_push(s, NSHL), &nsh, NSHL); - skb_queue_tail(&(info->txq), s); + dtl1_write_wakeup(info); + kfree_skb(skb); - dtl1_write_wakeup(info); - - kfree_skb(skb); - - - return 0; - + return 0; } -static void dtl1_hci_destruct(struct hci_dev *hdev) { +static void dtl1_hci_destruct(struct hci_dev *hdev) +{ } -static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) { - - return -ENOIOCTLCMD; - +static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) +{ + return -ENOIOCTLCMD; } @@ -509,101 +466,91 @@ /* ======================== Card services HCI interaction ======================== */ -int dtl1_open(dtl1_info_t *info) { +int dtl1_open(dtl1_info_t *info) +{ + unsigned long flags; + unsigned int iobase = info->link.io.BasePort1; + struct hci_dev *hdev; - unsigned long flags; - unsigned int iobase = info->link.io.BasePort1; - struct hci_dev *hdev; + spin_lock_init(&(info->lock)); + skb_queue_head_init(&(info->txq)); - spin_lock_init(&(info->lock)); + info->rx_state = RECV_WAIT_NSH; + info->rx_count = NSHL; + info->rx_skb = NULL; - skb_queue_head_init(&(info->txq)); + set_bit(XMIT_WAITING, &(info->tx_state)); - info->rx_state = RECV_WAIT_NSH; - info->rx_count = NSHL; - info->rx_skb = NULL; + spin_lock_irqsave(&(info->lock), flags); - set_bit(XMIT_WAITING, &(info->tx_state)); + /* Reset UART */ + outb(0, iobase + UART_MCR); + /* Turn off interrupts */ + outb(0, iobase + UART_IER); - spin_lock_irqsave(&(info->lock), flags); + /* Initialize UART */ + outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */ + outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR); - /* Reset UART */ - outb(0, iobase + UART_MCR); + info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI; - /* Turn off interrupts */ - outb(0, iobase + UART_IER); + /* Turn on interrupts */ + outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); - /* Initialize UART */ - outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */ - outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR); + spin_unlock_irqrestore(&(info->lock), flags); - info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI; + /* Timeout before it is safe to send the first HCI packet */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ * 2); - /* Turn on interrupts */ - outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); - spin_unlock_irqrestore(&(info->lock), flags); + /* Initialize and register HCI device */ + hdev = &(info->hdev); - /* Timeout before it is safe to send the first HCI packet */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ * 2); + hdev->type = HCI_PCCARD; + hdev->driver_data = info; + hdev->open = dtl1_hci_open; + hdev->close = dtl1_hci_close; + hdev->flush = dtl1_hci_flush; + hdev->send = dtl1_hci_send_frame; + hdev->destruct = dtl1_hci_destruct; + hdev->ioctl = dtl1_hci_ioctl; - /* Initialize and register HCI device */ - - hdev = &(info->hdev); - - hdev->type = HCI_PCCARD; - hdev->driver_data = info; - - hdev->open = dtl1_hci_open; - hdev->close = dtl1_hci_close; - hdev->flush = dtl1_hci_flush; - hdev->send = dtl1_hci_send_frame; - hdev->destruct = dtl1_hci_destruct; - hdev->ioctl = dtl1_hci_ioctl; - - if (hci_register_dev(hdev) < 0) { - printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name); - return -ENODEV; - } - - - return 0; + if (hci_register_dev(hdev) < 0) { + printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name); + return -ENODEV; + } + return 0; } -int dtl1_close(dtl1_info_t *info) { - - unsigned long flags; - unsigned int iobase = info->link.io.BasePort1; - struct hci_dev *hdev = &(info->hdev); - - - dtl1_hci_close(hdev); - - - spin_lock_irqsave(&(info->lock), flags); - - /* Reset UART */ - outb(0, iobase + UART_MCR); +int dtl1_close(dtl1_info_t *info) +{ + unsigned long flags; + unsigned int iobase = info->link.io.BasePort1; + struct hci_dev *hdev = &(info->hdev); - /* Turn off interrupts */ - outb(0, iobase + UART_IER); + dtl1_hci_close(hdev); - spin_unlock_irqrestore(&(info->lock), flags); + spin_lock_irqsave(&(info->lock), flags); + /* Reset UART */ + outb(0, iobase + UART_MCR); - if (hci_unregister_dev(hdev) < 0) - printk(KERN_WARNING "dtl1_cs: Can't unregister HCI device %s.\n", hdev->name); + /* Turn off interrupts */ + outb(0, iobase + UART_IER); + spin_unlock_irqrestore(&(info->lock), flags); - return 0; + if (hci_unregister_dev(hdev) < 0) + printk(KERN_WARNING "dtl1_cs: Can't unregister HCI device %s.\n", hdev->name); + return 0; } @@ -611,291 +558,267 @@ /* ======================== Card services ======================== */ -static void cs_error(client_handle_t handle, int func, int ret) { - - error_info_t err = { func, ret }; - - - CardServices(ReportError, handle, &err); - -} - - -dev_link_t *dtl1_attach(void) { - - dtl1_info_t *info; - client_reg_t client_reg; - dev_link_t *link; - int i, ret; - - - /* Create new info device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return NULL; - memset(info, 0, sizeof(*info)); - - - link = &info->link; - link->priv = info; - - link->release.function = &dtl1_release; - link->release.data = (u_long)link; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts1 = 8; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; - link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; - - if (irq_list[0] == -1) - link->irq.IRQInfo2 = irq_mask; - else - for (i = 0; i < 4; i++) - link->irq.IRQInfo2 |= 1 << irq_list[i]; - - link->irq.Handler = dtl1_interrupt; - link->irq.Instance = info; - - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; - link->conf.IntType = INT_MEMORY_AND_IO; - - - /* Register with Card Services */ - link->next = dev_list; - dev_list = link; - client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; - client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &dtl1_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - - ret = CardServices(RegisterClient, &link->handle, &client_reg); - if (ret != CS_SUCCESS) { - cs_error(link->handle, RegisterClient, ret); - dtl1_detach(link); - return NULL; - } - - - return link; - -} - - -void dtl1_detach(dev_link_t *link) { - - dtl1_info_t *info = link->priv; - dev_link_t **linkp; - int ret; - - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) - break; - - if (*linkp == NULL) - return; - - - del_timer(&link->release); - if (link->state & DEV_CONFIG) - dtl1_release((u_long)link); - - - if (link->handle) { - ret = CardServices(DeregisterClient, link->handle); - if (ret != CS_SUCCESS) - cs_error(link->handle, DeregisterClient, ret); - } - - - /* Unlink device structure, free bits */ - *linkp = link->next; - - kfree(info); - -} - - -static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, - cisparse_t *parse) { - - int i; - - - i = CardServices(fn, handle, tuple); - if (i != CS_SUCCESS) - return CS_NO_MORE_ITEMS; - - i = CardServices(GetTupleData, handle, tuple); - if (i != CS_SUCCESS) - return i; - - return CardServices(ParseTuple, handle, tuple, parse); +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + + CardServices(ReportError, handle, &err); +} + + +dev_link_t *dtl1_attach(void) +{ + dtl1_info_t *info; + client_reg_t client_reg; + dev_link_t *link; + int i, ret; + + /* Create new info device */ + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return NULL; + memset(info, 0, sizeof(*info)); + + link = &info->link; + link->priv = info; + + link->release.function = &dtl1_release; + link->release.data = (u_long)link; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.NumPorts1 = 8; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; + + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + + link->irq.Handler = dtl1_interrupt; + link->irq.Instance = info; + + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &dtl1_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + dtl1_detach(link); + return NULL; + } + + return link; +} + + +void dtl1_detach(dev_link_t *link) +{ + dtl1_info_t *info = link->priv; + dev_link_t **linkp; + int ret; + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) + break; + + if (*linkp == NULL) + return; + + del_timer(&link->release); + if (link->state & DEV_CONFIG) + dtl1_release((u_long)link); + + if (link->handle) { + ret = CardServices(DeregisterClient, link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + + /* Unlink device structure, free bits */ + *linkp = link->next; + + kfree(info); +} + + +static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +{ + int i; + + i = CardServices(fn, handle, tuple); + if (i != CS_SUCCESS) + return CS_NO_MORE_ITEMS; + + i = CardServices(GetTupleData, handle, tuple); + if (i != CS_SUCCESS) + return i; + return CardServices(ParseTuple, handle, tuple, parse); } #define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) #define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) -void dtl1_config(dev_link_t *link) { - - client_handle_t handle = link->handle; - dtl1_info_t *info = link->priv; - tuple_t tuple; - u_short buf[256]; - cisparse_t parse; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; - config_info_t config; - int i, last_ret, last_fn; - - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - - /* Get configuration register information */ - tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(handle, &tuple, &parse); - if (last_ret != CS_SUCCESS) { - last_fn = ParseTuple; - goto cs_failed; - } - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - - - /* Configure card */ - link->state |= DEV_CONFIG; - i = CardServices(GetConfigurationInfo, handle, &config); - link->conf.Vcc = config.Vcc; - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - - /* Look for a generic full-sized window */ - link->io.NumPorts1 = 8; - i = first_tuple(handle, &tuple, &parse); - while (i != CS_NO_MORE_ITEMS) { - if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) { - link->conf.ConfigIndex = cf->index; - link->io.BasePort1 = cf->io.win[0].base; - link->io.NumPorts1 = cf->io.win[0].len; /*yo*/ - link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - i = CardServices(RequestIO, link->handle, &link->io); - if (i == CS_SUCCESS) - break; - } - i = next_tuple(handle, &tuple, &parse); - } - - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); - goto failed; - } - - i = CardServices(RequestIRQ, link->handle, &link->irq); - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); - link->irq.AssignedIRQ = 0; - } - - i = CardServices(RequestConfiguration, link->handle, &link->conf); - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); - goto failed; - } - - - MOD_INC_USE_COUNT; - - if (dtl1_open(info) != 0) - goto failed; - - - link->dev = &info->node; - link->state &= ~DEV_CONFIG_PENDING; - - - return; +void dtl1_config(dev_link_t *link) +{ + client_handle_t handle = link->handle; + dtl1_info_t *info = link->priv; + tuple_t tuple; + u_short buf[256]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + config_info_t config; + int i, last_ret, last_fn; + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + + /* Get configuration register information */ + tuple.DesiredTuple = CISTPL_CONFIG; + last_ret = first_tuple(handle, &tuple, &parse); + if (last_ret != CS_SUCCESS) { + last_fn = ParseTuple; + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + i = CardServices(GetConfigurationInfo, handle, &config); + link->conf.Vcc = config.Vcc; + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + + /* Look for a generic full-sized window */ + link->io.NumPorts1 = 8; + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.NumPorts1 = cf->io.win[0].len; /*yo */ + link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; + i = CardServices(RequestIO, link->handle, &link->io); + if (i == CS_SUCCESS) + break; + } + i = next_tuple(handle, &tuple, &parse); + } + + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIO, i); + goto failed; + } + + i = CardServices(RequestIRQ, link->handle, &link->irq); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIRQ, i); + link->irq.AssignedIRQ = 0; + } + + i = CardServices(RequestConfiguration, link->handle, &link->conf); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestConfiguration, i); + goto failed; + } + + MOD_INC_USE_COUNT; + + if (dtl1_open(info) != 0) + goto failed; + + strcpy(info->node.dev_name, info->hdev.name); + link->dev = &info->node; + link->state &= ~DEV_CONFIG_PENDING; + return; cs_failed: - cs_error(link->handle, last_fn, last_ret); -failed: - dtl1_release((u_long)link); + cs_error(link->handle, last_fn, last_ret); +failed: + dtl1_release((u_long)link); } -void dtl1_release(u_long arg) { - - dev_link_t *link = (dev_link_t *)arg; - dtl1_info_t *info = link->priv; - - - if (link->state & DEV_PRESENT) - dtl1_close(info); - - MOD_DEC_USE_COUNT; - - - link->dev = NULL; - - CardServices(ReleaseConfiguration, link->handle); - CardServices(ReleaseIO, link->handle, &link->io); - CardServices(ReleaseIRQ, link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; - +void dtl1_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + dtl1_info_t *info = link->priv; + + if (link->state & DEV_PRESENT) + dtl1_close(info); + + MOD_DEC_USE_COUNT; + + link->dev = NULL; + + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + CardServices(ReleaseIRQ, link->handle, &link->irq); + + link->state &= ~DEV_CONFIG; } -int dtl1_event(event_t event, int priority, event_callback_args_t *args) { - - dev_link_t *link = args->client_data; - dtl1_info_t *info = link->priv; - - - switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) { - dtl1_close(info); - mod_timer(&link->release, jiffies + HZ/20); - } - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - dtl1_config(link); - break; - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if (link->state & DEV_CONFIG) - CardServices(ReleaseConfiguration, link->handle); - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (DEV_OK(link)) - CardServices(RequestConfiguration, link->handle, &link->conf); - break; - } - - - return 0; +int dtl1_event(event_t event, int priority, event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + dtl1_info_t *info = link->priv; + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + dtl1_close(info); + mod_timer(&link->release, jiffies + HZ / 20); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + dtl1_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (DEV_OK(link)) + CardServices(RequestConfiguration, link->handle, &link->conf); + break; + } + return 0; } @@ -903,33 +826,29 @@ /* ======================== Module initialization ======================== */ -int __init init_dtl1_cs(void) { +int __init init_dtl1_cs(void) +{ + servinfo_t serv; + int err; - servinfo_t serv; - int err; + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "dtl1_cs: Card Services release does not match!\n"); + return -1; + } + err = register_pccard_driver(&dev_info, &dtl1_attach, &dtl1_detach); - CardServices(GetCardServicesInfo, &serv); - if (serv.Revision != CS_RELEASE_CODE) { - printk(KERN_NOTICE "dtl1_cs: Card Services release does not match!\n"); - return -1; - } - - - err = register_pccard_driver(&dev_info, &dtl1_attach, &dtl1_detach); - - - return err; - + return err; } -void __exit exit_dtl1_cs(void) { - - unregister_pccard_driver(&dev_info); - while (dev_list != NULL) - dtl1_detach(dev_list); +void __exit exit_dtl1_cs(void) +{ + unregister_pccard_driver(&dev_info); + while (dev_list != NULL) + dtl1_detach(dev_list); } diff -Nru a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c --- a/drivers/cdrom/aztcd.c Thu Aug 1 14:17:41 2002 +++ b/drivers/cdrom/aztcd.c Thu Aug 1 14:17:41 2002 @@ -1931,7 +1931,7 @@ } devfs_register(NULL, "aztcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUGO | S_IWUGO, &azt_fops, NULL); - if (devfs_register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) { + if (register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) { printk(KERN_WARNING "aztcd: Unable to get major %d for Aztech" " CD-ROM\n", MAJOR_NR); ret = -EIO; @@ -1957,9 +1957,8 @@ void __exit aztcd_exit(void) { - devfs_unregister(devfs_find_handle - (NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0)); - if ((devfs_unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) { + devfs_find_and_unregister(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0); + if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) { printk("What's that: can't unregister aztcd\n"); return; } diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c --- a/drivers/cdrom/cdu31a.c Thu Aug 1 14:17:36 2002 +++ b/drivers/cdrom/cdu31a.c Thu Aug 1 14:17:36 2002 @@ -3367,7 +3367,7 @@ if (!request_region(cdu31a_port, 4, "cdu31a")) goto errout3; - if (devfs_register_blkdev(MAJOR_NR, "cdu31a", &scd_bdops)) { + if (register_blkdev(MAJOR_NR, "cdu31a", &scd_bdops)) { printk("Unable to get major %d for CDU-31a\n", MAJOR_NR); goto errout2; @@ -3460,7 +3460,7 @@ errout0: printk("Unable to register CDU-31a with Uniform cdrom driver\n"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - if (devfs_unregister_blkdev(MAJOR_NR, "cdu31a")) { + if (unregister_blkdev(MAJOR_NR, "cdu31a")) { printk("Can't unregister block device for cdu31a\n"); } errout2: @@ -3477,7 +3477,7 @@ ("Can't unregister cdu31a from Uniform cdrom driver\n"); return; } - if ((devfs_unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) { + if ((unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) { printk("Can't unregister cdu31a\n"); return; } diff -Nru a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c --- a/drivers/cdrom/cm206.c Thu Aug 1 14:17:40 2002 +++ b/drivers/cdrom/cm206.c Thu Aug 1 14:17:40 2002 @@ -1367,7 +1367,7 @@ printk("Can't unregister cdrom cm206\n"); return; } - if (devfs_unregister_blkdev(MAJOR_NR, "cm206")) { + if (unregister_blkdev(MAJOR_NR, "cm206")) { printk("Can't unregister major cm206\n"); return; } @@ -1490,7 +1490,7 @@ return -EIO; } printk(".\n"); - if (devfs_register_blkdev(MAJOR_NR, "cm206", &cm206_bdops) != 0) { + if (register_blkdev(MAJOR_NR, "cm206", &cm206_bdops) != 0) { printk(KERN_INFO "Cannot register for major %d!\n", MAJOR_NR); cleanup(3); diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c --- a/drivers/cdrom/gscd.c Thu Aug 1 14:17:36 2002 +++ b/drivers/cdrom/gscd.c Thu Aug 1 14:17:36 2002 @@ -933,9 +933,8 @@ { CLEAR_TIMER; - devfs_unregister(devfs_find_handle - (NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0)); - if ((devfs_unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) { + devfs_find_and_unregister(NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0); + if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) { printk("What's that: can't unregister GoldStar-module\n"); return; } @@ -1013,7 +1012,7 @@ i++; } - if (devfs_register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) { + if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) { printk(KERN_WARNING "GSCD: Unable to get major %d for GoldStar " "CD-ROM\n", MAJOR_NR); ret = -EIO; diff -Nru a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c --- a/drivers/cdrom/mcd.c Thu Aug 1 14:17:36 2002 +++ b/drivers/cdrom/mcd.c Thu Aug 1 14:17:36 2002 @@ -1039,7 +1039,7 @@ case 2: release_region(mcd_port, 4); case 1: - if (devfs_unregister_blkdev(MAJOR_NR, "mcd")) { + if (unregister_blkdev(MAJOR_NR, "mcd")) { printk(KERN_WARNING "Can't unregister major mcd\n"); return; } @@ -1065,7 +1065,7 @@ return -EIO; } - if (devfs_register_blkdev(MAJOR_NR, "mcd", &mcd_bdops) != 0) { + if (register_blkdev(MAJOR_NR, "mcd", &mcd_bdops) != 0) { printk(KERN_ERR "mcd: Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR); return -EIO; } diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c --- a/drivers/cdrom/mcdx.c Thu Aug 1 14:17:40 2002 +++ b/drivers/cdrom/mcdx.c Thu Aug 1 14:17:40 2002 @@ -1166,7 +1166,7 @@ } xtrace(INIT, "init() register blkdev\n"); - if (devfs_register_blkdev(MAJOR_NR, "mcdx", &mcdx_bdops) != 0) { + if (register_blkdev(MAJOR_NR, "mcdx", &mcdx_bdops) != 0) { release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE); xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n", @@ -1222,7 +1222,7 @@ MCDX_IO_SIZE); free_irq(stuffp->irq, NULL); kfree(stuffp); - if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0) + if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) xwarn("cleanup() unregister_blkdev() failed\n"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); return 2; diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c --- a/drivers/cdrom/optcd.c Thu Aug 1 14:17:39 2002 +++ b/drivers/cdrom/optcd.c Thu Aug 1 14:17:39 2002 @@ -2031,8 +2031,7 @@ DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status)); return -EIO; } - if (devfs_register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0) - { + if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0) { printk(KERN_ERR "optcd: unable to get major %d\n", MAJOR_NR); release_region(optcd_port, 4); return -EIO; @@ -2051,9 +2050,8 @@ void __exit optcd_exit(void) { - devfs_unregister(devfs_find_handle(NULL, "optcd", 0, 0, - DEVFS_SPECIAL_BLK, 0)); - if (devfs_unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) { + devfs_find_and_unregister(NULL, "optcd", 0, 0, DEVFS_SPECIAL_BLK, 0); + if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) { printk(KERN_ERR "optcd: what's that: can't unregister\n"); return; } diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c --- a/drivers/cdrom/sbpcd.c Thu Aug 1 14:17:36 2002 +++ b/drivers/cdrom/sbpcd.c Thu Aug 1 14:17:36 2002 @@ -5771,7 +5771,7 @@ OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */ #endif /* SOUND_BASE */ - if (devfs_register_blkdev(MAJOR_NR, major_name, &sbpcd_bdops) != 0) + if (register_blkdev(MAJOR_NR, major_name, &sbpcd_bdops) != 0) { msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR); #ifdef MODULE @@ -5806,7 +5806,7 @@ if (D_S[j].sbp_buf==NULL) { msg(DBG_INF,"data buffer (%d frames) not available.\n",D_S[j].sbp_bufsiz); - if ((devfs_unregister_blkdev(MAJOR_NR, major_name) == -EINVAL)) + if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL)) { printk("Can't unregister %s\n", major_name); } @@ -5858,7 +5858,7 @@ { int j; - if ((devfs_unregister_blkdev(MAJOR_NR, major_name) == -EINVAL)) + if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL)) { msg(DBG_INF, "What's that: can't unregister %s.\n", major_name); return; diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c --- a/drivers/cdrom/sjcd.c Thu Aug 1 14:17:41 2002 +++ b/drivers/cdrom/sjcd.c Thu Aug 1 14:17:41 2002 @@ -1680,7 +1680,7 @@ printk("SJCD: sjcd=0x%x: ", sjcd_base); #endif - if (devfs_register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) { + if (register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) { printk("SJCD: Unable to get major %d for Sanyo CD-ROM\n", MAJOR_NR); return (-EIO); @@ -1789,7 +1789,7 @@ static int sjcd_cleanup(void) { - if ((devfs_unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) + if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) printk("SJCD: cannot unregister device.\n"); else { release_region(sjcd_base, 4); @@ -1802,8 +1802,7 @@ void __exit sjcd_exit(void) { - devfs_unregister(devfs_find_handle - (NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0)); + devfs_find_and_unregister(NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0); if (sjcd_cleanup()) printk("SJCD: module: cannot be removed.\n"); else diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c --- a/drivers/cdrom/sonycd535.c Thu Aug 1 14:17:40 2002 +++ b/drivers/cdrom/sonycd535.c Thu Aug 1 14:17:40 2002 @@ -1572,7 +1572,7 @@ MAJOR_NR, 0, S_IFBLK | S_IRUGO | S_IWUGO, &cdu_fops, NULL); - if (devfs_register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) { + if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) { printk("Unable to get major %d for %s\n", MAJOR_NR, CDU535_MESSAGE_NAME); return -EIO; @@ -1585,7 +1585,7 @@ kmalloc(sizeof *sony_toc, GFP_KERNEL); if (sony_toc == NULL) { blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE); + unregister_blkdev(MAJOR_NR, CDU535_HANDLE); devfs_unregister(sony_devfs_handle); return -ENOMEM; } @@ -1594,7 +1594,7 @@ if (last_sony_subcode == NULL) { blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); kfree(sony_toc); - devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE); + unregister_blkdev(MAJOR_NR, CDU535_HANDLE); devfs_unregister(sony_devfs_handle); return -ENOMEM; } @@ -1604,7 +1604,7 @@ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); kfree(sony_toc); kfree(last_sony_subcode); - devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE); + unregister_blkdev(MAJOR_NR, CDU535_HANDLE); devfs_unregister(sony_devfs_handle); return -ENOMEM; } @@ -1618,7 +1618,7 @@ kfree(sony_buffer); kfree(sony_toc); kfree(last_sony_subcode); - devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE); + unregister_blkdev(MAJOR_NR, CDU535_HANDLE); devfs_unregister(sony_devfs_handle); return -ENOMEM; } @@ -1643,7 +1643,7 @@ kfree(sony_buffer); kfree(sony_toc); kfree(last_sony_subcode); - devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE); + unregister_blkdev(MAJOR_NR, CDU535_HANDLE); devfs_unregister(sony_devfs_handle); if (sony535_irq_used) free_irq(sony535_irq_used, NULL); @@ -1700,9 +1700,9 @@ kfree(sony_buffer); kfree(last_sony_subcode); kfree(sony_toc); - devfs_unregister(devfs_find_handle(NULL, CDU535_HANDLE, 0, 0, - DEVFS_SPECIAL_BLK, 0)); - if (devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL) + devfs_find_and_unregister(NULL, CDU535_HANDLE, 0, 0, + DEVFS_SPECIAL_BLK, 0); + if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL) printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n"); else printk(KERN_INFO CDU535_HANDLE " module released\n"); diff -Nru a/drivers/char/Config.help b/drivers/char/Config.help --- a/drivers/char/Config.help Thu Aug 1 14:17:40 2002 +++ b/drivers/char/Config.help Thu Aug 1 14:17:40 2002 @@ -1110,3 +1110,9 @@ pSeries machines when partitioned support a hypervisor virtual console. This driver allows each pSeries partition to have a console which is accessed via the HMC. + +CONFIG_RAW_DRIVER + The raw driver permits block devices to be bound to /dev/raw/rawN. + Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. + See the raw(8) manpage for more details. + diff -Nru a/drivers/char/Config.in b/drivers/char/Config.in --- a/drivers/char/Config.in Thu Aug 1 14:17:37 2002 +++ b/drivers/char/Config.in Thu Aug 1 14:17:37 2002 @@ -198,4 +198,6 @@ tristate 'ACP Modem (Mwave) support' CONFIG_MWAVE fi +tristate ' RAW driver (/dev/raw/rawN)' CONFIG_RAW_DRIVER + endmenu diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile --- a/drivers/char/Makefile Thu Aug 1 14:17:41 2002 +++ b/drivers/char/Makefile Thu Aug 1 14:17:41 2002 @@ -7,7 +7,7 @@ # FONTMAPFILE = cp437.uni -obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o raw.o pty.o misc.o random.o +obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o random.o # All of the (potential) objects that export symbols. # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. @@ -146,6 +146,7 @@ obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o obj-$(CONFIG_SERIAL_TX3912) += generic_serial.o serial_tx3912.o obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o +obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_PRINTER) += lp.o diff -Nru a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h --- a/drivers/char/drm/mga_drv.h Thu Aug 1 14:17:41 2002 +++ b/drivers/char/drm/mga_drv.h Thu Aug 1 14:17:41 2002 @@ -38,7 +38,7 @@ u32 tail; int space; - volatile int wrapped; + volatile long wrapped; volatile u32 *status; diff -Nru a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c --- a/drivers/char/dsp56k.c Thu Aug 1 14:17:40 2002 +++ b/drivers/char/dsp56k.c Thu Aug 1 14:17:40 2002 @@ -510,7 +510,7 @@ return -ENODEV; } - if(devfs_register_chrdev(DSP56K_MAJOR, "dsp56k", &dsp56k_fops)) { + if(register_chrdev(DSP56K_MAJOR, "dsp56k", &dsp56k_fops)) { printk("DSP56k driver: Unable to register driver\n"); return -ENODEV; } @@ -526,7 +526,7 @@ static void __exit dsp56k_cleanup_driver(void) { - devfs_unregister_chrdev(DSP56K_MAJOR, "dsp56k"); + unregister_chrdev(DSP56K_MAJOR, "dsp56k"); devfs_unregister(devfs_handle); } module_exit(dsp56k_cleanup_driver); diff -Nru a/drivers/char/dtlk.c b/drivers/char/dtlk.c --- a/drivers/char/dtlk.c Thu Aug 1 14:17:40 2002 +++ b/drivers/char/dtlk.c Thu Aug 1 14:17:40 2002 @@ -340,7 +340,7 @@ dtlk_port_lpc = 0; dtlk_port_tts = 0; dtlk_busy = 0; - dtlk_major = devfs_register_chrdev(0, "dtlk", &dtlk_fops); + dtlk_major = register_chrdev(0, "dtlk", &dtlk_fops); if (dtlk_major == 0) { printk(KERN_ERR "DoubleTalk PC - cannot register device\n"); return 0; @@ -369,7 +369,7 @@ signals... */ dtlk_write_tts(DTLK_CLEAR); - devfs_unregister_chrdev(dtlk_major, "dtlk"); + unregister_chrdev(dtlk_major, "dtlk"); devfs_unregister(devfs_handle); release_region(dtlk_port_lpc, DTLK_IO_EXTENT); } diff -Nru a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c --- a/drivers/char/ftape/zftape/zftape-init.c Thu Aug 1 14:17:40 2002 +++ b/drivers/char/ftape/zftape/zftape-init.c Thu Aug 1 14:17:40 2002 @@ -67,7 +67,7 @@ /* Local vars. */ -static int busy_flag; +static unsigned long busy_flag; static sigset_t orig_sigmask; @@ -345,7 +345,7 @@ TRACE(ft_t_info, "zft_init @ 0x%p", zft_init); TRACE(ft_t_info, "installing zftape VFS interface for ftape driver ..."); - TRACE_CATCH(devfs_register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),); + TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),); for (i = 0; i < 4; i++) { char devname[9]; @@ -419,24 +419,24 @@ TRACE_FUN(ft_t_flow); - if (devfs_unregister_chrdev(QIC117_TAPE_MAJOR, "zft") != 0) { + if (unregister_chrdev(QIC117_TAPE_MAJOR, "zft") != 0) { TRACE(ft_t_warn, "failed"); } else { TRACE(ft_t_info, "successful"); } for (i = 0; i < 4; i++) { sprintf(devname, "qft%i", i); - devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i, DEVFS_SPECIAL_CHR, 0)); + devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i, DEVFS_SPECIAL_CHR, 0); sprintf(devname, "nqft%i", i); - devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 4, DEVFS_SPECIAL_CHR, 0)); + devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 4, DEVFS_SPECIAL_CHR, 0); sprintf(devname, "zqft%i", i); - devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 16, DEVFS_SPECIAL_CHR, 0)); + devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 16, DEVFS_SPECIAL_CHR, 0); sprintf(devname, "nzqft%i", i); - devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 20, DEVFS_SPECIAL_CHR, 0)); + devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 20, DEVFS_SPECIAL_CHR, 0); sprintf(devname, "rawqft%i", i); - devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 32, DEVFS_SPECIAL_CHR, 0)); + devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 32, DEVFS_SPECIAL_CHR, 0); sprintf(devname, "nrawqft%i", i); - devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 36, DEVFS_SPECIAL_CHR, 0)); + devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 36, DEVFS_SPECIAL_CHR, 0); } zft_uninit_mem(); /* release remaining memory, if any */ printk(KERN_INFO "zftape successfully unloaded.\n"); diff -Nru a/drivers/char/ip2main.c b/drivers/char/ip2main.c --- a/drivers/char/ip2main.c Thu Aug 1 14:17:41 2002 +++ b/drivers/char/ip2main.c Thu Aug 1 14:17:41 2002 @@ -531,12 +531,7 @@ if ( ( err = tty_unregister_driver ( &ip2_callout_driver ) ) ) { printk(KERN_ERR "IP2: failed to unregister callout driver (%d)\n", err); } -#ifdef CONFIG_DEVFS_FS - if ( ( err = devfs_unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) -#else - if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) -#endif - { + if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) { printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err); } remove_proc_entry("ip2mem", &proc_root); @@ -866,12 +861,7 @@ printk(KERN_ERR "IP2: failed to register callout driver (%d)\n", err); } else /* Register the IPL driver. */ -#ifdef CONFIG_DEVFS_FS - if (( err = devfs_register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ))) -#else - if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) -#endif - { + if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) { printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err ); } else /* Register the read_procmem thing */ diff -Nru a/drivers/char/istallion.c b/drivers/char/istallion.c --- a/drivers/char/istallion.c Thu Aug 1 14:17:36 2002 +++ b/drivers/char/istallion.c Thu Aug 1 14:17:36 2002 @@ -869,7 +869,7 @@ return; } devfs_unregister (devfs_handle); - if ((i = devfs_unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) + if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) printk("STALLION: failed to un-register serial memory device, " "errno=%d\n", -i); if (stli_tmpwritebuf != (char *) NULL) @@ -5329,7 +5329,7 @@ * Set up a character driver for the shared memory region. We need this * to down load the slave code image. Also it is a useful debugging tool. */ - if (devfs_register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem)) + if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem)) printk(KERN_ERR "STALLION: failed to register serial memory " "device\n"); diff -Nru a/drivers/char/lp.c b/drivers/char/lp.c --- a/drivers/char/lp.c Thu Aug 1 14:17:36 2002 +++ b/drivers/char/lp.c Thu Aug 1 14:17:36 2002 @@ -903,7 +903,7 @@ lp_table[i].timeout = 10 * HZ; } - if (devfs_register_chrdev (LP_MAJOR, "lp", &lp_fops)) { + if (register_chrdev (LP_MAJOR, "lp", &lp_fops)) { printk ("lp: unable to get major %d\n", LP_MAJOR); return -EIO; } @@ -965,7 +965,7 @@ #endif devfs_unregister (devfs_handle); - devfs_unregister_chrdev(LP_MAJOR, "lp"); + unregister_chrdev(LP_MAJOR, "lp"); for (offset = 0; offset < LP_NO; offset++) { if (lp_table[offset].dev == NULL) continue; diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c --- a/drivers/char/mem.c Thu Aug 1 14:17:40 2002 +++ b/drivers/char/mem.c Thu Aug 1 14:17:40 2002 @@ -651,7 +651,7 @@ int __init chr_dev_init(void) { - if (devfs_register_chrdev(MEM_MAJOR,"mem",&memory_fops)) + if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) printk("unable to get major %d for memory devs\n", MEM_MAJOR); memory_devfs_register(); rand_initialize(); diff -Nru a/drivers/char/misc.c b/drivers/char/misc.c --- a/drivers/char/misc.c Thu Aug 1 14:17:40 2002 +++ b/drivers/char/misc.c Thu Aug 1 14:17:40 2002 @@ -281,7 +281,7 @@ #ifdef CONFIG_I8K i8k_init(); #endif - if (devfs_register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { + if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { printk("unable to get major %d for misc devices\n", MISC_MAJOR); return -EIO; diff -Nru a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c --- a/drivers/char/n_r3964.c Thu Aug 1 14:17:41 2002 +++ b/drivers/char/n_r3964.c Thu Aug 1 14:17:41 2002 @@ -13,6 +13,12 @@ * L. Haag * * $Log: n_r3964.c,v $ + * Revision 1.10 2001/03/18 13:02:24 dwmw2 + * Fix timer usage, use spinlocks properly. + * + * Revision 1.9 2001/03/18 12:52:14 dwmw2 + * Merge changes in 2.4.2 + * * Revision 1.8 2000/03/23 14:14:54 dwmw2 * Fix race in sleeping in r3964_read() * @@ -110,8 +116,6 @@ #define TRACE_Q(fmt, arg...) /**/ #endif -static void on_timer_1(void*); -static void on_timer_2(void*); static void add_tx_queue(struct r3964_info *, struct r3964_block_header *); static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code); static void put_char(struct r3964_info *pInfo, unsigned char ch); @@ -120,7 +124,7 @@ static void transmit_block(struct r3964_info *pInfo); static void receive_char(struct r3964_info *pInfo, const unsigned char c); static void receive_error(struct r3964_info *pInfo, const char flag); -static void on_timeout(struct r3964_info *pInfo); +static void on_timeout(unsigned long priv); static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg); static int read_telegram(struct r3964_info *pInfo, pid_t pid, unsigned char *buf); static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, @@ -217,7 +221,7 @@ { int status; - printk ("r3964: Philips r3964 Driver $Revision: 1.8 $\n"); + printk ("r3964: Philips r3964 Driver $Revision: 1.10 $\n"); /* * Register the tty line discipline @@ -247,40 +251,11 @@ * Protocol implementation routines *************************************************************/ -static void on_timer_1(void *arg) -{ - struct r3964_info *pInfo = (struct r3964_info *)arg; - - if(pInfo->count_down) - { - if(!--pInfo->count_down) - { - on_timeout(pInfo); - } - } - queue_task(&pInfo->bh_2, &tq_timer); -} - -static void on_timer_2(void *arg) -{ - struct r3964_info *pInfo = (struct r3964_info *)arg; - - if(pInfo->count_down) - { - if(!--pInfo->count_down) - { - on_timeout(pInfo); - } - } - queue_task(&pInfo->bh_1, &tq_timer); -} - static void add_tx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader) { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&pInfo->lock, flags); pHeader->next = NULL; @@ -294,7 +269,7 @@ pInfo->tx_last = pHeader; } - restore_flags(flags); + spin_unlock_irqrestore(&pInfo->lock, flags); TRACE_Q("add_tx_queue %x, length %d, tx_first = %x", (int)pHeader, pHeader->length, (int)pInfo->tx_first ); @@ -337,8 +312,7 @@ wake_up_interruptible (&pInfo->read_wait); } - save_flags(flags); - cli(); + spin_lock_irqsave(&pInfo->lock, flags); pInfo->tx_first = pHeader->next; if(pInfo->tx_first==NULL) @@ -346,7 +320,7 @@ pInfo->tx_last = NULL; } - restore_flags(flags); + spin_unlock_irqrestore(&pInfo->lock, flags); kfree(pHeader); TRACE_M("remove_from_tx_queue - kfree %x",(int)pHeader); @@ -359,8 +333,7 @@ { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&pInfo->lock, flags); pHeader->next = NULL; @@ -375,7 +348,7 @@ } pInfo->blocks_in_rx_queue++; - restore_flags(flags); + spin_unlock_irqrestore(&pInfo->lock, flags); TRACE_Q("add_rx_queue: %x, length = %d, rx_first = %x, count = %d", (int)pHeader, pHeader->length, @@ -396,8 +369,7 @@ TRACE_Q("remove_from_rx_queue: %x, length %d", (int)pHeader, (int)pHeader->length ); - save_flags(flags); - cli(); + spin_lock_irqsave(&pInfo->lock, flags); if(pInfo->rx_first == pHeader) { @@ -430,7 +402,7 @@ } } - restore_flags(flags); + spin_unlock_irqrestore(&pInfo->lock, flags); kfree(pHeader); TRACE_M("remove_from_rx_queue - kfree %x",(int)pHeader); @@ -471,17 +443,16 @@ unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&pInfo->lock, flags); if((pInfo->state == R3964_IDLE) && (pInfo->tx_first!=NULL)) { pInfo->state = R3964_TX_REQUEST; - pInfo->count_down = R3964_TO_QVZ; pInfo->nRetry=0; pInfo->flags &= ~R3964_ERROR; - - restore_flags(flags); + mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); + + spin_unlock_irqrestore(&pInfo->lock, flags); TRACE_PS("trigger_transmit - sent STX"); @@ -492,7 +463,7 @@ } else { - restore_flags(flags); + spin_unlock_irqrestore(&pInfo->lock, flags); } } @@ -506,8 +477,8 @@ put_char(pInfo, STX); flush(pInfo); pInfo->state = R3964_TX_REQUEST; - pInfo->count_down = R3964_TO_QVZ; pInfo->nRetry++; + mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); } else { @@ -566,7 +537,7 @@ put_char(pInfo, pInfo->bcc); } pInfo->state = R3964_WAIT_FOR_TX_ACK; - pInfo->count_down = R3964_TO_QVZ; + mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); } flush(pInfo); } @@ -601,8 +572,8 @@ if(pInfo->nRetrystate=R3964_WAIT_FOR_RX_REPEAT; - pInfo->count_down = R3964_TO_RX_PANIC; pInfo->nRetry++; + mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC); } else { @@ -616,7 +587,7 @@ /* received block; submit DLE: */ put_char(pInfo, DLE); flush(pInfo); - pInfo->count_down=0; + del_timer_sync(&pInfo->tmr); TRACE_PS(" rx success: got %d chars", length); /* prepare struct r3964_block_header: */ @@ -701,7 +672,7 @@ TRACE_PE("TRANSMITTING - got illegal char"); pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY; - pInfo->count_down = R3964_TO_ZVZ; + mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); } break; case R3964_WAIT_FOR_TX_ACK: @@ -728,7 +699,7 @@ { TRACE_PE("IDLE - got STX but no space in rx_queue!"); pInfo->state=R3964_WAIT_FOR_RX_BUF; - pInfo->count_down = R3964_TO_NO_BUF; + mod_timer(&pInfo->tmr, R3964_TO_NO_BUF); break; } start_receiving: @@ -738,8 +709,8 @@ pInfo->last_rx = 0; pInfo->flags &= ~R3964_ERROR; pInfo->state=R3964_RECEIVING; - pInfo->count_down = R3964_TO_ZVZ; - pInfo->nRetry = 0; + mod_timer(&pInfo->tmr, R3964_TO_ZVZ); + pInfo->nRetry = 0; put_char(pInfo, DLE); flush(pInfo); pInfo->bcc = 0; @@ -765,7 +736,7 @@ if(pInfo->flags & R3964_BCC) { pInfo->state = R3964_WAIT_FOR_BCC; - pInfo->count_down = R3964_TO_ZVZ; + mod_timer(&pInfo->tmr, R3964_TO_ZVZ); } else { @@ -777,7 +748,7 @@ pInfo->last_rx = c; char_to_buf: pInfo->rx_buf[pInfo->rx_position++] = c; - pInfo->count_down = R3964_TO_ZVZ; + mod_timer(&pInfo->tmr, R3964_TO_ZVZ); } } /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ @@ -818,8 +789,10 @@ } } -static void on_timeout(struct r3964_info *pInfo) +static void on_timeout(unsigned long priv) { + struct r3964_info *pInfo = (void *)priv; + switch(pInfo->state) { case R3964_TX_REQUEST: @@ -926,6 +899,7 @@ return -ENOMEM; TRACE_PS("add client %d to client list", pid); + spin_lock_init(&pClient->lock); pClient->sig_flags=arg; pClient->pid = pid; pClient->next=pInfo->firstClient; @@ -989,8 +963,7 @@ return; } - save_flags(flags); - cli(); + spin_lock_irqsave(&pClient->lock, flags); pMsg->msg_id = msg_id; pMsg->arg = arg; @@ -1014,7 +987,7 @@ { pBlock->locks++; } - restore_flags(flags); + spin_unlock_irqrestore(&pClient->lock, flags); } else { @@ -1049,8 +1022,7 @@ if(pClient->first_msg) { - save_flags(flags); - cli(); + spin_lock_irqsave(&pClient->lock, flags); pMsg = pClient->first_msg; pClient->first_msg = pMsg->next; @@ -1065,7 +1037,7 @@ remove_client_block(pInfo, pClient); pClient->next_block_to_read = pMsg->block; } - restore_flags(flags); + spin_unlock_irqrestore(&pClient->lock, flags); } return pMsg; } @@ -1137,6 +1109,7 @@ return -ENOMEM; } + spin_lock_init(&pInfo->lock); pInfo->tty = tty; init_waitqueue_head (&pInfo->read_wait); pInfo->priority = R3964_MASTER; @@ -1149,26 +1122,13 @@ pInfo->firstClient=NULL; pInfo->state=R3964_IDLE; pInfo->flags = R3964_DEBUG; - pInfo->count_down = 0; pInfo->nRetry = 0; tty->disc_data = pInfo; - /* - * Add 'on_timer' to timer task queue - * (will be called from timer bh) - */ - INIT_LIST_HEAD(&pInfo->bh_1.list); - pInfo->bh_1.sync = 0; - pInfo->bh_1.routine = &on_timer_1; - pInfo->bh_1.data = pInfo; - - INIT_LIST_HEAD(&pInfo->bh_2.list); - pInfo->bh_2.sync = 0; - pInfo->bh_2.routine = &on_timer_2; - pInfo->bh_2.data = pInfo; - - queue_task(&pInfo->bh_1, &tq_timer); + INIT_LIST_HEAD(&pInfo->tmr.list); + pInfo->tmr.data = (unsigned long)pInfo; + pInfo->tmr.function = on_timeout; return 0; } @@ -1187,12 +1147,7 @@ * Make sure that our task queue isn't activated. If it * is, take it out of the linked list. */ - spin_lock_irqsave(&tqueue_lock, flags); - if (pInfo->bh_1.sync) - list_del(&pInfo->bh_1.list); - if (pInfo->bh_2.sync) - list_del(&pInfo->bh_2.list); - spin_unlock_irqrestore(&tqueue_lock, flags); + del_timer_sync(&pInfo->tmr); /* Remove client-structs and message queues: */ pClient=pInfo->firstClient; @@ -1213,11 +1168,10 @@ pClient=pNext; } /* Remove jobs from tx_queue: */ - save_flags(flags); - cli(); + spin_lock_irqsave(&pInfo->lock, flags); pHeader=pInfo->tx_first; pInfo->tx_first=pInfo->tx_last=NULL; - restore_flags(flags); + spin_unlock_irqrestore(&pInfo->lock, flags); while(pHeader) { @@ -1430,10 +1384,9 @@ if(pClient) { poll_wait(file, &pInfo->read_wait, wait); - save_flags(flags); - cli(); + spin_lock_irqsave(&pInfo->lock, flags); pMsg=pClient->first_msg; - restore_flags(flags); + spin_unlock_irqrestore(&pInfo->lock, flags); if(pMsg) result |= POLLIN | POLLRDNORM; } diff -Nru a/drivers/char/nvram.c b/drivers/char/nvram.c --- a/drivers/char/nvram.c Thu Aug 1 14:17:40 2002 +++ b/drivers/char/nvram.c Thu Aug 1 14:17:40 2002 @@ -38,12 +38,12 @@ #include #define PC 1 -#define ATARI 2 +#define ATARI 2 /* select machine configuration */ #if defined(CONFIG_ATARI) #define MACH ATARI -#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and others?? */ +#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and others?? */ #define MACH PC #else #error Cannot build nvram driver for this machine configuration. @@ -52,12 +52,12 @@ #if MACH == PC /* RTC in a PC */ -#define CHECK_DRIVER_INIT() 1 +#define CHECK_DRIVER_INIT() 1 /* On PCs, the checksum is built only over bytes 2..31 */ #define PC_CKS_RANGE_START 2 #define PC_CKS_RANGE_END 31 -#define PC_CKS_LOC 32 +#define PC_CKS_LOC 32 #define mach_check_checksum pc_check_checksum #define mach_set_checksum pc_set_checksum @@ -70,14 +70,14 @@ /* Special parameters for RTC in Atari machines */ #include #include -#define RTC_PORT(x) (TT_RTC_BAS + 2*(x)) -#define CHECK_DRIVER_INIT() (MACH_IS_ATARI && ATARIHW_PRESENT(TT_CLK)) +#define RTC_PORT(x) (TT_RTC_BAS + 2*(x)) +#define CHECK_DRIVER_INIT() (MACH_IS_ATARI && ATARIHW_PRESENT(TT_CLK)) /* On Ataris, the checksum is over all bytes except the checksum bytes * themselves; these are at the very end */ #define ATARI_CKS_RANGE_START 0 -#define ATARI_CKS_RANGE_END 47 -#define ATARI_CKS_LOC 48 +#define ATARI_CKS_RANGE_END 47 +#define ATARI_CKS_LOC 48 #define mach_check_checksum atari_check_checksum #define mach_set_checksum atari_set_checksum @@ -109,46 +109,50 @@ static int nvram_open_cnt; /* #times opened */ static int nvram_open_mode; /* special open modes */ -static spinlock_t nvram_open_lock = SPIN_LOCK_UNLOCKED; - /* guards nvram_open_cnt and - nvram_open_mode */ -#define NVRAM_WRITE 1 /* opened for writing (exclusive) */ -#define NVRAM_EXCL 2 /* opened with O_EXCL */ +static spinlock_t nvram_open_lock = SPIN_LOCK_UNLOCKED; /* guards + * nvram_open_cnt and + * nvram_open_mode */ +#define NVRAM_WRITE 1 /* opened for writing (exclusive) */ +#define NVRAM_EXCL 2 /* opened with O_EXCL */ + +#define RTC_FIRST_BYTE 14 /* RTC register number of first + * NVRAM byte */ +#define NVRAM_BYTES 128-RTC_FIRST_BYTE /* number of NVRAM bytes */ -#define RTC_FIRST_BYTE 14 /* RTC register number of first NVRAM byte */ -#define NVRAM_BYTES 128-RTC_FIRST_BYTE /* number of NVRAM bytes */ +static int mach_check_checksum(void); +static void mach_set_checksum(void); - -static int mach_check_checksum( void ); -static void mach_set_checksum( void ); #ifdef CONFIG_PROC_FS -static int mach_proc_infos( unsigned char *contents, char *buffer, int *len, - off_t *begin, off_t offset, int size ); +static int mach_proc_infos(unsigned char *contents, char *buffer, int *len, + off_t *begin, off_t offset, int size); #endif - /* * These are the internal NVRAM access functions, which do NOT disable * interrupts and do not check the checksum. Both tasks are left to higher * level function, so they need to be done only once per syscall. */ -static __inline__ unsigned char nvram_read_int( int i ) +static __inline__ unsigned char +nvram_read_int(int i) { - return( CMOS_READ( RTC_FIRST_BYTE+i ) ); + return CMOS_READ(RTC_FIRST_BYTE + i); } -static __inline__ void nvram_write_int( unsigned char c, int i ) +static __inline__ void +nvram_write_int(unsigned char c, int i) { - CMOS_WRITE( c, RTC_FIRST_BYTE+i ); + CMOS_WRITE(c, RTC_FIRST_BYTE + i); } -static __inline__ int nvram_check_checksum_int( void ) +static __inline__ int +nvram_check_checksum_int(void) { - return( mach_check_checksum() ); + return mach_check_checksum(); } -static __inline__ void nvram_set_checksum_int( void ) +static __inline__ void +nvram_set_checksum_int(void) { mach_set_checksum(); } @@ -166,178 +170,183 @@ * module), so they access config information themselves. */ -unsigned char nvram_read_byte( int i ) +unsigned char +nvram_read_byte(int i) { unsigned long flags; unsigned char c; - spin_lock_irqsave (&rtc_lock, flags); - c = nvram_read_int( i ); - spin_unlock_irqrestore (&rtc_lock, flags); - return( c ); + spin_lock_irqsave(&rtc_lock, flags); + c = nvram_read_int(i); + spin_unlock_irqrestore(&rtc_lock, flags); + return c; } /* This races nicely with trying to read with checksum checking (nvram_read) */ -void nvram_write_byte( unsigned char c, int i ) +void +nvram_write_byte(unsigned char c, int i) { unsigned long flags; - spin_lock_irqsave (&rtc_lock, flags); - nvram_write_int( c, i ); - spin_unlock_irqrestore (&rtc_lock, flags); + spin_lock_irqsave(&rtc_lock, flags); + nvram_write_int(c, i); + spin_unlock_irqrestore(&rtc_lock, flags); } -int nvram_check_checksum( void ) +int +nvram_check_checksum(void) { unsigned long flags; int rv; - spin_lock_irqsave (&rtc_lock, flags); + spin_lock_irqsave(&rtc_lock, flags); rv = nvram_check_checksum_int(); - spin_unlock_irqrestore (&rtc_lock, flags); - return( rv ); + spin_unlock_irqrestore(&rtc_lock, flags); + return rv; } -void nvram_set_checksum( void ) +void +nvram_set_checksum(void) { unsigned long flags; - spin_lock_irqsave (&rtc_lock, flags); + spin_lock_irqsave(&rtc_lock, flags); nvram_set_checksum_int(); - spin_unlock_irqrestore (&rtc_lock, flags); + spin_unlock_irqrestore(&rtc_lock, flags); } #endif /* MACH == ATARI */ - /* * The are the file operation function for user access to /dev/nvram */ -static long long nvram_llseek(struct file *file,loff_t offset, int origin ) +static long long +nvram_llseek(struct file *file, loff_t offset, int origin) { lock_kernel(); - switch( origin ) { - case 0: + switch (origin) { + case 0: /* nothing to do */ break; - case 1: + case 1: offset += file->f_pos; break; - case 2: + case 2: offset += NVRAM_BYTES; break; } unlock_kernel(); - return( (offset >= 0) ? (file->f_pos = offset) : -EINVAL ); + return (offset >= 0) ? (file->f_pos = offset) : -EINVAL; } -static ssize_t nvram_read(struct file * file, - char * buf, size_t count, loff_t *ppos ) +static ssize_t +nvram_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - char contents [NVRAM_BYTES]; + char contents[NVRAM_BYTES]; unsigned i = *ppos; char *tmp; - spin_lock_irq (&rtc_lock); - + spin_lock_irq(&rtc_lock); + if (!nvram_check_checksum_int()) goto checksum_err; for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp) *tmp = nvram_read_int(i); - spin_unlock_irq (&rtc_lock); + spin_unlock_irq(&rtc_lock); - if (copy_to_user (buf, contents, tmp - contents)) + if (copy_to_user(buf, contents, tmp - contents)) return -EFAULT; *ppos = i; - return (tmp - contents); + return tmp - contents; -checksum_err: - spin_unlock_irq (&rtc_lock); + checksum_err: + spin_unlock_irq(&rtc_lock); return -EIO; } -static ssize_t nvram_write(struct file * file, - const char * buf, size_t count, loff_t *ppos ) +static ssize_t +nvram_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - char contents [NVRAM_BYTES]; + char contents[NVRAM_BYTES]; unsigned i = *ppos; - char * tmp; + char *tmp; - if (copy_from_user (contents, buf, (NVRAM_BYTES - i) < count ? - (NVRAM_BYTES - i) : count)) + if (copy_from_user(contents, buf, (NVRAM_BYTES - i) < count ? + (NVRAM_BYTES - i) : count)) return -EFAULT; - spin_lock_irq (&rtc_lock); + spin_lock_irq(&rtc_lock); if (!nvram_check_checksum_int()) goto checksum_err; for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp) - nvram_write_int (*tmp, i); + nvram_write_int(*tmp, i); nvram_set_checksum_int(); - spin_unlock_irq (&rtc_lock); + spin_unlock_irq(&rtc_lock); *ppos = i; - return (tmp - contents); + return tmp - contents; -checksum_err: - spin_unlock_irq (&rtc_lock); + checksum_err: + spin_unlock_irq(&rtc_lock); return -EIO; } -static int nvram_ioctl( struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg ) +static int +nvram_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { int i; - - switch( cmd ) { - case NVRAM_INIT: /* initialize NVRAM contents and checksum */ + switch (cmd) { + + case NVRAM_INIT: /* initialize NVRAM contents and checksum */ if (!capable(CAP_SYS_ADMIN)) - return( -EACCES ); + return -EACCES; - spin_lock_irq (&rtc_lock); + spin_lock_irq(&rtc_lock); - for( i = 0; i < NVRAM_BYTES; ++i ) - nvram_write_int( 0, i ); + for (i = 0; i < NVRAM_BYTES; ++i) + nvram_write_int(0, i); nvram_set_checksum_int(); - - spin_unlock_irq (&rtc_lock); - return( 0 ); - - case NVRAM_SETCKS: /* just set checksum, contents unchanged - * (maybe useful after checksum garbaged - * somehow...) */ + + spin_unlock_irq(&rtc_lock); + return 0; + + case NVRAM_SETCKS: /* just set checksum, contents unchanged + * (maybe useful after checksum garbaged + * somehow...) */ if (!capable(CAP_SYS_ADMIN)) - return( -EACCES ); + return -EACCES; - spin_lock_irq (&rtc_lock); + spin_lock_irq(&rtc_lock); nvram_set_checksum_int(); - spin_unlock_irq (&rtc_lock); - return( 0 ); + spin_unlock_irq(&rtc_lock); + return 0; - default: - return( -ENOTTY ); + default: + return -ENOTTY; } } -static int nvram_open( struct inode *inode, struct file *file ) +static int +nvram_open(struct inode *inode, struct file *file) { - spin_lock( &nvram_open_lock ); + spin_lock(&nvram_open_lock); if ((nvram_open_cnt && (file->f_flags & O_EXCL)) || - (nvram_open_mode & NVRAM_EXCL) || - ((file->f_mode & 2) && (nvram_open_mode & NVRAM_WRITE))) - { - spin_unlock( &nvram_open_lock ); - return( -EBUSY ); + (nvram_open_mode & NVRAM_EXCL) || + ((file->f_mode & 2) && (nvram_open_mode & NVRAM_WRITE))) { + spin_unlock(&nvram_open_lock); + return -EBUSY; } if (file->f_flags & O_EXCL) @@ -345,60 +354,65 @@ if (file->f_mode & 2) nvram_open_mode |= NVRAM_WRITE; nvram_open_cnt++; - spin_unlock( &nvram_open_lock ); - return( 0 ); + spin_unlock(&nvram_open_lock); + return 0; } -static int nvram_release( struct inode *inode, struct file *file ) +static int +nvram_release(struct inode *inode, struct file *file) { - spin_lock( &nvram_open_lock ); + spin_lock(&nvram_open_lock); nvram_open_cnt--; if (file->f_flags & O_EXCL) nvram_open_mode &= ~NVRAM_EXCL; if (file->f_mode & 2) nvram_open_mode &= ~NVRAM_WRITE; - spin_unlock( &nvram_open_lock ); - return( 0 ); + spin_unlock(&nvram_open_lock); + return 0; } - #ifndef CONFIG_PROC_FS -static int nvram_read_proc( char *buffer, char **start, off_t offset, - int size, int *eof, void *data) { return 0; } +static int +nvram_read_proc(char *buffer, char **start, off_t offset, + int size, int *eof, void *data) +{ + return 0; +} #else -static int nvram_read_proc( char *buffer, char **start, off_t offset, - int size, int *eof, void *data ) +static int +nvram_read_proc(char *buffer, char **start, off_t offset, + int size, int *eof, void *data) { unsigned char contents[NVRAM_BYTES]; - int i, len = 0; - off_t begin = 0; + int i, len = 0; + off_t begin = 0; + + spin_lock_irq(&rtc_lock); + for (i = 0; i < NVRAM_BYTES; ++i) + contents[i] = nvram_read_int(i); + spin_unlock_irq(&rtc_lock); + + *eof = mach_proc_infos(contents, buffer, &len, &begin, offset, size); + + if (offset >= begin + len) + return 0; + *start = buffer + (offset - begin); + return (size < begin + len - offset) ? size : begin + len - offset; - spin_lock_irq (&rtc_lock); - for( i = 0; i < NVRAM_BYTES; ++i ) - contents[i] = nvram_read_int( i ); - spin_unlock_irq (&rtc_lock); - - *eof = mach_proc_infos( contents, buffer, &len, &begin, offset, size ); - - if (offset >= begin + len) - return( 0 ); - *start = buffer + (offset - begin); - return( size < begin + len - offset ? size : begin + len - offset ); - } /* This macro frees the machine specific function from bounds checking and * this like that... */ -#define PRINT_PROC(fmt,args...) \ - do { \ - *len += sprintf( buffer+*len, fmt, ##args ); \ - if (*begin + *len > offset + size) \ - return( 0 ); \ - if (*begin + *len < offset) { \ - *begin += *len; \ - *len = 0; \ - } \ +#define PRINT_PROC(fmt,args...) \ + do { \ + *len += sprintf(buffer+*len, fmt, ##args); \ + if (*begin + *len > offset + size) \ + return 0; \ + if (*begin + *len < offset) { \ + *begin += *len; \ + *len = 0; \ + } \ } while(0) #endif /* CONFIG_PROC_FS */ @@ -419,72 +433,74 @@ &nvram_fops }; - -static int __init nvram_init(void) +static int __init +nvram_init(void) { int ret; /* First test whether the driver should init at all */ if (!CHECK_DRIVER_INIT()) - return( -ENXIO ); + return -ENXIO; - ret = misc_register( &nvram_dev ); + ret = misc_register(&nvram_dev); if (ret) { - printk(KERN_ERR "nvram: can't misc_register on minor=%d\n", NVRAM_MINOR); + printk(KERN_ERR "nvram: can't misc_register on minor=%d\n", + NVRAM_MINOR); goto out; } - if (!create_proc_read_entry("driver/nvram",0,0,nvram_read_proc,NULL)) { + if (!create_proc_read_entry("driver/nvram", 0, 0, nvram_read_proc, + NULL)) { printk(KERN_ERR "nvram: can't create /proc/driver/nvram\n"); ret = -ENOMEM; goto outmisc; } ret = 0; printk(KERN_INFO "Non-volatile memory driver v" NVRAM_VERSION "\n"); -out: - return( ret ); -outmisc: - misc_deregister( &nvram_dev ); + out: + return ret; + outmisc: + misc_deregister(&nvram_dev); goto out; } -static void __exit nvram_cleanup_module (void) +static void __exit +nvram_cleanup_module(void) { - remove_proc_entry( "driver/nvram", 0 ); - misc_deregister( &nvram_dev ); + remove_proc_entry("driver/nvram", 0); + misc_deregister(&nvram_dev); } module_init(nvram_init); module_exit(nvram_cleanup_module); - /* * Machine specific functions */ - #if MACH == PC -static int pc_check_checksum( void ) +static int +pc_check_checksum(void) { int i; unsigned short sum = 0; - - for( i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i ) - sum += nvram_read_int( i ); - return( (sum & 0xffff) == - ((nvram_read_int(PC_CKS_LOC) << 8) | - nvram_read_int(PC_CKS_LOC+1)) ); + + for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i) + sum += nvram_read_int(i); + return ((sum & 0xffff) == + ((nvram_read_int(PC_CKS_LOC)<<8) | nvram_read_int(PC_CKS_LOC+1))); } -static void pc_set_checksum( void ) +static void +pc_set_checksum(void) { int i; unsigned short sum = 0; - - for( i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i ) - sum += nvram_read_int( i ); - nvram_write_int( sum >> 8, PC_CKS_LOC ); - nvram_write_int( sum & 0xff, PC_CKS_LOC+1 ); + + for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i) + sum += nvram_read_int(i); + nvram_write_int(sum >> 8, PC_CKS_LOC); + nvram_write_int(sum & 0xff, PC_CKS_LOC + 1); } #ifdef CONFIG_PROC_FS @@ -501,69 +517,67 @@ "monochrome", }; -static int pc_proc_infos( unsigned char *nvram, char *buffer, int *len, - off_t *begin, off_t offset, int size ) +static int +pc_proc_infos(unsigned char *nvram, char *buffer, int *len, + off_t *begin, off_t offset, int size) { int checksum; int type; - spin_lock_irq (&rtc_lock); + spin_lock_irq(&rtc_lock); checksum = nvram_check_checksum_int(); - spin_unlock_irq (&rtc_lock); + spin_unlock_irq(&rtc_lock); - PRINT_PROC( "Checksum status: %svalid\n", checksum ? "" : "not " ); + PRINT_PROC("Checksum status: %svalid\n", checksum ? "" : "not "); - PRINT_PROC( "# floppies : %d\n", - (nvram[6] & 1) ? (nvram[6] >> 6) + 1 : 0 ); - PRINT_PROC( "Floppy 0 type : " ); + PRINT_PROC("# floppies : %d\n", + (nvram[6] & 1) ? (nvram[6] >> 6) + 1 : 0); + PRINT_PROC("Floppy 0 type : "); type = nvram[2] >> 4; - if (type < sizeof(floppy_types)/sizeof(*floppy_types)) - PRINT_PROC( "%s\n", floppy_types[type] ); + if (type < sizeof (floppy_types) / sizeof (*floppy_types)) + PRINT_PROC("%s\n", floppy_types[type]); else - PRINT_PROC( "%d (unknown)\n", type ); - PRINT_PROC( "Floppy 1 type : " ); + PRINT_PROC("%d (unknown)\n", type); + PRINT_PROC("Floppy 1 type : "); type = nvram[2] & 0x0f; - if (type < sizeof(floppy_types)/sizeof(*floppy_types)) - PRINT_PROC( "%s\n", floppy_types[type] ); + if (type < sizeof (floppy_types) / sizeof (*floppy_types)) + PRINT_PROC("%s\n", floppy_types[type]); else - PRINT_PROC( "%d (unknown)\n", type ); + PRINT_PROC("%d (unknown)\n", type); - PRINT_PROC( "HD 0 type : " ); + PRINT_PROC("HD 0 type : "); type = nvram[4] >> 4; if (type) - PRINT_PROC( "%02x\n", type == 0x0f ? nvram[11] : type ); + PRINT_PROC("%02x\n", type == 0x0f ? nvram[11] : type); else - PRINT_PROC( "none\n" ); + PRINT_PROC("none\n"); - PRINT_PROC( "HD 1 type : " ); + PRINT_PROC("HD 1 type : "); type = nvram[4] & 0x0f; if (type) - PRINT_PROC( "%02x\n", type == 0x0f ? nvram[12] : type ); + PRINT_PROC("%02x\n", type == 0x0f ? nvram[12] : type); else - PRINT_PROC( "none\n" ); + PRINT_PROC("none\n"); + + PRINT_PROC("HD type 48 data: %d/%d/%d C/H/S, precomp %d, lz %d\n", + nvram[18] | (nvram[19] << 8), + nvram[20], nvram[25], + nvram[21] | (nvram[22] << 8), nvram[23] | (nvram[24] << 8)); + PRINT_PROC("HD type 49 data: %d/%d/%d C/H/S, precomp %d, lz %d\n", + nvram[39] | (nvram[40] << 8), + nvram[41], nvram[46], + nvram[42] | (nvram[43] << 8), nvram[44] | (nvram[45] << 8)); + + PRINT_PROC("DOS base memory: %d kB\n", nvram[7] | (nvram[8] << 8)); + PRINT_PROC("Extended memory: %d kB (configured), %d kB (tested)\n", + nvram[9] | (nvram[10] << 8), nvram[34] | (nvram[35] << 8)); - PRINT_PROC( "HD type 48 data: %d/%d/%d C/H/S, precomp %d, lz %d\n", - nvram[18] | (nvram[19] << 8), - nvram[20], nvram[25], - nvram[21] | (nvram[22] << 8), - nvram[23] | (nvram[24] << 8) ); - PRINT_PROC( "HD type 49 data: %d/%d/%d C/H/S, precomp %d, lz %d\n", - nvram[39] | (nvram[40] << 8), - nvram[41], nvram[46], - nvram[42] | (nvram[43] << 8), - nvram[44] | (nvram[45] << 8) ); - - PRINT_PROC( "DOS base memory: %d kB\n", nvram[7] | (nvram[8] << 8) ); - PRINT_PROC( "Extended memory: %d kB (configured), %d kB (tested)\n", - nvram[9] | (nvram[10] << 8), - nvram[34] | (nvram[35] << 8) ); - - PRINT_PROC( "Gfx adapter : %s\n", gfx_types[ (nvram[6] >> 4)&3 ] ); - - PRINT_PROC( "FPU : %sinstalled\n", - (nvram[6] & 2) ? "" : "not " ); - - return( 1 ); + PRINT_PROC("Gfx adapter : %s\n", gfx_types[(nvram[6] >> 4) & 3]); + + PRINT_PROC("FPU : %sinstalled\n", + (nvram[6] & 2) ? "" : "not "); + + return 1; } #endif @@ -571,26 +585,28 @@ #if MACH == ATARI -static int atari_check_checksum( void ) +static int +atari_check_checksum(void) { int i; unsigned char sum = 0; - - for( i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i ) - sum += nvram_read_int( i ); - return( nvram_read_int( ATARI_CKS_LOC ) == (~sum & 0xff) && - nvram_read_int( ATARI_CKS_LOC+1 ) == (sum & 0xff) ); + + for (i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i) + sum += nvram_read_int(i); + return (nvram_read_int(ATARI_CKS_LOC) == (~sum & 0xff) && + nvram_read_int(ATARI_CKS_LOC + 1) == (sum & 0xff)); } -static void atari_set_checksum( void ) +static void +atari_set_checksum(void) { int i; unsigned char sum = 0; - - for( i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i ) - sum += nvram_read_int( i ); - nvram_write_int( ~sum, ATARI_CKS_LOC ); - nvram_write_int( sum, ATARI_CKS_LOC+1 ); + + for (i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i) + sum += nvram_read_int(i); + nvram_write_int(~sum, ATARI_CKS_LOC); + nvram_write_int(sum, ATARI_CKS_LOC + 1); } #ifdef CONFIG_PROC_FS @@ -635,81 +651,74 @@ #define fieldsize(a) (sizeof(a)/sizeof(*a)) -static int atari_proc_infos( unsigned char *nvram, char *buffer, int *len, - off_t *begin, off_t offset, int size ) +static int +atari_proc_infos(unsigned char *nvram, char *buffer, int *len, + off_t *begin, off_t offset, int size) { int checksum = nvram_check_checksum(); int i; unsigned vmode; - - PRINT_PROC( "Checksum status : %svalid\n", checksum ? "" : "not " ); - PRINT_PROC( "Boot preference : " ); - for( i = fieldsize(boot_prefs)-1; i >= 0; --i ) { + PRINT_PROC("Checksum status : %svalid\n", checksum ? "" : "not "); + + PRINT_PROC("Boot preference : "); + for (i = fieldsize(boot_prefs) - 1; i >= 0; --i) { if (nvram[1] == boot_prefs[i].val) { - PRINT_PROC( "%s\n", boot_prefs[i].name ); + PRINT_PROC("%s\n", boot_prefs[i].name); break; } } if (i < 0) - PRINT_PROC( "0x%02x (undefined)\n", nvram[1] ); + PRINT_PROC("0x%02x (undefined)\n", nvram[1]); - PRINT_PROC( "SCSI arbitration : %s\n", (nvram[16] & 0x80) ? "on" : "off" ); - PRINT_PROC( "SCSI host ID : " ); + PRINT_PROC("SCSI arbitration : %s\n", + (nvram[16] & 0x80) ? "on" : "off"); + PRINT_PROC("SCSI host ID : "); if (nvram[16] & 0x80) - PRINT_PROC( "%d\n", nvram[16] & 7 ); + PRINT_PROC("%d\n", nvram[16] & 7); else - PRINT_PROC( "n/a\n" ); + PRINT_PROC("n/a\n"); /* the following entries are defined only for the Falcon */ if ((atari_mch_cookie >> 16) != ATARI_MCH_FALCON) return 1; - PRINT_PROC( "OS language : " ); + PRINT_PROC("OS language : "); if (nvram[6] < fieldsize(languages)) - PRINT_PROC( "%s\n", languages[nvram[6]] ); + PRINT_PROC("%s\n", languages[nvram[6]]); else - PRINT_PROC( "%u (undefined)\n", nvram[6] ); - PRINT_PROC( "Keyboard language: " ); + PRINT_PROC("%u (undefined)\n", nvram[6]); + PRINT_PROC("Keyboard language: "); if (nvram[7] < fieldsize(languages)) - PRINT_PROC( "%s\n", languages[nvram[7]] ); + PRINT_PROC("%s\n", languages[nvram[7]]); else - PRINT_PROC( "%u (undefined)\n", nvram[7] ); - PRINT_PROC( "Date format : " ); - PRINT_PROC( dateformat[nvram[8]&7], - nvram[9] ? nvram[9] : '/', nvram[9] ? nvram[9] : '/' ); - PRINT_PROC( ", %dh clock\n", nvram[8] & 16 ? 24 : 12 ); - PRINT_PROC( "Boot delay : " ); + PRINT_PROC("%u (undefined)\n", nvram[7]); + PRINT_PROC("Date format : "); + PRINT_PROC(dateformat[nvram[8] & 7], + nvram[9] ? nvram[9] : '/', nvram[9] ? nvram[9] : '/'); + PRINT_PROC(", %dh clock\n", nvram[8] & 16 ? 24 : 12); + PRINT_PROC("Boot delay : "); if (nvram[10] == 0) - PRINT_PROC( "default" ); + PRINT_PROC("default"); else - PRINT_PROC( "%ds%s\n", nvram[10], - nvram[10] < 8 ? ", no memory test" : "" ); + PRINT_PROC("%ds%s\n", nvram[10], + nvram[10] < 8 ? ", no memory test" : ""); vmode = (nvram[14] << 8) || nvram[15]; - PRINT_PROC( "Video mode : %s colors, %d columns, %s %s monitor\n", - colors[vmode & 7], - vmode & 8 ? 80 : 40, - vmode & 16 ? "VGA" : "TV", - vmode & 32 ? "PAL" : "NTSC" ); - PRINT_PROC( " %soverscan, compat. mode %s%s\n", - vmode & 64 ? "" : "no ", - vmode & 128 ? "on" : "off", - vmode & 256 ? - (vmode & 16 ? ", line doubling" : ", half screen") : "" ); - - return( 1 ); + PRINT_PROC("Video mode : %s colors, %d columns, %s %s monitor\n", + colors[vmode & 7], + vmode & 8 ? 80 : 40, + vmode & 16 ? "VGA" : "TV", vmode & 32 ? "PAL" : "NTSC"); + PRINT_PROC(" %soverscan, compat. mode %s%s\n", + vmode & 64 ? "" : "no ", + vmode & 128 ? "on" : "off", + vmode & 256 ? + (vmode & 16 ? ", line doubling" : ", half screen") : ""); + + return 1; } #endif #endif /* MACH == ATARI */ MODULE_LICENSE("GPL"); - -/* - * Local variables: - * c-indent-level: 4 - * tab-width: 4 - * End: - */ - diff -Nru a/drivers/char/ppdev.c b/drivers/char/ppdev.c --- a/drivers/char/ppdev.c Thu Aug 1 14:17:40 2002 +++ b/drivers/char/ppdev.c Thu Aug 1 14:17:40 2002 @@ -749,7 +749,7 @@ static int __init ppdev_init (void) { - if (devfs_register_chrdev (PP_MAJOR, CHRDEV, &pp_fops)) { + if (register_chrdev (PP_MAJOR, CHRDEV, &pp_fops)) { printk (KERN_WARNING CHRDEV ": unable to get major %d\n", PP_MAJOR); return -EIO; @@ -768,7 +768,7 @@ { /* Clean up all parport stuff */ devfs_unregister (devfs_handle); - devfs_unregister_chrdev (PP_MAJOR, CHRDEV); + unregister_chrdev (PP_MAJOR, CHRDEV); } module_init(ppdev_init); diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c --- a/drivers/char/raw.c Thu Aug 1 14:17:36 2002 +++ b/drivers/char/raw.c Thu Aug 1 14:17:36 2002 @@ -12,165 +12,106 @@ #include #include #include +#include #include #include -#include -#include -#define dprintk(x...) +#include -typedef struct raw_device_data_s { +struct raw_device_data { struct block_device *binding; - int inuse, sector_size, sector_bits; - struct semaphore mutex; -} raw_device_data_t; - -static raw_device_data_t raw_devices[256]; - -static ssize_t rw_raw_dev(int rw, struct file *, char *, size_t, loff_t *); - -ssize_t raw_read(struct file *, char *, size_t, loff_t *); -ssize_t raw_write(struct file *, const char *, size_t, loff_t *); -int raw_open(struct inode *, struct file *); -int raw_release(struct inode *, struct file *); -int raw_ctl_ioctl(struct inode *, struct file *, unsigned int, unsigned long); -int raw_ioctl(struct inode *, struct file *, unsigned int, unsigned long); - - -static struct file_operations raw_fops = { - read: raw_read, - write: raw_write, - open: raw_open, - release: raw_release, - ioctl: raw_ioctl, -}; - -static struct file_operations raw_ctl_fops = { - ioctl: raw_ctl_ioctl, - open: raw_open, + int inuse; }; -static int __init raw_init(void) -{ - int i; - register_chrdev(RAW_MAJOR, "raw", &raw_fops); +static struct raw_device_data raw_devices[256]; +static DECLARE_MUTEX(raw_mutex); +static struct file_operations raw_ctl_fops; - for (i = 0; i < 256; i++) - init_MUTEX(&raw_devices[i].mutex); - - return 0; -} - -__initcall(raw_init); - -/* +/* * Open/close code for raw IO. + * + * Set the device's soft blocksize to the minimum possible. This gives the + * finest possible alignment and has no adverse impact on performance. */ - -int raw_open(struct inode *inode, struct file *filp) +static int raw_open(struct inode *inode, struct file *filp) { - int minor; - struct block_device * bdev; + const int minor = minor(inode->i_rdev); + struct block_device *bdev; int err; - int sector_size; - int sector_bits; - minor = minor(inode->i_rdev); - - /* - * Is it the control device? - */ - - if (minor == 0) { + if (minor == 0) { /* It is the control device */ filp->f_op = &raw_ctl_fops; return 0; } - down(&raw_devices[minor].mutex); + down(&raw_mutex); + /* - * No, it is a normal raw device. All we need to do on open is - * to check that the device is bound, and force the underlying - * block device to a sector-size blocksize. + * All we need to do on open is check that the device is bound. */ - bdev = raw_devices[minor].binding; err = -ENODEV; - if (!bdev) - goto out; - - atomic_inc(&bdev->bd_count); - err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW); - if (err) - goto out; - - /* - * Don't change the blocksize if we already have users using - * this device - */ - - if (raw_devices[minor].inuse++) - goto out; - - sector_size = bdev_hardsect_size(bdev); - raw_devices[minor].sector_size = sector_size; - for (sector_bits = 0; !(sector_size & 1); ) - sector_size>>=1, sector_bits++; - raw_devices[minor].sector_bits = sector_bits; - - out: - up(&raw_devices[minor].mutex); - + if (bdev) { + atomic_inc(&bdev->bd_count); + err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW); + if (!err) { + err = set_blocksize(bdev, bdev_hardsect_size(bdev)); + raw_devices[minor].inuse++; + } + } + up(&raw_mutex); return err; } -int raw_release(struct inode *inode, struct file *filp) +static int raw_release(struct inode *inode, struct file *filp) { - int minor; + const int minor= minor(inode->i_rdev); struct block_device *bdev; - minor = minor(inode->i_rdev); - down(&raw_devices[minor].mutex); + down(&raw_mutex); bdev = raw_devices[minor].binding; raw_devices[minor].inuse--; - up(&raw_devices[minor].mutex); + up(&raw_mutex); blkdev_put(bdev, BDEV_RAW); return 0; } - - -/* Forward ioctls to the underlying block device. */ -int raw_ioctl(struct inode *inode, - struct file *flip, - unsigned int command, - unsigned long arg) +/* + * Forward ioctls to the underlying block device. + */ +static int +raw_ioctl(struct inode *inode, struct file *filp, + unsigned int command, unsigned long arg) { - int minor = minor(inode->i_rdev), err; - struct block_device *b; + const int minor = minor(inode->i_rdev); + int err; + struct block_device *bdev; + + err = -ENODEV; if (minor < 1 && minor > 255) - return -ENODEV; + goto out; - b = raw_devices[minor].binding; - err = -EINVAL; - if (b && b->bd_inode && b->bd_op && b->bd_op->ioctl) { - err = b->bd_op->ioctl(b->bd_inode, NULL, command, arg); - } + bdev = raw_devices[minor].binding; + err = -EINVAL; + if (bdev == NULL) + goto out; + if (bdev->bd_inode && bdev->bd_op && bdev->bd_op->ioctl) + err = bdev->bd_op->ioctl(bdev->bd_inode, NULL, command, arg); +out: return err; -} +} /* * Deal with ioctls against the raw-device control interface, to bind - * and unbind other raw devices. + * and unbind other raw devices. */ - -int raw_ctl_ioctl(struct inode *inode, - struct file *flip, - unsigned int command, - unsigned long arg) +static int +raw_ctl_ioctl(struct inode *inode, struct file *filp, + unsigned int command, unsigned long arg) { struct raw_config_request rq; - int err = 0; - int minor; + struct raw_device_data *rawdev; + int err; switch (command) { case RAW_SETBIND: @@ -178,58 +119,64 @@ /* First, find out which raw minor we want */ - if (copy_from_user(&rq, (void *) arg, sizeof(rq))) { - err = -EFAULT; - break; - } + err = -EFAULT; + if (copy_from_user(&rq, (void *) arg, sizeof(rq))) + goto out; - minor = rq.raw_minor; - if (minor <= 0 || minor > MINORMASK) { - err = -EINVAL; - break; - } + err = -EINVAL; + if (rq.raw_minor < 0 || rq.raw_minor > MINORMASK) + goto out; + rawdev = &raw_devices[rq.raw_minor]; if (command == RAW_SETBIND) { /* * This is like making block devices, so demand the * same capability */ - if (!capable(CAP_SYS_ADMIN)) { - err = -EPERM; - break; - } + err = -EPERM; + if (!capable(CAP_SYS_ADMIN)) + goto out; - /* + /* * For now, we don't need to check that the underlying * block device is present or not: we can do that when * the raw device is opened. Just check that the - * major/minor numbers make sense. + * major/minor numbers make sense. */ - if ((rq.block_major == 0 && - rq.block_minor != 0) || - rq.block_major > MAX_BLKDEV || - rq.block_minor > MINORMASK) { - err = -EINVAL; - break; - } + err = -EINVAL; + if ((rq.block_major == 0 && rq.block_minor != 0) || + rq.block_major > MAX_BLKDEV || + rq.block_minor > MINORMASK) + goto out; - down(&raw_devices[minor].mutex); - if (raw_devices[minor].inuse) { - up(&raw_devices[minor].mutex); - err = -EBUSY; - break; + down(&raw_mutex); + err = -EBUSY; + if (rawdev->inuse) { + up(&raw_mutex); + goto out; + } + if (rawdev->binding) { + bdput(rawdev->binding); + MOD_DEC_USE_COUNT; } - if (raw_devices[minor].binding) - bdput(raw_devices[minor].binding); - raw_devices[minor].binding = - bdget(kdev_t_to_nr(mk_kdev(rq.block_major, rq.block_minor))); - up(&raw_devices[minor].mutex); + if (rq.block_major == 0 && rq.block_minor == 0) { + /* unbind */ + rawdev->binding = NULL; + } else { + kdev_t kdev; + + kdev = mk_kdev(rq.block_major, rq.block_minor); + rawdev->binding = bdget(kdev_t_to_nr(kdev)); + MOD_INC_USE_COUNT; + } + up(&raw_mutex); } else { struct block_device *bdev; kdev_t dev; - bdev = raw_devices[minor].binding; + down(&raw_mutex); + bdev = rawdev->binding; if (bdev) { dev = to_kdev_t(bdev->bd_dev); rq.block_major = major(dev); @@ -237,59 +184,85 @@ } else { rq.block_major = rq.block_minor = 0; } - err = copy_to_user((void *) arg, &rq, sizeof(rq)); - if (err) - err = -EFAULT; + up(&raw_mutex); + err = -EFAULT; + if (copy_to_user((void *)arg, &rq, sizeof(rq))) + goto out; } + err = 0; break; default: err = -EINVAL; + break; } - +out: return err; } -ssize_t raw_read(struct file *filp, char * buf, size_t size, loff_t *offp) -{ - return rw_raw_dev(READ, filp, buf, size, offp); -} - -ssize_t raw_write(struct file *filp, const char *buf, size_t size, loff_t *offp) -{ - return rw_raw_dev(WRITE, filp, (char *) buf, size, offp); -} - -ssize_t +static ssize_t rw_raw_dev(int rw, struct file *filp, char *buf, size_t size, loff_t *offp) { - struct block_device *bdev; - struct inode *inode; - int minor; + const int minor = minor(filp->f_dentry->d_inode->i_rdev); + struct block_device *bdev = raw_devices[minor].binding; + struct inode *inode = bdev->bd_inode; ssize_t ret = 0; - minor = minor(filp->f_dentry->d_inode->i_rdev); - bdev = raw_devices[minor].binding; - inode = bdev->bd_inode; - if (size == 0) goto out; - if (size < 0) { - ret = -EINVAL; + ret = -EINVAL; + if (size < 0) goto out; - } - if (*offp >= inode->i_size) { - ret = -ENXIO; + ret = -ENXIO; + if (*offp >= inode->i_size) goto out; - } + if (size + *offp > inode->i_size) size = inode->i_size - *offp; - ret = generic_file_direct_IO(rw, inode, buf, *offp, size); if (ret > 0) *offp += ret; - if (inode->i_mapping->nrpages) - invalidate_inode_pages2(inode->i_mapping); out: return ret; } + +static ssize_t +raw_read(struct file *filp, char * buf, size_t size, loff_t *offp) +{ + return rw_raw_dev(READ, filp, buf, size, offp); +} + +static ssize_t +raw_write(struct file *filp, const char *buf, size_t size, loff_t *offp) +{ + return rw_raw_dev(WRITE, filp, (char *)buf, size, offp); +} + +static struct file_operations raw_fops = { + .read = raw_read, + .write = raw_write, + .open = raw_open, + .release= raw_release, + .ioctl = raw_ioctl, + .owner = THIS_MODULE, +}; + +static struct file_operations raw_ctl_fops = { + .ioctl = raw_ctl_ioctl, + .open = raw_open, + .owner = THIS_MODULE, +}; + +static int __init raw_init(void) +{ + register_chrdev(RAW_MAJOR, "raw", &raw_fops); + return 0; +} + +static void __exit raw_exit(void) +{ + unregister_chrdev(RAW_MAJOR, "raw"); +} + +module_init(raw_init); +module_exit(raw_exit); diff -Nru a/drivers/char/rocket.c b/drivers/char/rocket.c --- a/drivers/char/rocket.c Thu Aug 1 14:17:36 2002 +++ b/drivers/char/rocket.c Thu Aug 1 14:17:36 2002 @@ -1881,15 +1881,23 @@ { int num_aiops, num_chan; int aiop, chan; + int extent = 0; unsigned int aiopio[MAX_AIOPS_PER_BOARD]; CONTROLLER_t *ctlp; if (rcktpt_io_addr[i] == 0) return(0); - if (check_region(rcktpt_io_addr[i],64)) { + if (rcktpt_io_addr[i] + 0x40 == controller) { + *reserved_controller = 1; + extent = 68; + } else { + extent = 64; + } + if (!request_region(rcktpt_io_addr[i], extent, + "Comtrol Rocketport")) { printk("RocketPort board address 0x%lx in use...\n", - rcktpt_io_addr[i]); + rcktpt_io_addr[i]); rcktpt_io_addr[i] = 0; return(0); } @@ -1901,6 +1909,7 @@ aiopio, MAX_AIOPS_PER_BOARD, 0, FREQ_DIS, 0); if (num_aiops <= 0) { + release_region(rcktpt_io_addr[i], extent); rcktpt_io_addr[i] = 0; return(0); } @@ -1914,14 +1923,6 @@ printk("Rocketport controller #%d found at 0x%lx, " "%d AIOPs\n", i, rcktpt_io_addr[i], num_aiops); - if (rcktpt_io_addr[i] + 0x40 == controller) { - *reserved_controller = 1; - request_region(rcktpt_io_addr[i], 68, - "Comtrol Rocketport"); - } else { - request_region(rcktpt_io_addr[i], 64, - "Comtrol Rocketport"); - } return(1); } diff -Nru a/drivers/char/stallion.c b/drivers/char/stallion.c --- a/drivers/char/stallion.c Thu Aug 1 14:17:37 2002 +++ b/drivers/char/stallion.c Thu Aug 1 14:17:37 2002 @@ -810,7 +810,7 @@ return; } devfs_unregister (devfs_handle); - if ((i = devfs_unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) + if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) printk("STALLION: failed to un-register serial memory device, " "errno=%d\n", -i); @@ -3208,7 +3208,7 @@ * Set up a character driver for per board stuff. This is mainly used * to do stats ioctls on the ports. */ - if (devfs_register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem)) + if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem)) printk("STALLION: failed to register serial board device\n"); devfs_handle = devfs_mk_dir (NULL, "staliomem", NULL); devfs_register_series (devfs_handle, "%u", 4, DEVFS_FL_DEFAULT, diff -Nru a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c --- a/drivers/char/tpqic02.c Thu Aug 1 14:17:40 2002 +++ b/drivers/char/tpqic02.c Thu Aug 1 14:17:40 2002 @@ -2846,7 +2846,7 @@ #endif printk(TPQIC02_NAME ": DMA buffers: %u blocks\n", NR_BLK_BUF); /* If we got this far, install driver functions */ - if (devfs_register_chrdev + if (register_chrdev (QIC02_TAPE_MAJOR, TPQIC02_NAME, &qic02_tape_fops)) { printk(TPQIC02_NAME ": Unable to get chrdev major %d\n", QIC02_TAPE_MAJOR); @@ -2930,31 +2930,23 @@ if (status_zombie == NO) { qic02_release_resources(); } - devfs_unregister_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME); - devfs_unregister(devfs_find_handle - (NULL, "ntpqic11", QIC02_TAPE_MAJOR, 2, - DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle - (NULL, "tpqic11", QIC02_TAPE_MAJOR, 3, - DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle - (NULL, "ntpqic24", QIC02_TAPE_MAJOR, 4, - DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle - (NULL, "tpqic24", QIC02_TAPE_MAJOR, 5, - DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle - (NULL, "ntpqic120", QIC02_TAPE_MAJOR, 6, - DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle - (NULL, "tpqic120", QIC02_TAPE_MAJOR, 7, - DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle - (NULL, "ntpqic150", QIC02_TAPE_MAJOR, 8, - DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle - (NULL, "tpqic150", QIC02_TAPE_MAJOR, 9, - DEVFS_SPECIAL_CHR, 0)); + unregister_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME); + devfs_find_and_unregister(NULL, "ntpqic11", QIC02_TAPE_MAJOR, 2, + DEVFS_SPECIAL_CHR, 0); + devfs_find_and_unregister(NULL, "tpqic11", QIC02_TAPE_MAJOR, 3, + DEVFS_SPECIAL_CHR, 0); + devfs_find_and_unregister(NULL, "ntpqic24", QIC02_TAPE_MAJOR, 4, + DEVFS_SPECIAL_CHR, 0); + devfs_find_and_unregister(NULL, "tpqic24", QIC02_TAPE_MAJOR, 5, + DEVFS_SPECIAL_CHR, 0); + devfs_find_and_unregister(NULL, "ntpqic120", QIC02_TAPE_MAJOR, 6, + DEVFS_SPECIAL_CHR, 0); + devfs_find_and_unregister(NULL, "tpqic120", QIC02_TAPE_MAJOR, 7, + DEVFS_SPECIAL_CHR, 0); + devfs_find_and_unregister(NULL, "ntpqic150", QIC02_TAPE_MAJOR, 8, + DEVFS_SPECIAL_CHR, 0); + devfs_find_and_unregister(NULL, "tpqic150", QIC02_TAPE_MAJOR, 9, + DEVFS_SPECIAL_CHR, 0); } int init_module(void) diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c --- a/drivers/char/tty_io.c Thu Aug 1 14:17:40 2002 +++ b/drivers/char/tty_io.c Thu Aug 1 14:17:40 2002 @@ -2047,14 +2047,12 @@ void tty_unregister_devfs (struct tty_driver *driver, unsigned minor) { #ifdef CONFIG_DEVFS_FS - void * handle; int idx = minor - driver->minor_start; char buf[32]; sprintf(buf, driver->name, idx + driver->name_base); - handle = devfs_find_handle (NULL, buf, driver->major, minor, - DEVFS_SPECIAL_CHR, 0); - devfs_unregister (handle); + devfs_find_and_unregister(NULL, buf, driver->major, minor, + DEVFS_SPECIAL_CHR, 0); #endif /* CONFIG_DEVFS_FS */ } @@ -2072,7 +2070,7 @@ if (driver->flags & TTY_DRIVER_INSTALLED) return 0; - error = devfs_register_chrdev(driver->major, driver->name, &tty_fops); + error = register_chrdev(driver->major, driver->name, &tty_fops); if (error < 0) return error; else if(driver->major == 0) @@ -2119,11 +2117,11 @@ return -ENOENT; if (othername == NULL) { - retval = devfs_unregister_chrdev(driver->major, driver->name); + retval = unregister_chrdev(driver->major, driver->name); if (retval) return retval; } else - devfs_register_chrdev(driver->major, othername, &tty_fops); + register_chrdev(driver->major, othername, &tty_fops); if (driver->prev) driver->prev->next = driver->next; diff -Nru a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c --- a/drivers/char/vc_screen.c Thu Aug 1 14:17:39 2002 +++ b/drivers/char/vc_screen.c Thu Aug 1 14:17:39 2002 @@ -480,10 +480,10 @@ sprintf (name, "a%u", index + 1); if (unregister) { - devfs_unregister ( devfs_find_handle (devfs_handle, name + 1, 0, 0, - DEVFS_SPECIAL_CHR, 0) ); - devfs_unregister ( devfs_find_handle (devfs_handle, name, 0, 0, - DEVFS_SPECIAL_CHR, 0) ); + devfs_find_and_unregister(devfs_handle, name + 1, 0, 0, + DEVFS_SPECIAL_CHR, 0); + devfs_find_and_unregister(devfs_handle, name, 0, 0, + DEVFS_SPECIAL_CHR, 0); } else { @@ -501,7 +501,7 @@ { int error; - error = devfs_register_chrdev(VCS_MAJOR, "vcs", &vcs_fops); + error = register_chrdev(VCS_MAJOR, "vcs", &vcs_fops); if (error) printk("unable to get major %d for vcs device", VCS_MAJOR); diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c --- a/drivers/i2c/i2c-dev.c Thu Aug 1 14:17:41 2002 +++ b/drivers/i2c/i2c-dev.c Thu Aug 1 14:17:41 2002 @@ -489,11 +489,7 @@ printk(KERN_INFO "i2c-dev.o: i2c /dev entries driver module version %s (%s)\n", I2C_VERSION, I2C_DATE); i2cdev_initialized = 0; -#ifdef CONFIG_DEVFS_FS - if (devfs_register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops)) { -#else if (register_chrdev(I2C_MAJOR,"i2c",&i2cdev_fops)) { -#endif printk(KERN_ERR "i2c-dev.o: unable to get major %d for i2c bus\n", I2C_MAJOR); return -EIO; @@ -528,10 +524,8 @@ if (i2cdev_initialized >= 1) { #ifdef CONFIG_DEVFS_FS devfs_unregister(devfs_handle); - if ((res = devfs_unregister_chrdev(I2C_MAJOR, "i2c"))) { -#else - if ((res = unregister_chrdev(I2C_MAJOR,"i2c"))) { #endif + if ((res = unregister_chrdev(I2C_MAJOR,"i2c"))) { printk(KERN_ERR "i2c-dev.o: unable to release major %d for i2c bus\n", I2C_MAJOR); return res; diff -Nru a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c --- a/drivers/ide/ali14xx.c Thu Aug 1 14:17:40 2002 +++ b/drivers/ide/ali14xx.c Thu Aug 1 14:17:40 2002 @@ -107,13 +107,14 @@ * Set PIO mode for the specified drive. * This function computes timing parameters * and sets controller registers accordingly. + * It assumes IRQ's are disabled or at least that no other process will + * attempt to access the IDE registers concurrently. */ static void ali14xx_tune_drive(struct ata_device *drive, u8 pio) { int drive_num; int time1, time2; u8 param1, param2, param3, param4; - unsigned long flags; struct ata_timing *t; if (pio == 255) @@ -140,15 +141,12 @@ /* stuff timing parameters into controller registers */ drive_num = (drive->channel->index << 1) + drive->select.b.unit; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ outb_p(reg_on, base_port); out_reg(param1, reg_tab[drive_num].reg1); out_reg(param2, reg_tab[drive_num].reg2); out_reg(param3, reg_tab[drive_num].reg3); out_reg(param4, reg_tab[drive_num].reg4); outb_p(reg_off, base_port); - restore_flags(flags); /* all CPUs */ } /* diff -Nru a/drivers/ide/ataraid.c b/drivers/ide/ataraid.c --- a/drivers/ide/ataraid.c Thu Aug 1 14:17:40 2002 +++ b/drivers/ide/ataraid.c Thu Aug 1 14:17:40 2002 @@ -45,7 +45,6 @@ struct gendisk ataraid_gendisk; -static int ataraid_gendisk_sizes[256]; static int ataraid_readahead[256]; static struct block_device_operations ataraid_fops = { @@ -257,7 +256,6 @@ ataraid_gendisk.major = ATAMAJOR; ataraid_gendisk.major_name = "ataraid"; ataraid_gendisk.minor_shift = 4; - ataraid_gendisk.sizes = &ataraid_gendisk_sizes[0]; ataraid_gendisk.nr_real = 16; ataraid_gendisk.fops = &ataraid_fops; @@ -282,7 +280,6 @@ static void __exit ataraid_exit(void) { unregister_blkdev(ATAMAJOR, "ataraid"); - blk_size[ATAMAJOR] = NULL; del_gendisk(&ataraid_gendisk); diff -Nru a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c --- a/drivers/ide/cmd640.c Thu Aug 1 14:17:40 2002 +++ b/drivers/ide/cmd640.c Thu Aug 1 14:17:40 2002 @@ -109,6 +109,7 @@ #include #include #include +#include #include @@ -164,6 +165,12 @@ #define BRST 0x59 /* + * Protects register file access from overlapping on primary and secondary + * channel, since those share hardware resources. + */ +static spinlock_t cmd640_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; + +/* * Registers and masks for easy access by drive index: */ static u8 prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; @@ -171,12 +178,6 @@ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED -/* - * Protects register file access from overlapping on primary and secondary - * channel, since those share hardware resources. - */ -static spinlock_t cmd640_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; - static u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23}; static u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM23, DRWTIM23}; @@ -214,19 +215,16 @@ * Therefore, we must use direct IO instead. */ -/* This is broken, but no more so than the old code.. */ -static spinlock_t cmd640_lock = SPIN_LOCK_UNLOCKED; - /* PCI method 1 access */ static void put_cmd640_reg_pci1 (unsigned short reg, u8 val) { unsigned long flags; - - spin_lock_irqsave(&cmd640_lock, flags); - outl_p((reg & 0xfc) | cmd640_key, 0xcf8); + + spin_lock_irqsave(&pci_lock, flags); + outb_p((reg & 0xfc) | cmd640_key, 0xcf8); outb_p(val, (reg & 3) | 0xcfc); - spin_unlock_irqrestore(&cmd640_lock, flags); + spin_unlock_irqrestore(&pci_lock, flags); } static u8 get_cmd640_reg_pci1 (unsigned short reg) @@ -234,10 +232,10 @@ u8 b; unsigned long flags; - spin_lock_irqsave(&cmd640_lock, flags); - outl_p((reg & 0xfc) | cmd640_key, 0xcf8); - b = inb_p((reg & 3) | 0xcfc); - spin_unlock_irqrestore(&cmd640_lock, flags); + spin_lock_irqsave(&pci_lock, flags); + outb_p((reg & 0xfc) | cmd640_key, 0xcf8); + b=inb_p((reg & 3) | 0xcfc); + spin_unlock_irqrestore(&pci_lock, flags); return b; } @@ -247,11 +245,11 @@ { unsigned long flags; - spin_lock_irqsave(&cmd640_lock, flags); + spin_lock_irqsave(&pci_lock, flags); outb_p(0x10, 0xcf8); outb_p(val, cmd640_key + reg); outb_p(0, 0xcf8); - spin_unlock_irqrestore(&cmd640_lock, flags); + spin_unlock_irqrestore(&pci_lock, flags); } static u8 get_cmd640_reg_pci2 (unsigned short reg) @@ -259,11 +257,11 @@ u8 b; unsigned long flags; - spin_lock_irqsave(&cmd640_lock, flags); + spin_lock_irqsave(&pci_lock, flags); outb_p(0x10, 0xcf8); b = inb_p(cmd640_key + reg); outb_p(0, 0xcf8); - spin_unlock_irqrestore(&cmd640_lock, flags); + spin_unlock_irqrestore(&pci_lock, flags); return b; } @@ -574,7 +572,7 @@ /* * Now that everything is ready, program the new timings */ - spin_lock(&cmd640_lock, flags); + spin_lock_irqsave(&cmd640_lock, flags); /* * Program the address_setup clocks into ARTTIM reg, * and then the active/recovery counts into the DRWTIM reg @@ -695,9 +693,61 @@ #endif +/** + * pci_conf1 - check for PCI type 1 configuration + * + * Issues a safe probe sequence for PCI configuration type 1 and + * returns non-zero if conf1 is supported. Takes the pci_config lock + */ + +static int pci_conf1(void) +{ + u32 tmp; + unsigned long flags; + + spin_lock_irqsave(&pci_lock, flags); + + OUT_BYTE(0x01, 0xCFB); + tmp = inl(0xCF8); + outl(0x80000000, 0xCF8); + if (inl(0xCF8) == 0x80000000) { + spin_unlock_irqrestore(&pci_lock, flags); + outl(tmp, 0xCF8); + return 1; + } + outl(tmp, 0xCF8); + spin_unlock_irqrestore(&pci_lock, flags); + return 0; +} + +/** + * pci_conf2 - check for PCI type 2 configuration + * + * Issues a safe probe sequence for PCI configuration type 2 and + * returns non-zero if conf2 is supported. Takes the pci_config lock. + */ + + +static int pci_conf2(void) +{ + unsigned long flags; + spin_lock_irqsave(&pci_lock, flags); + + OUT_BYTE(0x00, 0xCFB); + OUT_BYTE(0x00, 0xCF8); + OUT_BYTE(0x00, 0xCFA); + if (IN_BYTE(0xCF8) == 0x00 && IN_BYTE(0xCFA) == 0x00) { + spin_unlock_irqrestore(&pci_lock, flags); + return 1; + } + spin_unlock_irqrestore(&pci_lock, flags); + return 0; +} + /* * Probe for a cmd640 chipset, and initialize it if found. Called from ide.c */ + int __init ide_probe_for_cmd640x(void) { #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED @@ -712,9 +762,9 @@ bus_type = "VLB"; } else { cmd640_vlb = 0; - if (probe_for_cmd640_pci1()) + if (pci_conf1() && probe_for_cmd640_pci1()) bus_type = "PCI (type1)"; - else if (probe_for_cmd640_pci2()) + else if (pci_conf2() && probe_for_cmd640_pci2()) bus_type = "PCI (type2)"; else return 0; diff -Nru a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c --- a/drivers/ide/cs5530.c Thu Aug 1 14:17:41 2002 +++ b/drivers/ide/cs5530.c Thu Aug 1 14:17:41 2002 @@ -58,19 +58,18 @@ * After chip reset, the PIO timings are set to 0x0000e132, which is not valid. */ #define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132) -#define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->unit ? 0x30 : 0x20)) +#define CS5530_BASEREG(ch) (((ch)->dma_base & ~0xf) + ((ch)->unit ? 0x30 : 0x20)) /* - * cs5530_tuneproc() handles selection/setting of PIO modes - * for both the chipset and drive. + * Handle selection/setting of PIO modes for both the chipset and drive. * - * The ide_init_cs5530() routine guarantees that all drives - * will have valid default PIO timings set up before we get here. + * The ide_init_cs5530() routine guarantees that all drives will have valid + * default PIO timings set up before we get here. */ static void cs5530_tuneproc(struct ata_device *drive, u8 pio) { - struct ata_channel *hwif = drive->channel; - unsigned int format, basereg = CS5530_BASEREG(hwif); + unsigned int format; + unsigned int basereg = CS5530_BASEREG(drive->channel); if (pio == 255) pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); @@ -84,25 +83,26 @@ } #ifdef CONFIG_BLK_DEV_IDEDMA + /* - * cs5530_config_dma() handles selection/setting of DMA/UDMA modes - * for both the chipset and drive. + * Handle selection/setting of DMA/UDMA modes for both the chipset and drive. */ static int cs5530_config_dma(struct ata_device *drive) { - int udma_ok = 1, mode = 0; - struct ata_channel *hwif = drive->channel; - int unit = drive->select.b.unit; - struct ata_device *mate = &hwif->drives[unit^1]; - struct hd_driveid *id = drive->id; - unsigned int basereg, reg, timings; + int udma_ok = 1; + int mode = 0; + struct ata_channel *ch = drive->channel; + int unit = drive->select.b.unit; + struct ata_device *mate = &ch->drives[unit^1]; + struct hd_driveid *id = drive->id; + unsigned int basereg, reg, timings; /* * Default to DMA-off in case we run into trouble here. */ udma_enable(drive, 0, 0); - outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */ + outb(inb(ch->dma_base+2)&~(unit?0x40:0x20), ch->dma_base+2); /* clear DMA_capable bit */ /* * The CS5530 specifies that two drives sharing a cable cannot @@ -129,7 +129,7 @@ * Now see what the current drive is capable of, * selecting UDMA only if the mate said it was ok. */ - if (id && (id->capability & 1) && hwif->autodma && !udma_black_list(drive)) { + if (id && (id->capability & 1) && ch->autodma && !udma_black_list(drive)) { if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) { if (id->dma_ultra & 4) mode = XFER_UDMA_2; @@ -168,7 +168,7 @@ printk("%s: cs5530_config_dma: huh? mode=%02x\n", drive->name, mode); return 1; /* failure */ } - basereg = CS5530_BASEREG(hwif); + basereg = CS5530_BASEREG(ch); reg = inl(basereg+4); /* get drive0 config register */ timings |= reg & 0x80000000; /* preserve PIO format bit */ if (unit == 0) { /* are we configuring drive0? */ @@ -181,7 +181,7 @@ outl(reg, basereg+4); /* write drive0 config register */ outl(timings, basereg+12); /* write drive1 config register */ } - outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2); /* set DMA_capable bit */ + outb(inb(ch->dma_base+2)|(unit?0x40:0x20), ch->dma_base+2); /* set DMA_capable bit */ /* * Finally, turn DMA on in software, and exit. @@ -202,7 +202,8 @@ */ static unsigned int __init pci_init_cs5530(struct pci_dev *dev) { - struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; + struct pci_dev *master_0 = NULL; + struct pci_dev *cs5530_0 = NULL; unsigned short pcicmd = 0; unsigned long flags; @@ -218,6 +219,7 @@ } } } + if (!master_0) { printk("%s: unable to locate PCI MASTER function\n", dev->name); return 0; @@ -227,15 +229,13 @@ return 0; } - save_flags(flags); - cli(); /* all CPUs (there should only be one CPU with this chipset) */ - /* * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530: * --> OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530 */ - pci_read_config_word (cs5530_0, PCI_COMMAND, &pcicmd); - pci_write_config_word(cs5530_0, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE); + + pci_set_master(cs5530_0); + pci_set_mwi(cs5530_0); /* * Set PCI CacheLineSize to 16-bytes: @@ -274,41 +274,44 @@ pci_write_config_byte(master_0, 0x42, 0x00); pci_write_config_byte(master_0, 0x43, 0xc1); - restore_flags(flags); - return 0; } /* - * This gets invoked by the IDE driver once for each channel, - * and performs channel-specific pre-initialization before drive probing. + * This gets invoked once for each channel, and performs channel-specific + * pre-initialization before drive probing. */ -static void __init ide_init_cs5530(struct ata_channel *hwif) +static void __init ide_init_cs5530(struct ata_channel *ch) { - u32 basereg, d0_timings; + u32 basereg; + u32 d0_timings; - hwif->serialized = 1; + ch->serialized = 1; + + /* We think a 64kB transfer is a 0 byte transfer, so set our + segment size to be one sector smaller than 64kB. */ + ch->max_segment_size = (1<<16) - 512; #ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - hwif->highmem = 1; - hwif->udma_setup = cs5530_udma_setup; + if (ch->dma_base) { + ch->highmem = 1; + ch->udma_setup = cs5530_udma_setup; } #endif - hwif->tuneproc = &cs5530_tuneproc; - basereg = CS5530_BASEREG(hwif); - d0_timings = inl(basereg+0); - if (CS5530_BAD_PIO(d0_timings)) { /* PIO timings not initialized? */ - outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0); - if (!hwif->drives[0].autotune) - hwif->drives[0].autotune = 1; /* needs autotuning later */ - } - if (CS5530_BAD_PIO(inl(basereg+8))) { /* PIO timings not initialized? */ - outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8); - if (!hwif->drives[1].autotune) - hwif->drives[1].autotune = 1; /* needs autotuning later */ - } + ch->tuneproc = &cs5530_tuneproc; + basereg = CS5530_BASEREG(ch); + d0_timings = inl(basereg+0); + if (CS5530_BAD_PIO(d0_timings)) { /* PIO timings not initialized? */ + outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0); + if (!ch->drives[0].autotune) + ch->drives[0].autotune = 1; /* needs autotuning later */ + } + if (CS5530_BAD_PIO(inl(basereg+8))) { /* PIO timings not initialized? */ + outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8); + if (!ch->drives[1].autotune) + ch->drives[1].autotune = 1; /* needs autotuning later */ + } } diff -Nru a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c --- a/drivers/ide/dtc2278.c Thu Aug 1 14:17:40 2002 +++ b/drivers/ide/dtc2278.c Thu Aug 1 14:17:40 2002 @@ -66,21 +66,18 @@ } } +/* Assumes IRQ's are disabled or at least that no other process will + attempt to access the IDE registers concurrently. */ static void tune_dtc2278(struct ata_device *drive, u8 pio) { - unsigned long flags; - pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0; if (pio >= 3) { - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ /* * This enables PIO mode4 (3?) on the first interface */ sub22(1,0xc3); sub22(0,0xa0); - restore_flags(flags); /* all CPUs */ } else { /* we don't know how to set it back again.. */ } diff -Nru a/drivers/ide/hd.c b/drivers/ide/hd.c --- a/drivers/ide/hd.c Thu Aug 1 14:17:36 2002 +++ b/drivers/ide/hd.c Thu Aug 1 14:17:36 2002 @@ -1,15 +1,11 @@ /* - * linux/drivers/ide/hd.c - * * Copyright (C) 1991, 1992 Linus Torvalds - */ - -/* + * * This is the low-level hd interrupt support. It traverses the * request-list, using interrupts to jump between functions. As * all the functions are called within interrupts, we may not * sleep. Special care is recommended. - * + * * modified by Drew Eckhardt to check nr of hd's from the CMOS. * * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug @@ -26,18 +22,16 @@ * Bugfix: max_sectors must be <= 255 or the wheels tend to come * off in a hurry once you queue things up - Paul G. 02/2001 */ - + /* Uncomment the following if you want verbose error reports. */ /* #define VERBOSE_ERRORS */ - + #include #include #include #include #include -#include #include -#include #include #include #include @@ -45,6 +39,7 @@ #include /* CMOS defines */ #include #include +#include #define REALLY_SLOW_IO #include @@ -55,6 +50,15 @@ #define DEVICE_NR(device) (minor(device)>>6) #include +/* ATA commands we use. + */ +#define WIN_SPECIFY 0x91 /* set drive geometry translation */ +#define WIN_RESTORE 0x10 +#define WIN_READ 0x20 /* 28-Bit */ +#define WIN_WRITE 0x30 /* 28-Bit */ + +#define HD_IRQ 14 /* the standard disk interrupt */ + #ifdef __arm__ #undef HD_IRQ #endif @@ -63,6 +67,45 @@ #define HD_IRQ IRQ_HARDDISK #endif +/* Hd controller regster ports */ + +#define HD_DATA 0x1f0 /* _CTL when writing */ +#define HD_ERROR 0x1f1 /* see err-bits */ +#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */ +#define HD_SECTOR 0x1f3 /* starting sector */ +#define HD_LCYL 0x1f4 /* starting cylinder */ +#define HD_HCYL 0x1f5 /* high byte of starting cyl */ +#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */ +#define HD_STATUS 0x1f7 /* see status-bits */ +#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */ +#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */ +#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */ + +#define HD_CMD 0x3f6 /* used for resets */ +#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */ + +/* Bits of HD_STATUS */ +#define ERR_STAT 0x01 +#define INDEX_STAT 0x02 +#define ECC_STAT 0x04 /* Corrected error */ +#define DRQ_STAT 0x08 +#define SEEK_STAT 0x10 +#define SERVICE_STAT SEEK_STAT +#define WRERR_STAT 0x20 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 + +/* Bits for HD_ERROR */ +#define MARK_ERR 0x01 /* Bad address mark */ +#define TRK0_ERR 0x02 /* couldn't find track 0 */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* media change request */ +#define ID_ERR 0x10 /* ID field not found */ +#define MC_ERR 0x20 /* media changed */ +#define ECC_ERR 0x40 /* Uncorrectable ECC error */ +#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ +#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ + static spinlock_t hd_lock = SPIN_LOCK_UNLOCKED; static int revalidate_hddisk(kdev_t, int); @@ -105,7 +148,6 @@ #endif static struct hd_struct hd[MAX_HD<<6]; -static int hd_sizes[MAX_HD<<6]; static struct timer_list device_timer; @@ -162,12 +204,9 @@ static void dump_status (const char *msg, unsigned int stat) { - unsigned long flags; char devc; devc = !blk_queue_empty(QUEUE) ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?'; - save_flags (flags); - sti(); #ifdef VERBOSE_ERRORS printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff); if (stat & BUSY_STAT) printk("Busy "); @@ -207,8 +246,7 @@ hd_error = inb(HD_ERROR); printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff); } -#endif /* verbose errors */ - restore_flags (flags); +#endif } void check_status(void) @@ -467,7 +505,7 @@ if (i > 0) { SET_HANDLER(&write_intr); outsw(HD_DATA,CURRENT->buffer,256); - sti(); + local_irq_enable(); } else { #if (HD_DELAY > 0) last_req = read_timer(); @@ -500,7 +538,7 @@ return; disable_irq(HD_IRQ); - sti(); + local_irq_enable(); reset = 1; dev = DEVICE_NR(CURRENT->rq_dev); printk("hd%c: timeout\n", dev+'a'); @@ -510,7 +548,7 @@ #endif end_request(CURRENT, 0); } - cli(); + local_irq_disable(); hd_request(); enable_irq(HD_IRQ); } @@ -548,7 +586,7 @@ return; repeat: del_timer(&device_timer); - sti(); + local_irq_enable(); if (blk_queue_empty(QUEUE)) { do_hd = NULL; @@ -556,7 +594,7 @@ } if (reset) { - cli(); + local_irq_disable(); reset_hd(); return; } @@ -670,13 +708,22 @@ extern struct block_device_operations hd_fops; -static struct gendisk hd_gendisk = { +static struct gendisk hd_gendisk[2] = { +{ .major = MAJOR_NR, + .first_minor = 0, .major_name = "hd", .minor_shift = 6, .part = hd, - .sizes = hd_sizes, .fops = &hd_fops, +},{ + .major = MAJOR_NR, + .first_minor = 64, + .major_name = "hd", + .minor_shift = 6, + .part = hd + 64, + .fops = &hd_fops, +} }; static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -688,7 +735,7 @@ if (!handler) handler = unexpected_hd_interrupt; handler(); - sti(); + local_irq_enable(); } static struct block_device_operations hd_fops = { @@ -808,23 +855,24 @@ return; } - hd_gendisk.nr_real = NR_HD; - - for(drive=0; drive < NR_HD; drive++) - register_disk(&hd_gendisk, mk_kdev(MAJOR_NR,drive<<6), 1<<6, + for(drive=0; drive < NR_HD; drive++) { + hd_gendisk[i].nr_real = 1; + add_gendisk(hd_gendisk + drive); + register_disk(hd_gendisk + drive, + mk_kdev(MAJOR_NR,drive<<6), 1<<6, &hd_fops, hd_info[drive].head * hd_info[drive].sect * hd_info[drive].cyl); + } } int __init hd_init(void) { - if (devfs_register_blkdev(MAJOR_NR,"hd",&hd_fops)) { + if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) { printk("hd: unable to get major %d for hard disk\n",MAJOR_NR); return -1; } blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock); blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255); - add_gendisk(&hd_gendisk); init_timer(&device_timer); device_timer.function = hd_times_out; hd_geninit(); diff -Nru a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c --- a/drivers/ide/ht6560b.c Thu Aug 1 14:17:37 2002 +++ b/drivers/ide/ht6560b.c Thu Aug 1 14:17:37 2002 @@ -249,12 +249,8 @@ */ static void ht_set_prefetch(struct ata_device *drive, u8 state) { - unsigned long flags; int t = HT_PREFETCH_MODE << 8; - save_flags (flags); /* all CPUs */ - cli(); /* all CPUs */ - /* * Prefetch mode and unmask irq seems to conflict */ @@ -267,16 +263,16 @@ drive->channel->no_unmask = 0; } - restore_flags (flags); /* all CPUs */ - #ifdef DEBUG printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis")); #endif } +/* Assumes IRQ's are disabled or at least that no other process will attempt to + * access the IDE registers concurrently. + */ static void tune_ht6560b(struct ata_device *drive, u8 pio) { - unsigned long flags; u8 timing; switch (pio) { @@ -288,13 +284,8 @@ timing = ht_pio2timings(drive, pio); - save_flags (flags); /* all CPUs */ - cli(); /* all CPUs */ - drive->drive_data &= 0xff00; drive->drive_data |= timing; - - restore_flags (flags); /* all CPUs */ #ifdef DEBUG printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing); diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c --- a/drivers/ide/ide-cd.c Thu Aug 1 14:17:40 2002 +++ b/drivers/ide/ide-cd.c Thu Aug 1 14:17:40 2002 @@ -305,8 +305,9 @@ #include #include #include -#include #include +#include +#include #include #include @@ -1616,16 +1617,11 @@ if (rq->flags & REQ_CMD) { if (CDROM_CONFIG_FLAGS(drive)->seeking) { - unsigned long elpased = jiffies - info->start_seek; - - if (!ata_status(drive, SEEK_STAT, 0)) { - if (elpased < IDECD_SEEK_TIMEOUT) { - ide_stall_queue(drive, IDECD_SEEK_TIMER); - return ATA_OP_FINISHED; - } + if (ATA_OP_READY != ata_status_poll(drive, SEEK_STAT, 0, IDECD_SEEK_TIMEOUT, rq)) { printk ("%s: DSC timeout\n", drive->name); - } - CDROM_CONFIG_FLAGS(drive)->seeking = 0; + CDROM_CONFIG_FLAGS(drive)->seeking = 0; + } else + return ATA_OP_FINISHED; } if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) { ret = cdrom_start_seek(drive, rq, block); @@ -2016,7 +2012,6 @@ if (stat) toc->capacity = 0x1fffff; - drive->channel->gd->sizes[drive->select.b.unit << PARTN_BITS] = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9); drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME; /* Remember that we've read this stuff. */ @@ -2882,7 +2877,6 @@ { struct cdrom_info *info = drive->driver_data; struct atapi_toc *toc; - int minor = drive->select.b.unit << PARTN_BITS; struct request_sense sense; cdrom_read_toc(drive, &sense); @@ -2894,8 +2888,6 @@ /* for general /dev/cdrom like mounting, one big disc */ drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME; - drive->channel->gd->sizes[minor] = toc->capacity * BLOCKS_PER_FRAME; - blk_size[drive->channel->major] = drive->channel->gd->sizes; } static sector_t ide_cdrom_capacity(struct ata_device *drive) @@ -2914,7 +2906,7 @@ struct cdrom_info *info = drive->driver_data; struct cdrom_device_info *devinfo = &info->devinfo; - if (ide_unregister_subdriver (drive)) + if (ata_unregister_device(drive)) return 1; if (info->buffer != NULL) kfree(info->buffer); @@ -2973,7 +2965,7 @@ printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name); return; } - if (ide_register_subdriver (drive, &ide_cdrom_driver)) { + if (ata_register_device(drive, &ide_cdrom_driver)) { printk(KERN_ERR "%s: Failed to register the driver with ide.c\n", drive->name); kfree (info); return; diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c Thu Aug 1 14:17:36 2002 +++ b/drivers/ide/ide-disk.c Thu Aug 1 14:17:36 2002 @@ -723,7 +723,7 @@ static sector_t idedisk_capacity(struct ata_device *drive) { - return drive->capacity - drive->sect0; + return drive->capacity; } /* @@ -1064,9 +1064,9 @@ if (drive != &ch->drives[i]) continue; drvid = i; - ch->gd->de_arr[i] = drive->de; + ch->gd[i]->de_arr[0] = drive->de; if (drive->removable) - ch->gd->flags[i] |= GENHD_FL_REMOVABLE; + ch->gd[i]->flags[0] |= GENHD_FL_REMOVABLE; break; } @@ -1279,7 +1279,7 @@ printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", drive->name); } - ret = ide_unregister_subdriver(drive); + ret = ata_unregister_device(drive); /* FIXME: This is killing the kernel with BUG 185 at asm/spinlocks.h * horribly. Check whatever we did REGISTER the device properly @@ -1471,8 +1471,8 @@ if (req[0] != '\0' && strcmp(req, "ide-disk")) return; - if (ide_register_subdriver(drive, &idedisk_driver)) { - printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); + if (ata_register_device(drive, &idedisk_driver)) { + printk(KERN_ERR "%s: Failed to register the driver with ide.c\n", drive->name); return; } diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c --- a/drivers/ide/ide-floppy.c Thu Aug 1 14:17:39 2002 +++ b/drivers/ide/ide-floppy.c Thu Aug 1 14:17:39 2002 @@ -94,9 +94,10 @@ #include #include #include +#include +#include #include #include -#include #include #include @@ -1711,9 +1712,9 @@ struct ata_channel *hwif = drive->channel; if (drive != &hwif->drives[i]) continue; - hwif->gd->de_arr[i] = drive->de; + hwif->gd[i]->de_arr[0] = drive->de; if (drive->removable) - hwif->gd->flags[i] |= GENHD_FL_REMOVABLE; + hwif->gd[i]->flags[0] |= GENHD_FL_REMOVABLE; break; } } @@ -1722,10 +1723,10 @@ { idefloppy_floppy_t *floppy = drive->driver_data; - if (ide_unregister_subdriver (drive)) + if (ata_unregister_device(drive)) return 1; drive->driver_data = NULL; - kfree (floppy); + kfree(floppy); return 0; } @@ -1779,7 +1780,7 @@ drive->name); return; } - if (ide_register_subdriver(drive, &idefloppy_driver)) { + if (ata_register_device(drive, &idefloppy_driver)) { printk(KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name); kfree (floppy); return; diff -Nru a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c --- a/drivers/ide/ide-pci.c Thu Aug 1 14:17:41 2002 +++ b/drivers/ide/ide-pci.c Thu Aug 1 14:17:41 2002 @@ -550,7 +550,8 @@ if (!dev2) { return; } else { - byte irq = 0, irq2 = 0; + u8 irq = 0; + u8 irq2 = 0; pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2); if (irq != irq2) { diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c --- a/drivers/ide/ide-tape.c Thu Aug 1 14:17:36 2002 +++ b/drivers/ide/ide-tape.c Thu Aug 1 14:17:36 2002 @@ -7,400 +7,17 @@ * * It is hereby placed under the terms of the GNU general public license. * (See linux/COPYING). - */ - -/* - * BIG FAT FIXME: clean tape->spinlock locking --bzolnier - */ - -/* - * IDE ATAPI streaming tape driver. * - * This driver is a part of the Linux ide driver and works in co-operation - * with linux/drivers/block/ide.c. + * Contributors: * - * The driver, in co-operation with ide.c, basically traverses the - * request-list for the block device interface. The character device - * interface, on the other hand, creates new requests, adds them - * to the request-list of the block device, and waits for their completion. - * - * Pipelined operation mode is now supported on both reads and writes. - * - * The block device major and minor numbers are determined from the - * tape's relative position in the ide interfaces, as explained in ide.c. - * - * The character device interface consists of the following devices: - * - * ht0 major 37, minor 0 first IDE tape, rewind on close. - * ht1 major 37, minor 1 second IDE tape, rewind on close. - * ... - * nht0 major 37, minor 128 first IDE tape, no rewind on close. - * nht1 major 37, minor 129 second IDE tape, no rewind on close. - * ... - * - * Run linux/scripts/MAKEDEV.ide to create the above entries. - * - * The general magnetic tape commands compatible interface, as defined by - * include/linux/mtio.h, is accessible through the character device. - * - * General ide driver configuration options, such as the interrupt-unmask - * flag, can be configured by issuing an ioctl to the block device interface, - * as any other ide device. - * - * Our own ide-tape ioctl's can be issued to either the block device or - * the character device interface. - * - * Maximal throughput with minimal bus load will usually be achieved in the - * following scenario: - * - * 1. ide-tape is operating in the pipelined operation mode. - * 2. No buffering is performed by the user backup program. - * - * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive. - * - * Ver 0.1 Nov 1 95 Pre-working code :-) - * Ver 0.2 Nov 23 95 A short backup (few megabytes) and restore procedure - * was successful ! (Using tar cvf ... on the block - * device interface). - * A longer backup resulted in major swapping, bad - * overall Linux performance and eventually failed as - * we received non serial read-ahead requests from the - * buffer cache. - * Ver 0.3 Nov 28 95 Long backups are now possible, thanks to the - * character device interface. Linux's responsiveness - * and performance doesn't seem to be much affected - * from the background backup procedure. - * Some general mtio.h magnetic tape operations are - * now supported by our character device. As a result, - * popular tape utilities are starting to work with - * ide tapes :-) - * The following configurations were tested: - * 1. An IDE ATAPI TAPE shares the same interface - * and irq with an IDE ATAPI CDROM. - * 2. An IDE ATAPI TAPE shares the same interface - * and irq with a normal IDE disk. - * Both configurations seemed to work just fine ! - * However, to be on the safe side, it is meanwhile - * recommended to give the IDE TAPE its own interface - * and irq. - * The one thing which needs to be done here is to - * add a "request postpone" feature to ide.c, - * so that we won't have to wait for the tape to finish - * performing a long media access (DSC) request (such - * as a rewind) before we can access the other device - * on the same interface. This effect doesn't disturb - * normal operation most of the time because read/write - * requests are relatively fast, and once we are - * performing one tape r/w request, a lot of requests - * from the other device can be queued and ide.c will - * service all of them after this single tape request. - * Ver 1.0 Dec 11 95 Integrated into Linux 1.3.46 development tree. - * On each read / write request, we now ask the drive - * if we can transfer a constant number of bytes - * (a parameter of the drive) only to its buffers, - * without causing actual media access. If we can't, - * we just wait until we can by polling the DSC bit. - * This ensures that while we are not transferring - * more bytes than the constant referred to above, the - * interrupt latency will not become too high and - * we won't cause an interrupt timeout, as happened - * occasionally in the previous version. - * While polling for DSC, the current request is - * postponed and ide.c is free to handle requests from - * the other device. This is handled transparently to - * ide.c. The hwgroup locking method which was used - * in the previous version was removed. - * Use of new general features which are provided by - * ide.c for use with atapi devices. - * (Programming done by Mark Lord) - * Few potential bug fixes (Again, suggested by Mark) - * Single character device data transfers are now - * not limited in size, as they were before. - * We are asking the tape about its recommended - * transfer unit and send a larger data transfer - * as several transfers of the above size. - * For best results, use an integral number of this - * basic unit (which is shown during driver - * initialization). I will soon add an ioctl to get - * this important parameter. - * Our data transfer buffer is allocated on startup, - * rather than before each data transfer. This should - * ensure that we will indeed have a data buffer. - * Ver 1.1 Dec 14 95 Fixed random problems which occurred when the tape - * shared an interface with another device. - * (poll_for_dsc was a complete mess). - * Removed some old (non-active) code which had - * to do with supporting buffer cache originated - * requests. - * The block device interface can now be opened, so - * that general ide driver features like the unmask - * interrupts flag can be selected with an ioctl. - * This is the only use of the block device interface. - * New fast pipelined operation mode (currently only on - * writes). When using the pipelined mode, the - * throughput can potentially reach the maximum - * tape supported throughput, regardless of the - * user backup program. On my tape drive, it sometimes - * boosted performance by a factor of 2. Pipelined - * mode is enabled by default, but since it has a few - * downfalls as well, you may want to disable it. - * A short explanation of the pipelined operation mode - * is available below. - * Ver 1.2 Jan 1 96 Eliminated pipelined mode race condition. - * Added pipeline read mode. As a result, restores - * are now as fast as backups. - * Optimized shared interface behavior. The new behavior - * typically results in better IDE bus efficiency and - * higher tape throughput. - * Pre-calculation of the expected read/write request - * service time, based on the tape's parameters. In - * the pipelined operation mode, this allows us to - * adjust our polling frequency to a much lower value, - * and thus to dramatically reduce our load on Linux, - * without any decrease in performance. - * Implemented additional mtio.h operations. - * The recommended user block size is returned by - * the MTIOCGET ioctl. - * Additional minor changes. - * Ver 1.3 Feb 9 96 Fixed pipelined read mode bug which prevented the - * use of some block sizes during a restore procedure. - * The character device interface will now present a - * continuous view of the media - any mix of block sizes - * during a backup/restore procedure is supported. The - * driver will buffer the requests internally and - * convert them to the tape's recommended transfer - * unit, making performance almost independent of the - * chosen user block size. - * Some improvements in error recovery. - * By cooperating with ide-dma.c, bus mastering DMA can - * now sometimes be used with IDE tape drives as well. - * Bus mastering DMA has the potential to dramatically - * reduce the CPU's overhead when accessing the device, - * and can be enabled by using hdparm -d1 on the tape's - * block device interface. For more info, read the - * comments in ide-dma.c. - * Ver 1.4 Mar 13 96 Fixed serialize support. - * Ver 1.5 Apr 12 96 Fixed shared interface operation, broken in 1.3.85. - * Fixed pipelined read mode inefficiency. - * Fixed nasty null dereferencing bug. - * Ver 1.6 Aug 16 96 Fixed FPU usage in the driver. - * Fixed end of media bug. - * Ver 1.7 Sep 10 96 Minor changes for the CONNER CTT8000-A model. - * Ver 1.8 Sep 26 96 Attempt to find a better balance between good - * interactive response and high system throughput. - * Ver 1.9 Nov 5 96 Automatically cross encountered filemarks rather - * than requiring an explicit FSF command. - * Abort pending requests at end of media. - * MTTELL was sometimes returning incorrect results. - * Return the real block size in the MTIOCGET ioctl. - * Some error recovery bug fixes. - * Ver 1.10 Nov 5 96 Major reorganization. - * Reduced CPU overhead a bit by eliminating internal - * bounce buffers. - * Added module support. - * Added multiple tape drives support. - * Added partition support. - * Rewrote DSC handling. - * Some portability fixes. - * Removed ide-tape.h. - * Additional minor changes. - * Ver 1.11 Dec 2 96 Bug fix in previous DSC timeout handling. - * Use ide_stall_queue() for DSC overlap. - * Use the maximum speed rather than the current speed - * to compute the request service time. - * Ver 1.12 Dec 7 97 Fix random memory overwriting and/or last block data - * corruption, which could occur if the total number - * of bytes written to the tape was not an integral - * number of tape blocks. - * Add support for INTERRUPT DRQ devices. - * Ver 1.13 Jan 2 98 Add "speed == 0" work-around for HP COLORADO 5GB - * Ver 1.14 Dec 30 98 Partial fixes for the Sony/AIWA tape drives. - * Replace cli()/sti() with hwgroup spinlocks. - * Ver 1.15 Mar 25 99 Fix SMP race condition by replacing hwgroup - * spinlock with private per-tape spinlock. - * Ver 1.16 Sep 1 99 Add OnStream tape support. - * Abort read pipeline on EOD. - * Wait for the tape to become ready in case it returns - * "in the process of becoming ready" on open(). - * Fix zero padding of the last written block in - * case the tape block size is larger than PAGE_SIZE. - * Decrease the default disconnection time to tn. - * Ver 1.16e Oct 3 99 Minor fixes. - * Ver 1.16e1 Oct 13 99 Patches by Arnold Niessen, - * niessen@iae.nl / arnold.niessen@philips.com - * GO-1) Undefined code in idetape_read_position - * according to Gadi's email - * AJN-1) Minor fix asc == 11 should be asc == 0x11 - * in idetape_issue_packet_command (did effect - * debugging output only) - * AJN-2) Added more debugging output, and - * added ide-tape: where missing. I would also - * like to add tape->name where possible - * AJN-3) Added different debug_level's - * via /proc/ide/hdc/settings - * "debug_level" determines amount of debugging output; - * can be changed using /proc/ide/hdx/settings - * 0 : almost no debugging output - * 1 : 0+output errors only - * 2 : 1+output all sensekey/asc - * 3 : 2+follow all chrdev related procedures - * 4 : 3+follow all procedures - * 5 : 4+include pc_stack rq_stack info - * 6 : 5+USE_COUNT updates - * AJN-4) Fixed timeout for retension in idetape_queue_pc_tail - * from 5 to 10 minutes - * AJN-5) Changed maximum number of blocks to skip when - * reading tapes with multiple consecutive write - * errors from 100 to 1000 in idetape_get_logical_blk - * Proposed changes to code: - * 1) output "logical_blk_num" via /proc - * 2) output "current_operation" via /proc - * 3) Either solve or document the fact that `mt rewind' is - * required after reading from /dev/nhtx to be - * able to rmmod the idetape module; - * Also, sometimes an application finishes but the - * device remains `busy' for some time. Same cause ? - * Proposed changes to release-notes: - * 4) write a simple `quickstart' section in the - * release notes; I volunteer if you don't want to - * 5) include a pointer to video4linux in the doc - * to stimulate video applications - * 6) release notes lines 331 and 362: explain what happens - * if the application data rate is higher than 1100 KB/s; - * similar approach to lower-than-500 kB/s ? - * 7) 6.6 Comparison; wouldn't it be better to allow different - * strategies for read and write ? - * Wouldn't it be better to control the tape buffer - * contents instead of the bandwidth ? - * 8) line 536: replace will by would (if I understand - * this section correctly, a hypothetical and unwanted situation - * is being described) - * Ver 1.16f Dec 15 99 Change place of the secondary OnStream header frames. - * Ver 1.17 Nov 2000 / Jan 2001 Marcel Mol, marcel@mesa.nl - * - Add idetape_onstream_mode_sense_tape_parameter_page - * function to get tape capacity in frames: tape->capacity. - * - Add support for DI-50 drives( or any DI- drive). - * - 'workaround' for read error/blank block arround block 3000. - * - Implement Early warning for end of media for Onstream. - * - Cosmetic code changes for readability. - * - Idetape_position_tape should not use SKIP bit during - * Onstream read recovery. - * - Add capacity, logical_blk_num and first/last_frame_position - * to /proc/ide/hd?/settings. - * - Module use count was gone in the Linux 2.4 driver. - * Ver 1.17a Apr 2001 Willem Riede osst@riede.org - * - Get drive's actual block size from mode sense block descriptor - * - Limit size of pipeline - * - * Here are some words from the first releases of hd.c, which are quoted - * in ide.c and apply here as well: - * - * | Special care is recommended. Have Fun! - * - */ - -/* - * An overview of the pipelined operation mode. - * - * In the pipelined write mode, we will usually just add requests to our - * pipeline and return immediately, before we even start to service them. The - * user program will then have enough time to prepare the next request while - * we are still busy servicing previous requests. In the pipelined read mode, - * the situation is similar - we add read-ahead requests into the pipeline, - * before the user even requested them. - * - * The pipeline can be viewed as a "safety net" which will be activated when - * the system load is high and prevents the user backup program from keeping up - * with the current tape speed. At this point, the pipeline will get - * shorter and shorter but the tape will still be streaming at the same speed. - * Assuming we have enough pipeline stages, the system load will hopefully - * decrease before the pipeline is completely empty, and the backup program - * will be able to "catch up" and refill the pipeline again. - * - * When using the pipelined mode, it would be best to disable any type of - * buffering done by the user program, as ide-tape already provides all the - * benefits in the kernel, where it can be done in a more efficient way. - * As we will usually not block the user program on a request, the most - * efficient user code will then be a simple read-write-read-... cycle. - * Any additional logic will usually just slow down the backup process. - * - * Using the pipelined mode, I get a constant over 400 KBps throughput, - * which seems to be the maximum throughput supported by my tape. - * - * However, there are some downfalls: - * - * 1. We use memory (for data buffers) in proportional to the number - * of pipeline stages (each stage is about 26 KB with my tape). - * 2. In the pipelined write mode, we cheat and postpone error codes - * to the user task. In read mode, the actual tape position - * will be a bit further than the last requested block. - * - * Concerning (1): - * - * 1. We allocate stages dynamically only when we need them. When - * we don't need them, we don't consume additional memory. In - * case we can't allocate stages, we just manage without them - * (at the expense of decreased throughput) so when Linux is - * tight in memory, we will not pose additional difficulties. - * - * 2. The maximum number of stages (which is, in fact, the maximum - * amount of memory) which we allocate is limited by the compile - * time parameter IDETAPE_MAX_PIPELINE_STAGES. - * - * 3. The maximum number of stages is a controlled parameter - We - * don't start from the user defined maximum number of stages - * but from the lower IDETAPE_MIN_PIPELINE_STAGES (again, we - * will not even allocate this amount of stages if the user - * program can't handle the speed). We then implement a feedback - * loop which checks if the pipeline is empty, and if it is, we - * increase the maximum number of stages as necessary until we - * reach the optimum value which just manages to keep the tape - * busy with minimum allocated memory or until we reach - * IDETAPE_MAX_PIPELINE_STAGES. - * - * Concerning (2): - * - * In pipelined write mode, ide-tape can not return accurate error codes - * to the user program since we usually just add the request to the - * pipeline without waiting for it to be serviced. In case an error - * occurs, I will report it on the next user request. - * - * In the pipelined read mode, subsequent read requests or forward - * filemark spacing will perform correctly, as we preserve all blocks - * and filemarks which we encountered during our excess read-ahead. - * - * For accurate tape positioning and error reporting, disabling - * pipelined mode might be the best option. - * - * You can enable/disable/tune the pipelined operation mode by adjusting - * the compile time parameters below. - */ - -/* - * Possible improvements. - * - * 1. Support for the ATAPI overlap protocol. - * - * In order to maximize bus throughput, we currently use the DSC - * overlap method which enables ide.c to service requests from the - * other device while the tape is busy executing a command. The - * DSC overlap method involves polling the tape's status register - * for the DSC bit, and servicing the other device while the tape - * isn't ready. - * - * In the current QIC development standard (December 1995), - * it is recommended that new tape drives will *in addition* - * implement the ATAPI overlap protocol, which is used for the - * same purpose - efficient use of the IDE bus, but is interrupt - * driven and thus has much less CPU overhead. - * - * ATAPI overlap is likely to be supported in most new ATAPI - * devices, including new ATAPI cdroms, and thus provides us - * a method by which we can achieve higher throughput when - * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device. + * Oct 1999 Arnold Niessen, , + * Nov 2000, Jan 2001 Marcel Mol, + * Apr 2001 Willem Riede, */ -#define IDETAPE_VERSION "1.17a" +/* + * FIXME: clean tape->spinlock locking --bzolnier + */ #include #include @@ -419,9 +36,11 @@ #include #include #include +#include +#include #include #include -#include +#include #include #include @@ -445,6 +64,7 @@ #define OS_DATA_STARTFRAME1 20 #define OS_DATA_ENDFRAME1 2980 + /* * partition */ @@ -1249,7 +869,7 @@ } } -char *idetape_command_key_verbose (byte idetape_command_key) +char *idetape_command_key_verbose(u8 idetape_command_key) { switch (idetape_command_key) { case IDETAPE_TEST_UNIT_READY_CMD: return("TEST_UNIT_READY_CMD"); @@ -1439,7 +1059,7 @@ # if IDETAPE_DEBUG_LOG_VERBOSE if (tape->debug_level >= 1) printk (KERN_INFO "ide-tape: pc = %s, sense key = %x, asc = %x, ascq = %x\n", - idetape_command_key_verbose((byte) pc->c[0]), + idetape_command_key_verbose(pc->c[0]), result->sense_key, result->asc, result->ascq); @@ -1448,7 +1068,8 @@ if (tape->onstream && result->sense_key == 2 && result->asc == 0x53 && result->ascq == 2) { clear_bit(PC_DMA_ERROR, &pc->flags); - ide_stall_queue(drive, HZ / 2); + /* FIXME: we should use timeouts here */ + mdelay(HZ / 2 * 1000); return; } #ifdef CONFIG_BLK_DEV_IDEDMA @@ -1815,7 +1436,8 @@ printk(KERN_INFO "ide-tape: idetape_postpone_request\n"); #endif tape->postponed_rq = rq; - ide_stall_queue(drive, tape->dsc_polling_frequency); + /* FIXME: we should use timeouts here */ + mdelay(tape->dsc_polling_frequency * 1000); } /* @@ -2166,7 +1788,7 @@ /* * A mode sense command is used to "sense" tape parameters. */ -static void idetape_create_mode_sense_cmd(struct atapi_packet_command *pc, byte page_code) +static void idetape_create_mode_sense_cmd(struct atapi_packet_command *pc, u8 page_code) { atapi_init_pc(pc); pc->c[0] = IDETAPE_MODE_SENSE_CMD; @@ -3225,7 +2847,7 @@ * of the request queue and wait for their completion. * */ -static int idetape_position_tape(struct ata_device *drive, unsigned int block, byte partition, int skip) +static int idetape_position_tape(struct ata_device *drive, unsigned int block, u8 partition, int skip) { idetape_tape_t *tape = drive->driver_data; int retval; @@ -3981,7 +3603,7 @@ printk (KERN_ERR "ide-tape: bug: trying to return more bytes than requested\n"); bytes_read=blocks*tape->tape_block_size; } -#endif /* IDETAPE_DEBUG_BUGS */ +#endif return (bytes_read); } @@ -5892,18 +5514,17 @@ int minor = tape->minor; unsigned long flags; - save_flags (flags); /* all CPUs (overkill?) */ - cli(); /* all CPUs (overkill?) */ + spin_lock_irqsave (&tape->spinlock, flags); /* overkill? */ if (test_bit (IDETAPE_BUSY, &tape->flags) || tape->first_stage != NULL || tape->merge_stage_size || drive->usage) { - restore_flags(flags); /* all CPUs (overkill?) */ + spin_unlock_irqrestore(&tape->spinlock, flags); return 1; } idetape_chrdevs[minor].drive = NULL; - restore_flags (flags); /* all CPUs (overkill?) */ + spin_unlock_irqrestore(&tape->spinlock, flags); MOD_DEC_USE_COUNT; - ide_unregister_subdriver (drive); + ata_unregister_device(drive); drive->driver_data = NULL; devfs_unregister (tape->de_r); devfs_unregister (tape->de_n); @@ -5911,7 +5532,7 @@ for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++) if (idetape_chrdevs[minor].drive != NULL) return 0; - devfs_unregister_chrdev (IDETAPE_MAJOR, "ht"); + unregister_chrdev (IDETAPE_MAJOR, "ht"); idetape_chrdev_present = 0; return 0; } @@ -5973,7 +5594,7 @@ idetape_chrdevs[minor].drive = NULL; if (!idetape_chrdev_present && - devfs_register_chrdev (IDETAPE_MAJOR, "ht", &idetape_fops)) { + register_chrdev (IDETAPE_MAJOR, "ht", &idetape_fops)) { printk(KERN_ERR "ide-tape: Failed to register character device interface\n"); return; } @@ -5992,11 +5613,11 @@ } tape = (idetape_tape_t *) kmalloc (sizeof (idetape_tape_t), GFP_KERNEL); if (!tape) { - printk (KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name); + printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name); return; } - if (ide_register_subdriver (drive, &idetape_driver)) { - printk (KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name); + if (ata_register_device(drive, &idetape_driver)) { + printk(KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name); kfree (tape); return; } @@ -6017,7 +5638,7 @@ supported++; if (!idetape_chrdev_present && !supported) { - devfs_unregister_chrdev (IDETAPE_MAJOR, "ht"); + unregister_chrdev (IDETAPE_MAJOR, "ht"); } else idetape_chrdev_present = 1; diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c --- a/drivers/ide/ide.c Thu Aug 1 14:17:41 2002 +++ b/drivers/ide/ide.c Thu Aug 1 14:17:41 2002 @@ -481,12 +481,9 @@ udelay(1); ata_irq_enable(drive, 0); - /* This command actually looks suspicious, since I couldn't - * find it in any standard document. - */ OUT_BYTE(0x04, ch->io_ports[IDE_CONTROL_OFFSET]); udelay(10); - OUT_BYTE(WIN_NOP, ch->io_ports[IDE_CONTROL_OFFSET]); + OUT_BYTE(0x00, ch->io_ports[IDE_CONTROL_OFFSET]); ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_WORSTCASE, NULL); ata_mask(drive); @@ -503,138 +500,86 @@ } /* - * This is used by a drive to give excess bandwidth back by sleeping for - * timeout jiffies. - */ -void ide_stall_queue(struct ata_device *drive, unsigned long timeout) -{ - if (timeout > WAIT_WORSTCASE) - timeout = WAIT_WORSTCASE; - drive->sleep = timeout + jiffies; -} - -/* * Issue a new request. * Caller must have already done spin_lock_irqsave(channel->lock, ...) */ void do_ide_request(request_queue_t *q) { - struct ata_channel *channel = q->queuedata; + struct ata_device *drive = q->queuedata; + struct ata_channel *ch = drive->channel; - while (!test_and_set_bit(IDE_BUSY, channel->active)) { - struct ata_channel *ch; - struct ata_device *drive = NULL; + while (!test_and_set_bit(IDE_BUSY, ch->active)) { unsigned int unit; ide_startstop_t ret; - /* - * Select the next device which will be serviced. This selects - * only between devices on the same channel, since everything - * else will be scheduled on the queue level. - */ - - for (unit = 0; unit < MAX_DRIVES; ++unit) { - struct ata_device *tmp = &channel->drives[unit]; - - if (!tmp->present) - continue; - - /* There are no requests pending for this device. - */ - if (blk_queue_empty(&tmp->queue)) - continue; - - - /* This device still wants to remain idle. - */ - if (tmp->sleep && time_after(tmp->sleep, jiffies)) - continue; - - /* Take this device, if there is no device choosen thus - * far or which is more urgent. - */ - if (!drive || (tmp->sleep && (!drive->sleep || time_after(drive->sleep, tmp->sleep)))) { - if (!blk_queue_plugged(&tmp->queue)) - drive = tmp; - } + if (drive) { + /* No request pending?! */ + if (blk_queue_empty(&drive->queue)) + drive = NULL; + /* Still resorting requests?! */ + else if (blk_queue_plugged(&drive->queue)) + drive = NULL; } if (!drive) { - unsigned long sleep = 0; - + /* We should never get here! */ + /* Unless someone called us from IRQ context after + * finishing the actual request already. (Shrug!) + */ + // printk(KERN_INFO "no device found!\n"); for (unit = 0; unit < MAX_DRIVES; ++unit) { - struct ata_device *tmp = &channel->drives[unit]; + struct ata_device *tmp = &ch->drives[unit]; if (!tmp->present) continue; - /* This device is sleeping and waiting to be serviced - * earlier than any other device we checked thus far. + /* There are no requests pending for this + * device. */ - if (tmp->sleep && (!sleep || time_after(sleep, tmp->sleep))) - sleep = tmp->sleep; - } + if (blk_queue_empty(&tmp->queue)) + continue; - if (sleep) { - /* - * Take a short snooze, and then wake up again. Just - * in case there are big differences in relative - * throughputs.. don't want to hog the cpu too much. + /* Take this device, if there is no device + * choosen thus far and the queue is ready for + * processing. */ + if (!drive && !blk_queue_plugged(&tmp->queue)) + drive = tmp; + } + } - if (time_after(jiffies, sleep - WAIT_MIN_SLEEP)) - sleep = jiffies + WAIT_MIN_SLEEP; -#if 1 - if (timer_pending(&channel->timer)) - printk(KERN_ERR "%s: timer already active\n", __FUNCTION__); -#endif - set_bit(IDE_SLEEP, channel->active); - mod_timer(&channel->timer, sleep); + if (!drive) { + /* Ugly, but how can we sleep for the lock otherwise? + */ - /* - * We purposely leave us busy while sleeping becouse we - * are prepared to handle the IRQ from it. - * - * FIXME: Make sure sleeping can't interferre with - * operations of other devices on the same channel. - */ - } else { - /* FIXME: use queue plugging instead of active to block - * upper layers from stomping on us */ - /* Ugly, but how can we sleep for the lock otherwise? - * */ - - ide_release_lock(&ide_irq_lock);/* for atari only */ - clear_bit(IDE_BUSY, channel->active); - - /* All requests are done. - * - * Disable IRQs from the last drive on this channel, to - * make sure that it wan't throw stones at us when we - * are not prepared to take them. - */ + ide_release_lock(&ide_irq_lock);/* for atari only */ + clear_bit(IDE_BUSY, ch->active); - if (channel->drive && !channel->drive->using_tcq) - ata_irq_enable(channel->drive, 0); - } + /* All requests are done. + * + * Disable IRQs from the last drive on this channel, to + * make sure that it wan't throw stones at us when we + * are not prepared to take them. + */ + + if (ch->drive && !ch->drive->using_tcq) + ata_irq_enable(ch->drive, 0); return; } /* Remember the last drive we where acting on. */ - ch = drive->channel; ch->drive = drive; /* Feed commands to a drive until it barfs. */ do { struct request *rq = NULL; - sector_t block; - /* Abort early if we can't queue another command. for non tcq, - * ata_can_queue is always 1 since we never get here unless the - * drive is idle. + /* Abort early if we can't queue another command. for + * non tcq, ata_can_queue is always 1 since we never + * get here unless the drive is idle. */ if (!ata_can_queue(drive)) { @@ -646,18 +591,16 @@ break; } - drive->sleep = 0; - if (test_bit(IDE_DMA, ch->active)) { printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name); break; } - /* There's a small window between where the queue could be - * replugged while we are in here when using tcq (in which case - * the queue is probably empty anyways...), so check and leave - * if appropriate. When not using tcq, this is still a severe - * BUG! + /* There's a small window between where the queue could + * be replugged while we are in here when using tcq (in + * which case the queue is probably empty anyways...), + * so check and leave if appropriate. When not using + * tcq, this is still a severe BUG! */ if (blk_queue_plugged(&drive->queue)) { @@ -692,30 +635,12 @@ /* * This initiates handling of a new I/O request. */ - BUG_ON(!(rq->flags & REQ_STARTED)); -#ifdef DEBUG - printk("%s: %s: current=0x%08lx\n", ch->name, __FUNCTION__, (unsigned long) rq); -#endif - /* bail early if we've exceeded max_failures */ if (drive->max_failures && (drive->failures > drive->max_failures)) goto kill_rq; - block = rq->sector; - - /* Strange disk manager remap. - */ - if (rq->flags & REQ_CMD) - if (drive->type == ATA_DISK || drive->type == ATA_FLOPPY) - block += drive->sect0; - - /* Yecch - this will shift the entire interval, possibly killing some - * innocent following sector. - */ - if (block == 0 && drive->remap_0_to_1 == 1) - block = 1; /* redirect MBR access to EZ-Drive partn table */ ata_select(drive, 0); ret = ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT, @@ -737,9 +662,9 @@ * handler down to the device type driver. */ - if (ata_ops(drive)->do_request) { - ret = ata_ops(drive)->do_request(drive, rq, block); - } else { + if (ata_ops(drive)->do_request) + ret = ata_ops(drive)->do_request(drive, rq, rq->sector); + else { kill_rq: if (ata_ops(drive) && ata_ops(drive)->end_request) ata_ops(drive)->end_request(drive, rq, 0); @@ -749,12 +674,8 @@ } spin_lock_irq(ch->lock); - /* continue if command started, so we are busy */ } while (ret != ATA_OP_CONTINUES); - /* make sure the BUSY bit is set */ - /* FIXME: perhaps there is some place where we miss to set it? */ - // set_bit(IDE_BUSY, ch->active); } } @@ -1200,6 +1121,5 @@ EXPORT_SYMBOL(ata_error); EXPORT_SYMBOL(ata_end_request); -EXPORT_SYMBOL(ide_stall_queue); EXPORT_SYMBOL(ide_setup_ports); diff -Nru a/drivers/ide/ioctl.c b/drivers/ide/ioctl.c --- a/drivers/ide/ioctl.c Thu Aug 1 14:17:39 2002 +++ b/drivers/ide/ioctl.c Thu Aug 1 14:17:39 2002 @@ -33,6 +33,15 @@ #include "ioctl.h" + +/* BIG GEOMETRY - dying, used only by HDIO_GETGEO_BIG_RAW */ +struct hd_big_geometry { + u8 heads; + u8 sectors; + u32 cylinders; + unsigned long start; +}; + /* * Implement generic ioctls invoked from userspace to imlpement specific * functionality. diff -Nru a/drivers/ide/it8172.c b/drivers/ide/it8172.c --- a/drivers/ide/it8172.c Thu Aug 1 14:17:36 2002 +++ b/drivers/ide/it8172.c Thu Aug 1 14:17:36 2002 @@ -89,10 +89,7 @@ drive_enables |= 0x0006; } - save_flags(flags); - cli(); pci_write_config_word(dev, master_port, master_data); - restore_flags(flags); } #if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING) diff -Nru a/drivers/ide/main.c b/drivers/ide/main.c --- a/drivers/ide/main.c Thu Aug 1 14:17:36 2002 +++ b/drivers/ide/main.c Thu Aug 1 14:17:36 2002 @@ -176,22 +176,34 @@ }; unsigned int unit; - hw_regs_t hw; /* bulk initialize channel & drive info with zeros */ memset(ch, 0, sizeof(struct ata_channel)); - memset(&hw, 0, sizeof(hw_regs_t)); /* fill in any non-zero initial values */ ch->index = index; - ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &ch->irq); + ide_init_hwif_ports(&ch->hw, ide_default_io_base(index), 0, &ch->irq); - memcpy(&ch->hw, &hw, sizeof(hw)); - memcpy(ch->io_ports, hw.io_ports, sizeof(hw.io_ports)); + memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->hw.io_ports)); + + /* Most controllers cannot do transfers across 64kB boundaries. + trm290 can do transfers within a 4GB boundary, so it changes + this mask accordingly. */ + ch->seg_boundary_mask = 0xffff; + + /* Some chipsets (cs5530, any others?) think a 64kB transfer + is 0 byte transfer, so set the limit one sector smaller. + In the future, we may default to 64kB transfers and let + invidual chipsets with this problem change ch->max_segment_size. */ + ch->max_segment_size = (1<<16) - 512; ch->noprobe = !ch->io_ports[IDE_DATA_OFFSET]; #ifdef CONFIG_BLK_DEV_HD - if (ch->io_ports[IDE_DATA_OFFSET] == HD_DATA) + + /* Ignore disks for which handling by the legacy driver was requested + * by the used. + */ + if (ch->io_ports[IDE_DATA_OFFSET] == 0x1f0) ch->noprobe = 1; /* may be overridden by ide_setup() */ #endif @@ -361,7 +373,7 @@ if (ata_ops(drive)->cleanup(drive)) goto abort; } else - ide_unregister_subdriver(drive); + ata_unregister_device(drive); } } ch->present = 0; @@ -476,17 +488,19 @@ blk_dev[ch->major].data = NULL; blk_dev[ch->major].queue = NULL; blk_clear(ch->major); - gd = ch->gd; + gd = ch->gd[0]; if (gd) { - del_gendisk(gd); - kfree(gd->sizes); + int i; + for (i = 0; i < MAX_DRIVES; i++) + del_gendisk(gd + i); kfree(gd->part); if (gd->de_arr) kfree (gd->de_arr); if (gd->flags) kfree (gd->flags); kfree(gd); - ch->gd = NULL; + for (i = 0; i < MAX_DRIVES; i++) + ch->gd[i] = NULL; } /* @@ -701,79 +715,46 @@ /* * This gets called VERY EARLY during initialization, to handle kernel "command - * line" strings beginning with "hdx=" or "ide".It gets called even before the - * actual module gets initialized. + * line" strings beginning with "hdx=". It gets called even before the actual + * module gets initialized. * * Please look at Documentation/ide.txt to see the complete list of supported * options. */ -int __init ide_setup(char *s) +static int __init ata_hd_setup(char *s) { - int i, vals[4]; - struct ata_channel *ch; + int vals[4]; + struct ata_channel *ch; /* FIXME: Channel parms should not be accessed in ata_hd_setup */ struct ata_device *drive; unsigned int hw, unit; const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1); - const char max_ch = '0' + (MAX_HWIFS - 1); - - if (!strncmp(s, "hd=", 3)) /* hd= is for hd.c driver and not us */ - return 0; - if (strncmp(s,"ide",3) && - strncmp(s,"hd",2)) /* hdx= & hdxlun= */ + if (s[0] == '=') /* hd= is for hd.c driver and not us */ return 0; - printk(KERN_INFO "ide_setup: %s", s); + printk(KERN_INFO "hd%s", s); init_global_data(); -#ifdef CONFIG_BLK_DEV_IDEDOUBLER - if (!strcmp(s, "ide=doubler")) { - extern int ide_doubler; - - printk(KERN_INFO" : Enabled support for IDE doublers\n"); - ide_doubler = 1; - - return 1; - } -#endif - - if (!strcmp(s, "ide=nodma")) { - printk(KERN_INFO "ATA: Prevented DMA\n"); - noautodma = 1; - - return 1; - } - -#ifdef CONFIG_PCI - if (!strcmp(s, "ide=reverse")) { - ide_scan_direction = 1; - printk(" : Enabled support for IDE inverse scan order.\n"); - - return 1; - } -#endif - - /* - * Look for drive options: "hdx=" - */ - if (!strncmp(s, "hd", 2) && s[2] >= 'a' && s[2] <= max_drive) { - const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom", + if (s[0] >= 'a' && s[0] <= max_drive) { + static const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom", "serialize", "autotune", "noautotune", - "slow", "flash", "remap", "noremap", "scsi", NULL}; - unit = s[2] - 'a'; + "slow", "flash", "scsi", NULL}; + unit = s[0] - 'a'; hw = unit / MAX_DRIVES; unit = unit % MAX_DRIVES; ch = &ide_hwifs[hw]; drive = &ch->drives[unit]; - if (!strncmp(s+3, "=ide-", 5)) { - strncpy(drive->driver_req, s + 4, 9); + + /* Look for hdx=ide-* */ + if (!strncmp(s+1, "=ide-", 5)) { + strncpy(drive->driver_req, s+2, 9); goto done; } /* * Look for last lun option: "hdxlun=" */ - if (!strncmp(s+3, "lun=", 4)) { - if (*get_options(s+7, 2, vals) || vals[0]!=1) + if (!strncmp(s+1, "lun=", 4)) { + if (*get_options(s+5, 2, vals) || vals[0]!=1) goto bad_option; if (vals[1] >= 0 && vals[1] <= 7) { drive->last_lun = vals[1]; @@ -782,7 +763,7 @@ printk(" -- BAD LAST LUN! Expected value from 0 to 7"); goto done; } - switch (match_parm(s+3, hd_words, vals, 3)) { + switch (match_parm(s+1, hd_words, vals, 3)) { case -1: /* "none" */ drive->nobios = 1; /* drop into "noprobe" */ case -2: /* "noprobe" */ @@ -790,16 +771,16 @@ goto done; case -3: /* "nowerr" */ drive->bad_wstat = BAD_R_STAT; - ch->noprobe = 0; + ch->noprobe = 0; /* FIXME: Channel parm */ goto done; case -4: /* "cdrom" */ drive->present = 1; drive->type = ATA_ROM; - ch->noprobe = 0; + ch->noprobe = 0; /* FIXME: Channel parm */ goto done; case -5: /* "serialize" */ printk(" -- USE \"ide%d=serialize\" INSTEAD", hw); - goto do_serialize; + goto bad_option; case -6: /* "autotune" */ drive->autotune = 1; goto done; @@ -807,18 +788,12 @@ drive->autotune = 2; goto done; case -8: /* "slow" */ - ch->slow = 1; + ch->slow = 1; /* FIXME: Channel parm */ goto done; case -9: /* "flash" */ drive->ata_flash = 1; goto done; - case -10: /* "remap" */ - drive->remap_0_to_1 = 1; - goto done; - case -11: /* "noremap" */ - drive->remap_0_to_1 = 2; - goto done; - case -12: /* "scsi" */ + case -10: /* "scsi" */ #if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) drive->scsi = 1; goto done; @@ -840,11 +815,63 @@ } } +bad_option: + printk(" -- BAD OPTION\n"); + return 1; + +done: + printk("\n"); + + return 1; +} + +/* + * This gets called VERY EARLY during initialization, to handle kernel "command + * line" strings beginning with "ide". It gets called even before the actual + * module gets initialized. + * + * Please look at Documentation/ide.txt to see the complete list of supported + * options. + */ +int __init ide_setup(char *s) +{ + int i, vals[4]; + struct ata_channel *ch; + unsigned int hw; + const char max_ch = '0' + (MAX_HWIFS - 1); + + printk(KERN_INFO "ide%s", s); + init_global_data(); + +#ifdef CONFIG_BLK_DEV_IDEDOUBLER + if (!strcmp(s, "=doubler")) { + extern int ide_doubler; + + printk(KERN_INFO" : Enabled support for ATA doublers\n"); + ide_doubler = 1; + return 1; + } +#endif + + if (!strcmp(s, "=nodma")) { + printk(KERN_INFO "ATA: Prevented DMA\n"); + noautodma = 1; + return 1; + } + +#ifdef CONFIG_PCI + if (!strcmp(s, "=reverse")) { + ide_scan_direction = 1; + printk(" : Enabled support for IDE inverse scan order.\n"); + return 1; + } +#endif + /* * Look for bus speed option: "idebus=" */ - if (!strncmp(s, "idebus=", 7)) { - if (*get_options(s+7, 2, vals) || vals[0] != 1) + if (!strncmp(s, "bus=", 4)) { + if (*get_options(s+4, 2, vals) || vals[0] != 1) goto bad_option; idebus_parameter = vals[1]; goto done; @@ -853,7 +880,7 @@ /* * Look for interface options: "idex=" */ - if (!strncmp(s, "ide", 3) && s[3] >= '0' && s[3] <= max_ch) { + if (s[0] >= '0' && s[0] <= max_ch) { /* * Be VERY CAREFUL changing this: note hardcoded indexes below */ @@ -861,11 +888,11 @@ "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", NULL }; const char *ide_words[] = { "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; - hw = s[3] - '0'; + hw = s[0] - '0'; ch = &ide_hwifs[hw]; - switch (match_parm(s+4, ide_options, vals, 1)) { + switch (match_parm(s + 1, ide_options, vals, 1)) { case -7: /* ata66 */ #ifdef CONFIG_PCI ch->udma_four = 1; @@ -889,7 +916,6 @@ ch->drives[1].autotune = 1; goto done; case -2: /* "serialize" */ - do_serialize: { struct ata_channel *mate; @@ -904,7 +930,10 @@ goto done; } - i = match_parm(&s[4], ide_words, vals, 3); + /* + * Check for specific chipset name + */ + i = match_parm(s + 1, ide_words, vals, 3); /* * Cryptic check to ensure chipset not already set for a channel: @@ -913,7 +942,7 @@ if (ide_hwifs[hw].chipset != ide_unknown) goto bad_option; /* chipset already specified */ if (i != -7 && hw != 0) - goto bad_channel; /* chipset drivers are for "ide0=" only */ + goto bad_channel; /* chipset drivers are for "ide0=" only */ if (i != -7 && ide_hwifs[1].chipset != ide_unknown) goto bad_option; /* chipset for 2nd port already specified */ printk("\n"); @@ -931,7 +960,7 @@ #ifdef CONFIG_BLK_DEV_ALI14XX case -6: /* "ali14xx" */ { - extern void init_ali14xx (void); + extern void init_ali14xx(void); init_ali14xx(); goto done; } @@ -939,7 +968,7 @@ #ifdef CONFIG_BLK_DEV_UMC8672 case -5: /* "umc8672" */ { - extern void init_umc8672 (void); + extern void init_umc8672(void); init_umc8672(); goto done; } @@ -947,7 +976,7 @@ #ifdef CONFIG_BLK_DEV_DTC2278 case -4: /* "dtc2278" */ { - extern void init_dtc2278 (void); + extern void init_dtc2278(void); init_dtc2278(); goto done; } @@ -963,7 +992,7 @@ #ifdef CONFIG_BLK_DEV_HT6560B case -2: /* "ht6560b" */ { - extern void init_ht6560b (void); + extern void init_ht6560b(void); init_ht6560b(); goto done; } @@ -971,7 +1000,7 @@ #if CONFIG_BLK_DEV_QD65XX case -1: /* "qd65xx" */ { - extern void init_qd65xx (void); + extern void init_qd65xx(void); init_qd65xx(); goto done; } @@ -1012,10 +1041,7 @@ /****************************************************************************/ -/* - * This is in fact registering a device not a driver. - */ -int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driver) +int ata_register_device(struct ata_device *drive, struct ata_operations *driver) { unsigned long flags; @@ -1027,12 +1053,9 @@ return 1; } - /* FIXME: This will be pushed to the drivers! Thus allowing us to - * save one parameter here and to separate this out. - */ drive->driver = driver; - spin_unlock_irqrestore(&ide_lock, flags); + /* Default autotune or requested autotune */ if (drive->autotune != 2) { struct ata_channel *ch = drive->channel; @@ -1046,11 +1069,13 @@ * PARANOIA!!! */ + spin_lock_irqsave(ch->lock, flags); udma_enable(drive, 0, 0); ch->udma_setup(drive, ch->modes_map); #ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT udma_tcq_enable(drive, 1); #endif + spin_unlock_irqrestore(ch->lock, flags); } /* Only CD-ROMs and tape drives support DSC overlap. But only @@ -1078,13 +1103,8 @@ * * FIXME: Check whatever we maybe don't call it twice!. */ -int ide_unregister_subdriver(struct ata_device *drive) +int ata_unregister_device(struct ata_device *drive) { -#if 0 - if (__MOD_IN_USE(ata_ops(drive)->owner)) - return 1; -#endif - if (drive->usage || drive->busy || !ata_ops(drive)) return 1; @@ -1120,7 +1140,7 @@ EXPORT_SYMBOL(register_ata_driver); /* - * Unregister an ATA subdriver for a particular device type. + * Unregister an ATA sub-driver for a particular device type. */ void unregister_ata_driver(struct ata_operations *driver) { @@ -1156,8 +1176,8 @@ devfs_handle_t ide_devfs_handle; -EXPORT_SYMBOL(ide_register_subdriver); -EXPORT_SYMBOL(ide_unregister_subdriver); +EXPORT_SYMBOL(ata_register_device); +EXPORT_SYMBOL(ata_unregister_device); EXPORT_SYMBOL(ata_revalidate); EXPORT_SYMBOL(ide_register_hw); EXPORT_SYMBOL(ide_unregister); @@ -1432,8 +1452,14 @@ while ((options = next) != NULL) { if ((next = strchr(options,' ')) != NULL) *next++ = 0; - if (!ide_setup(options)) - printk(KERN_ERR "Unknown option '%s'\n", options); + if (!strncmp(options,"hd",2)) { + if (!ata_hd_setup(options+2)) + printk(KERN_ERR "Unknown option '%s'\n", options); + } + else if (!strncmp(options,"ide",3)) { + if (!ide_setup(options+3)) + printk(KERN_ERR "Unknown option '%s'\n", options); + } } } return ata_module_init(); @@ -1457,6 +1483,7 @@ #ifndef MODULE /* command line option parser */ -__setup("", ide_setup); +__setup("ide", ide_setup); +__setup("hd", ata_hd_setup); #endif diff -Nru a/drivers/ide/opti621.c b/drivers/ide/opti621.c --- a/drivers/ide/opti621.c Thu Aug 1 14:17:36 2002 +++ b/drivers/ide/opti621.c Thu Aug 1 14:17:36 2002 @@ -244,13 +244,15 @@ } -/* Main tune procedure, called from tuneproc. */ +/* Main tune procedure, called from tuneproc. + Assumes IRQ's are disabled or at least that no other process will + attempt to access the IDE registers concurrently. +*/ static void opti621_tune_drive(struct ata_device *drive, u8 pio) { /* primary and secondary drives share some registers, * so we have to program both drives */ - unsigned long flags; u8 pio1, pio2; pio_clocks_t first, second; int ax, drdy; @@ -281,9 +283,6 @@ hwif->name, ax, second.data_time, second.recovery_time, drdy); #endif - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - reg_base = hwif->io_ports[IDE_DATA_OFFSET]; outb(0xc0, reg_base+CNTRL_REG); /* allow Register-B */ outb(0xff, reg_base+5); /* hmm, setupvic.exe does this ;-) */ @@ -306,8 +305,6 @@ write_reg(misc, MISC_REG); /* set address setup, DRDY timings, */ /* and read prefetch for both drives */ - - restore_flags(flags); /* all CPUs */ } /* diff -Nru a/drivers/ide/pcidma.c b/drivers/ide/pcidma.c --- a/drivers/ide/pcidma.c Thu Aug 1 14:17:36 2002 +++ b/drivers/ide/pcidma.c Thu Aug 1 14:17:36 2002 @@ -379,12 +379,6 @@ { struct ata_channel *ch = drive->channel; unsigned int *table = ch->dmatable_cpu; -#ifdef CONFIG_BLK_DEV_TRM290 - unsigned int is_trm290_chipset = (ch->chipset == ide_trm290); -#else - const int is_trm290_chipset = 0; -#endif - unsigned int count = 0; int i; struct scatterlist *sg; @@ -392,68 +386,29 @@ if (!i) return 0; + BUG_ON(i > PRD_ENTRIES); + sg = ch->sg_table; - while (i) { - u32 cur_addr; - u32 cur_len; - - cur_addr = sg_dma_address(sg); - cur_len = sg_dma_len(sg); - - /* - * Fill in the dma table, without crossing any 64kB boundaries. - * Most hardware requires 16-bit alignment of all blocks, - * but the trm290 requires 32-bit alignment. - */ - - while (cur_len) { - u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff); - - if (count++ >= PRD_ENTRIES) { - printk("ide-dma: count %d, sg_nents %d, cur_len %d, cur_addr %u\n", - count, ch->sg_nents, cur_len, cur_addr); - BUG(); - } - - if (bcount > cur_len) - bcount = cur_len; - *table++ = cpu_to_le32(cur_addr); - xcount = bcount & 0xffff; - if (is_trm290_chipset) - xcount = ((xcount >> 2) - 1) << 16; - if (xcount == 0x0000) { - /* - * Most chipsets correctly interpret a length of - * 0x0000 as 64KB, but at least one (e.g. CS5530) - * misinterprets it as zero (!). So here we break - * the 64KB entry into two 32KB entries instead. - */ - if (count++ >= PRD_ENTRIES) { - pci_unmap_sg(ch->pci_dev, sg, - ch->sg_nents, - ch->sg_dma_direction); - return 0; - } - - *table++ = cpu_to_le32(0x8000); - *table++ = cpu_to_le32(cur_addr + 0x8000); - xcount = 0x8000; - } - *table++ = cpu_to_le32(xcount); - cur_addr += bcount; - cur_len -= bcount; - } + while (i--) { + u32 cur_addr = sg_dma_address(sg); + u32 cur_len = sg_dma_len(sg) & 0xffff; + + /* Delete this test after linux ~2.5.35, as we care + about performance in this loop. */ + BUG_ON(cur_len > ch->max_segment_size); + + *table++ = cpu_to_le32(cur_addr); + *table++ = cpu_to_le32(cur_len); sg++; - i--; } - if (!count) - printk(KERN_ERR "%s: empty DMA table?\n", ch->name); - else if (!is_trm290_chipset) +#ifdef CONFIG_BLK_DEV_TRM290 + if (ch->chipset == ide_trm290) *--table |= cpu_to_le32(0x80000000); +#endif - return count; + return ch->sg_nents; } /* diff -Nru a/drivers/ide/probe.c b/drivers/ide/probe.c --- a/drivers/ide/probe.c Thu Aug 1 14:17:36 2002 +++ b/drivers/ide/probe.c Thu Aug 1 14:17:36 2002 @@ -41,19 +41,10 @@ extern struct ata_device * get_info_ptr(kdev_t); /* - * This is called from the partition-table code in pt/msdos.c. + * This is called from the partition-table code in pt/msdos.c + * to invent a translated geometry. * - * It has two tasks: - * - * (I) to handle Ontrack DiskManager by offsetting everything by 63 sectors, - * or to handle EZdrive by remapping sector 0 to sector 1. - * - * (II) to invent a translated geometry. - * - * Part (I) is suppressed if the user specifies the "noremap" option - * on the command line. - * - * Part (II) is suppressed if the user specifies an explicit geometry. + * This is suppressed if the user specifies an explicit geometry. * * The ptheads parameter is either 0 or tells about the number of * heads shown by the end of the first nonempty partition. @@ -83,21 +74,6 @@ if (!drive) return 0; - /* remap? */ - if (drive->remap_0_to_1 != 2) { - if (xparm == 1) { /* DM */ - drive->sect0 = 63; - msg1 = " [remap +63]"; - ret = 1; - } else if (xparm == -1) { /* EZ-Drive */ - if (drive->remap_0_to_1 == 0) { - drive->remap_0_to_1 = 1; - msg1 = " [remap 0->1]"; - ret = 1; - } - } - } - /* There used to be code here that assigned drive->id->CHS to * drive->CHS and that to drive->bios_CHS. However, some disks have * id->C/H/S = 4092/16/63 but are larger than 2.1 GB. In such cases @@ -1001,22 +977,24 @@ ch->drive = drive; /* - * Init the per device request queue + * Init the per device request queue. */ q = &drive->queue; - q->queuedata = drive->channel; + q->queuedata = drive; blk_init_queue(q, do_ide_request, drive->channel->lock); - blk_queue_segment_boundary(q, 0xffff); + blk_queue_segment_boundary(q, ch->seg_boundary_mask); + blk_queue_max_segment_size(q, ch->max_segment_size); - /* ATA can do up to 128K per request, pdc4030 needs smaller limit */ + /* ATA can do up to 128K per request, pdc4030 needs smaller + * limit. */ #ifdef CONFIG_BLK_DEV_PDC4030 if (drive->channel->chipset == ide_pdc4030) max_sectors = 127; #endif blk_queue_max_sectors(q, max_sectors); - /* IDE DMA can do PRD_ENTRIES number of segments. */ + /* ATA DMA can do PRD_ENTRIES number of segments. */ blk_queue_max_hw_segments(q, PRD_ENTRIES); /* FIXME: This is a driver limit and could be eliminated. */ @@ -1065,6 +1043,9 @@ static void channel_init(struct ata_channel *ch) { struct gendisk *gd; + struct hd_struct *part; + devfs_handle_t *de_arr; + char *flags; unsigned int unit; extern devfs_handle_t ide_devfs_handle; @@ -1082,14 +1063,19 @@ } } #ifdef CONFIG_BLK_DEV_HD - if (ch->irq == HD_IRQ && ch->io_ports[IDE_DATA_OFFSET] != HD_DATA) { + + /* The first "legacy" HD gets distinguished by the IRQ it is attached + * to and the IO port it takes. + */ + + if (ch->irq == 14 && ch->io_ports[IDE_DATA_OFFSET] != 0x1f0) { printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", ch->name); return; } #endif - if (devfs_register_blkdev(ch->major, ch->name, ide_fops)) { + if (register_blkdev(ch->major, ch->name, ide_fops)) { printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", ch->name, ch->major); return; @@ -1120,43 +1106,42 @@ /* Initialize partition and global device data. */ - gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL); + gd = kmalloc (MAX_DRIVES * sizeof(struct gendisk), GFP_KERNEL); if (!gd) goto err_kmalloc_gd; - memset(gd, 0, sizeof(struct gendisk)); - gd->sizes = kmalloc(ATA_MINORS * sizeof(int), GFP_KERNEL); - if (!gd->sizes) - goto err_kmalloc_gd_sizes; - memset(gd->sizes, 0, ATA_MINORS*sizeof(gd->sizes[0])); + memset(gd, 0, MAX_DRIVES * sizeof(struct gendisk)); - gd->part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL); - if (!gd->part) + part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL); + if (!part) goto err_kmalloc_gd_part; - memset(gd->part, 0, ATA_MINORS * sizeof(struct hd_struct)); + memset(part, 0, ATA_MINORS * sizeof(struct hd_struct)); - gd->de_arr = kmalloc (sizeof(*gd->de_arr) * MAX_DRIVES, GFP_KERNEL); - if (!gd->de_arr) + de_arr = kmalloc (sizeof(devfs_handle_t) * MAX_DRIVES, GFP_KERNEL); + if (!de_arr) goto err_kmalloc_gd_de_arr; - memset(gd->de_arr, 0, sizeof(*gd->de_arr) * MAX_DRIVES); + memset(de_arr, 0, sizeof(devfs_handle_t) * MAX_DRIVES); - gd->flags = kmalloc (sizeof(*gd->flags) * MAX_DRIVES, GFP_KERNEL); - if (!gd->flags) + flags = kmalloc (sizeof(char) * MAX_DRIVES, GFP_KERNEL); + if (!flags) goto err_kmalloc_gd_flags; - memset(gd->flags, 0, sizeof(*gd->flags) * MAX_DRIVES); - - for (unit = 0; unit < MAX_DRIVES; ++unit) - ch->drives[unit].part = &gd->part[unit << PARTN_BITS]; + memset(flags, 0, sizeof(char) * MAX_DRIVES); - gd->major = ch->major; /* our major device number */ - gd->major_name = IDE_MAJOR_NAME; /* treated special in genhd.c */ - gd->minor_shift = PARTN_BITS; /* num bits for partitions */ - gd->nr_real = MAX_DRIVES; /* current num real drives */ - gd->next = NULL; /* linked list of major devs */ - gd->fops = ide_fops; /* file operations */ - - ch->gd = gd; - add_gendisk(gd); + for (unit = 0; unit < MAX_DRIVES; ++unit) { + gd[unit].part = part + (unit << PARTN_BITS); + gd[unit].de_arr = de_arr + unit; + gd[unit].flags = flags + unit; + ch->drives[unit].part = gd[unit].part; + gd[unit].major = ch->major; + gd[unit].first_minor = unit << PARTN_BITS; + /* treated special in genhd.c */ + gd[unit].major_name = IDE_MAJOR_NAME; + gd[unit].minor_shift = PARTN_BITS; + gd[unit].nr_real = 1; + gd[unit].fops = ide_fops; + ch->gd[unit] = gd + unit; + add_gendisk(gd + unit); + } for (unit = 0; unit < MAX_DRIVES; ++unit) { char name[80]; @@ -1177,12 +1162,10 @@ return; err_kmalloc_gd_flags: - kfree(gd->de_arr); + kfree(de_arr); err_kmalloc_gd_de_arr: - kfree(gd->part); + kfree(part); err_kmalloc_gd_part: - kfree(gd->sizes); -err_kmalloc_gd_sizes: kfree(gd); err_kmalloc_gd: printk(KERN_CRIT "(%s) Out of memory\n", __FUNCTION__); diff -Nru a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c --- a/drivers/ide/qd65xx.c Thu Aug 1 14:17:39 2002 +++ b/drivers/ide/qd65xx.c Thu Aug 1 14:17:39 2002 @@ -1,8 +1,6 @@ /* * Copyright (C) 1996-2001 Linus Torvalds & author (see below) - */ - -/* + * * Version 0.03 Cleaned auto-tune, added probe * Version 0.04 Added second channel tuning * Version 0.05 Enhanced tuning ; added qd6500 support @@ -81,36 +79,12 @@ * bit 5 : status, but of what ? * bit 6 : always set 1 by dos driver * bit 7 : set 1 for non-ATAPI devices on primary port - * (maybe read-ahead and post-write buffer ?) + * (maybe read-ahead and post-write buffer ?) */ static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */ -static void qd_write_reg(u8 content, unsigned int reg) -{ - unsigned long flags; - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - outb(content,reg); - restore_flags(flags); /* all CPUs */ -} - -static u8 __init qd_read_reg(unsigned int reg) -{ - unsigned long flags; - u8 read; - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - read = inb(reg); - restore_flags(flags); /* all CPUs */ - return read; -} - /* - * qd_select: - * * This routine is invoked from ide.c to prepare for access to a given drive. */ @@ -120,12 +94,10 @@ (QD_TIMREG(drive) & 0x02); if (timings[index] != QD_TIMING(drive)) - qd_write_reg(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); + outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); } /* - * qd6500_compute_timing - * * computes the timing value where * lower nibble represents active time, in count of VLB clocks * upper nibble represents recovery time, in count of VLB clocks @@ -147,8 +119,6 @@ } /* - * qd6580_compute_timing - * * idem for qd6580 */ @@ -161,8 +131,6 @@ } /* - * qd_find_disk_type - * * tries to find timing from dos driver's table */ @@ -187,8 +155,6 @@ } /* - * qd_timing_ok: - * * check whether timings don't conflict */ @@ -201,8 +167,6 @@ } /* - * qd_set_timing: - * * records the timing, and enables selectproc as needed */ @@ -221,10 +185,6 @@ printk(KERN_DEBUG "%s: %#x\n", drive->name, timing); } -/* - * qd6500_tune_drive - */ - static void qd6500_tune_drive(struct ata_device *drive, u8 pio) { int active_time = 175; @@ -242,10 +202,6 @@ qd_set_timing(drive, qd6500_compute_timing(drive->channel, active_time, recovery_time)); } -/* - * qd6580_tune_drive - */ - static void qd6580_tune_drive(struct ata_device *drive, u8 pio) { struct ata_timing *t; @@ -291,7 +247,7 @@ } if (!drive->channel->unit && drive->type != ATA_DISK) { - qd_write_reg(0x5f, QD_CONTROL_PORT); + outb(0x5f, QD_CONTROL_PORT); printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.\n", drive->name, drive->channel->name); } @@ -299,8 +255,6 @@ } /* - * qd_testreg - * * tests if the given port is a register */ @@ -308,15 +262,11 @@ { u8 savereg; u8 readreg; - unsigned long flags; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ savereg = inb_p(port); outb_p(QD_TESTVAL, port); /* safe value */ readreg = inb_p(port); outb(savereg, port); - restore_flags(flags); /* all CPUs */ if (savereg == QD_TESTVAL) { printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n"); @@ -329,8 +279,6 @@ } /* - * qd_setup: - * * called to setup an ata channel : adjusts attributes & links for tuning */ @@ -349,8 +297,6 @@ } /* - * qd_unsetup: - * * called to unsetup an ata channel : back to default values, unlinks tuning */ void __init qd_unsetup(int unit) { @@ -368,13 +314,13 @@ if (tuneproc == (void *) qd6500_tune_drive) { // will do it for both - qd_write_reg(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0])); + outb(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0])); } else if (tuneproc == (void *) qd6580_tune_drive) { if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) { - qd_write_reg(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0])); - qd_write_reg(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1])); + outb(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0])); + outb(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1])); } else { - qd_write_reg(unit?QD6580_DEF_DATA2:QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0])); + outb(unit ? QD6580_DEF_DATA2 : QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0])); } } else { printk(KERN_WARNING "Unknown qd65xx tuning fonction !\n"); @@ -383,8 +329,6 @@ } /* - * qd_probe: - * * looks at the specified baseport, and if qd found, registers & initialises it * return 1 if another qd may be probed */ @@ -394,7 +338,7 @@ u8 config; int unit; - config = qd_read_reg(QD_CONFIG_PORT); + config = inb(QD_CONFIG_PORT); if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) return 1; @@ -425,7 +369,7 @@ /* qd6580 found */ - control = qd_read_reg(QD_CONTROL_PORT); + control = inb(QD_CONTROL_PORT); printk(KERN_NOTICE "qd6580 at %#x\n", base); printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n", config, control, QD_ID3); @@ -434,7 +378,7 @@ /* secondary disabled */ printk(KERN_INFO "%s: qd6580: single IDE board\n", ide_hwifs[unit].name); qd_setup(unit, base, config | (control << 8), QD6580_DEF_DATA, QD6580_DEF_DATA2, &qd6580_tune_drive); - qd_write_reg(QD_DEF_CONTR, QD_CONTROL_PORT); + outb(QD_DEF_CONTR, QD_CONTROL_PORT); return 1; } else { @@ -443,7 +387,7 @@ qd_setup(ATA_PRIMARY, base, config | (control << 8), QD6580_DEF_DATA, QD6580_DEF_DATA, &qd6580_tune_drive); qd_setup(ATA_SECONDARY, base, config | (control << 8), QD6580_DEF_DATA2, QD6580_DEF_DATA2, &qd6580_tune_drive); - qd_write_reg(QD_DEF_CONTR, QD_CONTROL_PORT); + outb(QD_DEF_CONTR, QD_CONTROL_PORT); return 0; /* no other qd65xx possible */ } @@ -454,8 +398,6 @@ #ifndef MODULE /* - * init_qd65xx: - * * called by ide.c when parsing command line */ diff -Nru a/drivers/ide/trm290.c b/drivers/ide/trm290.c --- a/drivers/ide/trm290.c Thu Aug 1 14:17:36 2002 +++ b/drivers/ide/trm290.c Thu Aug 1 14:17:36 2002 @@ -255,6 +255,7 @@ struct pci_dev *dev = hwif->pci_dev; hwif->chipset = ide_trm290; + hwif->seg_boundary_mask = 0xffffffff; cfgbase = pci_resource_start(dev, 4); if ((dev->class & 5) && cfgbase) { diff -Nru a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c --- a/drivers/ide/umc8672.c Thu Aug 1 14:17:40 2002 +++ b/drivers/ide/umc8672.c Thu Aug 1 14:17:40 2002 @@ -108,19 +108,14 @@ static void tune_umc(struct ata_device *drive, u8 pio) { - unsigned long flags; - if (pio == 255) pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0; else pio = min_t(u8, pio, 4); printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]); - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; umc_set_speeds (current_speeds); - restore_flags(flags); /* all CPUs */ } void __init init_umc8672(void) /* called from ide.c */ diff -Nru a/drivers/input/evdev.c b/drivers/input/evdev.c --- a/drivers/input/evdev.c Thu Aug 1 14:17:41 2002 +++ b/drivers/input/evdev.c Thu Aug 1 14:17:41 2002 @@ -233,6 +233,7 @@ struct evdev_list *list = file->private_data; struct evdev *evdev = list->evdev; struct input_dev *dev = evdev->handle.dev; + struct input_absinfo abs; int t, u; if (!evdev->exist) return -ENODEV; @@ -378,11 +379,14 @@ int t = _IOC_NR(cmd) & ABS_MAX; - if (put_user(dev->abs[t], ((int *) arg) + 0)) return -EFAULT; - if (put_user(dev->absmin[t], ((int *) arg) + 1)) return -EFAULT; - if (put_user(dev->absmax[t], ((int *) arg) + 2)) return -EFAULT; - if (put_user(dev->absfuzz[t], ((int *) arg) + 3)) return -EFAULT; - if (put_user(dev->absflat[t], ((int *) arg) + 4)) return -EFAULT; + abs.value = dev->abs[t]; + abs.minimum = dev->absmin[t]; + abs.maximum = dev->absmax[t]; + abs.fuzz = dev->absfuzz[t]; + abs.flat = dev->absflat[t]; + + if (copy_to_user((void *) arg, &abs, sizeof(struct input_absinfo))) + return -EFAULT; return 0; } @@ -391,11 +395,14 @@ int t = _IOC_NR(cmd) & ABS_MAX; - if (get_user(dev->abs[t], ((int *) arg) + 0)) return -EFAULT; - if (get_user(dev->absmin[t], ((int *) arg) + 1)) return -EFAULT; - if (get_user(dev->absmax[t], ((int *) arg) + 2)) return -EFAULT; - if (get_user(dev->absfuzz[t], ((int *) arg) + 3)) return -EFAULT; - if (get_user(dev->absflat[t], ((int *) arg) + 4)) return -EFAULT; + if (copy_from_user(&abs, (void *) arg, sizeof(struct input_absinfo))) + return -EFAULT; + + dev->abs[t] = abs.value; + dev->absmin[t] = abs.minimum; + dev->absmax[t] = abs.maximum; + dev->absfuzz[t] = abs.fuzz; + dev->absflat[t] = abs.flat; return 0; } diff -Nru a/drivers/input/input.c b/drivers/input/input.c --- a/drivers/input/input.c Thu Aug 1 14:17:40 2002 +++ b/drivers/input/input.c Thu Aug 1 14:17:40 2002 @@ -100,18 +100,14 @@ if (code > KEY_MAX || !test_bit(code, dev->keybit) || !!test_bit(code, dev->key) == value) return; - if (value == 2) break; + if (value == 2) + break; change_bit(code, dev->key); - if (test_bit(EV_REP, dev->evbit) && dev->timer.function) { - if (value) { - mod_timer(&dev->timer, jiffies + dev->rep[REP_DELAY]); - dev->repeat_key = code; - break; - } - if (dev->repeat_key == code) - del_timer(&dev->timer); + if (test_bit(EV_REP, dev->evbit) && value) { + dev->repeat_key = code; + mod_timer(&dev->timer, jiffies + dev->rep[REP_DELAY]); } break; @@ -204,8 +200,13 @@ static void input_repeat_key(unsigned long data) { struct input_dev *dev = (void *) data; + + if (!test_bit(dev->repeat_key, dev->key)) + return; + input_event(dev, EV_KEY, dev->repeat_key, 2); input_sync(dev); + mod_timer(&dev->timer, jiffies + dev->rep[REP_PERIOD]); } @@ -268,6 +269,7 @@ * * Returns nothing. */ + #define input_find_and_remove(type, initval, targ, next) \ do { \ type **ptr; \ @@ -513,7 +515,7 @@ * Kill any pending repeat timers. */ - del_timer(&dev->timer); + del_timer_sync(&dev->timer); /* * Notify handlers. @@ -820,7 +822,7 @@ entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); entry->owner = THIS_MODULE; #endif - if (devfs_register_chrdev(INPUT_MAJOR, "input", &input_fops)) { + if (register_chrdev(INPUT_MAJOR, "input", &input_fops)) { printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR); return -EBUSY; } @@ -838,7 +840,7 @@ remove_proc_entry("input", proc_bus); #endif devfs_unregister(input_devfs_handle); - if (devfs_unregister_chrdev(INPUT_MAJOR, "input")) + if (unregister_chrdev(INPUT_MAJOR, "input")) printk(KERN_ERR "input: can't unregister char major %d", INPUT_MAJOR); } diff -Nru a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c --- a/drivers/input/serio/serio.c Thu Aug 1 14:17:36 2002 +++ b/drivers/input/serio/serio.c Thu Aug 1 14:17:36 2002 @@ -95,9 +95,9 @@ do { serio_handle_events(); + interruptible_sleep_on(&serio_wait); if (current->flags & PF_FREEZE) refrigerator(PF_IOTHREAD); - interruptible_sleep_on(&serio_wait); } while (!signal_pending(current)); printk(KERN_DEBUG "serio: kseriod exiting"); diff -Nru a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c --- a/drivers/isdn/capi/capi.c Thu Aug 1 14:17:41 2002 +++ b/drivers/isdn/capi/capi.c Thu Aug 1 14:17:41 2002 @@ -1485,7 +1485,7 @@ } else strcpy(rev, "1.0"); - if (devfs_register_chrdev(capi_major, "capi20", &capi_fops)) { + if (register_chrdev(capi_major, "capi20", &capi_fops)) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); MOD_DEC_USE_COUNT; return -EIO; @@ -1498,7 +1498,7 @@ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE if (capinc_tty_init() < 0) { - devfs_unregister_chrdev(capi_major, "capi20"); + unregister_chrdev(capi_major, "capi20"); MOD_DEC_USE_COUNT; return -ENOMEM; } @@ -1526,8 +1526,8 @@ { proc_exit(); - devfs_unregister_chrdev(capi_major, "capi20"); - devfs_unregister(devfs_find_handle(NULL, "isdn/capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0)); + unregister_chrdev(capi_major, "capi20"); + devfs_find_and_unregister(NULL, "isdn/capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE capinc_tty_exit(); diff -Nru a/drivers/isdn/hisax/Config.in b/drivers/isdn/hisax/Config.in --- a/drivers/isdn/hisax/Config.in Thu Aug 1 14:17:36 2002 +++ b/drivers/isdn/hisax/Config.in Thu Aug 1 14:17:36 2002 @@ -43,9 +43,9 @@ bool ' HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then # bool ' TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU - bool ' Formula-n enter:now PCI card' CONFIG_HISAX_ENTERNOW_PCI + bool ' Formula-n enter:now PCI card (EXPERIMENTAL)' CONFIG_HISAX_ENTERNOW_PCI if [ "$CONFIG_SPARC32" = "y" -o "$CONFIG_SPARC64" = "y" ]; then - bool ' Am7930' CONFIG_HISAX_AMD7930 + bool ' Am7930 (EXPERIMENTAL)' CONFIG_HISAX_AMD7930 fi fi bool ' HiSax debugging' CONFIG_HISAX_DEBUG diff -Nru a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c --- a/drivers/isdn/hysdn/boardergo.c Thu Aug 1 14:17:40 2002 +++ b/drivers/isdn/hysdn/boardergo.c Thu Aug 1 14:17:40 2002 @@ -424,16 +424,19 @@ int ergo_inithardware(hysdn_card * card) { - if (check_region(card->iobase + PCI9050_INTR_REG, 1) || - check_region(card->iobase + PCI9050_USER_IO, 1)) + if (!request_region(card->iobase + PCI9050_INTR_REG, 1, "HYSDN")) + return (-1); + if (!request_region(card->iobase + PCI9050_USER_IO, 1, "HYSDN")) { + release_region(card->iobase + PCI9050_INTR_REG, 1); return (-1); /* ports already in use */ - + } card->memend = card->membase + ERG_DPRAM_PAGE_SIZE - 1; - if (!(card->dpram = ioremap(card->membase, ERG_DPRAM_PAGE_SIZE))) + if (!(card->dpram = ioremap(card->membase, ERG_DPRAM_PAGE_SIZE))) { + release_region(card->iobase + PCI9050_INTR_REG, 1); + release_region(card->iobase + PCI9050_USER_IO, 1); return (-1); + } - request_region(card->iobase + PCI9050_INTR_REG, 1, "HYSDN"); - request_region(card->iobase + PCI9050_USER_IO, 1, "HYSDN"); ergo_stopcard(card); /* disable interrupts */ if (request_irq(card->irq, ergo_interrupt, SA_SHIRQ, "HYSDN", card)) { ergo_releasehardware(card); /* return the acquired hardware */ diff -Nru a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c --- a/drivers/isdn/i4l/isdn_common.c Thu Aug 1 14:17:40 2002 +++ b/drivers/isdn/i4l/isdn_common.c Thu Aug 1 14:17:40 2002 @@ -2266,7 +2266,7 @@ init_waitqueue_head(&dev->mdm.info[i].open_wait); init_waitqueue_head(&dev->mdm.info[i].close_wait); } - if (devfs_register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) { + if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) { printk(KERN_WARNING "isdn: Could not register control devices\n"); vfree(dev); return -EIO; @@ -2280,7 +2280,7 @@ tty_unregister_driver(&dev->mdm.tty_modem); vfree(dev); isdn_cleanup_devfs(); - devfs_unregister_chrdev(ISDN_MAJOR, "isdn"); + unregister_chrdev(ISDN_MAJOR, "isdn"); return -EIO; } #ifdef CONFIG_ISDN_PPP @@ -2291,7 +2291,7 @@ for (i = 0; i < ISDN_MAX_CHANNELS; i++) kfree(dev->mdm.info[i].xmit_buf - 4); isdn_cleanup_devfs(); - devfs_unregister_chrdev(ISDN_MAJOR, "isdn"); + unregister_chrdev(ISDN_MAJOR, "isdn"); vfree(dev); return -EIO; } @@ -2354,7 +2354,7 @@ kfree(dev->mdm.info[i].fax); #endif } - if (devfs_unregister_chrdev(ISDN_MAJOR, "isdn") != 0) { + if (unregister_chrdev(ISDN_MAJOR, "isdn") != 0) { printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n"); restore_flags(flags); } else { diff -Nru a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile --- a/drivers/macintosh/Makefile Thu Aug 1 14:17:40 2002 +++ b/drivers/macintosh/Makefile Thu Aug 1 14:17:40 2002 @@ -4,7 +4,7 @@ # Objects that export symbols. -export-objs := adb.o rtc.o mac_hid.o via-pmu.o +export-objs := adb.o mac_hid.o via-pmu.o # Object file lists. diff -Nru a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c --- a/drivers/macintosh/adb.c Thu Aug 1 14:17:40 2002 +++ b/drivers/macintosh/adb.c Thu Aug 1 14:17:40 2002 @@ -815,7 +815,7 @@ static void adbdev_init(void) { - if (devfs_register_chrdev(ADB_MAJOR, "adb", &adb_fops)) + if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR); else devfs_register (NULL, "adb", DEVFS_FL_DEFAULT, diff -Nru a/drivers/md/lvm.c b/drivers/md/lvm.c --- a/drivers/md/lvm.c Thu Aug 1 14:17:40 2002 +++ b/drivers/md/lvm.c Thu Aug 1 14:17:40 2002 @@ -213,7 +213,6 @@ #include #include #include -#include #include #include #include @@ -388,19 +387,18 @@ */ int lvm_init(void) { - if (devfs_register_chrdev(LVM_CHAR_MAJOR, + if (register_chrdev(LVM_CHAR_MAJOR, lvm_name, &lvm_chr_fops) < 0) { - printk(KERN_ERR "%s -- devfs_register_chrdev failed\n", + printk(KERN_ERR "%s -- register_chrdev failed\n", lvm_name); return -EIO; } - if (devfs_register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0) - { - printk("%s -- devfs_register_blkdev failed\n", lvm_name); - if (devfs_unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) + if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0) { + printk("%s -- register_blkdev failed\n", lvm_name); + if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) printk(KERN_ERR - "%s -- devfs_unregister_chrdev failed\n", + "%s -- unregister_chrdev failed\n", lvm_name); return -EIO; } @@ -442,11 +440,11 @@ */ static void lvm_cleanup(void) { - if (devfs_unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) - printk(KERN_ERR "%s -- devfs_unregister_chrdev failed\n", + if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) + printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name); - if (devfs_unregister_blkdev(MAJOR_NR, lvm_name) < 0) - printk(KERN_ERR "%s -- devfs_unregister_blkdev failed\n", + if (unregister_blkdev(MAJOR_NR, lvm_name) < 0) + printk(KERN_ERR "%s -- unregister_blkdev failed\n", lvm_name); del_gendisk(&lvm_gendisk); diff -Nru a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c Thu Aug 1 14:17:39 2002 +++ b/drivers/md/md.c Thu Aug 1 14:17:39 2002 @@ -122,7 +122,6 @@ .major_name = "md", .minor_shift = 0, .part = md_hd_struct, - .sizes = md_size, .nr_real = MAX_MD_DEVS, .next = NULL, .fops = &md_fops, @@ -3177,7 +3176,6 @@ for(i = 0; i < MAX_MD_DEVS; i++) { md_size[i] = 0; } - blk_size[MAJOR_NR] = md_size; dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t)); @@ -3207,8 +3205,7 @@ MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS); - if (devfs_register_blkdev (MAJOR_NR, "md", &md_fops)) - { + if (register_blkdev (MAJOR_NR, "md", &md_fops)) { printk(KERN_ALERT "md: Unable to get major %d for md\n", MAJOR_NR); return (-1); } @@ -3412,12 +3409,13 @@ *p++ = 0; dev = name_to_kdev_t(devname); - handle = devfs_find_handle(NULL, devname, major(dev), minor(dev), - DEVFS_SPECIAL_BLK, 1); + handle = devfs_get_handle(NULL, devname, major(dev), minor(dev), + DEVFS_SPECIAL_BLK, 1); if (handle != 0) { unsigned major, minor; devfs_get_maj_min(handle, &major, &minor); dev = mk_kdev(major, minor); + devfs_put(handle); } if (kdev_none(dev)) { printk(KERN_WARNING "md: Unknown device name: %s\n", devname); @@ -3567,7 +3565,7 @@ md_unregister_thread(md_recovery_thread); devfs_unregister(devfs_handle); - devfs_unregister_blkdev(MAJOR_NR,"md"); + unregister_blkdev(MAJOR_NR,"md"); unregister_reboot_notifier(&md_notifier); unregister_sysctl_table(raid_table_header); #ifdef CONFIG_PROC_FS diff -Nru a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c --- a/drivers/media/video/videodev.c Thu Aug 1 14:17:36 2002 +++ b/drivers/media/video/videodev.c Thu Aug 1 14:17:36 2002 @@ -484,8 +484,7 @@ static int __init videodev_init(void) { printk(KERN_INFO "Linux video capture interface: v1.00\n"); - if(devfs_register_chrdev(VIDEO_MAJOR,"video_capture", &video_fops)) - { + if (register_chrdev(VIDEO_MAJOR,"video_capture", &video_fops)) { printk("video_dev: unable to get major %d\n", VIDEO_MAJOR); return -EIO; } @@ -502,7 +501,7 @@ #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) videodev_proc_destroy (); #endif - devfs_unregister_chrdev(VIDEO_MAJOR, "video_capture"); + unregister_chrdev(VIDEO_MAJOR, "video_capture"); } module_init(videodev_init) diff -Nru a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile --- a/drivers/message/fusion/Makefile Thu Aug 1 14:17:41 2002 +++ b/drivers/message/fusion/Makefile Thu Aug 1 14:17:41 2002 @@ -43,7 +43,7 @@ #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC -export-objs := mptbase.o mptscsih.o mptlan.o mptctl.o isense.o +export-objs := mptbase.o obj-$(CONFIG_FUSION) += mptbase.o mptscsih.o obj-$(CONFIG_FUSION_ISENSE) += isense.o diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c --- a/drivers/message/i2o/i2o_block.c Thu Aug 1 14:17:41 2002 +++ b/drivers/message/i2o/i2o_block.c Thu Aug 1 14:17:41 2002 @@ -124,7 +124,6 @@ * Some of these can be made smaller later */ -static int i2ob_sizes[MAX_I2OB<<4]; static int i2ob_media_change_flag[MAX_I2OB]; static int i2ob_context; @@ -731,7 +730,6 @@ { for(i = unit; i <= unit+15; i++) { - i2ob_sizes[i] = 0; blk_queue_max_sectors(i2ob_dev[i].req_queue, 0); i2ob[i].nr_sects = 0; i2ob_gendisk.part[i].nr_sects = 0; @@ -767,7 +765,6 @@ i2ob_query_device(&i2ob_dev[unit], 0x0000, 4, &size, 8); spin_lock_irqsave(&I2O_LOCK(unit), flags); - i2ob_sizes[unit] = (int)(size>>10); i2ob_gendisk.part[unit].nr_sects = size>>9; i2ob[unit].nr_sects = (int)(size>>9); spin_unlock_irqrestore(&I2O_LOCK(unit), flags); @@ -1081,7 +1078,7 @@ { struct hd_geometry g; int u = minor(inode->i_rdev) & 0xF0; - i2o_block_biosparam(i2ob_sizes[u]<<1, + i2o_block_biosparam(i2ob[u].nr_sects, &g.cylinders, &g.heads, &g.sectors); g.start = get_start_sect(inode->i_bdev); return copy_to_user((void *)arg, &g, sizeof(g)) @@ -1268,7 +1265,6 @@ i2ob_query_device(dev, 0x0000, 5, &flags, 4); i2ob_query_device(dev, 0x0000, 6, &status, 4); - i2ob_sizes[unit] = (int)(size>>10); i2ob_gendisk.part[unit].nr_sects = size>>9; i2ob[unit].nr_sects = (int)(size>>9); @@ -1655,7 +1651,6 @@ for(i = unit; i <= unit+15; i++) { i2ob_dev[i].i2odev = NULL; - i2ob_sizes[i] = 0; blk_queue_max_sectors(i2ob_dev[i].req_queue, 0); i2ob[i].nr_sects = 0; i2ob_gendisk.part[i].nr_sects = 0; @@ -1762,7 +1757,6 @@ major_name: "i2o/hd", minor_shift: 4, part: i2ob, - sizes: i2ob_sizes, nr_real: MAX_I2OB, fops: &i2ob_fops, }; diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c --- a/drivers/mtd/ftl.c Thu Aug 1 14:17:39 2002 +++ b/drivers/mtd/ftl.c Thu Aug 1 14:17:39 2002 @@ -175,14 +175,12 @@ #define XFER_FAILED 0x04 static struct hd_struct ftl_hd[MINOR_NR(MAX_DEV, 0, 0)]; -static int ftl_sizes[MINOR_NR(MAX_DEV, 0, 0)]; static struct gendisk ftl_gendisk = { major: FTL_MAJOR, major_name: "ftl", minor_shift: PART_BITS, part: ftl_hd, - sizes: ftl_sizes, }; /*====================================================================*/ diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c --- a/drivers/mtd/mtdblock.c Thu Aug 1 14:17:40 2002 +++ b/drivers/mtd/mtdblock.c Thu Aug 1 14:17:40 2002 @@ -593,22 +593,14 @@ int i; spin_lock_init(&mtdblks_lock); -#ifdef CONFIG_DEVFS_FS - if (devfs_register_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME, &mtd_fops)) - { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_BLOCK_MAJOR); - return -EAGAIN; - } - - devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL); - register_mtd_user(¬ifier); -#else if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", MTD_BLOCK_MAJOR); return -EAGAIN; } +#ifdef CONFIG_DEVFS_FS + devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL); + register_mtd_user(¬ifier); #endif /* We fill it in at open() time. */ @@ -630,10 +622,8 @@ #ifdef CONFIG_DEVFS_FS unregister_mtd_user(¬ifier); devfs_unregister(devfs_dir_handle); - devfs_unregister_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME); -#else - unregister_blkdev(MAJOR_NR,DEVICE_NAME); #endif + unregister_blkdev(MAJOR_NR,DEVICE_NAME); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_size[MAJOR_NR] = NULL; } diff -Nru a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c --- a/drivers/mtd/mtdchar.c Thu Aug 1 14:17:41 2002 +++ b/drivers/mtd/mtdchar.c Thu Aug 1 14:17:41 2002 @@ -494,26 +494,17 @@ static int __init init_mtdchar(void) { -#ifdef CONFIG_DEVFS_FS - if (devfs_register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) - { + if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) { printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", MTD_CHAR_MAJOR); return -EAGAIN; } +#ifdef CONFIG_DEVFS_FS devfs_dir_handle = devfs_mk_dir(NULL, "mtd", NULL); register_mtd_user(¬ifier); -#else - if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) - { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_CHAR_MAJOR); - return -EAGAIN; - } #endif - return 0; } @@ -522,10 +513,8 @@ #ifdef CONFIG_DEVFS_FS unregister_mtd_user(¬ifier); devfs_unregister(devfs_dir_handle); - devfs_unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); -#else - unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); #endif + unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); } module_init(init_mtdchar); diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c --- a/drivers/mtd/nftlcore.c Thu Aug 1 14:17:36 2002 +++ b/drivers/mtd/nftlcore.c Thu Aug 1 14:17:36 2002 @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef CONFIG_KMOD #include @@ -52,17 +53,16 @@ * encountered, except ... */ -static int nftl_sizes[256]; - /* .. for the Linux partition table handling. */ +/* So why didn't you fucking go and clean it up? -- AV */ struct hd_struct part_table[256]; +static struct block_device_operations nftl_fops; static struct gendisk nftl_gendisk = { major: MAJOR_NR, major_name: "nftl", minor_shift: NFTL_PARTN_BITS, /* # of partition bits */ part: part_table, /* hd struct */ - sizes: nftl_sizes, /* block sizes */ }; struct NFTLrecord *NFTLs[MAX_NFTLS]; @@ -143,7 +143,6 @@ } NFTLs[firstfree] = nftl; /* Finally, set up the block device sizes */ - nftl_sizes[firstfree * 16] = nftl->nr_sects; part_table[firstfree * 16].nr_sects = nftl->nr_sects; nftl_gendisk.nr_real++; diff -Nru a/drivers/net/8139cp.c b/drivers/net/8139cp.c --- a/drivers/net/8139cp.c Thu Aug 1 14:17:40 2002 +++ b/drivers/net/8139cp.c Thu Aug 1 14:17:40 2002 @@ -18,7 +18,7 @@ See the file COPYING in this distribution for more information. - Contribuitors: + Contributors: Wake-on-LAN support - Felipe Damasio diff -Nru a/drivers/net/Config.in b/drivers/net/Config.in --- a/drivers/net/Config.in Thu Aug 1 14:17:36 2002 +++ b/drivers/net/Config.in Thu Aug 1 14:17:36 2002 @@ -273,7 +273,7 @@ dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP fi if [ ! "$CONFIG_ATM" = "n" ]; then - dep_tristate ' PPP over ATM (EXPERIMENTAL)' CONFIG_PPPOATM $CONFIG_PPP + dep_tristate ' PPP over ATM' CONFIG_PPPOATM $CONFIG_PPP fi fi diff -Nru a/drivers/net/Makefile.lib b/drivers/net/Makefile.lib --- a/drivers/net/Makefile.lib Thu Aug 1 14:17:41 2002 +++ b/drivers/net/Makefile.lib Thu Aug 1 14:17:41 2002 @@ -25,7 +25,7 @@ obj-$(CONFIG_PCNET32) += crc32.o obj-$(CONFIG_SIS900) += crc32.o obj-$(CONFIG_SMC9194) += crc32.o -obj-$(CONFIG_STARFIRE) += crc32.o +obj-$(CONFIG_ADAPTEC_STARFIRE) += crc32.o obj-$(CONFIG_SUNBMAC) += crc32.o obj-$(CONFIG_SUNDANCE) += crc32.o obj-$(CONFIG_SUNGEM) += crc32.o diff -Nru a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c --- a/drivers/net/au1000_eth.c Thu Aug 1 14:17:36 2002 +++ b/drivers/net/au1000_eth.c Thu Aug 1 14:17:36 2002 @@ -819,9 +819,9 @@ MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS)); if (dev->priv != NULL) kfree(dev->priv); - kfree(dev); printk(KERN_ERR "%s: au1000_probe1 failed. Returns %d\n", dev->name, retval); + kfree(dev); return retval; } diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c --- a/drivers/net/e1000/e1000_main.c Thu Aug 1 14:17:40 2002 +++ b/drivers/net/e1000/e1000_main.c Thu Aug 1 14:17:40 2002 @@ -1699,7 +1699,7 @@ { atomic_inc(&adapter->irq_sem); E1000_WRITE_REG(&adapter->hw, IMC, ~0); - synchronize_irq(); + synchronize_irq(adapter->netdev->irq); } /** diff -Nru a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c --- a/drivers/net/hamradio/baycom_ser_hdx.c Thu Aug 1 14:17:36 2002 +++ b/drivers/net/hamradio/baycom_ser_hdx.c Thu Aug 1 14:17:36 2002 @@ -476,19 +476,22 @@ if (!dev->base_addr || dev->base_addr > 0x1000-SER12_EXTENT || dev->irq < 2 || dev->irq > 15) return -ENXIO; - if (check_region(dev->base_addr, SER12_EXTENT)) + if (!request_region(dev->base_addr, SER12_EXTENT, "baycom_ser12")) return -EACCES; memset(&bc->modem, 0, sizeof(bc->modem)); bc->hdrv.par.bitrate = 1200; - if ((u = ser12_check_uart(dev->base_addr)) == c_uart_unknown) + if ((u = ser12_check_uart(dev->base_addr)) == c_uart_unknown) { + release_region(dev->base_addr, SER12_EXTENT); return -EIO; + } outb(0, FCR(dev->base_addr)); /* disable FIFOs */ outb(0x0d, MCR(dev->base_addr)); outb(0, IER(dev->base_addr)); if (request_irq(dev->irq, ser12_interrupt, SA_INTERRUPT | SA_SHIRQ, - "baycom_ser12", dev)) + "baycom_ser12", dev)) { + release_region(dev->base_addr, SER12_EXTENT); return -EBUSY; - request_region(dev->base_addr, SER12_EXTENT, "baycom_ser12"); + } /* * enable transmitter empty interrupt */ diff -Nru a/drivers/net/irda/Config.in b/drivers/net/irda/Config.in --- a/drivers/net/irda/Config.in Thu Aug 1 14:17:41 2002 +++ b/drivers/net/irda/Config.in Thu Aug 1 14:17:41 2002 @@ -19,20 +19,20 @@ dep_tristate ' EP7211 I/R support' CONFIG_EP7211_IR $CONFIG_IRDA fi if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - dep_tristate ' ACTiSYS IR-200L dongle (Experimental)' CONFIG_ACT200L_DONGLE $CONFIG_IRDA - dep_tristate ' Mobile Action MA600 dongle (Experimental)' CONFIG_MA600_DONGLE $CONFIG_IRDA + dep_tristate ' ACTiSYS IR-200L dongle (EXPERIMENTAL)' CONFIG_ACT200L_DONGLE $CONFIG_IRDA + dep_tristate ' Mobile Action MA600 dongle (EXPERIMENTAL)' CONFIG_MA600_DONGLE $CONFIG_IRDA fi fi comment 'FIR device drivers' -dep_tristate 'IrDA USB dongles (Experimental)' CONFIG_USB_IRDA $CONFIG_IRDA $CONFIG_USB $CONFIG_EXPERIMENTAL +dep_tristate 'IrDA USB dongles (EXPERIMENTAL)' CONFIG_USB_IRDA $CONFIG_IRDA $CONFIG_USB $CONFIG_EXPERIMENTAL dep_tristate 'NSC PC87108/PC87338' CONFIG_NSC_FIR $CONFIG_IRDA dep_tristate 'Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA dep_tristate 'Toshiba Type-O IR Port' CONFIG_TOSHIBA_FIR $CONFIG_IRDA if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then -dep_tristate 'SMC IrCC (Experimental)' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA -dep_tristate 'ALi M5123 FIR (Experimental)' CONFIG_ALI_FIR $CONFIG_IRDA -dep_tristate 'VLSI 82C147 SIR/MIR/FIR (Experimental)' CONFIG_VLSI_FIR $CONFIG_IRDA +dep_tristate 'SMC IrCC (EXPERIMENTAL)' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA +dep_tristate 'ALi M5123 FIR (EXPERIMENTAL)' CONFIG_ALI_FIR $CONFIG_IRDA +dep_tristate 'VLSI 82C147 SIR/MIR/FIR (EXPERIMENTAL)' CONFIG_VLSI_FIR $CONFIG_IRDA fi if [ "$CONFIG_ARCH_SA1100" = "y" ]; then dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c --- a/drivers/net/ppp_generic.c Thu Aug 1 14:17:41 2002 +++ b/drivers/net/ppp_generic.c Thu Aug 1 14:17:41 2002 @@ -785,7 +785,7 @@ int err; printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n"); - err = devfs_register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops); + err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops); if (err) printk(KERN_ERR "failed to register PPP device (%d)\n", err); devfs_handle = devfs_register(NULL, "ppp", DEVFS_FL_DEFAULT, @@ -2509,7 +2509,7 @@ if (atomic_read(&ppp_unit_count) || atomic_read(&channel_count)) printk(KERN_ERR "PPP: removing module but units remain!\n"); cardmap_destroy(&all_ppp_units); - if (devfs_unregister_chrdev(PPP_MAJOR, "ppp") != 0) + if (unregister_chrdev(PPP_MAJOR, "ppp") != 0) printk(KERN_ERR "PPP: failed to unregister PPP device\n"); devfs_unregister(devfs_handle); } diff -Nru a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile --- a/drivers/net/wan/Makefile Thu Aug 1 14:17:36 2002 +++ b/drivers/net/wan/Makefile Thu Aug 1 14:17:36 2002 @@ -6,7 +6,7 @@ # export-objs := z85230.o syncppp.o comx.o sdladrv.o cycx_drv.o hdlc_generic.o \ - dlci.o pc300_drv.o + dlci.o wanpipe-y := sdlamain.o sdla_ft1.o wanpipe-$(CONFIG_WANPIPE_X25) += sdla_x25.o diff -Nru a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c --- a/drivers/net/wan/cosa.c Thu Aug 1 14:17:36 2002 +++ b/drivers/net/wan/cosa.c Thu Aug 1 14:17:36 2002 @@ -373,13 +373,13 @@ printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n"); #endif if (cosa_major > 0) { - if (devfs_register_chrdev(cosa_major, "cosa", &cosa_fops)) { + if (register_chrdev(cosa_major, "cosa", &cosa_fops)) { printk(KERN_WARNING "cosa: unable to get major %d\n", cosa_major); return -EIO; } } else { - if (!(cosa_major=devfs_register_chrdev(0, "cosa", &cosa_fops))) { + if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) { printk(KERN_WARNING "cosa: unable to register chardev\n"); return -EIO; } @@ -395,7 +395,7 @@ &cosa_fops, NULL); if (!nr_cards) { printk(KERN_WARNING "cosa: no devices found.\n"); - devfs_unregister_chrdev(cosa_major, "cosa"); + unregister_chrdev(cosa_major, "cosa"); return -ENODEV; } return 0; @@ -422,7 +422,7 @@ free_dma(cosa->dma); release_region(cosa->datareg,is_8bit(cosa)?2:4); } - devfs_unregister_chrdev(cosa_major, "cosa"); + unregister_chrdev(cosa_major, "cosa"); } #endif diff -Nru a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c --- a/drivers/net/wan/sdla_chdlc.c Thu Aug 1 14:17:40 2002 +++ b/drivers/net/wan/sdla_chdlc.c Thu Aug 1 14:17:40 2002 @@ -2852,7 +2852,7 @@ #endif if(err) { printk(KERN_INFO - "%s: Remove route %s failed, (err %d)\n", + "%s: Remove route %u.%u.%u.%u failed, (err %d)\n", card->devname, NIPQUAD(remote_IP_addr), err); } else { diff -Nru a/drivers/parport/share.c b/drivers/parport/share.c --- a/drivers/parport/share.c Thu Aug 1 14:17:40 2002 +++ b/drivers/parport/share.c Thu Aug 1 14:17:40 2002 @@ -1002,7 +1002,6 @@ /* Try to claim the port. If this fails, we need to sleep. */ r = parport_claim(dev); if (r == -EAGAIN) { - unsigned long flags; #ifdef PARPORT_DEBUG_SHARING printk(KERN_DEBUG "%s: parport_claim() returned -EAGAIN\n", dev->name); #endif diff -Nru a/drivers/pci/access.c b/drivers/pci/access.c --- a/drivers/pci/access.c Thu Aug 1 14:17:41 2002 +++ b/drivers/pci/access.c Thu Aug 1 14:17:41 2002 @@ -7,7 +7,7 @@ * configuration space. */ -static spinlock_t pci_lock = SPIN_LOCK_UNLOCKED; +spinlock_t pci_lock = SPIN_LOCK_UNLOCKED; /* * Wrappers for all PCI configuration access functions. They just check @@ -44,3 +44,4 @@ EXPORT_SYMBOL(pci_write_config_byte); EXPORT_SYMBOL(pci_write_config_word); EXPORT_SYMBOL(pci_write_config_dword); +EXPORT_SYMBOL(pci_lock); diff -Nru a/drivers/pci/proc.c b/drivers/pci/proc.c --- a/drivers/pci/proc.c Thu Aug 1 14:17:36 2002 +++ b/drivers/pci/proc.c Thu Aug 1 14:17:36 2002 @@ -378,11 +378,7 @@ return off ? 0 : sprintf(buf,"%u\n",pci_dev->irq); } -static struct driver_file_entry pci_irq_entry = { - name: "irq", - mode: S_IRUGO, - show: pci_show_irq, -}; +static DEVICE_ATTR(irq,"irq",S_IRUGO,pci_show_irq,NULL); static ssize_t pci_show_resources(struct device * dev, char * buf, size_t count, loff_t off) { @@ -406,11 +402,7 @@ return (str - buf); } -static struct driver_file_entry pci_resource_entry = { - name: "resources", - mode: S_IRUGO, - show: pci_show_resources, -}; +static DEVICE_ATTR(resource,"resource",S_IRUGO,pci_show_resources,NULL); int pci_proc_attach_device(struct pci_dev *dev) { @@ -432,8 +424,8 @@ e->data = dev; e->size = PCI_CFG_SPACE_SIZE; - device_create_file(&dev->dev,&pci_irq_entry); - device_create_file(&dev->dev,&pci_resource_entry); + device_create_file(&dev->dev,&dev_attr_irq); + device_create_file(&dev->dev,&dev_attr_resource); return 0; } diff -Nru a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile --- a/drivers/pcmcia/Makefile Thu Aug 1 14:17:39 2002 +++ b/drivers/pcmcia/Makefile Thu Aug 1 14:17:39 2002 @@ -2,7 +2,7 @@ # Makefile for the kernel pcmcia subsystem (c/o David Hinds) # -export-objs := ds.o cs.o yenta.o pci_socket.o +export-objs := ds.o cs.o yenta.o obj-$(CONFIG_PCMCIA) += pcmcia_core.o ds.o ifeq ($(CONFIG_CARDBUS),y) diff -Nru a/drivers/pnp/pnpbios_core.c b/drivers/pnp/pnpbios_core.c --- a/drivers/pnp/pnpbios_core.c Thu Aug 1 14:17:36 2002 +++ b/drivers/pnp/pnpbios_core.c Thu Aug 1 14:17:36 2002 @@ -124,13 +124,13 @@ ".previous \n" ); -#define Q_SET_SEL(selname, address, size) \ -set_base (gdt [(selname) >> 3], __va((u32)(address))); \ -set_limit (gdt [(selname) >> 3], size) - -#define Q2_SET_SEL(selname, address, size) \ -set_base (gdt [(selname) >> 3], (u32)(address)); \ -set_limit (gdt [(selname) >> 3], size) +#define Q_SET_SEL(cpu, selname, address, size) \ +set_base(cpu_gdt_table[cpu][(selname) >> 3], __va((u32)(address))); \ +_set_limit(&cpu_gdt_table[cpu][(selname) >> 3], size) + +#define Q2_SET_SEL(cpu, selname, address, size) \ +set_base(cpu_gdt_table[cpu][(selname) >> 3], (u32)(address)); \ +_set_limit((char *)&cpu_gdt_table[cpu][(selname) >> 3], size) /* * At some point we want to use this stack frame pointer to unwind @@ -161,10 +161,11 @@ /* On some boxes IRQ's during PnP BIOS calls are deadly. */ spin_lock_irqsave(&pnp_bios_lock, flags); + /* The lock prevents us bouncing CPU here */ if (ts1_size) - Q2_SET_SEL(PNP_TS1, ts1_base, ts1_size); + Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size); if (ts2_size) - Q2_SET_SEL(PNP_TS2, ts2_base, ts2_size); + Q2_SET_SEL(smp_processor_id(), PNP_TS2, ts2_base, ts2_size); __asm__ __volatile__( "pushl %%ebp\n\t" @@ -1265,12 +1266,16 @@ check->fields.version >> 4, check->fields.version & 15, check->fields.pm16cseg, check->fields.pm16offset, check->fields.pm16dseg); - Q2_SET_SEL(PNP_CS32, &pnp_bios_callfunc, 64 * 1024); - Q_SET_SEL(PNP_CS16, check->fields.pm16cseg, 64 * 1024); - Q_SET_SEL(PNP_DS, check->fields.pm16dseg, 64 * 1024); pnp_bios_callpoint.offset = check->fields.pm16offset; pnp_bios_callpoint.segment = PNP_CS16; pnp_bios_hdr = check; + + for(i=0; i < NR_CPUS; i++) + { + Q2_SET_SEL(i, PNP_CS32, &pnp_bios_callfunc, 64 * 1024); + Q_SET_SEL(i, PNP_CS16, check->fields.pm16cseg, 64 * 1024); + Q_SET_SEL(i, PNP_DS, check->fields.pm16dseg, 64 * 1024); + } break; } if (!pnp_bios_present()) diff -Nru a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c --- a/drivers/s390/block/dasd_genhd.c Thu Aug 1 14:17:41 2002 +++ b/drivers/s390/block/dasd_genhd.c Thu Aug 1 14:17:41 2002 @@ -66,7 +66,6 @@ struct major_info *mi; struct hd_struct *gd_part; devfs_handle_t *gd_de_arr; - int *gd_sizes; char *gd_flags; int new_major, rc; @@ -79,11 +78,10 @@ GFP_KERNEL); gd_flags = kmalloc(DASD_PER_MAJOR * sizeof(char), GFP_KERNEL); gd_part = kmalloc(sizeof (struct hd_struct) << MINORBITS, GFP_ATOMIC); - gd_sizes = kmalloc(sizeof(int) << MINORBITS, GFP_ATOMIC); /* Check if one of the allocations failed. */ if (mi == NULL || gd_de_arr == NULL || gd_flags == NULL || - gd_part == NULL || gd_sizes == NULL) { + gd_part == NULL) { MESSAGE(KERN_WARNING, "%s", "Cannot get memory to allocate another " "major number"); @@ -92,8 +90,7 @@ } /* Register block device. */ - new_major = devfs_register_blkdev(major, "dasd", - &dasd_device_operations); + new_major = register_blkdev(major, "dasd", &dasd_device_operations); if (new_major < 0) { MESSAGE(KERN_WARNING, "Cannot register to major no %d, rc = %d", major, rc); @@ -113,17 +110,14 @@ mi->gendisk.de_arr = gd_de_arr; mi->gendisk.flags = gd_flags; mi->gendisk.part = gd_part; - mi->gendisk.sizes = gd_sizes; /* Initialize the gendisk arrays. */ memset(gd_de_arr, 0, DASD_PER_MAJOR * sizeof(devfs_handle_t)); memset(gd_flags, 0, DASD_PER_MAJOR * sizeof (char)); memset(gd_part, 0, sizeof (struct hd_struct) << MINORBITS); - memset(gd_sizes, 0, sizeof(int) << MINORBITS); /* Setup block device pointers for the new major. */ blk_dev[new_major].queue = dasd_get_queue; - blk_size[new_major] = gd_sizes; /* Insert the new major info structure into dasd_major_info list. */ spin_lock(&dasd_major_lock); @@ -137,7 +131,6 @@ /* Something failed. Do the cleanup and return rc. */ out_error: /* We rely on kfree to do the != NULL check. */ - kfree(gd_sizes); kfree(gd_part); kfree(gd_flags); kfree(gd_de_arr); @@ -148,7 +141,6 @@ static void dasd_unregister_major(struct major_info * mi) { - int *bs; int major, rc; if (mi == NULL) @@ -165,17 +157,15 @@ /* Clear block device pointers. */ major = mi->gendisk.major; blk_dev[major].queue = NULL; - bs = blk_size[major]; blk_clear(major); - rc = devfs_unregister_blkdev(major, "dasd"); + rc = unregister_blkdev(major, "dasd"); if (rc < 0) MESSAGE(KERN_WARNING, "Cannot unregister from major no %d, rc = %d", major, rc); /* Free memory. */ - kfree(bs); kfree(mi->gendisk.part); kfree(mi->gendisk.flags); kfree(mi->gendisk.de_arr); @@ -340,11 +330,6 @@ return; wipe_partitions(device->kdev); - - /* FIXME: do we really need that */ - minor = minor(device->kdev); - for (i = 0; i < (1 << DASD_PARTN_BITS); i++) - gdp->sizes[minor + i] = 0; /* * This is confusing. The funcions is devfs_register_partitions diff -Nru a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c --- a/drivers/s390/block/dasd_ioctl.c Thu Aug 1 14:17:36 2002 +++ b/drivers/s390/block/dasd_ioctl.c Thu Aug 1 14:17:36 2002 @@ -448,40 +448,6 @@ } /* - * Return device size in number of sectors. - */ -static int dasd_ioctl_blkgetsize(void *inp, int no, long args) -{ - struct gendisk *gdp; - kdev_t kdev; - long blocks; - - kdev = ((struct inode *) inp)->i_rdev; - gdp = dasd_gendisk_from_major(major(kdev)); - if (gdp == NULL) - return -EINVAL; - blocks = gdp->sizes[minor(kdev)] << 1; - return put_user(blocks, (long *) args); -} - -/* - * Return device size in number of sectors, 64bit version. - */ -static int dasd_ioctl_blkgetsize64(void *inp, int no, long args) -{ - struct gendisk *gdp; - kdev_t kdev; - u64 blocks; - - kdev = ((struct inode *) inp)->i_rdev; - gdp = dasd_gendisk_from_major(major(kdev)); - if (gdp == NULL) - return -EINVAL; - blocks = gdp->sizes[minor(kdev)] << 1; - return put_user(blocks << 10, (u64 *) args); -} - -/* * Reread partition table. */ static int dasd_ioctl_rr_partition(void *inp, int no, long args) @@ -549,8 +515,6 @@ { BIODASDINFO2, dasd_ioctl_information }, { BIODASDPRRD, dasd_ioctl_read_profile }, { BIODASDPRRST, dasd_ioctl_reset_profile }, - { BLKGETSIZE, dasd_ioctl_blkgetsize }, - { BLKGETSIZE64, dasd_ioctl_blkgetsize64 }, { BLKROSET, dasd_ioctl_set_ro }, { BLKRRPART, dasd_ioctl_rr_partition }, { DASDAPIVER, dasd_ioctl_api_version }, diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c --- a/drivers/s390/block/xpram.c Thu Aug 1 14:17:41 2002 +++ b/drivers/s390/block/xpram.c Thu Aug 1 14:17:41 2002 @@ -449,7 +449,7 @@ /* * Register xpram major. */ - rc = devfs_register_blkdev(XPRAM_MAJOR, XPRAM_NAME, &xpram_devops); + rc = register_blkdev(XPRAM_MAJOR, XPRAM_NAME, &xpram_devops); if (rc < 0) { PRINT_ERR("Can't get xpram major %d\n", XPRAM_MAJOR); return rc; @@ -489,7 +489,7 @@ static void __exit xpram_exit(void) { blk_clear(XPRAM_MAJOR); - devfs_unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); + unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); devfs_unregister(xpram_devfs_handle); unregister_sys_device(&xpram_sys_device); } diff -Nru a/drivers/s390/char/tapeblock.c b/drivers/s390/char/tapeblock.c --- a/drivers/s390/char/tapeblock.c Thu Aug 1 14:17:41 2002 +++ b/drivers/s390/char/tapeblock.c Thu Aug 1 14:17:41 2002 @@ -97,11 +97,7 @@ tape_dev_t* td; tape_init(); /* Register the tape major number to the kernel */ -#ifdef CONFIG_DEVFS_FS - result = devfs_register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops); -#else result = register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops); -#endif if (result < 0) { PRINT_WARN(KERN_ERR "tape: can't get major %d for block device\n", tapeblock_major); result=-ENODEV; @@ -149,11 +145,7 @@ out_undo_blk_size: kfree(blk_size[tapeblock_major]); out_undo_bdev: -#ifdef CONFIG_DEVFS_FS - devfs_unregister_blkdev(tapeblock_major, "tBLK"); -#else unregister_blkdev(tapeblock_major, "tBLK"); -#endif result=-ENOMEM; blk_size[tapeblock_major]= hardsect_size[tapeblock_major]= @@ -181,11 +173,7 @@ max_sectors[tapeblock_major]=NULL; } -#ifdef CONFIG_DEVFS_FS - devfs_unregister_blkdev(tapeblock_major, "tBLK"); -#else unregister_blkdev(tapeblock_major, "tBLK"); -#endif out: return; diff -Nru a/drivers/s390/char/tapechar.c b/drivers/s390/char/tapechar.c --- a/drivers/s390/char/tapechar.c Thu Aug 1 14:17:40 2002 +++ b/drivers/s390/char/tapechar.c Thu Aug 1 14:17:40 2002 @@ -128,11 +128,7 @@ tape_init(); /* Register the tape major number to the kernel */ -#ifdef CONFIG_DEVFS_FS - result = devfs_register_chrdev (tapechar_major, "tape", &tape_fops); -#else result = register_chrdev (tapechar_major, "tape", &tape_fops); -#endif if (result < 0) { PRINT_WARN (KERN_ERR "tape: can't get major %d\n", tapechar_major); tape_sprintf_event (tape_dbf_area,3,"c:initfail\n"); @@ -178,11 +174,7 @@ void tapechar_uninit (void) { -#ifdef CONFIG_DEVFS_FS - devfs_unregister_chrdev (tapechar_major, "tape"); -#else unregister_chrdev (tapechar_major, "tape"); -#endif } diff -Nru a/drivers/s390/char/tubfs.c b/drivers/s390/char/tubfs.c --- a/drivers/s390/char/tubfs.c Thu Aug 1 14:17:40 2002 +++ b/drivers/s390/char/tubfs.c Thu Aug 1 14:17:40 2002 @@ -54,18 +54,15 @@ void fs3270_devfs_unregister(tub_t *tubp) { char name[16]; - devfs_handle_t handle; sprintf(name, "tub%.4x", tubp->devno); - handle = devfs_find_handle (fs3270_devfs_dir, name, - IBM_FS3270_MAJOR, tubp->minor, - DEVFS_SPECIAL_CHR, 0); - devfs_unregister (handle); + devfs_find_and_unregister(fs3270_devfs_dir, name, + IBM_FS3270_MAJOR, tubp->minor, + DEVFS_SPECIAL_CHR, 0); sprintf(name, "tty%.4x", tubp->devno); - handle = devfs_find_handle (fs3270_devfs_dir, name, - IBM_TTY3270_MAJOR, tubp->minor, - DEVFS_SPECIAL_CHR, 0); - devfs_unregister(handle); + devfs_find_and_unregister(fs3270_devfs_dir, name, + IBM_TTY3270_MAJOR, tubp->minor, + DEVFS_SPECIAL_CHR, 0); } #endif @@ -77,26 +74,19 @@ { int rc; -#ifdef CONFIG_DEVFS_FS - rc = devfs_register_chrdev (IBM_FS3270_MAJOR, "fs3270", &fs3270_fops); + rc = register_chrdev(IBM_FS3270_MAJOR, "fs3270", &fs3270_fops); if (rc) { printk(KERN_ERR "tubmod can't get major nbr %d: error %d\n", IBM_FS3270_MAJOR, rc); return -1; } +#ifdef CONFIG_DEVFS_FS fs3270_devfs_dir = devfs_mk_dir(NULL, "3270", NULL); fs3270_devfs_tub = devfs_register(fs3270_devfs_dir, "tub", DEVFS_FL_DEFAULT, IBM_FS3270_MAJOR, 0, S_IFCHR | S_IRUGO | S_IWUGO, &fs3270_fops, NULL); -#else - rc = register_chrdev(IBM_FS3270_MAJOR, "fs3270", &fs3270_fops); - if (rc) { - printk(KERN_ERR "tubmod can't get major nbr %d: error %d\n", - IBM_FS3270_MAJOR, rc); - return -1; - } #endif fs3270_major = IBM_FS3270_MAJOR; return 0; diff -Nru a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile --- a/drivers/s390/cio/Makefile Thu Aug 1 14:17:36 2002 +++ b/drivers/s390/cio/Makefile Thu Aug 1 14:17:36 2002 @@ -8,6 +8,6 @@ obj-$(CONFIG_CHSC) += chsc.o obj-$(CONFIG_PROC_FS) += proc.o -export-objs += airq.o cio.o ioinfo.o misc.o requestirq.o s390io.o +export-objs += airq.o cio.o ioinfo.o requestirq.o s390io.o include $(TOPDIR)/Rules.make diff -Nru a/drivers/sbus/audio/audio.c b/drivers/sbus/audio/audio.c --- a/drivers/sbus/audio/audio.c Thu Aug 1 14:17:36 2002 +++ b/drivers/sbus/audio/audio.c Thu Aug 1 14:17:36 2002 @@ -2077,7 +2077,6 @@ int unregister_sparcaudio_driver(struct sparcaudio_driver *drv, int duplex) { - devfs_handle_t de; int i; char name_buf[32]; @@ -2104,9 +2103,8 @@ /* Unregister ourselves with devfs */ for (i=0; i < sizeof (dev_list) / sizeof (*dev_list); i++) { sparcaudio_mkname (name_buf, dev_list[i].name, drv->index); - de = devfs_find_handle (devfs_handle, name_buf, 0, 0, - DEVFS_SPECIAL_CHR, 0); - devfs_unregister (de); + devfs_find_and_unregister(devfs_handle, name_buf, 0, 0, + DEVFS_SPECIAL_CHR, 0); } MOD_DEC_USE_COUNT; @@ -2125,7 +2123,7 @@ static int __init sparcaudio_init(void) { /* Register our character device driver with the VFS. */ - if (devfs_register_chrdev(SOUND_MAJOR, "sparcaudio", &sparcaudio_fops)) + if (register_chrdev(SOUND_MAJOR, "sparcaudio", &sparcaudio_fops)) return -EIO; devfs_handle = devfs_mk_dir (NULL, "sound", NULL); @@ -2134,7 +2132,7 @@ static void __exit sparcaudio_exit(void) { - devfs_unregister_chrdev(SOUND_MAJOR, "sparcaudio"); + unregister_chrdev(SOUND_MAJOR, "sparcaudio"); devfs_unregister (devfs_handle); } diff -Nru a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c --- a/drivers/sbus/char/bpp.c Thu Aug 1 14:17:36 2002 +++ b/drivers/sbus/char/bpp.c Thu Aug 1 14:17:36 2002 @@ -1041,7 +1041,7 @@ if (rc == 0) return -ENODEV; - rc = devfs_register_chrdev(BPP_MAJOR, dev_name, &bpp_fops); + rc = register_chrdev(BPP_MAJOR, dev_name, &bpp_fops); if (rc < 0) return rc; @@ -1062,7 +1062,7 @@ unsigned idx; devfs_unregister (devfs_handle); - devfs_unregister_chrdev(BPP_MAJOR, dev_name); + unregister_chrdev(BPP_MAJOR, dev_name); for (idx = 0 ; idx < BPP_NO ; idx += 1) { if (instances[idx].present) diff -Nru a/drivers/sbus/char/sunkbd.c b/drivers/sbus/char/sunkbd.c --- a/drivers/sbus/char/sunkbd.c Thu Aug 1 14:17:41 2002 +++ b/drivers/sbus/char/sunkbd.c Thu Aug 1 14:17:41 2002 @@ -1615,7 +1615,7 @@ KBD_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &kbd_fops, NULL); - if (devfs_register_chrdev (KBD_MAJOR, "kbd", &kbd_fops)){ + if (register_chrdev (KBD_MAJOR, "kbd", &kbd_fops)){ printk ("Could not register /dev/kbd device\n"); return; } diff -Nru a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c --- a/drivers/sbus/char/vfc_dev.c Thu Aug 1 14:17:40 2002 +++ b/drivers/sbus/char/vfc_dev.c Thu Aug 1 14:17:40 2002 @@ -676,7 +676,7 @@ memset(vfc_dev_lst, 0, sizeof(struct vfc_dev *) * (cards + 1)); vfc_dev_lst[cards] = NULL; - ret = devfs_register_chrdev(VFC_MAJOR, vfcstr, &vfc_fops); + ret = register_chrdev(VFC_MAJOR, vfcstr, &vfc_fops); if(ret) { printk(KERN_ERR "Unable to get major number %d\n", VFC_MAJOR); kfree(vfc_dev_lst); @@ -732,7 +732,7 @@ { struct vfc_dev **devp; - devfs_unregister_chrdev(VFC_MAJOR,vfcstr); + unregister_chrdev(VFC_MAJOR,vfcstr); for (devp = vfc_dev_lst; *devp; devp++) deinit_vfc_device(*devp); diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c --- a/drivers/scsi/ide-scsi.c Thu Aug 1 14:17:36 2002 +++ b/drivers/scsi/ide-scsi.c Thu Aug 1 14:17:36 2002 @@ -1,33 +1,12 @@ /* * Copyright (C) 1996 - 1999 Gadi Oxman - */ -/* + * * Emulation of a SCSI host adapter for IDE ATAPI devices. * * With this driver, one can use the Linux SCSI drivers instead of the * native IDE ATAPI drivers. - * - * Ver 0.1 Dec 3 96 Initial version. - * Ver 0.2 Jan 26 97 Fixed bug in cleanup_module() and added emulation - * of MODE_SENSE_6/MODE_SELECT_6 for cdroms. Thanks - * to Janos Farkas for pointing this out. - * Avoid using bitfields in structures for m68k. - * Added Scatter/Gather and DMA support. - * Ver 0.4 Dec 7 97 Add support for ATAPI PD/CD drives. - * Use variable timeout for each command. - * Ver 0.5 Jan 2 98 Fix previous PD/CD support. - * Allow disabling of SCSI-6 to SCSI-10 transformation. - * Ver 0.6 Jan 27 98 Allow disabling of SCSI command translation layer - * for access through /dev/sg. - * Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation. - * Ver 0.7 Dec 04 98 Ignore commands where lun != 0 to avoid multiple - * detection of devices with CONFIG_SCSI_MULTI_LUN - * Ver 0.8 Feb 05 99 Optical media need translation too. Reverse 0.7. - * Ver 0.9 Jul 04 99 Fix a bug in SG_SET_TRANSFORM. */ -#define IDESCSI_VERSION "0.9" - #include #include #include @@ -495,9 +474,8 @@ static Scsi_Host_Template template; static int idescsi_cleanup (struct ata_device *drive) { - if (ide_unregister_subdriver (drive)) { + if (ata_unregister_device(drive)) return 1; - } scsi_unregister_host(&template); return 0; @@ -762,7 +740,7 @@ host = scsi_register(&template, sizeof(idescsi_scsi_t)); if (!host) { - printk (KERN_ERR + printk(KERN_ERR "ide-scsi: %s: Can't allocate a scsi host structure\n", drive->name); return; @@ -771,8 +749,8 @@ host->max_lun = drive->last_lun + 1; host->max_id = 1; - if (ide_register_subdriver(drive, &ata_ops)) { - printk (KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name); + if (ata_register_device(drive, &ata_ops)) { + printk(KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name); scsi_unregister(host); return; } diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c --- a/drivers/scsi/osst.c Thu Aug 1 14:17:40 2002 +++ b/drivers/scsi/osst.c Thu Aug 1 14:17:40 2002 @@ -5585,11 +5585,7 @@ if (osst_template.dev_noticed == 0) return 0; if(!osst_registered) { -#ifdef CONFIG_DEVFS_FS - if (devfs_register_chrdev(MAJOR_NR,"osst",&osst_fops)) { -#else if (register_chrdev(MAJOR_NR,"osst",&osst_fops)) { -#endif printk(KERN_ERR "osst :W: Unable to get major %d for OnStream tapes\n",MAJOR_NR); return 1; } @@ -5605,11 +5601,7 @@ GFP_ATOMIC); if (os_scsi_tapes == NULL) { printk(KERN_ERR "osst :W: Unable to allocate array for OnStream SCSI tapes.\n"); -#ifdef CONFIG_DEVFS_FS - devfs_unregister_chrdev(MAJOR_NR, "osst"); -#else unregister_chrdev(MAJOR_NR, "osst"); -#endif return 1; } @@ -5621,11 +5613,7 @@ GFP_ATOMIC); if (osst_buffers == NULL) { printk(KERN_ERR "osst :W: Unable to allocate tape buffer pointers.\n"); -#ifdef CONFIG_DEVFS_FS - devfs_unregister_chrdev(MAJOR_NR, "osst"); -#else unregister_chrdev(MAJOR_NR, "osst"); -#endif kfree(os_scsi_tapes); return 1; } @@ -5684,11 +5672,7 @@ OS_Scsi_Tape * STp; scsi_unregister_device(&osst_template); -#ifdef CONFIG_DEVFS_FS - devfs_unregister_chrdev(MAJOR_NR, "osst"); -#else unregister_chrdev(MAJOR_NR, "osst"); -#endif osst_registered--; if(os_scsi_tapes != NULL) { for (i=0; i < osst_template.dev_max; ++i) { diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c --- a/drivers/scsi/scsi_error.c Thu Aug 1 14:17:36 2002 +++ b/drivers/scsi/scsi_error.c Thu Aug 1 14:17:36 2002 @@ -1878,6 +1878,7 @@ */ daemonize(); + reparent_to_init(); /* * Set the name of this process. diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Thu Aug 1 14:17:41 2002 +++ b/drivers/scsi/scsi_scan.c Thu Aug 1 14:17:41 2002 @@ -305,12 +305,8 @@ return 0; } +static DEVICE_ATTR(type,"type",S_IRUGO,scsi_device_type_read,NULL); -static struct driver_file_entry scsi_device_type_file = { - name: "type", - mode: S_IRUGO, - show: scsi_device_type_read, -}; /* end content handlers */ static void print_inquiry(unsigned char *data) @@ -715,7 +711,7 @@ scsi_wait_req (SRpnt, (void *) scsi_cmd, (void *) scsi_result, - 256, SCSI_TIMEOUT+4*HZ, 3); + scsi_cmd[4], SCSI_TIMEOUT+4*HZ, 3); /* assume successful */ } SDpnt->inquiry_len = possible_inq_resp_len; @@ -825,7 +821,7 @@ /* Create driverfs file entries */ device_create_file(&SDpnt->sdev_driverfs_dev, - &scsi_device_type_file); + &dev_attr_type); sprintf (devname, "host%d/bus%d/target%d/lun%d", SDpnt->host->host_no, SDpnt->channel, SDpnt->id, SDpnt->lun); diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c Thu Aug 1 14:17:37 2002 +++ b/drivers/scsi/sd.c Thu Aug 1 14:17:37 2002 @@ -90,9 +90,6 @@ static Scsi_Disk ** sd_dsk_arr; static rwlock_t sd_dsk_arr_lock = RW_LOCK_UNLOCKED; -static int *sd_sizes; -static int *sd_max_sectors; - static int check_scsidisk_media_change(kdev_t); static int fop_revalidate_scsidisk(kdev_t); @@ -536,7 +533,7 @@ * See if we are requesting a non-existent partition. Do this * after checking for disk change. */ - if (sd_sizes[SD_PARTITION(inode->i_rdev)] == 0) { + if (sd[SD_PARTITION(inode->i_rdev)].nr_sects == 0) { goto error_out; } @@ -606,22 +603,7 @@ revalidate: fop_revalidate_scsidisk }; -/* - * If we need more than one SCSI disk major (i.e. more than - * 16 SCSI disks), we'll have to vmalloc() more gendisks later. - */ - -static struct gendisk sd_gendisk = -{ - major: SCSI_DISK0_MAJOR, - major_name: "sd", - minor_shift: 4, - fops: &sd_fops, -}; - -static struct gendisk *sd_gendisks = &sd_gendisk; - -#define SD_GENDISK(i) sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR] +static struct gendisk **sd_disks; /** * sd_rw_intr - bottom half handler: called when the lower level @@ -1077,7 +1059,7 @@ SRpnt->sr_data_direction = SCSI_DATA_READ; scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, - 512, SD_TIMEOUT, MAX_RETRIES); + 255, SD_TIMEOUT, MAX_RETRIES); the_result = SRpnt->sr_result; @@ -1198,8 +1180,7 @@ if (!sd_registered) { for (k = 0; k < N_USED_SD_MAJORS; k++) { - if (devfs_register_blkdev(SD_MAJOR(k), "sd", - &sd_fops)) { + if (register_blkdev(SD_MAJOR(k), "sd", &sd_fops)) { printk(KERN_NOTICE "Unable to get major %d " "for SCSI disk\n", SD_MAJOR(k)); return 1; @@ -1226,69 +1207,25 @@ sd_dsk_arr[k] = sdkp; } } - init_mem_lth(sd_sizes, maxparts); + init_mem_lth(sd_disks, sd_template.dev_max); + if (sd_disks) + zero_mem_lth(sd_disks, sd_template.dev_max); init_mem_lth(sd, maxparts); - init_mem_lth(sd_gendisks, N_USED_SD_MAJORS); - init_mem_lth(sd_max_sectors, sd_template.dev_max << 4); - if (!sd_dsk_arr || !sd_sizes || !sd || !sd_gendisks) + if (!sd_dsk_arr || !sd || !sd_disks) goto cleanup_mem; - zero_mem_lth(sd_sizes, maxparts); zero_mem_lth(sd, maxparts); - - for (k = 0; k < maxparts; k++) { - /* - * Allow lowlevel device drivers to generate 512k large scsi - * commands if they know what they're doing and they ask for it - * explicitly via the SHpnt->max_sectors API. - */ - sd_max_sectors[k] = MAX_PHYS_SEGMENTS*8; - } - - for (k = 0; k < N_USED_SD_MAJORS; k++) { - int N = SCSI_DISKS_PER_MAJOR; - - sd_gendisks[k] = sd_gendisk; - - init_mem_lth(sd_gendisks[k].de_arr, N); - init_mem_lth(sd_gendisks[k].flags, N); - init_mem_lth(sd_gendisks[k].driverfs_dev_arr, N); - - if (!sd_gendisks[k].de_arr || !sd_gendisks[k].flags || - !sd_gendisks[k].driverfs_dev_arr) - goto cleanup_gendisks; - - zero_mem_lth(sd_gendisks[k].de_arr, N); - zero_mem_lth(sd_gendisks[k].flags, N); - zero_mem_lth(sd_gendisks[k].driverfs_dev_arr, N); - - sd_gendisks[k].major = SD_MAJOR(k); - sd_gendisks[k].major_name = "sd"; - sd_gendisks[k].minor_shift = 4; - sd_gendisks[k].part = sd + k * (N << 4); - sd_gendisks[k].sizes = sd_sizes + k * (N << 4); - sd_gendisks[k].nr_real = 0; - } return 0; #undef init_mem_lth #undef zero_mem_lth -cleanup_gendisks: - /* vfree can handle NULL, so no test is required here */ - for (k = 0; k < N_USED_SD_MAJORS; k++) { - vfree(sd_gendisks[k].de_arr); - vfree(sd_gendisks[k].flags); - vfree(sd_gendisks[k].driverfs_dev_arr); - } cleanup_mem: - vfree(sd_gendisks); - sd_gendisks = NULL; + vfree(sd_disks); + sd_disks = NULL; vfree(sd); sd = NULL; - vfree(sd_sizes); - sd_sizes = NULL; if (sd_dsk_arr) { for (k = 0; k < sd_template.dev_max; ++k) vfree(sd_dsk_arr[k]); @@ -1296,7 +1233,7 @@ sd_dsk_arr = NULL; } for (k = 0; k < N_USED_SD_MAJORS; k++) { - devfs_unregister_blkdev(SD_MAJOR(k), "sd"); + unregister_blkdev(SD_MAJOR(k), "sd"); } sd_registered--; return 1; @@ -1317,18 +1254,16 @@ Scsi_Disk * sdkp; SCSI_LOG_HLQUEUE(3, printk("sd_finish: \n")); - for (k = 0; k < N_USED_SD_MAJORS; k++) { + for (k = 0; k < N_USED_SD_MAJORS; k++) blk_dev[SD_MAJOR(k)].queue = sd_find_queue; - add_gendisk(&(sd_gendisks[k])); - } for (k = 0; k < sd_template.dev_max; ++k) { sdkp = sd_get_sdisk(k); if (sdkp && (0 == sdkp->capacity) && sdkp->device) { sd_init_onedisk(sdkp, k); if (!sdkp->has_been_registered) { - sd_sizes[k << 4] = sdkp->capacity; - register_disk(&SD_GENDISK(k), MKDEV_SD(k), + add_gendisk(sd_disks[k]); + register_disk(sd_disks[k], MKDEV_SD(k), 1<<4, &sd_fops, sdkp->capacity); sdkp->has_been_registered = 1; @@ -1374,21 +1309,36 @@ **/ static int sd_attach(Scsi_Device * sdp) { - unsigned int devnum; Scsi_Disk *sdkp; int dsk_nr; char diskname[6]; unsigned long iflags; + struct { + struct gendisk disk; + devfs_handle_t de; + struct device *dev; + char flags; + } *p; + struct gendisk *gd; if ((NULL == sdp) || ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD))) return 0; + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return 1; + gd = &p->disk; + gd->de_arr = &p->de; + gd->flags = &p->flags; + gd->driverfs_dev_arr = &p->dev; + SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun)); if (sd_template.nr_dev >= sd_template.dev_max) { sdp->attached--; printk(KERN_ERR "sd_init: no more room for device\n"); + kfree(p); return 1; } @@ -1408,17 +1358,23 @@ if (dsk_nr >= sd_template.dev_max) { /* panic("scsi_devices corrupt (sd)"); overkill */ printk(KERN_ERR "sd_init: sd_dsk_arr corrupted\n"); + kfree(p); return 1; } sd_template.nr_dev++; - SD_GENDISK(dsk_nr).nr_real++; - devnum = dsk_nr % SCSI_DISKS_PER_MAJOR; - SD_GENDISK(dsk_nr).de_arr[devnum] = sdp->de; - SD_GENDISK(dsk_nr).driverfs_dev_arr[devnum] = - &sdp->sdev_driverfs_dev; + gd->nr_real = 1; + gd->de_arr[0] = sdp->de; + gd->driverfs_dev_arr[0] = &sdp->sdev_driverfs_dev; + gd->major = SD_MAJOR(dsk_nr>>4); + gd->first_minor = (dsk_nr & 15)<<4; + gd->major_name = "sd"; + gd->minor_shift = 4; + gd->part = sd + (dsk_nr << 4); + gd->fops = &sd_fops; if (sdp->removable) - SD_GENDISK(dsk_nr).flags[devnum] |= GENHD_FL_REMOVABLE; + gd->flags[0] |= GENHD_FL_REMOVABLE; + sd_disks[dsk_nr] = gd; sd_dskname(dsk_nr, diskname); printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, " "id %d, lun %d\n", sdp->removable ? "removable " : "", @@ -1487,9 +1443,7 @@ { Scsi_Disk *sdkp = NULL; kdev_t dev; - int dsk_nr, j; - int max_p; - int start; + int dsk_nr; unsigned long iflags; SCSI_LOG_HLQUEUE(3, printk("sd_detach: <%d,%d,%d,%d>\n", @@ -1499,7 +1453,6 @@ for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) { sdkp = sd_dsk_arr[dsk_nr]; if (sdkp->device == sdp) { - sdkp->has_been_registered = 0; sdkp->device = NULL; sdkp->capacity = 0; /* sdkp->detaching = 1; */ @@ -1510,22 +1463,20 @@ if (dsk_nr >= sd_template.dev_max) return; - max_p = 1 << sd_gendisk.minor_shift; - start = dsk_nr << sd_gendisk.minor_shift; - dev = MKDEV_SD_PARTITION(start); - driverfs_remove_partitions(&SD_GENDISK (dsk_nr), - SD_MINOR_NUMBER (start)); - wipe_partitions(dev); - for (j = max_p - 1; j >= 0; j--) - sd_sizes[start + j] = 0; - - devfs_register_partitions (&SD_GENDISK (dsk_nr), - SD_MINOR_NUMBER (start), 1); - /* unregister_disk() */ + if (sdkp->has_been_registered) { + sdkp->has_been_registered = 0; + dev = MKDEV_SD(dsk_nr); + driverfs_remove_partitions(sd_disks[dsk_nr], minor(dev)); + wipe_partitions(dev); + devfs_register_partitions (sd_disks[dsk_nr], minor(dev), 1); + /* unregister_disk() */ + del_gendisk(sd_disks[dsk_nr]); + } sdp->attached--; sd_template.dev_noticed--; sd_template.nr_dev--; - SD_GENDISK(dsk_nr).nr_real--; + kfree(sd_disks[dsk_nr]); + sd_disks[dsk_nr] = NULL; } /** @@ -1560,7 +1511,7 @@ SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n")); scsi_unregister_device(&sd_template); for (k = 0; k < N_USED_SD_MAJORS; k++) - devfs_unregister_blkdev(SD_MAJOR(k), "sd"); + unregister_blkdev(SD_MAJOR(k), "sd"); sd_registered--; if (sd_dsk_arr != NULL) { @@ -1568,16 +1519,12 @@ vfree(sd_dsk_arr[k]); vfree(sd_dsk_arr); } - vfree(sd_sizes); vfree((char *) sd); for (k = 0; k < N_USED_SD_MAJORS; k++) { blk_dev[SD_MAJOR(k)].queue = NULL; - del_gendisk(&(sd_gendisks[k])); blk_clear(SD_MAJOR(k)); } sd_template.dev_max = 0; - if (sd_gendisks != &sd_gendisk) - vfree(sd_gendisks); remove_driver(&sd_template.scsi_driverfs_driver); } diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c --- a/drivers/scsi/sg.c Thu Aug 1 14:17:40 2002 +++ b/drivers/scsi/sg.c Thu Aug 1 14:17:40 2002 @@ -1348,8 +1348,7 @@ write_lock_irqsave(&sg_dev_arr_lock, iflags); if(!sg_registered) { - if (devfs_register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops)) - { + if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops)) { printk(KERN_ERR "Unable to get major %d for generic SCSI device\n", SCSI_GENERIC_MAJOR); write_unlock_irqrestore(&sg_dev_arr_lock, iflags); @@ -1402,22 +1401,14 @@ Sg_device * sdp=list_entry(driverfs_dev, Sg_device, sg_driverfs_dev); return off ? 0 : sprintf(page, "%x\n",sdp->i_rdev.value); } -static struct driver_file_entry sg_device_kdev_file = { - name: "kdev", - mode: S_IRUGO, - show: sg_device_kdev_read, -}; +static DEVICE_ATTR(kdev,"kdev",S_IRUGO,sg_device_kdev_read,NULL); static ssize_t sg_device_type_read(struct device *driverfs_dev, char *page, size_t count, loff_t off) { return off ? 0 : sprintf (page, "CHR\n"); } -static struct driver_file_entry sg_device_type_file = { - name: "type", - mode: S_IRUGO, - show: sg_device_type_read, -}; +static DEVICE_ATTR(type,"type",S_IRUGO,sg_device_type_read,NULL); static int sg_attach(Scsi_Device * scsidp) { @@ -1485,8 +1476,8 @@ sdp->sg_driverfs_dev.parent = &scsidp->sdev_driverfs_dev; sdp->sg_driverfs_dev.bus = &scsi_driverfs_bus_type; device_register(&sdp->sg_driverfs_dev); - device_create_file(&sdp->sg_driverfs_dev, &sg_device_type_file); - device_create_file(&sdp->sg_driverfs_dev, &sg_device_kdev_file); + device_create_file(&sdp->sg_driverfs_dev, &dev_attr_type); + device_create_file(&sdp->sg_driverfs_dev, &dev_attr_kdev); sdp->de = devfs_register (scsidp->de, "generic", DEVFS_FL_DEFAULT, SCSI_GENERIC_MAJOR, k, @@ -1556,8 +1547,8 @@ } SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty\n", k)); devfs_unregister (sdp->de); - device_remove_file(&sdp->sg_driverfs_dev,sg_device_type_file.name); - device_remove_file(&sdp->sg_driverfs_dev,sg_device_kdev_file.name); + device_remove_file(&sdp->sg_driverfs_dev,&dev_attr_type); + device_remove_file(&sdp->sg_driverfs_dev,&dev_attr_kdev); put_device(&sdp->sg_driverfs_dev); sdp->de = NULL; if (NULL == sdp->headfp) { @@ -1611,7 +1602,7 @@ sg_proc_cleanup(); #endif /* CONFIG_PROC_FS */ scsi_unregister_device(&sg_template); - devfs_unregister_chrdev(SCSI_GENERIC_MAJOR, "sg"); + unregister_chrdev(SCSI_GENERIC_MAJOR, "sg"); if(sg_dev_arr != NULL) { kfree((char *)sg_dev_arr); sg_dev_arr = NULL; diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c --- a/drivers/scsi/sr.c Thu Aug 1 14:17:39 2002 +++ b/drivers/scsi/sr.c Thu Aug 1 14:17:39 2002 @@ -702,7 +702,7 @@ return 0; if (!sr_registered) { - if (devfs_register_blkdev(MAJOR_NR, "sr", &sr_bdops)) { + if (register_blkdev(MAJOR_NR, "sr", &sr_bdops)) { printk("Unable to get major %d for SCSI-CD\n", MAJOR_NR); return 1; } @@ -714,7 +714,7 @@ sr_template.dev_max = sr_template.dev_noticed + SR_EXTRA_DEVS; scsi_CDs = kmalloc(sr_template.dev_max * sizeof(Scsi_CD), GFP_ATOMIC); if (!scsi_CDs) - goto cleanup_devfs; + goto cleanup_dev; memset(scsi_CDs, 0, sr_template.dev_max * sizeof(Scsi_CD)); sr_sizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC); @@ -725,8 +725,8 @@ cleanup_cds: kfree(scsi_CDs); -cleanup_devfs: - devfs_unregister_blkdev(MAJOR_NR, "sr"); +cleanup_dev: + unregister_blkdev(MAJOR_NR, "sr"); sr_registered--; return 1; } @@ -739,22 +739,14 @@ kdev.value=(int)driverfs_dev->driver_data; return off ? 0 : sprintf(page, "%x\n",kdev.value); } -static struct driver_file_entry sr_device_kdev_file = { - name: "kdev", - mode: S_IRUGO, - show: sr_device_kdev_read, -}; +static DEVICE_ATTR(kdev,"kdev",S_IRUGO,sr_device_kdev_read,NULL); static ssize_t sr_device_type_read(struct device *driverfs_dev, char *page, size_t count, loff_t off) { return off ? 0 : sprintf (page, "CHR\n"); } -static struct driver_file_entry sr_device_type_file = { - name: "type", - mode: S_IRUGO, - show: sr_device_type_read, -}; +static DEVICE_ATTR(type,"type",S_IRUGO,sr_device_type_read,NULL); void sr_finish() @@ -813,9 +805,9 @@ (void *)__mkdev(MAJOR_NR, i); device_register(&SCp->cdi.cdrom_driverfs_dev); device_create_file(&SCp->cdi.cdrom_driverfs_dev, - &sr_device_type_file); + &dev_attr_type); device_create_file(&SCp->cdi.cdrom_driverfs_dev, - &sr_device_kdev_file); + &dev_attr_kdev); SCp->cdi.de = devfs_register(SCp->device->de, "cd", DEVFS_FL_DEFAULT, MAJOR_NR, i, S_IFBLK | S_IRUGO | S_IWUGO, @@ -869,7 +861,7 @@ static void __exit exit_sr(void) { scsi_unregister_device(&sr_template); - devfs_unregister_blkdev(MAJOR_NR, "sr"); + unregister_blkdev(MAJOR_NR, "sr"); sr_registered--; if (scsi_CDs != NULL) { kfree(scsi_CDs); diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c Thu Aug 1 14:17:41 2002 +++ b/drivers/scsi/st.c Thu Aug 1 14:17:41 2002 @@ -3533,22 +3533,14 @@ kdev.value=(int)driverfs_dev->driver_data; return off ? 0 : sprintf(page, "%x\n",kdev.value); } -static struct driver_file_entry st_device_kdev_file = { - name: "kdev", - mode: S_IRUGO, - show: st_device_kdev_read, -}; +static DEVICE_ATTR(kdev,"kdev",S_IRUGO,st_device_kdev_read,NULL); static ssize_t st_device_type_read(struct device *driverfs_dev, char *page, size_t count, loff_t off) { return off ? 0 : sprintf (page, "CHR\n"); } -static struct driver_file_entry st_device_type_file = { - name: "type", - mode: S_IRUGO, - show: st_device_type_read, -}; +static DEVICE_ATTR(type,"type",S_IRUGO,st_device_type_read,NULL); static struct file_operations st_fops = @@ -3664,8 +3656,8 @@ (void *)__mkdev(MAJOR_NR, i + (mode << 5)); device_register(&tpnt->driverfs_dev_r[mode]); device_create_file(&tpnt->driverfs_dev_r[mode], - &st_device_type_file); - device_create_file(&tpnt->driverfs_dev_r[mode], &st_device_kdev_file); + &dev_attr_type); + device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev); tpnt->de_r[mode] = devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, MAJOR_NR, i + (mode << 5), @@ -3683,9 +3675,9 @@ (void *)__mkdev(MAJOR_NR, i + (mode << 5) + 128); device_register(&tpnt->driverfs_dev_n[mode]); device_create_file(&tpnt->driverfs_dev_n[mode], - &st_device_type_file); + &dev_attr_type); device_create_file(&tpnt->driverfs_dev_n[mode], - &st_device_kdev_file); + &dev_attr_kdev); tpnt->de_n[mode] = devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, MAJOR_NR, i + (mode << 5) + 128, @@ -3785,16 +3777,16 @@ devfs_unregister (tpnt->de_r[mode]); tpnt->de_r[mode] = NULL; device_remove_file(&tpnt->driverfs_dev_r[mode], - st_device_type_file.name); + &dev_attr_type); device_remove_file(&tpnt->driverfs_dev_r[mode], - st_device_kdev_file.name); + &dev_attr_type); put_device(&tpnt->driverfs_dev_r[mode]); devfs_unregister (tpnt->de_n[mode]); tpnt->de_n[mode] = NULL; device_remove_file(&tpnt->driverfs_dev_n[mode], - st_device_type_file.name); + &dev_attr_type); device_remove_file(&tpnt->driverfs_dev_n[mode], - st_device_kdev_file.name); + &dev_attr_kdev); put_device(&tpnt->driverfs_dev_n[mode]); } if (tpnt->buffer) { @@ -3826,7 +3818,7 @@ verstr, st_fixed_buffer_size, st_write_threshold, st_max_sg_segs); - if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) { + if (register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) { if (scsi_register_device(&st_template) == 0) { st_template.scsi_driverfs_driver.name = (char *)st_template.tag; @@ -3846,7 +3838,7 @@ int i; scsi_unregister_device(&st_template); - devfs_unregister_chrdev(SCSI_TAPE_MAJOR, "st"); + unregister_chrdev(SCSI_TAPE_MAJOR, "st"); if (scsi_tapes != NULL) { for (i=0; i < st_template.dev_max; ++i) if (scsi_tapes[i]) diff -Nru a/drivers/serial/21285.c b/drivers/serial/21285.c --- a/drivers/serial/21285.c Thu Aug 1 14:17:37 2002 +++ b/drivers/serial/21285.c Thu Aug 1 14:17:37 2002 @@ -5,29 +5,19 @@ * * Based on drivers/char/serial.c * - * $Id: 21285.c,v 1.34 2002/07/22 15:27:32 rmk Exp $ + * $Id: 21285.c,v 1.37 2002/07/28 10:03:27 rmk Exp $ */ #include #include -#include -#include -#include -#include #include -#include -#include -#include -#include #include -#include -#include #include #include #include +#include #include #include -#include #include #include @@ -85,14 +75,10 @@ static void serial21285_stop_rx(struct uart_port *port) { - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); if (rx_enabled(port)) { disable_irq(IRQ_CONRX); rx_enabled(port) = 0; } - spin_unlock_irqrestore(&port->lock, flags); } static void serial21285_enable_ms(struct uart_port *port) @@ -514,7 +500,7 @@ { int ret; - printk(KERN_INFO "Serial: 21285 driver $Revision: 1.34 $\n"); + printk(KERN_INFO "Serial: 21285 driver $Revision: 1.37 $\n"); serial21285_setup_ports(); @@ -537,4 +523,4 @@ EXPORT_NO_SYMBOLS; MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver $Revision: 1.34 $"); +MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver $Revision: 1.37 $"); diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c --- a/drivers/serial/8250.c Thu Aug 1 14:17:36 2002 +++ b/drivers/serial/8250.c Thu Aug 1 14:17:36 2002 @@ -12,7 +12,7 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * $Id: 8250.c,v 1.84 2002/07/22 15:27:32 rmk Exp $ + * $Id: 8250.c,v 1.90 2002/07/28 10:03:27 rmk Exp $ * * A note about mapbase / membase * @@ -25,29 +25,17 @@ */ #include #include -#include -#include -#include #include -#include -#include -#include -#include #include #include -#include #include #include #include #include #include -#include -#include #include #include -#include -#include #if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -724,24 +712,18 @@ static void serial8250_stop_rx(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; - unsigned long flags; - spin_lock_irqsave(&up->port.lock, flags); up->ier &= ~UART_IER_RLSI; up->port.read_status_mask &= ~UART_LSR_DR; serial_out(up, UART_IER, up->ier); - spin_unlock_irqrestore(&up->port.lock, flags); } static void serial8250_enable_ms(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; - unsigned long flags; - spin_lock_irqsave(&up->port.lock, flags); up->ier |= UART_IER_MSI; serial_out(up, UART_IER, up->ier); - spin_unlock_irqrestore(&up->port.lock, flags); } static _INLINE_ void @@ -1364,17 +1346,18 @@ up->port.ignore_status_mask |= UART_LSR_DR; /* + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ + spin_lock_irqsave(&up->port.lock, flags); + + /* * CTS flow control flag and modem status interrupts */ up->ier &= ~UART_IER_MSI; if (UART_ENABLE_MS(&up->port, cflag)) up->ier |= UART_IER_MSI; - /* - * Ok, we're now changing the port state. Do it with - * interrupts disabled. - */ - spin_lock_irqsave(&up->port.lock, flags); serial_out(up, UART_IER, up->ier); if (uart_config[up->port.type].flags & UART_STARTECH) { @@ -1956,7 +1939,7 @@ { int ret, i; - printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.84 $ " + printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.90 $ " "IRQ sharing %sabled\n", share_irqs ? "en" : "dis"); for (i = 0; i < NR_IRQS; i++) @@ -1988,7 +1971,7 @@ EXPORT_SYMBOL(serial8250_get_irq_map); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Generic 8250/16x50 serial driver $Revision: 1.84 $"); +MODULE_DESCRIPTION("Generic 8250/16x50 serial driver $Revision: 1.90 $"); MODULE_PARM(share_irqs, "i"); MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices" diff -Nru a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c --- a/drivers/serial/8250_pci.c Thu Aug 1 14:17:41 2002 +++ b/drivers/serial/8250_pci.c Thu Aug 1 14:17:41 2002 @@ -11,7 +11,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * - * $Id: 8250_pci.c,v 1.19 2002/07/21 21:32:30 rmk Exp $ + * $Id: 8250_pci.c,v 1.24 2002/07/29 14:39:56 rmk Exp $ */ #include #include @@ -30,6 +30,7 @@ #include #include #include +#include #include "8250.h" @@ -137,7 +138,29 @@ offset = 8 * (idx - 2); } } - + + /* HP's Diva chip puts the 4th/5th serial port further out, and + * some serial ports are supposed to be hidden on certain models. + */ + if (dev->vendor == PCI_VENDOR_ID_HP && + dev->device == PCI_DEVICE_ID_HP_DIVA) { + switch (dev->subsystem_device) { + case PCI_DEVICE_ID_HP_DIVA_MAESTRO: + if (idx == 3) + idx++; + break; + case PCI_DEVICE_ID_HP_DIVA_EVEREST: + if (idx > 0) + idx++; + if (idx > 2) + idx++; + break; + } + if (idx > 2) { + offset = 0x18; + } + } + port = pci_resource_start(dev, base_idx) + offset; if ((board->flags & SPCI_FL_BASE_TABLE) == 0) @@ -379,6 +402,41 @@ return 0; } +/* + * HP's Remote Management Console. The Diva chip came in several + * different versions. N-class, L2000 and A500 have two Diva chips, each + * with 3 UARTs (the third UART on the second chip is unused). Superdome + * and Keystone have one Diva chip with 3 UARTs. Some later machines have + * one Diva chip, but it has been expanded to 5 UARTs. + */ +static int __devinit +pci_hp_diva(struct pci_dev *dev, struct pci_board *board, int enable) +{ + if (!enable) + return 0; + + switch (dev->subsystem_device) { + case PCI_DEVICE_ID_HP_DIVA_TOSCA1: + case PCI_DEVICE_ID_HP_DIVA_HALFDOME: + case PCI_DEVICE_ID_HP_DIVA_KEYSTONE: + case PCI_DEVICE_ID_HP_DIVA_EVEREST: + board->num_ports = 3; + break; + case PCI_DEVICE_ID_HP_DIVA_TOSCA2: + board->num_ports = 2; + break; + case PCI_DEVICE_ID_HP_DIVA_MAESTRO: + board->num_ports = 4; + break; + case PCI_DEVICE_ID_HP_DIVA_POWERBAR: + board->num_ports = 1; + break; + } + + return 0; +} + + static int __devinit pci_xircom_fn(struct pci_dev *dev, struct pci_board *board, int enable) { @@ -423,6 +481,7 @@ pbn_b1_4_1382400, pbn_b1_8_1382400, + pbn_b2_1_115200, pbn_b2_8_115200, pbn_b2_4_460800, pbn_b2_8_460800, @@ -443,6 +502,7 @@ pbn_timedia, pbn_intel_i960, pbn_sgi_ioc3, + pbn_hp_diva, pbn_nec_nile4, pbn_dci_pccom4, @@ -501,6 +561,7 @@ { SPCI_FL_BASE1, 4, 1382400 }, /* pbn_b1_4_1382400 */ { SPCI_FL_BASE1, 8, 1382400 }, /* pbn_b1_8_1382400 */ + { SPCI_FL_BASE2, 1, 115200 }, /* pbn_b2_1_115200 */ { SPCI_FL_BASE2, 8, 115200 }, /* pbn_b2_8_115200 */ { SPCI_FL_BASE2, 4, 460800 }, /* pbn_b2_4_460800 */ { SPCI_FL_BASE2, 8, 460800 }, /* pbn_b2_8_460800 */ @@ -531,6 +592,7 @@ 8<<2, 2, pci_inteli960ni_fn, 0x10000}, { SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE, /* pbn_sgi_ioc3 */ 1, 458333, 0, 0, 0, 0x20178 }, + { SPCI_FL_BASE0, 5, 115200, 8, 0, pci_hp_diva, 0 },/* pbn_hp_diva */ /* * NEC Vrc-5074 (Nile 4) builtin UART. @@ -636,9 +698,10 @@ return rc; if (ent->driver_data == pbn_default && - serial_pci_guess_board(dev, board)) + serial_pci_guess_board(dev, board)) { + pci_disable_device(dev); return -ENODEV; - else if (serial_pci_guess_board(dev, &tmp) == 0) { + } else if (serial_pci_guess_board(dev, &tmp) == 0) { printk(KERN_INFO "Redundant entry in serial pci_table. " "Please send the output of\n" "lspci -vv, this message (%d,%d,%d,%d)\n" @@ -652,8 +715,10 @@ priv = kmalloc(sizeof(struct serial_private) + sizeof(unsigned int) * board->num_ports, GFP_KERNEL); - if (!priv) + if (!priv) { + pci_disable_device(dev); return -ENOMEM; + } /* * Run the initialization function, if any @@ -661,6 +726,7 @@ if (board->init_fn) { rc = board->init_fn(dev, board, 1); if (rc != 0) { + pci_disable_device(dev); kfree(priv); return rc; } @@ -1074,6 +1140,14 @@ 0xFF00, 0, 0, 0, pbn_sgi_ioc3 }, + /* HP Diva card */ + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_hp_diva }, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_1_115200 }, + /* * NEC Vrc-5074 (Nile 4) builtin UART. */ @@ -1102,14 +1176,6 @@ 0xffff00, }, { 0, } }; - -#ifndef __devexit_p -#if defined(MODULE) || defined(CONFIG_HOTPLUG) -#define __devexit_p(x) x -#else -#define __devexit_p(x) NULL -#endif -#endif static struct pci_driver serial_pci_driver = { .name = "serial", diff -Nru a/drivers/serial/amba.c b/drivers/serial/amba.c --- a/drivers/serial/amba.c Thu Aug 1 14:17:36 2002 +++ b/drivers/serial/amba.c Thu Aug 1 14:17:36 2002 @@ -22,7 +22,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: amba.c,v 1.37 2002/07/22 15:27:32 rmk Exp $ + * $Id: amba.c,v 1.41 2002/07/28 10:03:27 rmk Exp $ * * This is a generic driver for ARM AMBA-type serial ports. They * have a lot of 16550-like features, but are not register compatable. @@ -33,30 +33,15 @@ */ #include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include #include -#include -#include #include -#include #include #include #include -#include #include #include -#include -#include #if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -138,26 +123,20 @@ static void ambauart_stop_rx(struct uart_port *port) { - unsigned long flags; unsigned int cr; - spin_lock_irqsave(&port->lock, flags); cr = UART_GET_CR(port); cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE); UART_PUT_CR(port, cr); - spin_unlock_irqrestore(&port->lock, flags); } static void ambauart_enable_ms(struct uart_port *port) { - unsigned long flags; unsigned int cr; - spin_lock_irqsave(&port->lock, flags); cr = UART_GET_CR(port); cr |= AMBA_UARTCR_MSIE; UART_PUT_CR(port, cr); - spin_unlock_irqrestore(&port->lock, flags); } static void @@ -742,7 +721,7 @@ { int ret; - printk(KERN_INFO "Serial: AMBA driver $Revision: 1.37 $\n"); + printk(KERN_INFO "Serial: AMBA driver $Revision: 1.41 $\n"); ret = uart_register_driver(&amba_reg); if (ret == 0) { @@ -770,5 +749,5 @@ EXPORT_NO_SYMBOLS; MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd"); -MODULE_DESCRIPTION("ARM AMBA serial port driver $Revision: 1.37 $"); +MODULE_DESCRIPTION("ARM AMBA serial port driver $Revision: 1.41 $"); MODULE_LICENSE("GPL"); diff -Nru a/drivers/serial/anakin.c b/drivers/serial/anakin.c --- a/drivers/serial/anakin.c Thu Aug 1 14:17:37 2002 +++ b/drivers/serial/anakin.c Thu Aug 1 14:17:37 2002 @@ -19,35 +19,20 @@ * SA_INTERRUPT. Works reliably now. No longer requires * changes to the serial_core API. * - * $Id: anakin.c,v 1.29 2002/07/22 15:27:32 rmk Exp $ + * $Id: anakin.c,v 1.32 2002/07/28 10:03:27 rmk Exp $ */ #include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include #include -#include -#include #include -#include #include #include #include -#include #include #include -#include -#include #include @@ -119,13 +104,9 @@ static void anakin_stop_rx(struct uart_port *port) { - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); while (anakin_in(port, 0x10) & RXRELEASE) anakin_in(port, 0x14); anakin_out(port, 0x18, anakin_in(port, 0x18) | BLOCKRX); - spin_unlock_irqrestore(&port->lock, flags); } static void @@ -518,7 +499,7 @@ { int ret; - printk(KERN_INFO "Serial: Anakin driver $Revision: 1.29 $\n"); + printk(KERN_INFO "Serial: Anakin driver $Revision: 1.32 $\n"); ret = uart_register_driver(&anakin_reg); if (ret == 0) { diff -Nru a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c --- a/drivers/serial/clps711x.c Thu Aug 1 14:17:39 2002 +++ b/drivers/serial/clps711x.c Thu Aug 1 14:17:39 2002 @@ -22,37 +22,22 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: clps711x.c,v 1.40 2002/07/22 15:27:32 rmk Exp $ + * $Id: clps711x.c,v 1.42 2002/07/28 10:03:28 rmk Exp $ * */ #include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include #include -#include -#include #include -#include #include #include #include #include -#include #include #include #include -#include -#include #if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -597,7 +582,7 @@ { int ret, i; - printk(KERN_INFO "Serial: CLPS711x driver $Revision: 1.40 $\n"); + printk(KERN_INFO "Serial: CLPS711x driver $Revision: 1.42 $\n"); ret = uart_register_driver(&clps711x_reg); if (ret) @@ -625,5 +610,5 @@ EXPORT_NO_SYMBOLS; MODULE_AUTHOR("Deep Blue Solutions Ltd"); -MODULE_DESCRIPTION("CLPS-711x generic serial driver $Revision: 1.40 $"); +MODULE_DESCRIPTION("CLPS-711x generic serial driver $Revision: 1.42 $"); MODULE_LICENSE("GPL"); diff -Nru a/drivers/serial/core.c b/drivers/serial/core.c --- a/drivers/serial/core.c Thu Aug 1 14:17:39 2002 +++ b/drivers/serial/core.c Thu Aug 1 14:17:39 2002 @@ -22,38 +22,22 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: core.c,v 1.91 2002/07/22 15:27:32 rmk Exp $ + * $Id: core.c,v 1.100 2002/07/28 10:03:28 rmk Exp $ * */ #include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include #include #include -#include #include -#include #include #include #include #include /* for serial_state and serial_icounter_struct */ -#include -#include #include #include -#include #undef DEBUG #ifdef DEBUG @@ -931,12 +915,12 @@ */ spin_lock_irq(&port->lock); memcpy(&cprev, &port->icount, sizeof(struct uart_icount)); - spin_unlock_irq(&port->lock); /* * Force modem status interrupts on */ port->ops->enable_ms(port); + spin_unlock_irq(&port->lock); add_wait_queue(&info->delta_msr_wait, &wait); for (;;) { @@ -1200,7 +1184,9 @@ * disable the receive line status interrupts. */ if (info->flags & UIF_INITIALIZED) { + spin_lock_irqsave(&port->lock, flags); port->ops->stop_rx(port); + spin_unlock_irqrestore(&port->lock, flags); /* * Before we drop DTR, make sure the UART transmitter * has completely drained; this is especially @@ -1948,8 +1934,8 @@ spin_lock_irq(&port->lock); ops->stop_tx(port, 0); ops->set_mctrl(port, 0); - spin_unlock_irq(&port->lock); ops->stop_rx(port); + spin_unlock_irq(&port->lock); ops->shutdown(port); } if (ops->pm) diff -Nru a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c --- a/drivers/serial/sa1100.c Thu Aug 1 14:17:36 2002 +++ b/drivers/serial/sa1100.c Thu Aug 1 14:17:36 2002 @@ -21,35 +21,20 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: sa1100.c,v 1.43 2002/07/22 15:27:32 rmk Exp $ + * $Id: sa1100.c,v 1.50 2002/07/29 14:41:04 rmk Exp $ * */ #include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include #include -#include -#include #include -#include #include #include #include -#include #include #include -#include -#include #include #include @@ -190,13 +175,10 @@ static void sa1100_stop_rx(struct uart_port *port) { struct sa1100_port *sport = (struct sa1100_port *)port; - unsigned long flags; u32 utcr3; - spin_lock_irqsave(&sport->port.lock, flags); utcr3 = UART_GET_UTCR3(sport); UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_RIE); - spin_unlock_irqrestore(&sport->port.lock, flags); } /* @@ -426,7 +408,9 @@ /* * Enable modem status interrupts */ + spin_lock_irq(&sport->port.lock); sa1100_enable_ms(&sport->port); + spin_unlock_irq(&sport->port.lock); return 0; } @@ -527,10 +511,11 @@ UART_PUT_UTSR0(sport, -1); UART_PUT_UTCR3(sport, old_utcr3); - spin_unlock_irqrestore(&sport->port.lock, flags); if (UART_ENABLE_MS(&sport->port, cflag)) sa1100_enable_ms(&sport->port); + + spin_unlock_irqrestore(&sport->port.lock, flags); } static const char *sa1100_type(struct uart_port *port) @@ -857,7 +842,7 @@ { int ret; - printk(KERN_INFO "Serial: SA11x0 driver $Revision: 1.43 $\n"); + printk(KERN_INFO "Serial: SA11x0 driver $Revision: 1.50 $\n"); sa1100_init_ports(); ret = uart_register_driver(&sa1100_reg); @@ -886,5 +871,5 @@ EXPORT_NO_SYMBOLS; MODULE_AUTHOR("Deep Blue Solutions Ltd"); -MODULE_DESCRIPTION("SA1100 generic serial port driver $Revision: 1.43 $"); +MODULE_DESCRIPTION("SA1100 generic serial port driver $Revision: 1.50 $"); MODULE_LICENSE("GPL"); diff -Nru a/drivers/serial/uart00.c b/drivers/serial/uart00.c --- a/drivers/serial/uart00.c Thu Aug 1 14:17:40 2002 +++ b/drivers/serial/uart00.c Thu Aug 1 14:17:40 2002 @@ -21,36 +21,21 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: uart00.c,v 1.33 2002/07/21 21:32:31 rmk Exp $ + * $Id: uart00.c,v 1.35 2002/07/28 10:03:28 rmk Exp $ * */ #include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include #include -#include -#include #include -#include #include #include #include #include -#include #include #include -#include -#include #include #if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) @@ -755,7 +740,7 @@ { int result; - printk(KERN_INFO "Serial: UART00 driver $Revision: 1.33 $\n"); + printk(KERN_INFO "Serial: UART00 driver $Revision: 1.35 $\n"); printk(KERN_WARNING "serial_uart00:Using temporary major/minor pairs" " - these WILL change in the future\n"); diff -Nru a/drivers/sgi/char/Makefile b/drivers/sgi/char/Makefile --- a/drivers/sgi/char/Makefile Thu Aug 1 14:17:36 2002 +++ b/drivers/sgi/char/Makefile Thu Aug 1 14:17:36 2002 @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -export-objs := newport.o shmiq.o sgicons.o usema.o +export-objs := newport.o shmiq.o sgicons.o usema.o rrm.o obj-y := newport.o shmiq.o sgicons.o usema.o streamable.o obj-$(CONFIG_SGI_SERIAL) += sgiserial.o diff -Nru a/drivers/sgi/char/shmiq.c b/drivers/sgi/char/shmiq.c --- a/drivers/sgi/char/shmiq.c Thu Aug 1 14:17:41 2002 +++ b/drivers/sgi/char/shmiq.c Thu Aug 1 14:17:41 2002 @@ -466,7 +466,7 @@ shmiq_init (void) { printk ("SHMIQ setup\n"); - devfs_register_chrdev(SHMIQ_MAJOR, "shmiq", &shmiq_fops); + register_chrdev(SHMIQ_MAJOR, "shmiq", &shmiq_fops); devfs_register (NULL, "shmiq", DEVFS_FL_DEFAULT, SHMIQ_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &shmiq_fops, NULL); diff -Nru a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile --- a/drivers/usb/core/Makefile Thu Aug 1 14:17:41 2002 +++ b/drivers/usb/core/Makefile Thu Aug 1 14:17:41 2002 @@ -2,7 +2,7 @@ # Makefile for USB Core files and filesystem # -export-objs := usb.o hcd.o hcd-pci.o urb.o message.o config.o file.o +export-objs := usb.o hcd.o hcd-pci.o urb.o message.o file.o usbcore-objs := usb.o usb-debug.o hub.o hcd.o urb.o message.o \ config.o file.o diff -Nru a/drivers/usb/core/file.c b/drivers/usb/core/file.c --- a/drivers/usb/core/file.c Thu Aug 1 14:17:41 2002 +++ b/drivers/usb/core/file.c Thu Aug 1 14:17:41 2002 @@ -71,7 +71,7 @@ int usb_major_init(void) { - if (devfs_register_chrdev(USB_MAJOR, "usb", &usb_fops)) { + if (register_chrdev(USB_MAJOR, "usb", &usb_fops)) { err("unable to get major %d for usb devices", USB_MAJOR); return -EBUSY; } @@ -84,7 +84,7 @@ void usb_major_cleanup(void) { devfs_unregister(usb_devfs_handle); - devfs_unregister_chrdev(USB_MAJOR, "usb"); + unregister_chrdev(USB_MAJOR, "usb"); } /** diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c --- a/drivers/usb/core/hub.c Thu Aug 1 14:17:40 2002 +++ b/drivers/usb/core/hub.c Thu Aug 1 14:17:40 2002 @@ -1059,9 +1059,9 @@ /* Send me a signal to get me die (for debugging) */ do { usb_hub_events(); + wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list)); if (current->flags & PF_FREEZE) refrigerator(PF_IOTHREAD); - wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list)); } while (!signal_pending(current)); dbg("usb_hub_thread exiting"); diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c Thu Aug 1 14:17:40 2002 +++ b/drivers/usb/core/usb.c Thu Aug 1 14:17:40 2002 @@ -835,11 +835,8 @@ udev = to_usb_device (dev); return sprintf (buf, "%u\n", udev->actconfig->bConfigurationValue); } -static struct driver_file_entry usb_config_entry = { - .name = "configuration", - .mode = S_IRUGO, - .show = show_config, -}; + +static DEVICE_ATTR(config,"configuration",S_IRUGO,show_config,NULL); /* interfaces have one current setting; alternates * can have different endpoints and class info. @@ -854,11 +851,7 @@ interface = to_usb_interface (dev); return sprintf (buf, "%u\n", interface->altsetting->bAlternateSetting); } -static struct driver_file_entry usb_altsetting_entry = { - .name = "altsetting", - .mode = S_IRUGO, - .show = show_altsetting, -}; +static DEVICE_ATTR(altsetting,"altsetting",S_IRUGO,show_altsetting,NULL); /* product driverfs file */ static ssize_t show_product (struct device *dev, char *buf, size_t count, loff_t off) @@ -875,11 +868,7 @@ buf[len+1] = 0x00; return len+1; } -static struct driver_file_entry usb_product_entry = { - .name = "product", - .mode = S_IRUGO, - .show = show_product, -}; +static DEVICE_ATTR(product,"product",S_IRUGO,show_product,NULL); /* manufacturer driverfs file */ static ssize_t @@ -897,11 +886,7 @@ buf[len+1] = 0x00; return len+1; } -static struct driver_file_entry usb_manufacturer_entry = { - .name = "manufacturer", - .mode = S_IRUGO, - .show = show_manufacturer, -}; +static DEVICE_ATTR(manufacturer,"manufacturer",S_IRUGO,show_manufacturer,NULL); /* serial number driverfs file */ static ssize_t @@ -919,11 +904,7 @@ buf[len+1] = 0x00; return len+1; } -static struct driver_file_entry usb_serial_entry = { - .name = "serial", - .mode = S_IRUGO, - .show = show_serial, -}; +static DEVICE_ATTR(serial,"serial",S_IRUGO,show_serial,NULL); /* * This entrypoint gets called for each new device. @@ -965,7 +946,7 @@ interface->altsetting->bInterfaceNumber); } device_register (&interface->dev); - device_create_file (&interface->dev, &usb_altsetting_entry); + device_create_file (&interface->dev, &dev_attr_altsetting); /* if this interface hasn't already been claimed */ if (!usb_interface_claimed(interface)) { @@ -1453,13 +1434,13 @@ err = device_register (&dev->dev); if (err) return err; - device_create_file (&dev->dev, &usb_config_entry); + device_create_file (&dev->dev, &dev_attr_config); if (dev->descriptor.iManufacturer) - device_create_file (&dev->dev, &usb_manufacturer_entry); + device_create_file (&dev->dev, &dev_attr_manufacturer); if (dev->descriptor.iProduct) - device_create_file (&dev->dev, &usb_product_entry); + device_create_file (&dev->dev, &dev_attr_product); if (dev->descriptor.iSerialNumber) - device_create_file (&dev->dev, &usb_serial_entry); + device_create_file (&dev->dev, &dev_attr_serial); /* now that the basic setup is over, add a /proc/bus/usb entry */ usbfs_add_device(dev); diff -Nru a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile --- a/drivers/usb/host/Makefile Thu Aug 1 14:17:41 2002 +++ b/drivers/usb/host/Makefile Thu Aug 1 14:17:41 2002 @@ -3,8 +3,6 @@ # framework and drivers # -export-objs := usb-ohci.o - obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_UHCI_HCD_ALT) += uhci-hcd.o diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c --- a/drivers/usb/host/ohci-q.c Thu Aug 1 14:17:41 2002 +++ b/drivers/usb/host/ohci-q.c Thu Aug 1 14:17:41 2002 @@ -534,6 +534,8 @@ /* aim for only one interrupt per urb. mostly applies to control * and iso; other urbs rarely need more than one TD per urb. * this way, only final tds (or ones with an error) cause IRQs. + * at least immediately; use DI=6 in case any control request is + * tempted to die part way through. * * NOTE: could delay interrupts even for the last TD, and get fewer * interrupts ... increasing per-urb latency by sharing interrupts. @@ -541,7 +543,7 @@ */ if (index != (urb_priv->length - 1) || (urb->transfer_flags & URB_NO_INTERRUPT)) - info |= TD_DI_SET (7); + info |= TD_DI_SET (6); /* use this td as the next dummy */ td_pt = urb_priv->td [index]; @@ -809,12 +811,16 @@ ohci->hcca->done_head = 0; while (td_list_hc) { + int cc; + td_list = dma_to_td (ohci, td_list_hc); td_list->hwINFO |= cpu_to_le32 (TD_DONE); - if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) { + cc = TD_CC_GET (le32_to_cpup (&td_list->hwINFO)); + if (cc != TD_CC_NOERROR) { urb_priv = (urb_priv_t *) td_list->urb->hcpriv; + /* Non-iso endpoints can halt on error; un-halt, * and dequeue any other TDs from this urb. * No other TD could have caused the halt. @@ -822,12 +828,21 @@ if (td_list->ed->hwHeadP & ED_H) { if (urb_priv && ((td_list->index + 1) < urb_priv->length)) { -#ifdef OHCI_VERBOSE_DEBUG - dbg ("urb %p TD %p (%d/%d), patch ED", - td_list->urb, td_list, + struct urb *urb = td_list->urb; + + /* help for troubleshooting: */ + dbg ("urb %p usb-%s-%s ep-%d-%s " + "(td %d/%d), " + "cc %d --> status %d", + td_list->urb, + urb->dev->bus->bus_name, + urb->dev->devpath, + usb_pipeendpoint (urb->pipe), + usb_pipein (urb->pipe) + ? "IN" : "OUT", 1 + td_list->index, - urb_priv->length); -#endif + urb_priv->length, + cc, cc_to_error [cc]); td_list->ed->hwHeadP = (urb_priv->td [urb_priv->length - 1]->hwNextTD & __constant_cpu_to_le32 (TD_MASK)) diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c --- a/drivers/usb/input/hiddev.c Thu Aug 1 14:17:40 2002 +++ b/drivers/usb/input/hiddev.c Thu Aug 1 14:17:40 2002 @@ -765,8 +765,11 @@ int __init hiddev_init(void) { - hiddev_devfs_handle = - devfs_mk_dir(devfs_find_handle(NULL, "usb", 0, 0, 0, 0), "hid", NULL); + devfs_handle_t de; + + de = devfs_get_handle(NULL, "usb", 0, 0, 0, 0); + hiddev_devfs_handle = devfs_mk_dir(de, "hid", NULL); + devfs_put(de); usb_register(&hiddev_driver); return 0; } diff -Nru a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c --- a/drivers/usb/misc/tiglusb.c Thu Aug 1 14:17:36 2002 +++ b/drivers/usb/misc/tiglusb.c Thu Aug 1 14:17:36 2002 @@ -476,7 +476,7 @@ } /* register device */ - if (devfs_register_chrdev (TIUSB_MAJOR, "tiglusb", &tiglusb_fops)) { + if (register_chrdev (TIUSB_MAJOR, "tiglusb", &tiglusb_fops)) { err ("unable to get major %d", TIUSB_MAJOR); return -EIO; } @@ -487,7 +487,7 @@ /* register USB module */ result = usb_register (&tiglusb_driver); if (result < 0) { - devfs_unregister_chrdev (TIUSB_MAJOR, "tiglusb"); + unregister_chrdev (TIUSB_MAJOR, "tiglusb"); return -1; } @@ -501,7 +501,7 @@ { usb_deregister (&tiglusb_driver); devfs_unregister (devfs_handle); - devfs_unregister_chrdev (TIUSB_MAJOR, "tiglusb"); + unregister_chrdev (TIUSB_MAJOR, "tiglusb"); } /* --------------------------------------------------------------------- */ diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c --- a/drivers/usb/storage/freecom.c Thu Aug 1 14:17:41 2002 +++ b/drivers/usb/storage/freecom.c Thu Aug 1 14:17:41 2002 @@ -40,43 +40,47 @@ static void pdump (void *, int); #endif +/* Bits of HD_STATUS */ +#define ERR_STAT 0x01 +#define DRQ_STAT 0x08 + struct freecom_udata { - __u8 buffer[64]; /* Common command block. */ + u8 buffer[64]; /* Common command block. */ }; typedef struct freecom_udata *freecom_udata_t; /* All of the outgoing packets are 64 bytes long. */ struct freecom_cb_wrap { - __u8 Type; /* Command type. */ - __u8 Timeout; /* Timeout in seconds. */ - __u8 Atapi[12]; /* An ATAPI packet. */ - __u8 Filler[50]; /* Padding Data. */ + u8 Type; /* Command type. */ + u8 Timeout; /* Timeout in seconds. */ + u8 Atapi[12]; /* An ATAPI packet. */ + u8 Filler[50]; /* Padding Data. */ }; struct freecom_xfer_wrap { - __u8 Type; /* Command type. */ - __u8 Timeout; /* Timeout in seconds. */ - __u32 Count; /* Number of bytes to transfer. */ - __u8 Pad[58]; + u8 Type; /* Command type. */ + u8 Timeout; /* Timeout in seconds. */ + u32 Count; /* Number of bytes to transfer. */ + u8 Pad[58]; } __attribute__ ((packed)); struct freecom_ide_out { - __u8 Type; /* Type + IDE register. */ - __u8 Pad; - __u16 Value; /* Value to write. */ - __u8 Pad2[60]; + u8 Type; /* Type + IDE register. */ + u8 Pad; + u16 Value; /* Value to write. */ + u8 Pad2[60]; }; struct freecom_ide_in { - __u8 Type; /* Type | IDE register. */ - __u8 Pad[63]; + u8 Type; /* Type | IDE register. */ + u8 Pad[63]; }; struct freecom_status { - __u8 Status; - __u8 Reason; - __u16 Count; - __u8 Pad[60]; + u8 Status; + u8 Reason; + u16 Count; + u8 Pad[60]; }; /* Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide diff -Nru a/drivers/video/aty/Makefile b/drivers/video/aty/Makefile --- a/drivers/video/aty/Makefile Thu Aug 1 14:17:39 2002 +++ b/drivers/video/aty/Makefile Thu Aug 1 14:17:39 2002 @@ -1,6 +1,3 @@ - -export-objs := atyfb_base.o mach64_accel.o - obj-$(CONFIG_FB_ATY) += atyfb.o atyfb-y := atyfb_base.o mach64_accel.o ../cfbimgblt.o diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c --- a/drivers/video/fbmem.c Thu Aug 1 14:17:36 2002 +++ b/drivers/video/fbmem.c Thu Aug 1 14:17:36 2002 @@ -845,7 +845,7 @@ create_proc_read_entry("fb", 0, 0, fbmem_read_proc, NULL); devfs_handle = devfs_mk_dir (NULL, "fb", NULL); - if (devfs_register_chrdev(FB_MAJOR,"fb",&fb_fops)) + if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) printk("unable to get major %d for fb devs\n", FB_MAJOR); #ifdef CONFIG_FB_OF diff -Nru a/drivers/video/modedb.c b/drivers/video/modedb.c --- a/drivers/video/modedb.c Thu Aug 1 14:17:40 2002 +++ b/drivers/video/modedb.c Thu Aug 1 14:17:40 2002 @@ -111,10 +111,6 @@ NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, 0, FB_VMODE_INTERLACED }, { - /* 1400x1050 @ 60Hz, 63.9 kHz hsync */ - NULL, 68, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3, - 0, FB_VMODE_NONINTERLACED - }, { /* 800x600 @ 100 Hz, 64.02 kHz hsync */ NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, 0, FB_VMODE_NONINTERLACED diff -Nru a/fs/Config.in b/fs/Config.in --- a/fs/Config.in Thu Aug 1 14:17:41 2002 +++ b/fs/Config.in Thu Aug 1 14:17:41 2002 @@ -26,7 +26,7 @@ dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL -tristate 'Ext3 journalling file system support (EXPERIMENTAL)' CONFIG_EXT3_FS +tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS # CONFIG_JBD could be its own option (even modular), but until there are # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS diff -Nru a/fs/Makefile b/fs/Makefile --- a/fs/Makefile Thu Aug 1 14:17:36 2002 +++ b/fs/Makefile Thu Aug 1 14:17:36 2002 @@ -7,8 +7,7 @@ O_TARGET := fs.o -export-objs := filesystems.o open.o dcache.o buffer.o bio.o inode.o dquot.o \ - mpage.o +export-objs := open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o obj-y := open.o read_write.o devices.o file_table.o buffer.o \ bio.o super.o block_dev.o char_dev.o stat.o exec.o pipe.o \ diff -Nru a/fs/adfs/file.c b/fs/adfs/file.c --- a/fs/adfs/file.c Thu Aug 1 14:17:37 2002 +++ b/fs/adfs/file.c Thu Aug 1 14:17:37 2002 @@ -36,6 +36,7 @@ mmap: generic_file_mmap, fsync: file_fsync, write: generic_file_write, + sendfile: generic_file_sendfile, }; struct inode_operations adfs_file_inode_operations = { diff -Nru a/fs/affs/file.c b/fs/affs/file.c --- a/fs/affs/file.c Thu Aug 1 14:17:40 2002 +++ b/fs/affs/file.c Thu Aug 1 14:17:40 2002 @@ -50,6 +50,7 @@ open: affs_file_open, release: affs_file_release, fsync: file_fsync, + sendfile: generic_file_sendfile, }; struct inode_operations affs_file_inode_operations = { diff -Nru a/fs/bfs/file.c b/fs/bfs/file.c --- a/fs/bfs/file.c Thu Aug 1 14:17:36 2002 +++ b/fs/bfs/file.c Thu Aug 1 14:17:36 2002 @@ -18,10 +18,11 @@ #endif struct file_operations bfs_file_operations = { - llseek: generic_file_llseek, - read: generic_file_read, - write: generic_file_write, - mmap: generic_file_mmap, + llseek: generic_file_llseek, + read: generic_file_read, + write: generic_file_write, + mmap: generic_file_mmap, + sendfile: generic_file_sendfile, }; static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb) diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c --- a/fs/binfmt_elf.c Thu Aug 1 14:17:40 2002 +++ b/fs/binfmt_elf.c Thu Aug 1 14:17:40 2002 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -1249,7 +1250,7 @@ flush_page_to_ram(page); kunmap(page); } - put_page(page); + page_cache_release(page); } } } diff -Nru a/fs/block_dev.c b/fs/block_dev.c --- a/fs/block_dev.c Thu Aug 1 14:17:41 2002 +++ b/fs/block_dev.c Thu Aug 1 14:17:41 2002 @@ -24,14 +24,14 @@ #include -static unsigned long max_block(struct block_device *bdev) +static sector_t max_block(struct block_device *bdev) { - unsigned int retval = ~0U; + sector_t retval = ~0U; loff_t sz = bdev->bd_inode->i_size; if (sz) { - unsigned int size = block_size(bdev); - unsigned int sizebits = blksize_bits(size); + sector_t size = block_size(bdev); + unsigned sizebits = blksize_bits(size); retval = (sz >> sizebits); } return retval; @@ -88,7 +88,9 @@ return sb_set_blocksize(sb, size); } -static int blkdev_get_block(struct inode * inode, sector_t iblock, struct buffer_head * bh, int create) +static int +blkdev_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh, int create) { if (iblock >= max_block(inode->i_bdev)) return -EIO; @@ -100,11 +102,25 @@ } static int +blkdev_get_blocks(struct inode *inode, sector_t iblock, + unsigned long max_blocks, struct buffer_head *bh, int create) +{ + if ((iblock + max_blocks) >= max_block(inode->i_bdev)) + return -EIO; + + bh->b_bdev = inode->i_bdev; + bh->b_blocknr = iblock; + bh->b_size = max_blocks << inode->i_blkbits; + set_buffer_mapped(bh); + return 0; +} + +static int blkdev_direct_IO(int rw, struct inode *inode, char *buf, loff_t offset, size_t count) { return generic_direct_IO(rw, inode, buf, offset, - count, blkdev_get_block); + count, blkdev_get_blocks); } static int blkdev_writepage(struct page * page) @@ -437,6 +453,8 @@ int register_blkdev(unsigned int major, const char * name, struct block_device_operations *bdops) { + if (devfs_only()) + return 0; if (major == 0) { for (major = MAX_BLKDEV-1; major > 0; major--) { if (blkdevs[major].bdops == NULL) { @@ -458,6 +476,8 @@ int unregister_blkdev(unsigned int major, const char * name) { + if (devfs_only()) + return 0; if (major >= MAX_BLKDEV) return -EINVAL; if (!blkdevs[major].bdops) @@ -489,11 +509,12 @@ if (bdops == NULL) { devfs_handle_t de; - de = devfs_find_handle (NULL, NULL, i, minor(dev), - DEVFS_SPECIAL_BLK, 0); + de = devfs_get_handle(NULL, NULL, i, minor(dev), + DEVFS_SPECIAL_BLK, 0); if (de) { - bdops = devfs_get_ops (de); - devfs_put_ops (de); /* We're running in owner module */ + bdops = devfs_get_ops(de); + devfs_put_ops(de); /* We're running in owner module */ + devfs_put(de); } } if (bdops == NULL) @@ -578,9 +599,10 @@ bdev->bd_offset = 0; if (g) { - bdev->bd_inode->i_size = - (loff_t) g->part[minor(dev)].nr_sects << 9; - bdev->bd_offset = g->part[minor(dev)].start_sect; + struct hd_struct *p; + p = g->part + minor(dev) - g->first_minor; + bdev->bd_inode->i_size = (loff_t) p->nr_sects << 9; + bdev->bd_offset = p->start_sect; } else if (blk_size[major(dev)]) bdev->bd_inode->i_size = (loff_t) blk_size[major(dev)][minor(dev)] << 10; @@ -774,6 +796,7 @@ mmap: generic_file_mmap, fsync: block_fsync, ioctl: blkdev_ioctl, + sendfile: generic_file_sendfile, }; int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) diff -Nru a/fs/buffer.c b/fs/buffer.c --- a/fs/buffer.c Thu Aug 1 14:17:36 2002 +++ b/fs/buffer.c Thu Aug 1 14:17:36 2002 @@ -448,9 +448,7 @@ * We really want to use invalidate_inode_pages2() for * that, but not until that's cleaned up. */ - current->flags |= PF_INVALIDATE; invalidate_inode_pages(bdev->bd_inode); - current->flags &= ~PF_INVALIDATE; } void __invalidate_buffers(kdev_t dev, int destroy_dirty_buffers) @@ -514,9 +512,8 @@ if (!buffer_uptodate(tmp)) page_uptodate = 0; if (buffer_async_read(tmp)) { - if (buffer_locked(tmp)) - goto still_busy; - BUG(); + BUG_ON(!buffer_locked(tmp)); + goto still_busy; } tmp = tmp->b_this_page; } while (tmp != bh); @@ -564,9 +561,8 @@ tmp = bh->b_this_page; while (tmp != bh) { if (buffer_async_write(tmp)) { - if (buffer_locked(tmp)) - goto still_busy; - BUG(); + BUG_ON(!buffer_locked(tmp)); + goto still_busy; } tmp = tmp->b_this_page; } diff -Nru a/fs/coda/psdev.c b/fs/coda/psdev.c --- a/fs/coda/psdev.c Thu Aug 1 14:17:41 2002 +++ b/fs/coda/psdev.c Thu Aug 1 14:17:41 2002 @@ -366,7 +366,7 @@ static int init_coda_psdev(void) { - if(devfs_register_chrdev(CODA_PSDEV_MAJOR,"coda_psdev", + if(register_chrdev(CODA_PSDEV_MAJOR,"coda_psdev", &coda_psdev_fops)) { printk(KERN_ERR "coda_psdev: unable to get major %d\n", CODA_PSDEV_MAJOR); @@ -411,7 +411,7 @@ return 0; out: devfs_unregister(devfs_handle); - devfs_unregister_chrdev(CODA_PSDEV_MAJOR,"coda_psdev"); + unregister_chrdev(CODA_PSDEV_MAJOR,"coda_psdev"); coda_sysctl_clean(); out1: coda_destroy_inodecache(); @@ -428,7 +428,7 @@ printk("coda: failed to unregister filesystem\n"); } devfs_unregister(devfs_handle); - devfs_unregister_chrdev(CODA_PSDEV_MAJOR, "coda_psdev"); + unregister_chrdev(CODA_PSDEV_MAJOR, "coda_psdev"); coda_sysctl_clean(); coda_destroy_inodecache(); } diff -Nru a/fs/coda/sysctl.c b/fs/coda/sysctl.c --- a/fs/coda/sysctl.c Thu Aug 1 14:17:40 2002 +++ b/fs/coda/sysctl.c Thu Aug 1 14:17:40 2002 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c --- a/fs/devfs/base.c Thu Aug 1 14:17:36 2002 +++ b/fs/devfs/base.c Thu Aug 1 14:17:36 2002 @@ -639,6 +639,12 @@ 20020722 Richard Gooch Fixed devfs entry leak in when *readdir fails. v1.18 + 20020725 Richard Gooch + Created . + v1.19 + 20020728 Richard Gooch + Removed deprecated . + v1.20 */ #include #include @@ -671,7 +677,7 @@ #include #include -#define DEVFS_VERSION "1.18 (20020722)" +#define DEVFS_VERSION "1.20 (20020728)" #define DEVFS_NAME "devfs" @@ -1881,19 +1887,15 @@ return _devfs_find_entry (dir, name, major, minor, type,traverse_symlinks); } /* End Function devfs_get_handle */ - -/* Compatibility function. Will be removed in sometime in 2.5 */ - -devfs_handle_t devfs_find_handle (devfs_handle_t dir, const char *name, - unsigned int major, unsigned int minor, - char type, int traverse_symlinks) -{ - devfs_handle_t de; - - de = devfs_get_handle (dir, name, major, minor, type, traverse_symlinks); +void devfs_find_and_unregister (devfs_handle_t dir, const char *name, + unsigned int major, unsigned int minor, + char type, int traverse_symlinks) +{ + devfs_handle_t de = devfs_get_handle (dir, name, major, minor, + type, traverse_symlinks); + devfs_unregister (de); devfs_put (de); - return de; -} /* End Function devfs_find_handle */ +} /** @@ -2226,75 +2228,17 @@ /** - * devfs_register_chrdev - Optionally register a conventional character driver. - * @major: The major number for the driver. - * @name: The name of the driver (as seen in /proc/devices). - * @fops: The &file_operations structure pointer. - * - * This function will register a character driver provided the "devfs=only" - * option was not provided at boot time. - * Returns 0 on success, else a negative error code on failure. - */ - -int devfs_register_chrdev (unsigned int major, const char *name, - struct file_operations *fops) -{ - if (boot_options & OPTION_ONLY) return 0; - return register_chrdev (major, name, fops); -} /* End Function devfs_register_chrdev */ - - -/** - * devfs_register_blkdev - Optionally register a conventional block driver. - * @major: The major number for the driver. - * @name: The name of the driver (as seen in /proc/devices). - * @bdops: The &block_device_operations structure pointer. - * - * This function will register a block driver provided the "devfs=only" - * option was not provided at boot time. - * Returns 0 on success, else a negative error code on failure. - */ - -int devfs_register_blkdev (unsigned int major, const char *name, - struct block_device_operations *bdops) -{ - if (boot_options & OPTION_ONLY) return 0; - return register_blkdev (major, name, bdops); -} /* End Function devfs_register_blkdev */ - - -/** - * devfs_unregister_chrdev - Optionally unregister a conventional character driver. - * @major: The major number for the driver. - * @name: The name of the driver (as seen in /proc/devices). + * devfs_only - returns if "devfs=only" is a boot option * - * This function will unregister a character driver provided the "devfs=only" - * option was not provided at boot time. - * Returns 0 on success, else a negative error code on failure. + * If "devfs=only" this function will return 1, otherwise 0 is returned. */ - -int devfs_unregister_chrdev (unsigned int major, const char *name) +int devfs_only (void) { - if (boot_options & OPTION_ONLY) return 0; - return unregister_chrdev (major, name); -} /* End Function devfs_unregister_chrdev */ - - -/** - * devfs_unregister_blkdev - Optionally unregister a conventional block driver. - * @major: The major number for the driver. - * @name: The name of the driver (as seen in /proc/devices). - * - * This function will unregister a block driver provided the "devfs=only" - * option was not provided at boot time. - * Returns 0 on success, else a negative error code on failure. - */ + if (boot_options & OPTION_ONLY) + return 1; + return 0; +} -int devfs_unregister_blkdev (unsigned int major, const char *name) -{ - if (boot_options & OPTION_ONLY) return 0; - return unregister_blkdev (major, name); -} /* End Function devfs_unregister_blkdev */ /** * devfs_setup - Process kernel boot options. @@ -2368,7 +2312,6 @@ EXPORT_SYMBOL(devfs_mk_symlink); EXPORT_SYMBOL(devfs_mk_dir); EXPORT_SYMBOL(devfs_get_handle); -EXPORT_SYMBOL(devfs_find_handle); EXPORT_SYMBOL(devfs_get_flags); EXPORT_SYMBOL(devfs_set_flags); EXPORT_SYMBOL(devfs_get_maj_min); @@ -2384,10 +2327,6 @@ EXPORT_SYMBOL(devfs_auto_unregister); EXPORT_SYMBOL(devfs_get_unregister_slave); EXPORT_SYMBOL(devfs_get_name); -EXPORT_SYMBOL(devfs_register_chrdev); -EXPORT_SYMBOL(devfs_register_blkdev); -EXPORT_SYMBOL(devfs_unregister_chrdev); -EXPORT_SYMBOL(devfs_unregister_blkdev); /** diff -Nru a/fs/devices.c b/fs/devices.c --- a/fs/devices.c Thu Aug 1 14:17:40 2002 +++ b/fs/devices.c Thu Aug 1 14:17:40 2002 @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef CONFIG_KMOD #include @@ -97,6 +98,8 @@ int register_chrdev(unsigned int major, const char * name, struct file_operations *fops) { + if (devfs_only()) + return 0; if (major == 0) { write_lock(&chrdevs_lock); for (major = MAX_CHRDEV-1; major > 0; major--) { @@ -125,6 +128,8 @@ int unregister_chrdev(unsigned int major, const char * name) { + if (devfs_only()) + return 0; if (major >= MAX_CHRDEV) return -EINVAL; write_lock(&chrdevs_lock); diff -Nru a/fs/direct-io.c b/fs/direct-io.c --- a/fs/direct-io.c Thu Aug 1 14:17:36 2002 +++ b/fs/direct-io.c Thu Aug 1 14:17:36 2002 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -39,13 +40,17 @@ struct bio_vec *bvec; /* current bvec in that bio */ struct inode *inode; int rw; + unsigned blkbits; /* doesn't change */ sector_t block_in_file; /* changes */ + unsigned blocks_available; /* At block_in_file. changes */ sector_t final_block_in_request;/* doesn't change */ - unsigned first_block_in_page; /* doesn't change */ + unsigned first_block_in_page; /* doesn't change, Used only once */ int boundary; /* prev block is at a boundary */ int reap_counter; /* rate limit reaping */ - get_block_t *get_block; - sector_t last_block_in_bio; + get_blocks_t *get_blocks; /* block mapping function */ + sector_t last_block_in_bio; /* current final block in bio */ + sector_t next_block_in_bio; /* next block to be added to bio */ + struct buffer_head map_bh; /* last get_blocks() result */ /* Page fetching state */ int curr_page; /* changes */ @@ -53,15 +58,16 @@ unsigned long curr_user_address;/* changes */ /* Page queue */ - struct page *pages[DIO_PAGES]; - unsigned head; - unsigned tail; + struct page *pages[DIO_PAGES]; /* page buffer */ + unsigned head; /* next page to process */ + unsigned tail; /* last valid page + 1 */ + int page_errors; /* errno from get_user_pages() */ /* BIO completion state */ - atomic_t bio_count; - spinlock_t bio_list_lock; + atomic_t bio_count; /* nr bios in flight */ + spinlock_t bio_list_lock; /* protects bio_list */ struct bio *bio_list; /* singly linked via bi_private */ - struct task_struct *waiter; + struct task_struct *waiter; /* waiting task (NULL if none) */ }; /* @@ -93,6 +99,21 @@ NULL); /* vmas */ up_read(¤t->mm->mmap_sem); + if (ret < 0 && dio->blocks_available && (dio->rw == WRITE)) { + /* + * A memory fault, but the filesystem has some outstanding + * mapped blocks. We need to use those blocks up to avoid + * leaking stale data in the file. + */ + if (dio->page_errors == 0) + dio->page_errors = ret; + dio->pages[0] = ZERO_PAGE(dio->cur_user_address); + dio->head = 0; + dio->tail = 1; + ret = 0; + goto out; + } + if (ret >= 0) { dio->curr_user_address += ret * PAGE_SIZE; dio->curr_page += ret; @@ -100,6 +121,7 @@ dio->tail = ret; ret = 0; } +out: return ret; } @@ -115,11 +137,8 @@ int ret; ret = dio_refill_pages(dio); - if (ret) { - printk("%s: dio_refill_pages returns %d\n", - __FUNCTION__, ret); + if (ret) return ERR_PTR(ret); - } BUG_ON(dio_pages_present(dio) == 0); } return dio->pages[dio->head++]; @@ -140,8 +159,9 @@ spin_lock_irqsave(&dio->bio_list_lock, flags); bio->bi_private = dio->bio_list; dio->bio_list = bio; + if (dio->waiter) + wake_up_process(dio->waiter); spin_unlock_irqrestore(&dio->bio_list_lock, flags); - wake_up_process(dio->waiter); } static int @@ -179,6 +199,7 @@ dio->bio = NULL; dio->bvec = NULL; + dio->boundary = 0; } /* @@ -202,10 +223,12 @@ while (dio->bio_list == NULL) { set_current_state(TASK_UNINTERRUPTIBLE); if (dio->bio_list == NULL) { + dio->waiter = current; spin_unlock_irqrestore(&dio->bio_list_lock, flags); blk_run_queues(); schedule(); spin_lock_irqsave(&dio->bio_list_lock, flags); + dio->waiter = NULL; } set_current_state(TASK_RUNNING); } @@ -268,15 +291,12 @@ while (dio->bio_list) { unsigned long flags; struct bio *bio; - int ret2; spin_lock_irqsave(&dio->bio_list_lock, flags); bio = dio->bio_list; dio->bio_list = bio->bi_private; spin_unlock_irqrestore(&dio->bio_list_lock, flags); - ret2 = dio_bio_complete(dio, bio); - if (ret == 0) - ret = ret2; + ret = dio_bio_complete(dio, bio); } dio->reap_counter = 0; } @@ -284,13 +304,129 @@ } /* + * Call into the fs to map some more disk blocks. We record the current number + * of available blocks at dio->blocks_available. These are in units of the + * fs blocksize, (1 << inode->i_blkbits). + * + * The fs is allowed to map lots of blocks at once. If it wants to do that, + * it uses the passed inode-relative block number as the file offset, as usual. + * + * get_blocks() is passed the number of i_blkbits-sized blocks which direct_io + * has remaining to do. The fs should not map more than this number of blocks. + * + * If the fs has mapped a lot of blocks, it should populate bh->b_size to + * indicate how much contiguous disk space has been made available at + * bh->b_blocknr. + * + * If *any* of the mapped blocks are new, then the fs must set buffer_new(). + * This isn't very efficient... + * + * In the case of filesystem holes: the fs may return an arbitrarily-large + * hole by returning an appropriate value in b_size and by clearing + * buffer_mapped(). This code _should_ handle that case correctly, but it has + * only been tested against single-block holes (b_size == blocksize). + */ +static int get_more_blocks(struct dio *dio) +{ + int ret; + struct buffer_head *map_bh = &dio->map_bh; + + if (dio->blocks_available) + return 0; + + /* + * If there was a memory error and we've overwritten all the + * mapped blocks then we can now return that memory error + */ + if (dio->page_errors) { + ret = dio->page_errors; + goto out; + } + + map_bh->b_state = 0; + map_bh->b_size = 0; + BUG_ON(dio->block_in_file >= dio->final_block_in_request); + ret = (*dio->get_blocks)(dio->inode, dio->block_in_file, + dio->final_block_in_request - dio->block_in_file, + map_bh, dio->rw == WRITE); + if (ret) + goto out; + + if (buffer_mapped(map_bh)) { + BUG_ON(map_bh->b_size == 0); + BUG_ON((map_bh->b_size & ((1 << dio->blkbits) - 1)) != 0); + + dio->blocks_available = map_bh->b_size >> dio->blkbits; + + /* blockdevs do not set buffer_new */ + if (buffer_new(map_bh)) { + sector_t block = map_bh->b_blocknr; + unsigned i; + + for (i = 0; i < dio->blocks_available; i++) + unmap_underlying_metadata(map_bh->b_bdev, + block++); + } + } else { + BUG_ON(dio->rw != READ); + if (dio->bio) + dio_bio_submit(dio); + } + dio->next_block_in_bio = map_bh->b_blocknr; +out: + return ret; +} + +/* + * Check to see if we can continue to grow the BIO. If not, then send it. + */ +static void dio_prep_bio(struct dio *dio) +{ + if (dio->bio == NULL) + return; + + if (dio->bio->bi_idx == dio->bio->bi_vcnt || + dio->boundary || + dio->last_block_in_bio != dio->next_block_in_bio - 1) + dio_bio_submit(dio); +} + +/* + * There is no bio. Make one now. + */ +static int dio_new_bio(struct dio *dio) +{ + sector_t sector; + int ret; + + ret = dio_bio_reap(dio); + if (ret) + goto out; + sector = dio->next_block_in_bio << (dio->blkbits - 9); + ret = dio_bio_alloc(dio, dio->map_bh.b_bdev, sector, + DIO_BIO_MAX_SIZE / PAGE_SIZE); + dio->boundary = 0; +out: + return ret; +} + +/* * Walk the user pages, and the file, mapping blocks to disk and emitting BIOs. + * + * Direct IO against a blockdev is different from a file. Because we can + * happily perform page-sized but 512-byte aligned IOs. It is important that + * blockdev IO be able to have fine alignment and large sizes. + * + * So what we do is to permit the ->get_blocks function to populate bh.b_size + * with the size of IO which is permitted at this offset and this i_blkbits. + * + * For best results, the blockdev should be set up with 512-byte i_blkbits and + * it should set b_size to PAGE_SIZE or more inside get_blocks(). This gives + * fine alignment but still allows this function to work in PAGE_SIZE units. */ int do_direct_IO(struct dio *dio) { - struct inode * const inode = dio->inode; - const unsigned blkbits = inode->i_blkbits; - const unsigned blocksize = 1 << blkbits; + const unsigned blkbits = dio->blkbits; const unsigned blocks_per_page = PAGE_SIZE >> blkbits; struct page *page; unsigned block_in_page; @@ -309,46 +445,35 @@ } new_page = 1; - for ( ; block_in_page < blocks_per_page; block_in_page++) { - struct buffer_head map_bh; + while (block_in_page < blocks_per_page) { struct bio *bio; + unsigned this_chunk_bytes; /* # of bytes mapped */ + unsigned this_chunk_blocks; /* # of blocks */ + unsigned u; - map_bh.b_state = 0; - ret = (*dio->get_block)(inode, dio->block_in_file, - &map_bh, dio->rw == WRITE); - if (ret) { - printk("%s: get_block returns %d\n", - __FUNCTION__, ret); + ret = get_more_blocks(dio); + if (ret) goto fail_release; + + /* Handle holes */ + if (!buffer_mapped(&dio->map_bh)) { + char *kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr + (block_in_page << blkbits), + 0, 1 << blkbits); + flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); + dio->block_in_file++; + dio->next_block_in_bio++; + block_in_page++; + goto next_block; } - /* blockdevs do not set buffer_new */ - if (buffer_new(&map_bh)) - unmap_underlying_metadata(map_bh.b_bdev, - map_bh.b_blocknr); - if (!buffer_mapped(&map_bh)) { - ret = -EINVAL; /* A hole */ - goto fail_release; - } - if (dio->bio) { - if (dio->bio->bi_idx == dio->bio->bi_vcnt || - dio->boundary || - dio->last_block_in_bio != - map_bh.b_blocknr - 1) { - dio_bio_submit(dio); - dio->boundary = 0; - } - } + + dio_prep_bio(dio); if (dio->bio == NULL) { - ret = dio_bio_reap(dio); - if (ret) - goto fail_release; - ret = dio_bio_alloc(dio, map_bh.b_bdev, - map_bh.b_blocknr << (blkbits - 9), - DIO_BIO_MAX_SIZE / PAGE_SIZE); + ret = dio_new_bio(dio); if (ret) goto fail_release; new_page = 1; - dio->boundary = 0; } bio = dio->bio; @@ -357,17 +482,34 @@ page_cache_get(page); dio->bvec->bv_page = page; dio->bvec->bv_len = 0; - dio->bvec->bv_offset = block_in_page*blocksize; + dio->bvec->bv_offset = block_in_page << blkbits; bio->bi_idx++; + new_page = 0; } - new_page = 0; - dio->bvec->bv_len += blocksize; - bio->bi_size += blocksize; - dio->last_block_in_bio = map_bh.b_blocknr; - dio->boundary = buffer_boundary(&map_bh); - dio->block_in_file++; - if (dio->block_in_file >= dio->final_block_in_request) + /* Work out how much disk we can add to this page */ + this_chunk_blocks = dio->blocks_available; + u = (PAGE_SIZE - dio->bvec->bv_len) >> blkbits; + if (this_chunk_blocks > u) + this_chunk_blocks = u; + u = dio->final_block_in_request - dio->block_in_file; + if (this_chunk_blocks > u) + this_chunk_blocks = u; + this_chunk_bytes = this_chunk_blocks << blkbits; + BUG_ON(this_chunk_bytes == 0); + + dio->bvec->bv_len += this_chunk_bytes; + bio->bi_size += this_chunk_bytes; + dio->next_block_in_bio += this_chunk_blocks; + dio->last_block_in_bio = dio->next_block_in_bio - 1; + dio->boundary = buffer_boundary(&dio->map_bh); + dio->block_in_file += this_chunk_blocks; + block_in_page += this_chunk_blocks; + dio->blocks_available -= this_chunk_blocks; +next_block: + if (dio->block_in_file > dio->final_block_in_request) + BUG(); + if (dio->block_in_file == dio->final_block_in_request) break; } block_in_page = 0; @@ -381,11 +523,16 @@ return ret; } +/* + * The main direct-IO function. This is a library function for use by + * filesystem drivers. + */ int generic_direct_IO(int rw, struct inode *inode, char *buf, loff_t offset, - size_t count, get_block_t get_block) + size_t count, get_blocks_t get_blocks) { - const unsigned blocksize_mask = (1 << inode->i_blkbits) - 1; + const unsigned blkbits = inode->i_blkbits; + const unsigned blocksize_mask = (1 << blkbits) - 1; const unsigned long user_addr = (unsigned long)buf; int ret; int ret2; @@ -403,16 +550,18 @@ dio.bvec = NULL; dio.inode = inode; dio.rw = rw; - dio.block_in_file = offset >> inode->i_blkbits; - dio.final_block_in_request = (offset + count) >> inode->i_blkbits; + dio.blkbits = blkbits; + dio.block_in_file = offset >> blkbits; + dio.blocks_available = 0; + dio.final_block_in_request = (offset + count) >> blkbits; /* Index into the first page of the first block */ - dio.first_block_in_page = (user_addr & (PAGE_SIZE - 1)) - >> inode->i_blkbits; + dio.first_block_in_page = (user_addr & (PAGE_SIZE - 1)) >> blkbits; dio.boundary = 0; dio.reap_counter = 0; - dio.get_block = get_block; + dio.get_blocks = get_blocks; dio.last_block_in_bio = -1; + dio.next_block_in_bio = -1; /* Page fetching state */ dio.curr_page = 0; @@ -428,12 +577,13 @@ /* Page queue */ dio.head = 0; dio.tail = 0; + dio.page_errors = 0; /* BIO completion state */ atomic_set(&dio.bio_count, 0); spin_lock_init(&dio.bio_list_lock); dio.bio_list = NULL; - dio.waiter = current; + dio.waiter = NULL; ret = do_direct_IO(&dio); @@ -445,8 +595,10 @@ if (ret == 0) ret = ret2; if (ret == 0) + ret = dio.page_errors; + if (ret == 0) ret = count - ((dio.final_block_in_request - - dio.block_in_file) << inode->i_blkbits); + dio.block_in_file) << blkbits); out: return ret; } @@ -473,6 +625,8 @@ goto out; } retval = mapping->a_ops->direct_IO(rw, inode, buf, offset, count); + if (inode->i_mapping->nrpages) + invalidate_inode_pages2(inode->i_mapping); out: return retval; } diff -Nru a/fs/driverfs/inode.c b/fs/driverfs/inode.c --- a/fs/driverfs/inode.c Thu Aug 1 14:17:36 2002 +++ b/fs/driverfs/inode.c Thu Aug 1 14:17:36 2002 @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include @@ -50,7 +50,6 @@ static struct super_operations driverfs_ops; static struct file_operations driverfs_file_operations; static struct inode_operations driverfs_dir_inode_operations; -static struct dentry_operations driverfs_dentry_file_ops; static struct address_space_operations driverfs_aops; static struct vfsmount *driverfs_mount; @@ -139,7 +138,7 @@ /* only allow create if ->d_fsdata is not NULL (so we can assume it * comes from the driverfs API below. */ - if (dentry->d_fsdata && inode) { + if (inode) { d_instantiate(dentry, inode); dget(dentry); error = 0; @@ -161,7 +160,6 @@ { int res; mode = (mode & S_IALLUGO) | S_IFREG; - dentry->d_op = &driverfs_dentry_file_ops; res = driverfs_mknod(dir, dentry, mode, 0); return res; } @@ -268,7 +266,7 @@ * * Userspace wants data from a file. It is up to the creator of the file to * provide that data. - * There is a struct driver_file_entry embedded in file->private_data. We + * There is a struct device_attribute embedded in file->private_data. We * obtain that and check if the read callback is implemented. If so, we call * it, passing the data field of the file entry. * Said callback is responsible for filling the buffer and returning the number @@ -277,24 +275,18 @@ static ssize_t driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos) { - struct driver_file_entry * entry; + struct attribute * attr = file->f_dentry->d_fsdata; + struct driver_dir_entry * dir; unsigned char *page; ssize_t retval = 0; - struct device * dev; - entry = (struct driver_file_entry *)file->private_data; - if (!entry) { - DBG("%s: file entry is NULL\n",__FUNCTION__); - return -ENOENT; - } - if (!entry->show) + dir = file->f_dentry->d_parent->d_fsdata; + if (!dir->ops->show) return 0; if (count > PAGE_SIZE) count = PAGE_SIZE; - dev = to_device(entry->parent); - page = (unsigned char*)__get_free_page(GFP_KERNEL); if (!page) return -ENOMEM; @@ -302,7 +294,7 @@ while (count > 0) { ssize_t len; - len = entry->show(dev,page,count,*ppos); + len = dir->ops->show(dir,attr,page,count,*ppos); if (len <= 0) { if (len < 0) @@ -341,20 +333,12 @@ static ssize_t driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *ppos) { - struct driver_file_entry * entry; - struct device * dev; + struct attribute * attr = file->f_dentry->d_fsdata; + struct driver_dir_entry * dir; ssize_t retval = 0; char * page; - entry = (struct driver_file_entry *)file->private_data; - if (!entry) { - DBG("%s: file entry is NULL\n",__FUNCTION__); - return -ENOENT; - } - if (!entry->store) - return 0; - - dev = to_device(entry->parent); + dir = file->f_dentry->d_parent->d_fsdata; page = (char *)__get_free_page(GFP_KERNEL); if (!page) @@ -369,7 +353,7 @@ while (count > 0) { ssize_t len; - len = entry->store(dev,page + retval,count,*ppos); + len = dir->ops->store(dir,attr,page + retval,count,*ppos); if (len <= 0) { if (len < 0) @@ -414,38 +398,29 @@ static int driverfs_open_file(struct inode * inode, struct file * filp) { - struct driver_file_entry * entry; - struct device * dev; + struct driver_dir_entry * dir; + int error = 0; - entry = (struct driver_file_entry *)inode->u.generic_ip; - if (!entry) - return -EFAULT; - dev = to_device(entry->parent); - get_device(dev); - filp->private_data = entry; - return 0; + dir = (struct driver_dir_entry *)filp->f_dentry->d_parent->d_fsdata; + if (dir) { + struct attribute * attr = filp->f_dentry->d_fsdata; + if (attr && dir->ops) { + if (dir->ops->open) + error = dir->ops->open(dir); + goto Done; + } + } + error = -EINVAL; + Done: + return error; } static int driverfs_release(struct inode * inode, struct file * filp) { - struct driver_file_entry * entry; - struct device * dev; - - entry = (struct driver_file_entry *)filp->private_data; - if (!entry) - return -EFAULT; - dev = to_device(entry->parent); - put_device(dev); - return 0; -} - -static int driverfs_d_delete_file (struct dentry * dentry) -{ - struct driver_file_entry * entry; - - entry = (struct driver_file_entry *)dentry->d_fsdata; - if (entry) - kfree(entry); + struct driver_dir_entry * dir; + dir = (struct driver_dir_entry *)filp->f_dentry->d_parent->d_fsdata; + if (dir->ops->close) + dir->ops->close(dir); return 0; } @@ -468,10 +443,6 @@ .commit_write = driverfs_commit_write }; -static struct dentry_operations driverfs_dentry_file_ops = { - .d_delete = driverfs_d_delete_file, -}; - static struct super_operations driverfs_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, @@ -572,6 +543,16 @@ return register_filesystem(&driverfs_fs_type); } +static struct dentry * get_dentry(struct dentry * parent, const char * name) +{ + struct qstr qstr; + + qstr.name = name; + qstr.len = strlen(name); + qstr.hash = full_name_hash(name,qstr.len); + return lookup_hash(&qstr,parent); +} + /** * driverfs_create_dir - create a directory in the filesystem * @entry: directory entry @@ -583,7 +564,6 @@ { struct dentry * dentry = NULL; struct dentry * parent_dentry; - struct qstr qstr; int error = 0; if (!entry) @@ -603,10 +583,7 @@ } down(&parent_dentry->d_inode->i_sem); - qstr.name = entry->name; - qstr.len = strlen(entry->name); - qstr.hash = full_name_hash(entry->name,qstr.len); - dentry = lookup_hash(&qstr,parent_dentry); + dentry = get_dentry(parent_dentry,entry->name); if (!IS_ERR(dentry)) { dentry->d_fsdata = (void *) entry; entry->dentry = dentry; @@ -626,11 +603,10 @@ * @parent: directory to create it in */ int -driverfs_create_file(struct driver_file_entry * entry, +driverfs_create_file(struct attribute * entry, struct driver_dir_entry * parent) { struct dentry * dentry; - struct qstr qstr; int error = 0; if (!entry || !parent) @@ -645,21 +621,10 @@ } down(&parent->dentry->d_inode->i_sem); - qstr.name = entry->name; - qstr.len = strlen(entry->name); - qstr.hash = full_name_hash(entry->name,qstr.len); - dentry = lookup_hash(&qstr,parent->dentry); + dentry = get_dentry(parent->dentry,entry->name); if (!IS_ERR(dentry)) { dentry->d_fsdata = (void *)entry; error = driverfs_create(parent->dentry->d_inode,dentry,entry->mode); - - /* Still good? Ok, then fill in the blanks: */ - if (!error) { - dentry->d_inode->u.generic_ip = (void *)entry; - entry->dentry = dentry; - entry->parent = parent; - list_add_tail(&entry->node,&parent->files); - } } else error = PTR_ERR(dentry); up(&parent->dentry->d_inode->i_sem); @@ -676,14 +641,12 @@ * */ int driverfs_create_symlink(struct driver_dir_entry * parent, - struct driver_file_entry * entry, - char * target) + char * name, char * target) { struct dentry * dentry; - struct qstr qstr; int error = 0; - if (!entry || !parent) + if (!parent) return -EINVAL; get_mount(); @@ -693,20 +656,10 @@ return -EINVAL; } down(&parent->dentry->d_inode->i_sem); - qstr.name = entry->name; - qstr.len = strlen(entry->name); - qstr.hash = full_name_hash(entry->name,qstr.len); - dentry = lookup_hash(&qstr,parent->dentry); - if (!IS_ERR(dentry)) { - dentry->d_fsdata = (void *)entry; + dentry = get_dentry(parent->dentry,name); + if (!IS_ERR(dentry)) error = driverfs_symlink(parent->dentry->d_inode,dentry,target); - if (!error) { - dentry->d_inode->u.generic_ip = (void *)entry; - entry->dentry = dentry; - entry->parent = parent; - list_add_tail(&entry->node,&parent->files); - } - } else + else error = PTR_ERR(dentry); up(&parent->dentry->d_inode->i_sem); if (error) @@ -724,26 +677,21 @@ */ void driverfs_remove_file(struct driver_dir_entry * dir, const char * name) { - struct list_head * node; + struct dentry * dentry; if (!dir->dentry) return; down(&dir->dentry->d_inode->i_sem); - - node = dir->files.next; - while (node != &dir->files) { - struct driver_file_entry * entry = NULL; - - entry = list_entry(node,struct driver_file_entry,node); - if (!strcmp(entry->name,name)) { - list_del_init(node); - driverfs_unlink(entry->dentry->d_parent->d_inode,entry->dentry); - dput(entry->dentry); + dentry = get_dentry(dir->dentry,name); + if (!IS_ERR(dentry)) { + /* make sure dentry is really there */ + if (dentry->d_inode && + (dentry->d_parent->d_inode == dir->dentry->d_inode)) { + driverfs_unlink(dir->dentry->d_inode,dentry); + dput(dir->dentry); put_mount(); - break; } - node = node->next; } up(&dir->dentry->d_inode->i_sem); } @@ -767,19 +715,16 @@ down(&dentry->d_parent->d_inode->i_sem); down(&dentry->d_inode->i_sem); - node = dir->files.next; - while (node != &dir->files) { - struct driver_file_entry * entry; - entry = list_entry(node,struct driver_file_entry,node); - - list_del_init(node); - driverfs_unlink(dentry->d_inode,entry->dentry); - dput(entry->dentry); + node = dentry->d_subdirs.next; + while (node != &dentry->d_subdirs) { + struct dentry * d = list_entry(node,struct dentry,d_child); + + node = node->next; + driverfs_unlink(dentry->d_inode,d); + dput(dentry); put_mount(); - node = dir->files.next; } up(&dentry->d_inode->i_sem); - driverfs_rmdir(dentry->d_parent->d_inode,dentry); up(&dentry->d_parent->d_inode->i_sem); dput(dentry); diff -Nru a/fs/exec.c b/fs/exec.c --- a/fs/exec.c Thu Aug 1 14:17:40 2002 +++ b/fs/exec.c Thu Aug 1 14:17:40 2002 @@ -313,8 +313,13 @@ mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); if (!mpnt) - return -ENOMEM; - + return -ENOMEM; + + if (!vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) { + kmem_cache_free(vm_area_cachep, mpnt); + return -ENOMEM; + } + down_write(¤t->mm->mmap_sem); { mpnt->vm_mm = current->mm; diff -Nru a/fs/ext2/file.c b/fs/ext2/file.c --- a/fs/ext2/file.c Thu Aug 1 14:17:40 2002 +++ b/fs/ext2/file.c Thu Aug 1 14:17:40 2002 @@ -46,6 +46,7 @@ open: generic_file_open, release: ext2_release_file, fsync: ext2_sync_file, + sendfile: generic_file_sendfile, }; struct inode_operations ext2_file_inode_operations = { diff -Nru a/fs/ext2/inode.c b/fs/ext2/inode.c --- a/fs/ext2/inode.c Thu Aug 1 14:17:36 2002 +++ b/fs/ext2/inode.c Thu Aug 1 14:17:36 2002 @@ -607,10 +607,23 @@ } static int +ext2_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks, + struct buffer_head *bh_result, int create) +{ + int ret; + + ret = ext2_get_block(inode, iblock, bh_result, create); + if (ret == 0) + bh_result->b_size = (1 << inode->i_blkbits); + return ret; +} + +static int ext2_direct_IO(int rw, struct inode *inode, char *buf, loff_t offset, size_t count) { - return generic_direct_IO(rw, inode, buf, offset, count, ext2_get_block); + return generic_direct_IO(rw, inode, buf, + offset, count, ext2_get_blocks); } static int diff -Nru a/fs/ext3/dir.c b/fs/ext3/dir.c --- a/fs/ext3/dir.c Thu Aug 1 14:17:40 2002 +++ b/fs/ext3/dir.c Thu Aug 1 14:17:40 2002 @@ -31,10 +31,10 @@ static int ext3_readdir(struct file *, void *, filldir_t); struct file_operations ext3_dir_operations = { - read: generic_read_dir, - readdir: ext3_readdir, /* we take BKL. needed?*/ - ioctl: ext3_ioctl, /* BKL held */ - fsync: ext3_sync_file, /* BKL held */ + .read = generic_read_dir, + .readdir = ext3_readdir, /* we take BKL. needed?*/ + .ioctl = ext3_ioctl, /* BKL held */ + .fsync = ext3_sync_file, /* BKL held */ }; int ext3_check_dir_entry (const char * function, struct inode * dir, diff -Nru a/fs/ext3/file.c b/fs/ext3/file.c --- a/fs/ext3/file.c Thu Aug 1 14:17:41 2002 +++ b/fs/ext3/file.c Thu Aug 1 14:17:41 2002 @@ -76,18 +76,19 @@ } struct file_operations ext3_file_operations = { - llseek: generic_file_llseek, /* BKL held */ - read: generic_file_read, /* BKL not held. Don't need */ - write: ext3_file_write, /* BKL not held. Don't need */ - ioctl: ext3_ioctl, /* BKL held */ - mmap: generic_file_mmap, - open: ext3_open_file, /* BKL not held. Don't need */ - release: ext3_release_file, /* BKL not held. Don't need */ - fsync: ext3_sync_file, /* BKL held */ + .llseek = generic_file_llseek, /* BKL held */ + .read = generic_file_read, /* BKL not held. Don't need */ + .write = ext3_file_write, /* BKL not held. Don't need */ + .ioctl = ext3_ioctl, /* BKL held */ + .mmap = generic_file_mmap, + .open = ext3_open_file, /* BKL not held. Don't need */ + .release = ext3_release_file, /* BKL not held. Don't need */ + .fsync = ext3_sync_file, /* BKL held */ + .sendfile = generic_file_sendfile, /* BKL not held. Don't need */ }; struct inode_operations ext3_file_inode_operations = { - truncate: ext3_truncate, /* BKL held */ - setattr: ext3_setattr, /* BKL held */ + .truncate = ext3_truncate, /* BKL held */ + .setattr = ext3_setattr, /* BKL held */ }; diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c --- a/fs/ext3/inode.c Thu Aug 1 14:17:41 2002 +++ b/fs/ext3/inode.c Thu Aug 1 14:17:41 2002 @@ -1378,15 +1378,15 @@ struct address_space_operations ext3_aops = { - readpage: ext3_readpage, /* BKL not held. Don't need */ - readpages: ext3_readpages, /* BKL not held. Don't need */ - writepage: ext3_writepage, /* BKL not held. We take it */ - sync_page: block_sync_page, - prepare_write: ext3_prepare_write, /* BKL not held. We take it */ - commit_write: ext3_commit_write, /* BKL not held. We take it */ - bmap: ext3_bmap, /* BKL held */ - invalidatepage: ext3_invalidatepage, /* BKL not held. Don't need */ - releasepage: ext3_releasepage, /* BKL not held. Don't need */ + .readpage = ext3_readpage, /* BKL not held. Don't need */ + .readpages = ext3_readpages, /* BKL not held. Don't need */ + .writepage = ext3_writepage, /* BKL not held. We take it */ + .sync_page = block_sync_page, + .prepare_write = ext3_prepare_write, /* BKL not held. We take it */ + .commit_write = ext3_commit_write, /* BKL not held. We take it */ + .bmap = ext3_bmap, /* BKL held */ + .invalidatepage = ext3_invalidatepage, /* BKL not held. Don't need */ + .releasepage = ext3_releasepage, /* BKL not held. Don't need */ }; /* For writeback mode, we can use mpage_writepages() */ @@ -1405,16 +1405,16 @@ } struct address_space_operations ext3_writeback_aops = { - readpage: ext3_readpage, /* BKL not held. Don't need */ - readpages: ext3_readpages, /* BKL not held. Don't need */ - writepage: ext3_writepage, /* BKL not held. We take it */ - writepages: ext3_writepages, /* BKL not held. Don't need */ - sync_page: block_sync_page, - prepare_write: ext3_prepare_write, /* BKL not held. We take it */ - commit_write: ext3_commit_write, /* BKL not held. We take it */ - bmap: ext3_bmap, /* BKL held */ - invalidatepage: ext3_invalidatepage, /* BKL not held. Don't need */ - releasepage: ext3_releasepage, /* BKL not held. Don't need */ + .readpage = ext3_readpage, /* BKL not held. Don't need */ + .readpages = ext3_readpages, /* BKL not held. Don't need */ + .writepage = ext3_writepage, /* BKL not held. We take it */ + .writepages = ext3_writepages, /* BKL not held. Don't need */ + .sync_page = block_sync_page, + .prepare_write = ext3_prepare_write, /* BKL not held. We take it */ + .commit_write = ext3_commit_write, /* BKL not held. We take it */ + .bmap = ext3_bmap, /* BKL held */ + .invalidatepage = ext3_invalidatepage, /* BKL not held. Don't need */ + .releasepage = ext3_releasepage, /* BKL not held. Don't need */ }; /* diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c --- a/fs/ext3/namei.c Thu Aug 1 14:17:40 2002 +++ b/fs/ext3/namei.c Thu Aug 1 14:17:40 2002 @@ -1194,13 +1194,13 @@ * directories can handle most operations... */ struct inode_operations ext3_dir_inode_operations = { - create: ext3_create, - lookup: ext3_lookup, - link: ext3_link, - unlink: ext3_unlink, - symlink: ext3_symlink, - mkdir: ext3_mkdir, - rmdir: ext3_rmdir, - mknod: ext3_mknod, - rename: ext3_rename, + .create = ext3_create, + .lookup = ext3_lookup, + .link = ext3_link, + .unlink = ext3_unlink, + .symlink = ext3_symlink, + .mkdir = ext3_mkdir, + .rmdir = ext3_rmdir, + .mknod = ext3_mknod, + .rename = ext3_rename, }; diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c --- a/fs/ext3/super.c Thu Aug 1 14:17:41 2002 +++ b/fs/ext3/super.c Thu Aug 1 14:17:41 2002 @@ -489,24 +489,24 @@ } static struct super_operations ext3_sops = { - alloc_inode: ext3_alloc_inode, - destroy_inode: ext3_destroy_inode, - read_inode: ext3_read_inode, /* BKL held */ - write_inode: ext3_write_inode, /* BKL not held. Don't need */ - dirty_inode: ext3_dirty_inode, /* BKL not held. We take it */ - put_inode: ext3_put_inode, /* BKL not held. Don't need */ - delete_inode: ext3_delete_inode, /* BKL not held. We take it */ - put_super: ext3_put_super, /* BKL held */ - write_super: ext3_write_super, /* BKL not held. We take it. Needed? */ - write_super_lockfs: ext3_write_super_lockfs, /* BKL not held. Take it */ - unlockfs: ext3_unlockfs, /* BKL not held. We take it */ - statfs: ext3_statfs, /* BKL not held. */ - remount_fs: ext3_remount, /* BKL held */ + .alloc_inode = ext3_alloc_inode, + .destroy_inode = ext3_destroy_inode, + .read_inode = ext3_read_inode, /* BKL held */ + .write_inode = ext3_write_inode, /* BKL not held. Don't need */ + .dirty_inode = ext3_dirty_inode, /* BKL not held. We take it */ + .put_inode = ext3_put_inode, /* BKL not held. Don't need */ + .delete_inode = ext3_delete_inode, /* BKL not held. We take it */ + .put_super = ext3_put_super, /* BKL held */ + .write_super = ext3_write_super, /* BKL not held. We take it. Needed? */ + .write_super_lockfs = ext3_write_super_lockfs, /* BKL not held. Take it */ + .unlockfs = ext3_unlockfs, /* BKL not held. We take it */ + .statfs = ext3_statfs, /* BKL not held. */ + .remount_fs = ext3_remount, /* BKL held */ }; struct dentry *ext3_get_parent(struct dentry *child); static struct export_operations ext3_export_ops = { - get_parent: ext3_get_parent, + .get_parent = ext3_get_parent, }; @@ -1770,11 +1770,11 @@ } static struct file_system_type ext3_fs_type = { - owner: THIS_MODULE, - name: "ext3", - get_sb: ext3_get_sb, - kill_sb: kill_block_super, - fs_flags: FS_REQUIRES_DEV, + .owner = THIS_MODULE, + .name = "ext3", + .get_sb = ext3_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV, }; static int __init init_ext3_fs(void) diff -Nru a/fs/ext3/symlink.c b/fs/ext3/symlink.c --- a/fs/ext3/symlink.c Thu Aug 1 14:17:40 2002 +++ b/fs/ext3/symlink.c Thu Aug 1 14:17:40 2002 @@ -34,6 +34,6 @@ } struct inode_operations ext3_fast_symlink_inode_operations = { - readlink: ext3_readlink, /* BKL not held. Don't need */ - follow_link: ext3_follow_link, /* BKL not held. Don't need */ + .readlink = ext3_readlink, /* BKL not held. Don't need */ + .follow_link = ext3_follow_link, /* BKL not held. Don't need */ }; diff -Nru a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c --- a/fs/freevxfs/vxfs_inode.c Thu Aug 1 14:17:37 2002 +++ b/fs/freevxfs/vxfs_inode.c Thu Aug 1 14:17:37 2002 @@ -53,6 +53,7 @@ .llseek = generic_file_llseek, .read = generic_file_read, .mmap = generic_file_mmap, + .sendfile = generic_file_sendfile, }; diff -Nru a/fs/hpfs/inode.c b/fs/hpfs/inode.c --- a/fs/hpfs/inode.c Thu Aug 1 14:17:39 2002 +++ b/fs/hpfs/inode.c Thu Aug 1 14:17:39 2002 @@ -21,6 +21,7 @@ open: hpfs_open, release: hpfs_file_release, fsync: hpfs_file_fsync, + sendfile: generic_file_sendfile, }; static struct inode_operations hpfs_file_iops = diff -Nru a/fs/intermezzo/sysctl.c b/fs/intermezzo/sysctl.c --- a/fs/intermezzo/sysctl.c Thu Aug 1 14:17:36 2002 +++ b/fs/intermezzo/sysctl.c Thu Aug 1 14:17:36 2002 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff -Nru a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c --- a/fs/jffs/inode-v23.c Thu Aug 1 14:17:40 2002 +++ b/fs/jffs/inode-v23.c Thu Aug 1 14:17:40 2002 @@ -1631,13 +1631,14 @@ static struct file_operations jffs_file_operations = { - open: generic_file_open, - llseek: generic_file_llseek, - read: generic_file_read, - write: generic_file_write, - ioctl: jffs_ioctl, - mmap: generic_file_mmap, - fsync: jffs_fsync, + open: generic_file_open, + llseek: generic_file_llseek, + read: generic_file_read, + write: generic_file_write, + ioctl: jffs_ioctl, + mmap: generic_file_mmap, + fsync: jffs_fsync, + sendfile: generic_file_sendfile, }; diff -Nru a/fs/jffs2/LICENCE b/fs/jffs2/LICENCE --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/jffs2/LICENCE Thu Aug 1 14:17:41 2002 @@ -0,0 +1,35 @@ +The files in this directory and elsewhere which refer to this LICENCE +file are part of JFFS2, the Journalling Flash File System v2. + + Copyright (C) 2001, 2002 Red Hat, Inc. + +JFFS2 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 or (at your option) any later +version. + +JFFS2 is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with JFFS2; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +As a special exception, if other files instantiate templates or use +macros or inline functions from these files, or you compile these +files and link them with other works to produce a work based on these +files, these files do not by themselves cause the resulting work to be +covered by the GNU General Public License. However the source code for +these files must still be made available in accordance with section (3) +of the GNU General Public License. + +This exception does not invalidate any other reasons why a work based on +this file might be covered by the GNU General Public License. + +For information on obtaining alternative licences for JFFS2, see +http://sources.redhat.com/jffs2/jffs2-licence.html + + + $Id: LICENCE,v 1.1 2002/05/20 14:56:37 dwmw2 Exp $ diff -Nru a/fs/jffs2/TODO b/fs/jffs2/TODO --- a/fs/jffs2/TODO Thu Aug 1 14:17:41 2002 +++ b/fs/jffs2/TODO Thu Aug 1 14:17:41 2002 @@ -1,6 +1,5 @@ -$Id: TODO,v 1.7 2002/03/11 12:36:59 dwmw2 Exp $ +$Id: TODO,v 1.9 2002/07/11 10:39:04 dwmw2 Exp $ - - Locking audit. Even more so now 2.5 took away the BKL. - disable compression in commit_write()? - fine-tune the allocation / GC thresholds - chattr support - turning on/off and tuning compression per-inode @@ -9,7 +8,6 @@ mount doesn't have to read the flash twice for large files. Make this a per-inode option, changable with chattr, so you can decide which inodes should be in-core immediately after mount. - - stop it depending on a block device. - test, test, test - NAND flash support: @@ -22,3 +20,25 @@ - timed flush of old wbuf - fix magical second arg of jffs2_flush_wbuf(). Split into two or more functions instead. + + - Optimisations: + - Stop GC from decompressing and immediately recompressing nodes which could + just be copied intact. + - Furthermore, in the case where it could be copied intact we don't even need + to call iget() for it -- if we use (raw_node_raw->flash_offset & 2) as a flag + to show a node can be copied intact and it's _not_ in icache, we could just do + it, fix up the next_in_ino list and move on. We would need a way to find out + _whether_ it's in icache though -- if it's in icache we also need to do the + fragment lists, etc. P'raps a flag or pointer in the jffs2_inode_cache could + help. + - Stop keeping name in-core with struct jffs2_full_dirent. If we keep the hash in + the full dirent, we only need to go to the flash in lookup() when we think we've + got a match, and in readdir(). + - Doubly-linked next_in_ino list to allow us to free obsoleted raw_node_refs immediately? + - Remove totlen from jffs2_raw_node_ref? Need to have totlen passed into + jffs2_mark_node_obsolete(). Can all callers work it out? + - Don't check data CRC on node scan during mount. We don't really need to know + yet. This means we can't build up node fragment lists, and hence can't + build accurate clean/dirty information. But we don't _need_ that for reading, + only for writing. And in fact we don't even need it for writing until we + start to need GC. diff -Nru a/fs/jffs2/background.c b/fs/jffs2/background.c --- a/fs/jffs2/background.c Thu Aug 1 14:17:36 2002 +++ b/fs/jffs2/background.c Thu Aug 1 14:17:36 2002 @@ -5,45 +5,21 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: background.c,v 1.23 2002/03/06 12:37:08 dwmw2 Exp $ + * $Id: background.c,v 1.29 2002/06/07 10:04:28 dwmw2 Exp $ * */ #define __KERNEL_SYSCALLS__ #include -#include #include #include #include #include #include /* recalc_sigpending() */ +#include #include "nodelist.h" @@ -86,6 +62,13 @@ void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c) { + if (c->mtd->type == MTD_NANDFLASH) { + /* stop a eventually scheduled wbuf flush timer */ + del_timer_sync(&c->wbuf_timer); + /* make sure, that a scheduled wbuf flush task is completed */ + flush_scheduled_tasks(); + } + spin_lock_bh(&c->erase_completion_lock); if (c->gc_task) { D1(printk(KERN_DEBUG "jffs2: Killing GC task %d\n", c->gc_task->pid)); @@ -171,11 +154,23 @@ static int thread_should_wake(struct jffs2_sb_info *c) { - D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x\n", - c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size)); + uint32_t gcnodeofs = 0; + int ret; + + /* Don't count any progress we've already made through the gcblock + as dirty space, for the purposes of this calculation */ + if (c->gcblock && c->gcblock->gc_node) + gcnodeofs = c->gcblock->gc_node->flash_offset & ~3 & (c->sector_size-1); + if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER && - c->dirty_size > c->sector_size) - return 1; + (c->dirty_size - gcnodeofs) > c->sector_size) + ret = 1; else - return 0; + ret = 0; + + D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x (mod 0x%x): %s\n", + c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, + c->dirty_size - gcnodeofs, ret?"yes":"no")); + + return ret; } diff -Nru a/fs/jffs2/build.c b/fs/jffs2/build.c --- a/fs/jffs2/build.c Thu Aug 1 14:17:40 2002 +++ b/fs/jffs2/build.c Thu Aug 1 14:17:40 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: build.c,v 1.32 2002/03/08 15:11:24 dwmw2 Exp $ + * $Id: build.c,v 1.35 2002/05/20 14:56:37 dwmw2 Exp $ * */ @@ -124,6 +100,9 @@ } D1(printk(KERN_DEBUG "Pass 3 complete\n")); + /* Rotate the lists by some number to ensure wear levelling */ + jffs2_rotate_lists(c); + return ret; } @@ -304,6 +283,7 @@ spin_lock_init(&c->inocache_lock); INIT_LIST_HEAD(&c->clean_list); + INIT_LIST_HEAD(&c->very_dirty_list); INIT_LIST_HEAD(&c->dirty_list); INIT_LIST_HEAD(&c->erasable_list); INIT_LIST_HEAD(&c->erasing_list); diff -Nru a/fs/jffs2/compr.c b/fs/jffs2/compr.c --- a/fs/jffs2/compr.c Thu Aug 1 14:17:39 2002 +++ b/fs/jffs2/compr.c Thu Aug 1 14:17:39 2002 @@ -5,33 +5,9 @@ * * Created by Arjan van de Ven * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: compr.c,v 1.23 2002/01/25 01:49:26 dwmw2 Exp $ + * $Id: compr.c,v 1.24 2002/05/20 14:56:37 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c --- a/fs/jffs2/compr_rtime.c Thu Aug 1 14:17:36 2002 +++ b/fs/jffs2/compr_rtime.c Thu Aug 1 14:17:36 2002 @@ -5,33 +5,9 @@ * * Created by Arjan van de Ven * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: compr_rtime.c,v 1.8 2002/01/25 01:49:26 dwmw2 Exp $ + * $Id: compr_rtime.c,v 1.9 2002/05/20 14:56:37 dwmw2 Exp $ * * * Very simple lz77-ish encoder. diff -Nru a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c --- a/fs/jffs2/compr_rubin.c Thu Aug 1 14:17:41 2002 +++ b/fs/jffs2/compr_rubin.c Thu Aug 1 14:17:41 2002 @@ -5,33 +5,9 @@ * * Created by Arjan van de Ven * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: compr_rubin.c,v 1.16 2002/01/25 01:49:26 dwmw2 Exp $ + * $Id: compr_rubin.c,v 1.17 2002/05/20 14:56:37 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c --- a/fs/jffs2/compr_zlib.c Thu Aug 1 14:17:36 2002 +++ b/fs/jffs2/compr_zlib.c Thu Aug 1 14:17:36 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: compr_zlib.c,v 1.15 2002/03/04 09:35:48 dwmw2 Exp $ + * $Id: compr_zlib.c,v 1.18 2002/05/20 14:56:37 dwmw2 Exp $ * */ @@ -65,21 +41,21 @@ { deflate_workspace = vmalloc(zlib_deflate_workspacesize()); if (!deflate_workspace) { - printk("Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize()); + printk(KERN_WARNING "Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize()); return -ENOMEM; } - D1(printk("Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize())); + D1(printk(KERN_DEBUG "Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize())); inflate_workspace = vmalloc(zlib_inflate_workspacesize()); if (!inflate_workspace) { - printk("Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize()); + printk(KERN_WARNING "Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize()); vfree(deflate_workspace); return -ENOMEM; } - D1(printk("Allocated %d bytes for inflate workspace\n", zlib_inflate_workspacesize())); + D1(printk(KERN_DEBUG "Allocated %d bytes for inflate workspace\n", zlib_inflate_workspacesize())); return 0; } -void __exit jffs2_zlib_exit(void) +void jffs2_zlib_exit(void) { vfree(deflate_workspace); vfree(inflate_workspace); diff -Nru a/fs/jffs2/dir.c b/fs/jffs2/dir.c --- a/fs/jffs2/dir.c Thu Aug 1 14:17:39 2002 +++ b/fs/jffs2/dir.c Thu Aug 1 14:17:39 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: dir.c,v 1.68 2002/03/11 12:36:59 dwmw2 Exp $ + * $Id: dir.c,v 1.71 2002/07/23 17:00:45 dwmw2 Exp $ * */ @@ -45,7 +21,6 @@ #include #include #include -#include #include "nodelist.h" static int jffs2_readdir (struct file *, void *, filldir_t); @@ -63,25 +38,25 @@ struct file_operations jffs2_dir_operations = { - read: generic_read_dir, - readdir: jffs2_readdir, - ioctl: jffs2_ioctl, - fsync: jffs2_fsync + .read = generic_read_dir, + .readdir = jffs2_readdir, + .ioctl = jffs2_ioctl, + .fsync = jffs2_fsync }; struct inode_operations jffs2_dir_inode_operations = { - create: jffs2_create, - lookup: jffs2_lookup, - link: jffs2_link, - unlink: jffs2_unlink, - symlink: jffs2_symlink, - mkdir: jffs2_mkdir, - rmdir: jffs2_rmdir, - mknod: jffs2_mknod, - rename: jffs2_rename, - setattr: jffs2_setattr, + .create = jffs2_create, + .lookup = jffs2_lookup, + .link = jffs2_link, + .unlink = jffs2_unlink, + .symlink = jffs2_symlink, + .mkdir = jffs2_mkdir, + .rmdir = jffs2_rmdir, + .mknod = jffs2_mknod, + .rename = jffs2_rename, + .setattr = jffs2_setattr, }; /***********************************************************************/ @@ -144,8 +119,6 @@ D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_dentry->d_inode->i_ino)); - lock_kernel(); - f = JFFS2_INODE_INFO(inode); c = JFFS2_SB_INFO(inode->i_sb); @@ -189,7 +162,6 @@ up(&f->sem); out: filp->f_pos = offset; - unlock_kernel(); return 0; } @@ -744,8 +716,30 @@ { int ret; struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); + struct jffs2_inode_info *victim_f = NULL; uint8_t type; + /* The VFS will check for us and prevent trying to rename a + * file over a directory and vice versa, but if it's a directory, + * the VFS can't check whether the victim is empty. The filesystem + * needs to do that for itself. + */ + if (new_dentry->d_inode) { + victim_f = JFFS2_INODE_INFO(new_dentry->d_inode); + if (S_ISDIR(new_dentry->d_inode->i_mode)) { + struct jffs2_full_dirent *fd; + + down(&victim_f->sem); + for (fd = victim_f->dents; fd; fd = fd->next) { + if (fd->ino) { + up(&victim_f->sem); + return -ENOTEMPTY; + } + } + up(&victim_f->sem); + } + } + /* XXX: We probably ought to alloc enough space for both nodes at the same time. Writing the new link, then getting -ENOSPC, is quite bad :) @@ -764,7 +758,21 @@ if (ret) return ret; - if (S_ISDIR(old_dentry->d_inode->i_mode)) + if (victim_f) { + /* There was a victim. Kill it off nicely */ + new_dentry->d_inode->i_nlink--; + /* Don't oops if the victim was a dirent pointing to an + inode which didn't exist. */ + if (victim_f->inocache) { + down(&victim_f->sem); + victim_f->inocache->nlink--; + up(&victim_f->sem); + } + } + + /* If it was a directory we moved, and there was no victim, + increase i_nlink on its new parent */ + if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f) new_dir_i->i_nlink++; /* Unlink the original */ diff -Nru a/fs/jffs2/erase.c b/fs/jffs2/erase.c --- a/fs/jffs2/erase.c Thu Aug 1 14:17:36 2002 +++ b/fs/jffs2/erase.c Thu Aug 1 14:17:36 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: erase.c,v 1.35 2002/03/08 15:11:24 dwmw2 Exp $ + * $Id: erase.c,v 1.39 2002/07/23 17:00:45 dwmw2 Exp $ * */ @@ -286,20 +262,12 @@ void jffs2_mark_erased_blocks(struct jffs2_sb_info *c) { - static struct jffs2_unknown_node marker = { - magic: JFFS2_MAGIC_BITMASK, - nodetype: JFFS2_NODETYPE_CLEANMARKER, - totlen: sizeof(struct jffs2_unknown_node) - }; struct jffs2_eraseblock *jeb; struct jffs2_raw_node_ref *marker_ref = NULL; unsigned char *ebuf; size_t retlen; int ret; - if (unlikely(!marker.hdr_crc)) - marker.hdr_crc = crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4); - spin_lock_bh(&c->erase_completion_lock); while (!list_empty(&c->erase_complete_list)) { jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list); @@ -359,6 +327,7 @@ } } ofs += readlen; + cond_resched(); } kfree(ebuf); } @@ -376,22 +345,30 @@ jeb->used_size = 0; jeb->dirty_size = 0; } else { - ret = jffs2_flash_write(c, jeb->offset, sizeof(marker), &retlen, (char *)&marker); + struct jffs2_unknown_node marker = { + .magic = JFFS2_MAGIC_BITMASK, + .nodetype = JFFS2_NODETYPE_CLEANMARKER, + .totlen = c->cleanmarker_size + }; + + marker.hdr_crc = crc32(0, &marker, marker.totlen - 4); + + ret = jffs2_flash_write(c, jeb->offset, marker.totlen, &retlen, (char *)&marker); if (ret) { printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n", jeb->offset, ret); goto bad2; } - if (retlen != sizeof(marker)) { + if (retlen != marker.totlen) { printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %d, got %d\n", - jeb->offset, sizeof(marker), retlen); + jeb->offset, marker.totlen, retlen); goto bad2; } marker_ref->next_in_ino = NULL; marker_ref->next_phys = NULL; marker_ref->flash_offset = jeb->offset; - marker_ref->totlen = PAD(sizeof(marker)); + marker_ref->totlen = PAD(marker.totlen); jeb->first_node = jeb->last_node = marker_ref; diff -Nru a/fs/jffs2/file.c b/fs/jffs2/file.c --- a/fs/jffs2/file.c Thu Aug 1 14:17:41 2002 +++ b/fs/jffs2/file.c Thu Aug 1 14:17:41 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: file.c,v 1.70 2002/03/05 09:55:07 dwmw2 Exp $ + * $Id: file.c,v 1.76 2002/07/29 08:25:35 dwmw2 Exp $ * */ @@ -43,7 +19,6 @@ #include #include #include -#include #include "nodelist.h" extern int generic_file_open(struct inode *, struct file *) __attribute__((weak)); @@ -66,36 +41,41 @@ * maybe we have to think about it to find a smarter * solution. */ + down(&c->alloc_sem); down(&f->sem); jffs2_flush_wbuf(c,2); up(&f->sem); + up(&c->alloc_sem); return 0; } struct file_operations jffs2_file_operations = { - llseek: generic_file_llseek, - open: generic_file_open, - read: generic_file_read, - write: generic_file_write, - ioctl: jffs2_ioctl, - mmap: generic_file_mmap, - fsync: jffs2_fsync + .llseek = generic_file_llseek, + .open = generic_file_open, + .read = generic_file_read, + .write = generic_file_write, + .ioctl = jffs2_ioctl, + .mmap = generic_file_mmap, + .fsync = jffs2_fsync, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,29) + .sendfile = generic_file_sendfile +#endif }; /* jffs2_file_inode_operations */ struct inode_operations jffs2_file_inode_operations = { - setattr: jffs2_setattr + .setattr = jffs2_setattr }; struct address_space_operations jffs2_file_address_operations = { - readpage: jffs2_readpage, - prepare_write: jffs2_prepare_write, - commit_write: jffs2_commit_write + .readpage = jffs2_readpage, + .prepare_write =jffs2_prepare_write, + .commit_write = jffs2_commit_write }; int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) @@ -110,12 +90,11 @@ int mdatalen = 0; unsigned int ivalid; uint32_t phys_ofs, alloclen; - int ret = 0; - lock_kernel(); + int ret; D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); ret = inode_change_ok(inode, iattr); if (ret) - goto out; + return ret; /* Special cases - we don't want more than one data node for these types on the medium at any time. So setattr @@ -132,14 +111,12 @@ } else if (S_ISLNK(inode->i_mode)) { mdatalen = f->metadata->size; mdata = kmalloc(f->metadata->size, GFP_USER); - if (!mdata) { - ret = -ENOMEM; - goto out; - } + if (!mdata) + return -ENOMEM; ret = jffs2_read_dnode(c, f->metadata, mdata, 0, mdatalen); if (ret) { kfree(mdata); - goto out; + return ret; } D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen)); } @@ -148,8 +125,7 @@ if (!ri) { if (S_ISLNK(inode->i_mode)) kfree(mdata); - ret = -ENOMEM; - goto out; + return -ENOMEM; } ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL); @@ -157,7 +133,7 @@ jffs2_free_raw_inode(ri); if (S_ISLNK(inode->i_mode & S_IFMT)) kfree(mdata); - goto out; + return ret; } down(&f->sem); ivalid = iattr->ia_valid; @@ -206,8 +182,7 @@ jffs2_complete_reservation(c); jffs2_free_raw_inode(ri); up(&f->sem); - ret = PTR_ERR(new_metadata); - goto out; + return PTR_ERR(new_metadata); } /* It worked. Update the inode */ inode->i_atime = ri->atime; @@ -241,9 +216,7 @@ up(&f->sem); jffs2_complete_reservation(c); -out: - unlock_kernel(); - return ret; + return 0; } int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg) @@ -288,18 +261,18 @@ int jffs2_readpage (struct file *filp, struct page *pg) { - struct jffs2_inode_info *f = JFFS2_INODE_INFO(filp->f_dentry->d_inode); + struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host); int ret; down(&f->sem); - ret = jffs2_do_readpage_unlock(filp->f_dentry->d_inode, pg); + ret = jffs2_do_readpage_unlock(pg->mapping->host, pg); up(&f->sem); return ret; } int jffs2_prepare_write (struct file *filp, struct page *pg, unsigned start, unsigned end) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = pg->mapping->host; struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT; int ret = 0; @@ -383,7 +356,7 @@ /* Actually commit the write from the page cache page we're looking at. * For now, we write the full page out each time. It sucks, but it's simple */ - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = pg->mapping->host; struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_raw_inode *ri; diff -Nru a/fs/jffs2/fs.c b/fs/jffs2/fs.c --- a/fs/jffs2/fs.c Thu Aug 1 14:17:40 2002 +++ b/fs/jffs2/fs.c Thu Aug 1 14:17:40 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: fs.c,v 1.4 2002/03/11 12:36:59 dwmw2 Exp $ + * $Id: fs.c,v 1.13 2002/07/02 22:48:24 dwmw2 Exp $ * */ @@ -44,7 +20,6 @@ #include #include #include -#include #include "nodelist.h" int jffs2_statfs(struct super_block *sb, struct statfs *buf) @@ -69,122 +44,10 @@ buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT; -#if CONFIG_JFFS2_FS_DEBUG > 0 - printk(KERN_DEBUG "STATFS:\n"); - printk(KERN_DEBUG "flash_size: %08x\n", c->flash_size); - printk(KERN_DEBUG "used_size: %08x\n", c->used_size); - printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size); - printk(KERN_DEBUG "free_size: %08x\n", c->free_size); - printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size); - printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size); - printk(KERN_DEBUG "sector_size: %08x\n", c->sector_size); - printk(KERN_DEBUG "jffs2_reserved_blocks size: %08x\n",c->sector_size * JFFS2_RESERVED_BLOCKS_WRITE); - - if (c->nextblock) { - printk(KERN_DEBUG "nextblock: 0x%08x\n", c->nextblock->offset); - } else { - printk(KERN_DEBUG "nextblock: NULL\n"); - } - if (c->gcblock) { - printk(KERN_DEBUG "gcblock: 0x%08x\n", c->gcblock->offset); - } else { - printk(KERN_DEBUG "gcblock: NULL\n"); - } - if (list_empty(&c->clean_list)) { - printk(KERN_DEBUG "clean_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->clean_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "clean_list: %08x\n", jeb->offset); - } - } - if (list_empty(&c->dirty_list)) { - printk(KERN_DEBUG "dirty_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->dirty_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "dirty_list: %08x\n", jeb->offset); - } - } - if (list_empty(&c->erasable_list)) { - printk(KERN_DEBUG "erasable_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->erasable_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "erasable_list: %08x\n", jeb->offset); - } - } - if (list_empty(&c->erasing_list)) { - printk(KERN_DEBUG "erasing_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->erasing_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "erasing_list: %08x\n", jeb->offset); - } - } - if (list_empty(&c->erase_pending_list)) { - printk(KERN_DEBUG "erase_pending_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->erase_pending_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "erase_pending_list: %08x\n", jeb->offset); - } - } - if (list_empty(&c->erasable_pending_wbuf_list)) { - printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->erasable_pending_wbuf_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "erase_pending_wbuf_list: %08x\n", jeb->offset); - } - } - if (list_empty(&c->free_list)) { - printk(KERN_DEBUG "free_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->free_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "free_list: %08x\n", jeb->offset); - } - } - if (list_empty(&c->bad_list)) { - printk(KERN_DEBUG "bad_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->bad_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "bad_list: %08x\n", jeb->offset); - } - } - if (list_empty(&c->bad_used_list)) { - printk(KERN_DEBUG "bad_used_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->bad_used_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "bad_used_list: %08x\n", jeb->offset); - } - } -#endif /* CONFIG_JFFS2_FS_DEBUG */ + D1(jffs2_dump_block_lists(c)); spin_unlock_bh(&c->erase_completion_lock); - return 0; } @@ -275,9 +138,9 @@ if (jffs2_read_dnode(c, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) { /* Eep */ printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); + up(&f->sem); jffs2_do_clear_inode(c, f); make_bad_inode(inode); - up(&f->sem); return; } @@ -321,21 +184,24 @@ void jffs2_write_super (struct super_block *sb) { struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); - - lock_kernel(); sb->s_dirt = 0; - if (sb->s_flags & MS_RDONLY) { - unlock_kernel(); + if (sb->s_flags & MS_RDONLY) return; - } - D1(printk("jffs2_write_super(): flush_wbuf before gc-trigger\n")); - jffs2_flush_wbuf(c, 2); + D1(printk(KERN_DEBUG "jffs2_write_super(): flush_wbuf before gc-trigger\n")); jffs2_garbage_collect_trigger(c); jffs2_erase_pending_blocks(c); jffs2_mark_erased_blocks(c); - unlock_kernel(); + /* Eep. If we lock this here, we deadlock with jffs2_reserve_space() when + * it locks the alloc_sem and jffs2_do_reserve_space() waits for erases + * to happen. I think the erases and/or the flush_wbuf want doing from + * + */ + if (!down_trylock(&c->alloc_sem)) { + jffs2_flush_wbuf(c, 2); + up(&c->alloc_sem); + } // else it stays dirty. FIXME. } @@ -400,33 +266,61 @@ { struct jffs2_sb_info *c; struct inode *root_i; + int ret; c = JFFS2_SB_INFO(sb); c->sector_size = c->mtd->erasesize; c->flash_size = c->mtd->size; +#if 0 if (c->sector_size < 0x10000) { printk(KERN_INFO "jffs2: Erase block size too small (%dKiB). Using 64KiB instead\n", c->sector_size / 1024); c->sector_size = 0x10000; } +#endif if (c->flash_size < 5*c->sector_size) { printk(KERN_ERR "jffs2: Too few erase blocks (%d)\n", c->flash_size / c->sector_size); return -EINVAL; } + + c->cleanmarker_size = sizeof(struct jffs2_unknown_node); + /* Jörn -- stick alignment for weird 8-byte-page flash here */ + + if (jffs2_cleanmarker_oob(c)) { + /* Cleanmarker is out-of-band, so inline size zero */ + c->cleanmarker_size = 0; + } + if (c->mtd->type == MTD_NANDFLASH) { /* Initialise write buffer */ c->wbuf_pagesize = c->mtd->oobblock; c->wbuf_ofs = 0xFFFFFFFF; c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); if (!c->wbuf) - goto out_mtd; + return -ENOMEM; + + /* Initialize process for timed wbuf flush */ + INIT_TQUEUE(&c->wbuf_task,(void*) jffs2_wbuf_process, (void *)c); + /* Initialize timer for timed wbuf flush */ + init_timer(&c->wbuf_timer); + c->wbuf_timer.function = jffs2_wbuf_timeout; + c->wbuf_timer.data = (unsigned long) c; } - if (jffs2_do_mount_fs(c)) - goto out_mtd; + c->inocache_list = kmalloc(INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *), GFP_KERNEL); + if (!c->inocache_list) { + ret = -ENOMEM; + goto out_wbuf; + } + memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *)); + + if ((ret = jffs2_do_mount_fs(c))) + goto out_inohash; + + ret = -EINVAL; D1(printk(KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n")); root_i = iget(sb, 1); @@ -456,6 +350,10 @@ jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); kfree(c->blocks); - out_mtd: - return -EINVAL; + out_inohash: + kfree(c->inocache_list); + out_wbuf: + if (c->wbuf) + kfree(c->wbuf); + return ret; } diff -Nru a/fs/jffs2/gc.c b/fs/jffs2/gc.c --- a/fs/jffs2/gc.c Thu Aug 1 14:17:39 2002 +++ b/fs/jffs2/gc.c Thu Aug 1 14:17:39 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: gc.c,v 1.68 2002/03/08 15:11:24 dwmw2 Exp $ + * $Id: gc.c,v 1.74 2002/05/20 14:56:38 dwmw2 Exp $ * */ @@ -65,14 +41,21 @@ /* Pick an eraseblock to garbage collect next. This is where we'll put the clever wear-levelling algorithms. Eventually. */ + /* We possibly want to favour the dirtier blocks more when the + number of free blocks is low. */ if (!list_empty(&c->bad_used_list) && c->nr_free_blocks > JFFS2_RESERVED_BLOCKS_GCBAD) { D1(printk(KERN_DEBUG "Picking block from bad_used_list to GC next\n")); nextlist = &c->bad_used_list; - } else if (n < 100 && !list_empty(&c->erasable_list)) { + } else if (n < 50 && !list_empty(&c->erasable_list)) { + /* Note that most of them will have gone directly to be erased. + So don't favour the erasable_list _too_ much. */ D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next\n")); nextlist = &c->erasable_list; + } else if (n < 110 && !list_empty(&c->very_dirty_list)) { + /* Most of the time, pick one off the very_dirty list */ + D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next\n")); + nextlist = &c->very_dirty_list; } else if (n < 126 && !list_empty(&c->dirty_list)) { - /* Most of the time, pick one off the dirty list */ D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next\n")); nextlist = &c->dirty_list; } else if (!list_empty(&c->clean_list)) { @@ -82,12 +65,15 @@ D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next (clean_list was empty)\n")); nextlist = &c->dirty_list; + } else if (!list_empty(&c->very_dirty_list)) { + D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next (clean_list and dirty_list were empty)\n")); + nextlist = &c->very_dirty_list; } else if (!list_empty(&c->erasable_list)) { - D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next (clean_list and dirty_list were empty)\n")); + D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next (clean_list and {very_,}dirty_list were empty)\n")); nextlist = &c->erasable_list; } else { - /* Eep. Both were empty */ + /* Eep. All were empty */ printk(KERN_NOTICE "jffs2: No clean, dirty _or_ erasable blocks to GC from! Where are they all?\n"); return NULL; } @@ -100,6 +86,8 @@ printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset); BUG(); } + + D1(jffs2_dump_block_lists(c)); return ret; } @@ -138,7 +126,9 @@ return -EIO; } - D1(printk(KERN_DEBUG "garbage collect from block at phys 0x%08x\n", jeb->offset)); + D1(printk(KERN_DEBUG "GC from block %08x, used_size %08x, dirty_size %08x, free_size %08x\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size)); + D1(if (c->nextblock) + printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->free_size)); if (!jeb->used_size) goto eraseit; @@ -606,9 +596,21 @@ jffs2_mark_node_obsolete(c, f->metadata->raw); jffs2_free_full_dnode(f->metadata); f->metadata = NULL; - return 0; } + return 0; } + + /* + * We should only get here in the case where the node we are + * replacing had more than one frag, so we kept the same version + * number as before. (Except in case of error -- see 'goto fill;' + * above.) + */ + D1(if(unlikely(fn->frags <= 1)) { + printk(KERN_WARNING "jffs2_garbage_collect_hole: Replacing fn with %d frag(s) but new ver %d != highest_version %d of ino #%d\n", + fn->frags, ri.version, f->highest_version, ri.ino); + }); + for (frag = f->fraglist; frag; frag = frag->next) { if (frag->ofs > fn->size + fn->ofs) break; @@ -760,7 +762,7 @@ kunmap(pg); /* XXX: Does the page get freed automatically? */ - /* AAA: Judging by the unmount getting stuck in __wait_on_page_locked, nope. */ + /* AAA: Judging by the unmount getting stuck in __wait_on_page, nope. */ page_cache_release(pg); return ret; } diff -Nru a/fs/jffs2/ioctl.c b/fs/jffs2/ioctl.c --- a/fs/jffs2/ioctl.c Thu Aug 1 14:17:41 2002 +++ b/fs/jffs2/ioctl.c Thu Aug 1 14:17:41 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: ioctl.c,v 1.5 2001/03/15 15:38:24 dwmw2 Exp $ + * $Id: ioctl.c,v 1.6 2002/05/20 14:56:38 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c --- a/fs/jffs2/malloc.c Thu Aug 1 14:17:36 2002 +++ b/fs/jffs2/malloc.c Thu Aug 1 14:17:36 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: malloc.c,v 1.21 2002/03/12 17:36:55 dwmw2 Exp $ + * $Id: malloc.c,v 1.22 2002/05/20 14:56:38 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c --- a/fs/jffs2/nodelist.c Thu Aug 1 14:17:40 2002 +++ b/fs/jffs2/nodelist.c Thu Aug 1 14:17:40 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: nodelist.c,v 1.42 2002/03/11 11:17:29 dwmw2 Exp $ + * $Id: nodelist.c,v 1.47 2002/06/26 01:25:30 dwmw2 Exp $ * */ @@ -69,7 +45,7 @@ *prev = new; out: - D1(while(*list) { + D2(while(*list) { printk(KERN_DEBUG "Dirent \"%s\" (hash 0x%08x, ino #%u\n", (*list)->name, (*list)->nhash, (*list)->ino); list = &(*list)->next; }); @@ -311,17 +287,14 @@ D2(printk(KERN_DEBUG "jffs2_get_ino_cache(): ino %u\n", ino)); spin_lock (&c->inocache_lock); - if (c->inocache_last && c->inocache_last->ino == ino) { - ret = c->inocache_last; - } else { - ret = c->inocache_list[ino % INOCACHE_HASHSIZE]; - while (ret && ret->ino < ino) { - ret = ret->next; - } - - if (ret && ret->ino != ino) - ret = NULL; + ret = c->inocache_list[ino % INOCACHE_HASHSIZE]; + while (ret && ret->ino < ino) { + ret = ret->next; } + + if (ret && ret->ino != ino) + ret = NULL; + spin_unlock(&c->inocache_lock); D2(printk(KERN_DEBUG "jffs2_get_ino_cache found %p for ino %u\n", ret, ino)); @@ -342,8 +315,6 @@ new->next = *prev; *prev = new; - c->inocache_last = new; - spin_unlock(&c->inocache_lock); } @@ -361,8 +332,6 @@ if ((*prev) == old) { *prev = old->next; } - if (c->inocache_last == old) - c->inocache_last = NULL; spin_unlock(&c->inocache_lock); } @@ -382,7 +351,6 @@ } c->inocache_list[i] = NULL; } - c->inocache_last = NULL; } void jffs2_free_raw_node_refs(struct jffs2_sb_info *c) diff -Nru a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h --- a/fs/jffs2/nodelist.h Thu Aug 1 14:17:41 2002 +++ b/fs/jffs2/nodelist.h Thu Aug 1 14:17:41 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: nodelist.h,v 1.68 2002/03/08 11:27:19 dwmw2 Exp $ + * $Id: nodelist.h,v 1.74 2002/06/26 01:20:43 dwmw2 Exp $ * */ @@ -117,6 +93,8 @@ int nlink; }; +#define INOCACHE_HASHSIZE 128 + struct jffs2_scan_info { struct jffs2_full_dirent *dents; struct jffs2_tmp_dnode_info *tmpnodes; @@ -172,7 +150,6 @@ struct jffs2_full_dnode *node; /* NULL for holes */ uint32_t size; uint32_t ofs; /* Don't really need this, but optimisation */ - uint32_t node_ofs; /* offset within the physical node */ }; struct jffs2_eraseblock @@ -240,6 +217,9 @@ #define JFFS2_RESERVED_BLOCKS_GCMERGE (JFFS2_RESERVED_BLOCKS_BASE) /* ... merge pages when garbage collecting */ +/* How much dirty space before it goes on the very_dirty_list */ +#define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2)) + #define PAD(x) (((x)+3)&~3) static inline int jffs2_raw_ref_to_inum(struct jffs2_raw_node_ref *raw) @@ -271,6 +251,7 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, uint32_t len, int dirty); void jffs2_complete_reservation(struct jffs2_sb_info *c); void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); +void jffs2_dump_block_lists(struct jffs2_sb_info *c); /* write.c */ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri); @@ -331,6 +312,7 @@ /* scan.c */ int jffs2_scan_medium(struct jffs2_sb_info *c); +void jffs2_rotate_lists(struct jffs2_sb_info *c); /* build.c */ int jffs2_do_mount_fs(struct jffs2_sb_info *c); diff -Nru a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c --- a/fs/jffs2/nodemgmt.c Thu Aug 1 14:17:36 2002 +++ b/fs/jffs2/nodemgmt.c Thu Aug 1 14:17:36 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: nodemgmt.c,v 1.63 2002/03/08 14:54:09 dwmw2 Exp $ + * $Id: nodemgmt.c,v 1.70 2002/07/02 22:48:24 dwmw2 Exp $ * */ @@ -158,9 +134,15 @@ c->free_size -= jeb->free_size; jeb->dirty_size += jeb->free_size; jeb->free_size = 0; - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + if (VERYDIRTY(c, jeb->dirty_size)) { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->dirty_list); + list_add_tail(&jeb->list, &c->very_dirty_list); + } else { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + list_add_tail(&jeb->list, &c->dirty_list); + } c->nextblock = jeb = NULL; } @@ -180,6 +162,7 @@ list_del(&ejeb->list); list_add_tail(&ejeb->list, &c->erase_pending_list); c->nr_erasing_blocks++; + jffs2_erase_pending_trigger(c); D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Triggering erase of erasable block at 0x%08x\n", ejeb->offset)); } @@ -232,10 +215,7 @@ c->nextblock = jeb = list_entry(next, struct jffs2_eraseblock, list); c->nr_free_blocks--; - /* On NAND free_size == sector_size, cleanmarker is in spare area !*/ - if (jeb->free_size != c->sector_size - - (jffs2_cleanmarker_oob(c)) ? 0 : sizeof(struct jffs2_unknown_node)) { - + if (jeb->free_size != c->sector_size - c->cleanmarker_size) { printk(KERN_WARNING "Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size); goto restart; } @@ -420,8 +400,19 @@ BUG(); } } else { - D1(printk(KERN_DEBUG "...and adding to erasable_list\n")); - list_add_tail(&jeb->list, &c->erasable_list); + if (jiffies & 127) { + /* Most of the time, we just erase it immediately. Otherwise we + spend ages scanning it on mount, etc. */ + D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n")); + list_add_tail(&jeb->list, &c->erase_pending_list); + c->nr_erasing_blocks++; + jffs2_erase_pending_trigger(c); + } else { + /* Sometimes, however, we leave it elsewhere so it doesn't get + immediately reused, and we spread the load a bit. */ + D1(printk(KERN_DEBUG "...and adding to erasable_list\n")); + list_add_tail(&jeb->list, &c->erasable_list); + } } D1(printk(KERN_DEBUG "Done OK\n")); } else if (jeb == c->gcblock) { @@ -431,6 +422,12 @@ list_del(&jeb->list); D1(printk(KERN_DEBUG "...and adding to dirty_list\n")); list_add_tail(&jeb->list, &c->dirty_list); + } else if (VERYDIRTY(c, jeb->dirty_size) && + !VERYDIRTY(c, jeb->dirty_size - ref->totlen)) { + D1(printk(KERN_DEBUG "Eraseblock at 0x%08x is now very dirty. Removing from dirty list...\n", jeb->offset)); + list_del(&jeb->list); + D1(printk(KERN_DEBUG "...and adding to very_dirty_list\n")); + list_add_tail(&jeb->list, &c->very_dirty_list); } spin_unlock_bh(&c->erase_completion_lock); @@ -469,3 +466,129 @@ return; } } + +#if CONFIG_JFFS2_FS_DEBUG > 0 +void jffs2_dump_block_lists(struct jffs2_sb_info *c) +{ + printk(KERN_DEBUG "jffs2_dump_block_lists:\n"); + printk(KERN_DEBUG "flash_size: %08x\n", c->flash_size); + printk(KERN_DEBUG "used_size: %08x\n", c->used_size); + printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size); + printk(KERN_DEBUG "free_size: %08x\n", c->free_size); + printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size); + printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size); + printk(KERN_DEBUG "sector_size: %08x\n", c->sector_size); + printk(KERN_DEBUG "jffs2_reserved_blocks size: %08x\n",c->sector_size * JFFS2_RESERVED_BLOCKS_WRITE); + + if (c->nextblock) { + printk(KERN_DEBUG "nextblock: %08x (used %08x, dirty %08x, free %08x)\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->free_size); + } else { + printk(KERN_DEBUG "nextblock: NULL\n"); + } + if (c->gcblock) { + printk(KERN_DEBUG "gcblock: %08x (used %08x, dirty %08x, free %08x)\n", c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, c->gcblock->free_size); + } else { + printk(KERN_DEBUG "gcblock: NULL\n"); + } + if (list_empty(&c->clean_list)) { + printk(KERN_DEBUG "clean_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->clean_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + } + } + if (list_empty(&c->very_dirty_list)) { + printk(KERN_DEBUG "very_dirty_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->very_dirty_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + printk(KERN_DEBUG "very_dirty_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + } + } + if (list_empty(&c->dirty_list)) { + printk(KERN_DEBUG "dirty_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->dirty_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + printk(KERN_DEBUG "dirty_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + } + } + if (list_empty(&c->erasable_list)) { + printk(KERN_DEBUG "erasable_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->erasable_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + printk(KERN_DEBUG "erasable_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + } + } + if (list_empty(&c->erasing_list)) { + printk(KERN_DEBUG "erasing_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->erasing_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + printk(KERN_DEBUG "erasing_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + } + } + if (list_empty(&c->erase_pending_list)) { + printk(KERN_DEBUG "erase_pending_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->erase_pending_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + printk(KERN_DEBUG "erase_pending_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + } + } + if (list_empty(&c->erasable_pending_wbuf_list)) { + printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->erasable_pending_wbuf_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + printk(KERN_DEBUG "erase_pending_wbuf_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + } + } + if (list_empty(&c->free_list)) { + printk(KERN_DEBUG "free_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->free_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + printk(KERN_DEBUG "free_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + } + } + if (list_empty(&c->bad_list)) { + printk(KERN_DEBUG "bad_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->bad_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + printk(KERN_DEBUG "bad_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + } + } + if (list_empty(&c->bad_used_list)) { + printk(KERN_DEBUG "bad_used_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->bad_used_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + printk(KERN_DEBUG "bad_used_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + } + } +} +#endif /* CONFIG_JFFS2_FS_DEBUG */ diff -Nru a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h --- a/fs/jffs2/os-linux.h Thu Aug 1 14:17:36 2002 +++ b/fs/jffs2/os-linux.h Thu Aug 1 14:17:36 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: os-linux.h,v 1.16 2002/03/17 10:18:42 dwmw2 Exp $ + * $Id: os-linux.h,v 1.19 2002/05/20 14:56:38 dwmw2 Exp $ * */ @@ -101,6 +77,8 @@ #define jffs2_nand_read_failcnt(c,jeb) do { ; } while(0) #define jffs2_write_nand_badblock(c,jeb) do { ; } while(0) #define jffs2_flash_writev jffs2_flash_direct_writev +#define jffs2_wbuf_timeout NULL +#define jffs2_wbuf_process NULL #else /* NAND support present */ @@ -119,6 +97,8 @@ int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); +void jffs2_wbuf_timeout(unsigned long data); +void jffs2_wbuf_process(void *data); #endif /* NAND */ /* background.c */ diff -Nru a/fs/jffs2/pushpull.h b/fs/jffs2/pushpull.h --- a/fs/jffs2/pushpull.h Thu Aug 1 14:17:36 2002 +++ b/fs/jffs2/pushpull.h Thu Aug 1 14:17:36 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: pushpull.h,v 1.7 2002/03/06 12:37:08 dwmw2 Exp $ + * $Id: pushpull.h,v 1.8 2002/05/20 14:56:38 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/read.c b/fs/jffs2/read.c --- a/fs/jffs2/read.c Thu Aug 1 14:17:39 2002 +++ b/fs/jffs2/read.c Thu Aug 1 14:17:39 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: read.c,v 1.22 2002/03/02 22:08:27 dwmw2 Exp $ + * $Id: read.c,v 1.23 2002/05/20 14:56:38 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c --- a/fs/jffs2/readinode.c Thu Aug 1 14:17:36 2002 +++ b/fs/jffs2/readinode.c Thu Aug 1 14:17:36 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: readinode.c,v 1.71 2002/03/06 12:25:59 dwmw2 Exp $ + * $Id: readinode.c,v 1.73 2002/05/20 14:56:38 dwmw2 Exp $ * */ @@ -337,6 +313,7 @@ printk(KERN_NOTICE "MTD read in jffs2_do_read_inode() failed: Returned %d, %ld of %d bytes read\n", ret, (long)retlen, sizeof(*latest_node)); /* FIXME: If this fails, there seems to be a memory leak. Find it. */ + up(&f->sem); jffs2_do_clear_inode(c, f); return ret?ret:-EIO; } @@ -344,6 +321,7 @@ crc = crc32(0, latest_node, sizeof(*latest_node)-8); if (crc != latest_node->node_crc) { printk(KERN_NOTICE "CRC failed for read_inode of inode %u at physical location 0x%x\n", ino, fn->raw->flash_offset & ~3); + up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; } @@ -378,11 +356,13 @@ kept as the metadata node */ if (f->metadata) { printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had metadata node\n", ino, latest_node->mode); + up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; } if (!f->fraglist) { printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n", ino, latest_node->mode); + up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; } @@ -390,6 +370,7 @@ if (f->fraglist->next) { printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had more than one node\n", ino, latest_node->mode); /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ + up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; } diff -Nru a/fs/jffs2/scan.c b/fs/jffs2/scan.c --- a/fs/jffs2/scan.c Thu Aug 1 14:17:40 2002 +++ b/fs/jffs2/scan.c Thu Aug 1 14:17:40 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: scan.c,v 1.69 2002/03/08 11:03:23 dwmw2 Exp $ + * $Id: scan.c,v 1.79 2002/07/25 20:48:51 dwmw2 Exp $ * */ #include @@ -62,7 +38,6 @@ } while(0) static uint32_t pseudo_random; -static void jffs2_rotate_lists(struct jffs2_sb_info *c); static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); @@ -141,13 +116,23 @@ not the one with most free space. */ if (jeb->free_size > 2*sizeof(struct jffs2_raw_inode) && - (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { + (jffs2_can_mark_obsolete(c) || jeb->free_size > c->wbuf_pagesize) && + (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { /* Better candidate for the next writes to go to */ - if (c->nextblock) - list_add(&c->nextblock->list, &c->dirty_list); + if (c->nextblock) { + if (VERYDIRTY(c, c->nextblock->dirty_size)) { + list_add(&c->nextblock->list, &c->very_dirty_list); + } else { + list_add(&c->nextblock->list, &c->dirty_list); + } + } c->nextblock = jeb; } else { - list_add(&jeb->list, &c->dirty_list); + if (VERYDIRTY(c, jeb->dirty_size)) { + list_add(&jeb->list, &c->very_dirty_list); + } else { + list_add(&jeb->list, &c->dirty_list); + } } break; @@ -167,14 +152,26 @@ bad_blocks++; break; default: - printk("jffs2_scan_medium(): unknown block state\n"); + printk(KERN_WARNING "jffs2_scan_medium(): unknown block state\n"); BUG(); } } - /* Rotate the lists by some number to ensure wear levelling */ - jffs2_rotate_lists(c); + if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) { + /* If we're going to start writing into a block which already + contains data, and the end of the data isn't page-aligned, + skip a little and align it. */ + + uint32_t skip = c->nextblock->free_size & (c->wbuf_pagesize-1); + + D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n", + skip)); + c->nextblock->dirty_size += skip; + c->dirty_size += skip; + c->nextblock->free_size -= skip; + c->free_size -= skip; + } if (c->nr_erasing_blocks) { if ( !c->used_size && ((empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n"); @@ -245,7 +242,9 @@ while(ofs < jeb->offset + c->sector_size) { size_t retlen; ACCT_PARANOIA_CHECK(jeb); - + + cond_resched(); + if (ofs & 3) { printk(KERN_WARNING "Eep. ofs 0x%08x not word-aligned!\n", ofs); ofs = (ofs+3)&~3; @@ -323,6 +322,16 @@ continue; } + if (ofs + node.totlen > jeb->offset + c->sector_size) { + /* Eep. Node goes over the end of the erase block. */ + printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", + ofs, node.totlen); + printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n"); + DIRTY_SPACE(4); + ofs += 4; + continue; + } + if (!(node.nodetype & JFFS2_NODE_ACCURATE)) { /* Wheee. This is an obsoleted node */ D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs)); @@ -343,9 +352,9 @@ break; case JFFS2_NODETYPE_CLEANMARKER: - if (node.totlen != sizeof(struct jffs2_unknown_node)) { + if (node.totlen != c->cleanmarker_size) { printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", - ofs, node.totlen, sizeof(struct jffs2_unknown_node)); + ofs, node.totlen, c->cleanmarker_size); DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); } else if (jeb->first_node) { printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset); @@ -369,6 +378,11 @@ ofs += PAD(sizeof(struct jffs2_unknown_node)); break; + case JFFS2_NODETYPE_PADDING: + DIRTY_SPACE(PAD(node.totlen)); + ofs += PAD(node.totlen); + break; + default: switch (node.nodetype & JFFS2_COMPAT_MASK) { case JFFS2_FEATURE_ROCOMPAT: @@ -378,7 +392,7 @@ return -EROFS; DIRTY_SPACE(PAD(node.totlen)); ofs += PAD(node.totlen); - continue; + break; case JFFS2_FEATURE_INCOMPAT: printk(KERN_NOTICE "Incompatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs); @@ -624,7 +638,7 @@ if (!jeb->used_size) { D1(printk(KERN_DEBUG "No valid nodes yet found in this eraseblock 0x%08x, so obsoleting the new instance at 0x%08x\n", jeb->offset, raw->flash_offset & ~3)); - ri.nodetype &= ~JFFS2_NODE_ACCURATE; + ri.nodetype &= ~JFFS2_NODE_ACCURATE; /* Perhaps we could also mark it as such on the medium. Maybe later */ } break; @@ -650,7 +664,11 @@ tn->version = ri.version; USED_SPACE(PAD(ri.totlen)); - jffs2_add_tn_to_list(tn, &ic->scan->tmpnodes); + + /* No need to scan from the beginning of the list again. + We can start from tn_list instead (Thanks Jocke) */ + jffs2_add_tn_to_list(tn, tn_list); + /* Make sure the one we just added is the _last_ in the list with this version number, so the older ones get obsoleted */ while (tn->next && tn->next->version == tn->version) { @@ -813,22 +831,84 @@ list_add(head, n); } -static void jffs2_rotate_lists(struct jffs2_sb_info *c) +void jffs2_rotate_lists(struct jffs2_sb_info *c) { uint32_t x; + uint32_t rotateby; x = count_list(&c->clean_list); - if (x) - rotate_list((&c->clean_list), pseudo_random % x); + if (x) { + rotateby = pseudo_random % x; + D1(printk(KERN_DEBUG "Rotating clean_list by %d\n", rotateby)); + + rotate_list((&c->clean_list), rotateby); + + D1(printk(KERN_DEBUG "Erase block at front of clean_list is at %08x\n", + list_entry(c->clean_list.next, struct jffs2_eraseblock, list)->offset)); + } else { + D1(printk(KERN_DEBUG "Not rotating empty clean_list\n")); + } + + x = count_list(&c->very_dirty_list); + if (x) { + rotateby = pseudo_random % x; + D1(printk(KERN_DEBUG "Rotating very_dirty_list by %d\n", rotateby)); + + rotate_list((&c->very_dirty_list), rotateby); + + D1(printk(KERN_DEBUG "Erase block at front of very_dirty_list is at %08x\n", + list_entry(c->very_dirty_list.next, struct jffs2_eraseblock, list)->offset)); + } else { + D1(printk(KERN_DEBUG "Not rotating empty very_dirty_list\n")); + } x = count_list(&c->dirty_list); - if (x) - rotate_list((&c->dirty_list), pseudo_random % x); + if (x) { + rotateby = pseudo_random % x; + D1(printk(KERN_DEBUG "Rotating dirty_list by %d\n", rotateby)); + + rotate_list((&c->dirty_list), rotateby); + + D1(printk(KERN_DEBUG "Erase block at front of dirty_list is at %08x\n", + list_entry(c->dirty_list.next, struct jffs2_eraseblock, list)->offset)); + } else { + D1(printk(KERN_DEBUG "Not rotating empty dirty_list\n")); + } + + x = count_list(&c->erasable_list); + if (x) { + rotateby = pseudo_random % x; + D1(printk(KERN_DEBUG "Rotating erasable_list by %d\n", rotateby)); - if (c->nr_erasing_blocks) - rotate_list((&c->erase_pending_list), pseudo_random % c->nr_erasing_blocks); + rotate_list((&c->erasable_list), rotateby); - if (c->nr_free_blocks) /* Not that it should ever be zero */ - rotate_list((&c->free_list), pseudo_random % c->nr_free_blocks); + D1(printk(KERN_DEBUG "Erase block at front of erasable_list is at %08x\n", + list_entry(c->erasable_list.next, struct jffs2_eraseblock, list)->offset)); + } else { + D1(printk(KERN_DEBUG "Not rotating empty erasable_list\n")); + } + + if (c->nr_erasing_blocks) { + rotateby = pseudo_random % c->nr_erasing_blocks; + D1(printk(KERN_DEBUG "Rotating erase_pending_list by %d\n", rotateby)); + + rotate_list((&c->erase_pending_list), rotateby); + + D1(printk(KERN_DEBUG "Erase block at front of erase_pending_list is at %08x\n", + list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list)->offset)); + } else { + D1(printk(KERN_DEBUG "Not rotating empty erase_pending_list\n")); + } + + if (c->nr_free_blocks) { + rotateby = pseudo_random % c->nr_free_blocks; + D1(printk(KERN_DEBUG "Rotating free_list by %d\n", rotateby)); + rotate_list((&c->free_list), rotateby); + + D1(printk(KERN_DEBUG "Erase block at front of free_list is at %08x\n", + list_entry(c->free_list.next, struct jffs2_eraseblock, list)->offset)); + } else { + D1(printk(KERN_DEBUG "Not rotating empty free_list\n")); + } } diff -Nru a/fs/jffs2/super.c b/fs/jffs2/super.c --- a/fs/jffs2/super.c Thu Aug 1 14:17:40 2002 +++ b/fs/jffs2/super.c Thu Aug 1 14:17:40 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: super.c,v 1.64 2002/03/17 10:18:42 dwmw2 Exp $ + * $Id: super.c,v 1.73 2002/07/23 17:00:45 dwmw2 Exp $ * */ @@ -43,12 +19,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include "nodelist.h" void jffs2_put_super (struct super_block *); @@ -83,14 +59,14 @@ static struct super_operations jffs2_super_operations = { - alloc_inode: jffs2_alloc_inode, - destroy_inode: jffs2_destroy_inode, - read_inode: jffs2_read_inode, - put_super: jffs2_put_super, - write_super: jffs2_write_super, - statfs: jffs2_statfs, - remount_fs: jffs2_remount_fs, - clear_inode: jffs2_clear_inode + .alloc_inode = jffs2_alloc_inode, + .destroy_inode =jffs2_destroy_inode, + .read_inode = jffs2_read_inode, + .put_super = jffs2_put_super, + .write_super = jffs2_write_super, + .statfs = jffs2_statfs, + .remount_fs = jffs2_remount_fs, + .clear_inode = jffs2_clear_inode }; static int jffs2_sb_compare(struct super_block *sb, void *data) @@ -101,11 +77,11 @@ /* The superblocks are considered to be equivalent if the underlying MTD device is the same one */ if (c->mtd == p->mtd) { - D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", mtd->index, mtd->name)); + D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", p->mtd->index, p->mtd->name)); return 1; } else { D1(printk(KERN_DEBUG "jffs2_sb_compare: No match, device %d (\"%s\"), device %d (\"%s\")\n", - c->mtd->index, c->mtd->name, mtd->index, mtd->name)); + c->mtd->index, c->mtd->name, p->mtd->index, p->mtd->name)); return 0; } } @@ -282,10 +258,15 @@ if (!(sb->s_flags & MS_RDONLY)) jffs2_stop_garbage_collect_thread(c); + down(&c->alloc_sem); jffs2_flush_wbuf(c, 1); + up(&c->alloc_sem); jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); kfree(c->blocks); + if (c->wbuf) + kfree(c->wbuf); + kfree(c->inocache_list); if (c->mtd->sync) c->mtd->sync(c->mtd); @@ -301,10 +282,10 @@ } static struct file_system_type jffs2_fs_type = { - owner: THIS_MODULE, - name: "jffs2", - get_sb: jffs2_get_sb, - kill_sb: jffs2_kill_sb, + .owner = THIS_MODULE, + .name = "jffs2", + .get_sb = jffs2_get_sb, + .kill_sb = jffs2_kill_sb, }; @@ -326,18 +307,25 @@ ret = jffs2_zlib_init(); if (ret) { printk(KERN_ERR "JFFS2 error: Failed to initialise zlib workspaces\n"); - return ret; + goto out; } ret = jffs2_create_slab_caches(); if (ret) { printk(KERN_ERR "JFFS2 error: Failed to initialise slab caches\n"); - return ret; + goto out_zlib; } ret = register_filesystem(&jffs2_fs_type); if (ret) { printk(KERN_ERR "JFFS2 error: Failed to register filesystem\n"); - jffs2_destroy_slab_caches(); + goto out_slab; } + return 0; + + out_slab: + jffs2_destroy_slab_caches(); + out_zlib: + jffs2_zlib_exit(); + out: return ret; } diff -Nru a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c --- a/fs/jffs2/symlink.c Thu Aug 1 14:17:36 2002 +++ b/fs/jffs2/symlink.c Thu Aug 1 14:17:36 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: symlink.c,v 1.9 2002/01/10 09:29:53 dwmw2 Exp $ + * $Id: symlink.c,v 1.11 2002/07/23 17:00:45 dwmw2 Exp $ * */ @@ -46,9 +22,9 @@ struct inode_operations jffs2_symlink_inode_operations = { - readlink: jffs2_readlink, - follow_link: jffs2_follow_link, - setattr: jffs2_setattr + .readlink = jffs2_readlink, + .follow_link = jffs2_follow_link, + .setattr = jffs2_setattr }; int jffs2_readlink(struct dentry *dentry, char *buffer, int buflen) diff -Nru a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c --- a/fs/jffs2/wbuf.c Thu Aug 1 14:17:39 2002 +++ b/fs/jffs2/wbuf.c Thu Aug 1 14:17:39 2002 @@ -5,34 +5,10 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. - * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: wbuf.c,v 1.7 2002/03/08 11:27:59 dwmw2 Exp $ + * For licensing information, see the file 'LICENCE' in this directory. * + * $Id: wbuf.c,v 1.12 2002/05/20 14:56:39 dwmw2 Exp $ + * -- with the NAND definitions added back pending MTD update for 2.5. */ #include @@ -51,25 +27,100 @@ #define NAND_JFFS2_OOB8_FSDALEN 2 #define NAND_JFFS2_OOB16_FSDALEN 8 + +/* max. erase failures before we mark a block bad */ #define MAX_ERASE_FAILURES 5 +/* two seconds timeout for timed wbuf-flushing */ +#define WBUF_FLUSH_TIMEOUT 2 * HZ + static inline void jffs2_refile_wbuf_blocks(struct jffs2_sb_info *c) { struct list_head *this, *next; + static int n; if (list_empty(&c->erasable_pending_wbuf_list)) return; list_for_each_safe(this, next, &c->erasable_pending_wbuf_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + + D1(printk(KERN_DEBUG "Removing eraseblock at 0x%08x from erasable_pending_wbuf_list...\n", jeb->offset)); list_del(this); - list_add_tail(this, &c->erasable_list); + if ((jiffies + (n++)) & 127) { + /* Most of the time, we just erase it immediately. Otherwise we + spend ages scanning it on mount, etc. */ + D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n")); + list_add_tail(&jeb->list, &c->erase_pending_list); + c->nr_erasing_blocks++; + jffs2_erase_pending_trigger(c); + } else { + /* Sometimes, however, we leave it elsewhere so it doesn't get + immediately reused, and we spread the load a bit. */ + D1(printk(KERN_DEBUG "...and adding to erasable_list\n")); + list_add_tail(&jeb->list, &c->erasable_list); + } } } +/* +* Timed flushing of wbuf. If we have no consecutive write to wbuf, within +* the specified time, we flush the contents with padding ! +*/ +void jffs2_wbuf_timeout (unsigned long data) +{ + struct jffs2_sb_info *c = (struct jffs2_sb_info *) data; + /* + * Wake up the flush process, we need process context to have the right + * to sleep on flash write + */ + D1(printk(KERN_DEBUG "jffs2_wbuf_timeout(): timer expired\n")); + schedule_task(&c->wbuf_task); +} + +/* +* Process for timed wbuf flush +* +* FIXME What happens, if we have a write failure there ???? +*/ +void jffs2_wbuf_process (void *data) +{ + struct jffs2_sb_info *c = (struct jffs2_sb_info *) data; + + D1(printk(KERN_DEBUG "jffs2_wbuf_process() entered\n")); + + if (!down_trylock(&c->alloc_sem)) { + D1(printk (KERN_DEBUG "jffs2_wbuf_process() alloc_sem got\n")); + + if(!c->nextblock || (c->nextblock->free_size < (c->wbuf_pagesize - c->wbuf_len))) + jffs2_flush_wbuf(c, 1); /* pad only */ + else + jffs2_flush_wbuf(c, 2); /* pad and adjust nextblock */ + up(&c->alloc_sem); + } else { + D1(printk (KERN_DEBUG "jffs2_wbuf_process() alloc_sem already occupied\n")); + } +} + + +/* Meaning of pad argument: + 0: Do not pad. Probably pointless - we only ever use this when we can't pad anyway. + 1: Pad, do not adjust nextblock free_size + 2: Pad, adjust nextblock free_size +*/ int jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) { int ret; size_t retlen; + + if (!down_trylock(&c->alloc_sem)) { + up(&c->alloc_sem); + printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n"); + BUG(); + } + + /* delete a eventually started timed wbuf flush */ + del_timer_sync(&c->wbuf_timer); if(!c->wbuf || !c->wbuf_len) return 0; @@ -339,6 +390,11 @@ alldone: *retlen = donelen; + /* Setup timed wbuf flush, if buffer len != 0 */ + if (c->wbuf_len) { + D1(printk (KERN_DEBUG "jffs2_flash_writev: mod wbuf_timer\n")); + mod_timer(&c->wbuf_timer, jiffies + WBUF_FLUSH_TIMEOUT); + } return 0; } diff -Nru a/fs/jffs2/write.c b/fs/jffs2/write.c --- a/fs/jffs2/write.c Thu Aug 1 14:17:40 2002 +++ b/fs/jffs2/write.c Thu Aug 1 14:17:40 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: write.c,v 1.52 2002/03/08 11:01:43 dwmw2 Exp $ + * $Id: write.c,v 1.56 2002/07/10 14:05:16 dwmw2 Exp $ * */ @@ -89,7 +65,7 @@ ret = 1; } if (ret) { - printk(KERN_WARNING "ARGH. About to write node to 0x%08x on flash, but there's data already there:\n", ofs); + printk(KERN_WARNING "ARGH. About to write node to 0x%08x on flash, but there are data already there:\n", ofs); printk(KERN_WARNING "0x%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", ofs, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], @@ -386,8 +362,10 @@ */ ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); - if (ret) + if (ret) { + up(&f->sem); return ret; + } ri->data_crc = 0; ri->node_crc = crc32(0, ri, sizeof(*ri)-8); @@ -472,7 +450,8 @@ } -int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f) +int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, + const char *name, int namelen, struct jffs2_inode_info *dead_f) { struct jffs2_raw_dirent *rd; struct jffs2_full_dirent *fd; @@ -522,7 +501,10 @@ jffs2_complete_reservation(c); up(&dir_f->sem); - if (dead_f) { /* Null if this was a rename not a real unlink */ + /* dead_f is NULL if this was a rename not a real unlink */ + /* Also catch the !f->inocache case, where there was a dirent + pointing to an inode which didn't exist. */ + if (dead_f && dead_f->inocache) { down(&dead_f->sem); diff -Nru a/fs/jffs2/writev.c b/fs/jffs2/writev.c --- a/fs/jffs2/writev.c Thu Aug 1 14:17:40 2002 +++ b/fs/jffs2/writev.c Thu Aug 1 14:17:40 2002 @@ -5,33 +5,9 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in this directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: writev.c,v 1.1 2002/03/08 11:27:59 dwmw2 Exp $ + * $Id: writev.c,v 1.2 2002/05/20 14:56:39 dwmw2 Exp $ * */ diff -Nru a/fs/jfs/file.c b/fs/jfs/file.c --- a/fs/jfs/file.c Thu Aug 1 14:17:39 2002 +++ b/fs/jfs/file.c Thu Aug 1 14:17:39 2002 @@ -98,5 +98,6 @@ .write = generic_file_write, .read = generic_file_read, .mmap = generic_file_mmap, + .sendfile = generic_file_sendfile, .fsync = jfs_fsync, }; diff -Nru a/fs/jfs/inode.c b/fs/jfs/inode.c --- a/fs/jfs/inode.c Thu Aug 1 14:17:36 2002 +++ b/fs/jfs/inode.c Thu Aug 1 14:17:36 2002 @@ -293,10 +293,23 @@ return generic_block_bmap(mapping, block, jfs_get_block); } +static int +jfs_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks, + struct buffer_head *bh_result, int create) +{ + int ret; + + ret = jfs_get_block(inode, iblock, bh_result, create); + if (ret == 0) + bh_result->b_size = (1 << inode->i_blkbits); + return ret; +} + static int jfs_direct_IO(int rw, struct inode *inode, char *buf, loff_t offset, size_t count) { - return generic_direct_IO(rw, inode, buf, offset, count, jfs_get_block); + return generic_direct_IO(rw, inode, buf, + offset, count, jfs_get_blocks); } struct address_space_operations jfs_aops = { diff -Nru a/fs/jfs/namei.c b/fs/jfs/namei.c --- a/fs/jfs/namei.c Thu Aug 1 14:17:41 2002 +++ b/fs/jfs/namei.c Thu Aug 1 14:17:41 2002 @@ -399,8 +399,6 @@ IWRITE_UNLOCK(dip); - d_delete(dentry); - out2: free_UCSname(&dname); @@ -542,8 +540,6 @@ } IWRITE_UNLOCK(dip); - - d_delete(dentry); out1: free_UCSname(&dname); diff -Nru a/fs/locks.c b/fs/locks.c --- a/fs/locks.c Thu Aug 1 14:17:41 2002 +++ b/fs/locks.c Thu Aug 1 14:17:41 2002 @@ -477,27 +477,21 @@ } /* - * Remove lock from the lock lists + * Delete a lock and then free it. + * Wake up processes that are blocked waiting for this lock, + * notify the FS that the lock has been cleared and + * finally free the lock. */ -static inline void _unhash_lock(struct file_lock **thisfl_p) +static void locks_delete_lock(struct file_lock **thisfl_p) { struct file_lock *fl = *thisfl_p; *thisfl_p = fl->fl_next; fl->fl_next = NULL; - list_del_init(&fl->fl_link); -} -/* - * Wake up processes that are blocked waiting for this lock, - * notify the FS that the lock has been cleared and - * finally free the lock. - */ -static inline void _delete_lock(struct file_lock *fl) -{ fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync); - if (fl->fl_fasync != NULL){ + if (fl->fl_fasync != NULL) { printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); fl->fl_fasync = NULL; } @@ -509,36 +503,6 @@ locks_free_lock(fl); } -/* - * Delete a lock and then free it. - */ -static void locks_delete_lock(struct file_lock **thisfl_p) -{ - struct file_lock *fl = *thisfl_p; - - _unhash_lock(thisfl_p); - _delete_lock(fl); -} - -/* - * Call back client filesystem in order to get it to unregister a lock, - * then delete lock. Essentially useful only in locks_remove_*(). - * Note: this must be called with the semaphore already held! - */ -static inline void locks_unlock_delete(struct file_lock **thisfl_p) -{ - struct file_lock *fl = *thisfl_p; - int (*lock)(struct file *, int, struct file_lock *); - - _unhash_lock(thisfl_p); - if (fl->fl_file->f_op && - (lock = fl->fl_file->f_op->lock) != NULL) { - fl->fl_type = F_UNLCK; - lock(fl->fl_file, F_SETLK, fl); - } - _delete_lock(fl); -} - /* Determine if lock sys_fl blocks lock caller_fl. Common functionality * checks for shared/exclusive status of overlapping locks. */ @@ -1242,6 +1206,9 @@ return -EACCES; if (!S_ISREG(inode->i_mode)) return -EINVAL; + error = security_ops->file_lock(filp, arg); + if (error) + return error; lock_kernel(); @@ -1359,8 +1326,7 @@ if (error < 0) goto out_putf; - error = security_ops->file_lock(filp, cmd, - (cmd & LOCK_NB) ? 0 : 1); + error = security_ops->file_lock(filp, lock->fl_type); if (error) goto out_putf; @@ -1494,8 +1460,7 @@ goto out; } - error = security_ops->file_lock(filp, file_lock->fl_type, - cmd == F_SETLKW); + error = security_ops->file_lock(filp, file_lock->fl_type); if (error) goto out; @@ -1618,8 +1583,7 @@ goto out; } - error = security_ops->file_lock(filp, file_lock->fl_type, - cmd == F_SETLKW64); + error = security_ops->file_lock(filp, file_lock->fl_type); if (error) goto out; @@ -1638,37 +1602,27 @@ /* * This function is called when the file is being removed - * from the task's fd array. + * from the task's fd array. POSIX locks belonging to this task + * are deleted at this time. */ void locks_remove_posix(struct file *filp, fl_owner_t owner) { - struct inode * inode = filp->f_dentry->d_inode; - struct file_lock *fl; - struct file_lock **before; + struct file_lock lock; - /* - * For POSIX locks we free all locks on this file for the given task. - */ - if (!inode->i_flock) { - /* - * Notice that something might be grabbing a lock right now. - * Consider it as a race won by us - event is async, so even if - * we miss the lock added we can trivially consider it as added - * after we went through this call. - */ - return; - } - lock_kernel(); - before = &inode->i_flock; - while ((fl = *before) != NULL) { - if (IS_POSIX(fl) && fl->fl_owner == owner) { - locks_unlock_delete(before); - before = &inode->i_flock; - continue; - } - before = &fl->fl_next; + lock.fl_type = F_UNLCK; + lock.fl_flags = FL_POSIX; + lock.fl_start = 0; + lock.fl_end = OFFSET_MAX; + lock.fl_owner = owner; + lock.fl_pid = current->pid; + lock.fl_file = filp; + + if (filp->f_op && filp->f_op->lock != NULL) { + filp->f_op->lock(filp, F_SETLK, &lock); + /* Ignore any error -- we must remove the locks anyway */ } - unlock_kernel(); + + posix_lock_file(filp, &lock, 0); } /* diff -Nru a/fs/minix/file.c b/fs/minix/file.c --- a/fs/minix/file.c Thu Aug 1 14:17:40 2002 +++ b/fs/minix/file.c Thu Aug 1 14:17:40 2002 @@ -21,6 +21,7 @@ write: generic_file_write, mmap: generic_file_mmap, fsync: minix_sync_file, + sendfile: generic_file_sendfile, }; struct inode_operations minix_file_inode_operations = { diff -Nru a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c --- a/fs/ncpfs/dir.c Thu Aug 1 14:17:40 2002 +++ b/fs/ncpfs/dir.c Thu Aug 1 14:17:40 2002 @@ -51,22 +51,22 @@ struct file_operations ncp_dir_operations = { - read: generic_read_dir, - readdir: ncp_readdir, - ioctl: ncp_ioctl, + .read = generic_read_dir, + .readdir = ncp_readdir, + .ioctl = ncp_ioctl, }; struct inode_operations ncp_dir_inode_operations = { - create: ncp_create, - lookup: ncp_lookup, - unlink: ncp_unlink, - symlink: ncp_symlink, - mkdir: ncp_mkdir, - rmdir: ncp_rmdir, - mknod: ncp_mknod, - rename: ncp_rename, - setattr: ncp_notify_change, + .create = ncp_create, + .lookup = ncp_lookup, + .unlink = ncp_unlink, + .symlink = ncp_symlink, + .mkdir = ncp_mkdir, + .rmdir = ncp_rmdir, + .mknod = ncp_mknod, + .rename = ncp_rename, + .setattr = ncp_notify_change, }; /* @@ -79,17 +79,17 @@ static struct dentry_operations ncp_dentry_operations = { - d_revalidate: ncp_lookup_validate, - d_hash: ncp_hash_dentry, - d_compare: ncp_compare_dentry, - d_delete: ncp_delete_dentry, + .d_revalidate = ncp_lookup_validate, + .d_hash = ncp_hash_dentry, + .d_compare = ncp_compare_dentry, + .d_delete = ncp_delete_dentry, }; struct dentry_operations ncp_root_dentry_operations = { - d_hash: ncp_hash_dentry, - d_compare: ncp_compare_dentry, - d_delete: ncp_delete_dentry, + .d_hash = ncp_hash_dentry, + .d_compare = ncp_compare_dentry, + .d_delete = ncp_delete_dentry, }; diff -Nru a/fs/ncpfs/file.c b/fs/ncpfs/file.c --- a/fs/ncpfs/file.c Thu Aug 1 14:17:36 2002 +++ b/fs/ncpfs/file.c Thu Aug 1 14:17:36 2002 @@ -296,16 +296,16 @@ struct file_operations ncp_file_operations = { - llseek: remote_llseek, - read: ncp_file_read, - write: ncp_file_write, - ioctl: ncp_ioctl, - mmap: ncp_mmap, - release: ncp_release, - fsync: ncp_fsync, + .llseek = remote_llseek, + .read = ncp_file_read, + .write = ncp_file_write, + .ioctl = ncp_ioctl, + .mmap = ncp_mmap, + .release = ncp_release, + .fsync = ncp_fsync, }; struct inode_operations ncp_file_inode_operations = { - setattr: ncp_notify_change, + .setattr = ncp_notify_change, }; diff -Nru a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c --- a/fs/ncpfs/inode.c Thu Aug 1 14:17:40 2002 +++ b/fs/ncpfs/inode.c Thu Aug 1 14:17:40 2002 @@ -83,12 +83,12 @@ static struct super_operations ncp_sops = { - alloc_inode: ncp_alloc_inode, - destroy_inode: ncp_destroy_inode, - drop_inode: generic_delete_inode, - delete_inode: ncp_delete_inode, - put_super: ncp_put_super, - statfs: ncp_statfs, + .alloc_inode = ncp_alloc_inode, + .destroy_inode = ncp_destroy_inode, + .drop_inode = generic_delete_inode, + .delete_inode = ncp_delete_inode, + .put_super = ncp_put_super, + .statfs = ncp_statfs, }; extern struct dentry_operations ncp_root_dentry_operations; @@ -792,10 +792,10 @@ } static struct file_system_type ncp_fs_type = { - owner: THIS_MODULE, - name: "ncpfs", - get_sb: ncp_get_sb, - kill_sb: kill_anon_super, + .owner = THIS_MODULE, + .name = "ncpfs", + .get_sb = ncp_get_sb, + .kill_sb = kill_anon_super, }; static int __init init_ncp_fs(void) diff -Nru a/fs/nfs/dir.c b/fs/nfs/dir.c --- a/fs/nfs/dir.c Thu Aug 1 14:17:40 2002 +++ b/fs/nfs/dir.c Thu Aug 1 14:17:40 2002 @@ -37,6 +37,8 @@ static int nfs_readdir(struct file *, void *, filldir_t); static struct dentry *nfs_lookup(struct inode *, struct dentry *); +static int nfs_cached_lookup(struct inode *, struct dentry *, + struct nfs_fh *, struct nfs_fattr *); static int nfs_create(struct inode *, struct dentry *, int); static int nfs_mkdir(struct inode *, struct dentry *, int); static int nfs_rmdir(struct inode *, struct dentry *); @@ -107,14 +109,16 @@ again: error = NFS_PROTO(inode)->readdir(inode, cred, desc->entry->cookie, page, NFS_SERVER(inode)->dtsize, desc->plus); - /* We requested READDIRPLUS, but the server doesn't grok it */ - if (desc->plus && error == -ENOTSUPP) { - NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS; - desc->plus = 0; - goto again; - } - if (error < 0) + if (error < 0) { + /* We requested READDIRPLUS, but the server doesn't grok it */ + if (error == -ENOTSUPP && desc->plus) { + NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS; + NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS; + desc->plus = 0; + goto again; + } goto error; + } SetPageUptodate(page); /* Ensure consistent page alignment of the data. * Note: assumes we have exclusive access to this mapping either @@ -194,8 +198,7 @@ dfprintk(VFS, "NFS: find_dirent_page() searching directory page %ld\n", desc->page_index); - desc->plus = NFS_USE_READDIRPLUS(inode); - page = read_cache_page(&inode->i_data, desc->page_index, + page = read_cache_page(inode->i_mapping, desc->page_index, (filler_t *)nfs_readdir_filler, desc); if (IS_ERR(page)) { status = PTR_ERR(page); @@ -246,6 +249,24 @@ return res; } +static unsigned int nfs_type2dtype[] = { + DT_UNKNOWN, + DT_REG, + DT_DIR, + DT_BLK, + DT_CHR, + DT_LNK, + DT_SOCK, + DT_UNKNOWN, + DT_FIFO +}; + +static inline +unsigned int nfs_type_to_d_type(enum nfs_ftype type) +{ + return nfs_type2dtype[type]; +} + /* * Once we've found the start of the dirent within a page: fill 'er up... */ @@ -262,11 +283,17 @@ dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)desc->target); for(;;) { + unsigned d_type = DT_UNKNOWN; /* Note: entry->prev_cookie contains the cookie for * retrieving the current dirent on the server */ fileid = nfs_fileid_to_ino_t(entry->ino); + + /* Use readdirplus info */ + if (desc->plus && (entry->fattr->valid & NFS_ATTR_FATTR)) + d_type = nfs_type_to_d_type(entry->fattr->type); + res = filldir(dirent, entry->name, entry->len, - entry->prev_cookie, fileid, DT_UNKNOWN); + entry->prev_cookie, fileid, d_type); if (res < 0) break; file->f_pos = desc->target = entry->cookie; @@ -333,7 +360,8 @@ /* Reset read descriptor so it searches the page cache from * the start upon the next call to readdir_search_pagecache() */ desc->page_index = 0; - memset(desc->entry, 0, sizeof(*desc->entry)); + desc->entry->cookie = desc->entry->prev_cookie = 0; + desc->entry->eof = 0; out: dfprintk(VFS, "NFS: uncached_readdir() returns %d\n", status); return status; @@ -352,6 +380,8 @@ nfs_readdir_descriptor_t my_desc, *desc = &my_desc; struct nfs_entry my_entry; + struct nfs_fh fh; + struct nfs_fattr fattr; long res; lock_kernel(); @@ -369,12 +399,17 @@ * itself. */ memset(desc, 0, sizeof(*desc)); - memset(&my_entry, 0, sizeof(my_entry)); desc->file = filp; desc->target = filp->f_pos; - desc->entry = &my_entry; desc->decode = NFS_PROTO(inode)->decode_dirent; + desc->plus = NFS_USE_READDIRPLUS(inode); + + my_entry.cookie = my_entry.prev_cookie = 0; + my_entry.eof = 0; + my_entry.fh = &fh; + my_entry.fattr = &fattr; + desc->entry = &my_entry; while(!desc->entry->eof) { res = readdir_search_pagecache(desc); @@ -495,6 +530,15 @@ goto out_valid; } + error = nfs_cached_lookup(dir, dentry, &fhandle, &fattr); + if (!error) { + if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0) + goto out_bad; + if (nfs_lookup_verify_inode(inode)) + goto out_bad; + goto out_valid_renew; + } + if (NFS_STALE(inode)) goto out_bad; @@ -506,6 +550,7 @@ if ((error = nfs_refresh_inode(inode, &fattr)) != 0) goto out_bad; + out_valid_renew: nfs_renew_times(dentry); out_valid: unlock_kernel(); @@ -569,7 +614,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry) { - struct inode *inode; + struct inode *inode = NULL; int error; struct nfs_fh fhandle; struct nfs_fattr fattr; @@ -585,8 +630,19 @@ dentry->d_op = &nfs_dentry_operations; lock_kernel(); + error = nfs_cached_lookup(dir, dentry, &fhandle, &fattr); + if (!error) { + error = -EACCES; + inode = nfs_fhget(dentry, &fhandle, &fattr); + if (inode) { + d_add(dentry, inode); + nfs_renew_times(dentry); + error = 0; + } + goto out_unlock; + } + error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); - inode = NULL; if (error == -ENOENT) goto no_entry; if (!error) { @@ -599,9 +655,84 @@ } nfs_renew_times(dentry); } +out_unlock: unlock_kernel(); out: + BUG_ON(error > 0); return ERR_PTR(error); +} + +static inline +int find_dirent_name(nfs_readdir_descriptor_t *desc, struct page *page, struct dentry *dentry) +{ + struct nfs_entry *entry = desc->entry; + int status; + + while((status = dir_decode(desc)) == 0) { + if (entry->len != dentry->d_name.len) + continue; + if (memcmp(entry->name, dentry->d_name.name, entry->len)) + continue; + if (!(entry->fattr->valid & NFS_ATTR_FATTR)) + continue; + break; + } + return status; +} + +/* + * Use the cached Readdirplus results in order to avoid a LOOKUP call + * whenever we believe that the parent directory has not changed. + * + * We assume that any file creation/rename changes the directory mtime. + * As this results in a page cache invalidation whenever it occurs, + * we don't require any other tests for cache coherency. + */ +static +int nfs_cached_lookup(struct inode *dir, struct dentry *dentry, + struct nfs_fh *fh, struct nfs_fattr *fattr) +{ + nfs_readdir_descriptor_t desc; + struct nfs_server *server; + struct nfs_entry entry; + struct page *page; + unsigned long timestamp = NFS_MTIME_UPDATE(dir); + int res; + + if (!NFS_USE_READDIRPLUS(dir)) + return -ENOENT; + server = NFS_SERVER(dir); + if (server->flags & NFS_MOUNT_NOAC) + return -ENOENT; + nfs_revalidate_inode(server, dir); + + entry.fh = fh; + entry.fattr = fattr; + + desc.decode = NFS_PROTO(dir)->decode_dirent; + desc.entry = &entry; + desc.page_index = 0; + desc.plus = 1; + + for(;(page = find_get_page(dir->i_mapping, desc.page_index)); desc.page_index++) { + + res = -EIO; + if (PageUptodate(page)) { + desc.ptr = kmap(page); + res = find_dirent_name(&desc, page, dentry); + kunmap(page); + } + page_cache_release(page); + + if (res == 0) + goto out_found; + if (res != -EAGAIN) + break; + } + return -ENOENT; + out_found: + fattr->timestamp = timestamp; + return 0; } /* diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c --- a/fs/nfs/inode.c Thu Aug 1 14:17:41 2002 +++ b/fs/nfs/inode.c Thu Aug 1 14:17:41 2002 @@ -283,12 +283,14 @@ INIT_LIST_HEAD(&server->lru_busy); nfsv3_try_again: + server->caps = 0; /* Check NFS protocol revision and initialize RPC op vector * and file handle pool. */ if (data->flags & NFS_MOUNT_VER3) { #ifdef CONFIG_NFS_V3 server->rpc_ops = &nfs_v3_clientops; version = 3; + server->caps |= NFS_CAP_READDIRPLUS; if (data->version < 4) { printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n"); goto out_unlock; @@ -642,6 +644,9 @@ return __nfs_fhget(sb, fhandle, fattr); } +/* Don't use READDIRPLUS on directories that we believe are too large */ +#define NFS_LIMIT_READDIRPLUS (8*PAGE_SIZE) + /* * Look up the inode by super block and fattr->fileid. */ @@ -690,6 +695,9 @@ } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &nfs_dir_inode_operations; inode->i_fop = &nfs_dir_operations; + if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS) + && fattr->size <= NFS_LIMIT_READDIRPLUS) + NFS_FLAGS(inode) |= NFS_INO_ADVISE_RDPLUS; } else if (S_ISLNK(inode->i_mode)) inode->i_op = &nfs_symlink_inode_operations; else @@ -700,13 +708,13 @@ new_isize = nfs_size_to_loff_t(fattr->size); new_atime = nfs_time_to_secs(fattr->atime); - NFS_READTIME(inode) = jiffies; + NFS_READTIME(inode) = fattr->timestamp; NFS_CACHE_CTIME(inode) = fattr->ctime; inode->i_ctime = nfs_time_to_secs(fattr->ctime); inode->i_atime = new_atime; NFS_CACHE_MTIME(inode) = new_mtime; inode->i_mtime = nfs_time_to_secs(new_mtime); - NFS_MTIME_UPDATE(inode) = jiffies; + NFS_MTIME_UPDATE(inode) = fattr->timestamp; NFS_CACHE_ISIZE(inode) = new_size; inode->i_size = new_isize; inode->i_mode = fattr->mode; @@ -1014,6 +1022,9 @@ goto out_err; } + /* Throw out obsolete READDIRPLUS attributes */ + if (time_before(fattr->timestamp, NFS_READTIME(inode))) + return 0; /* * Make sure the inode's type hasn't changed. */ @@ -1032,7 +1043,7 @@ /* * Update the read time so we don't revalidate too often. */ - NFS_READTIME(inode) = jiffies; + NFS_READTIME(inode) = fattr->timestamp; /* * Note: NFS_CACHE_ISIZE(inode) reflects the state of the cache. @@ -1082,7 +1093,7 @@ if (NFS_CACHE_MTIME(inode) != new_mtime) { if (invalid) - NFS_MTIME_UPDATE(inode) = jiffies; + NFS_MTIME_UPDATE(inode) = fattr->timestamp; NFS_CACHE_MTIME(inode) = new_mtime; inode->i_mtime = nfs_time_to_secs(new_mtime); } diff -Nru a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c --- a/fs/nfs/nfs2xdr.c Thu Aug 1 14:17:40 2002 +++ b/fs/nfs/nfs2xdr.c Thu Aug 1 14:17:40 2002 @@ -118,6 +118,7 @@ fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; fattr->rdev = 0; } + fattr->timestamp = jiffies; return p; } @@ -419,9 +420,9 @@ kunmap(*page); return nr; short_pkt: - kunmap(*page); printk(KERN_NOTICE "NFS: short packet in readdir reply!\n"); entry[0] = entry[1] = 0; + kunmap(*page); return nr; err_unmap: kunmap(*page); diff -Nru a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c --- a/fs/nfs/nfs3xdr.c Thu Aug 1 14:17:41 2002 +++ b/fs/nfs/nfs3xdr.c Thu Aug 1 14:17:41 2002 @@ -181,6 +181,7 @@ /* Update the mode bits */ fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3); + fattr->timestamp = jiffies; return p; } @@ -573,10 +574,10 @@ kunmap(*page); return nr; short_pkt: - kunmap(*page); printk(KERN_NOTICE "NFS: short packet in readdir reply!\n"); /* truncate listing */ entry[0] = entry[1] = 0; + kunmap(*page); return nr; err_unmap: kunmap(*page); @@ -603,21 +604,19 @@ p = xdr_decode_hyper(p, &entry->cookie); if (plus) { - p = xdr_decode_post_op_attr(p, &entry->fattr); + entry->fattr->valid = 0; + p = xdr_decode_post_op_attr(p, entry->fattr); /* In fact, a post_op_fh3: */ if (*p++) { - p = xdr_decode_fhandle(p, &entry->fh); + p = xdr_decode_fhandle(p, entry->fh); /* Ugh -- server reply was truncated */ if (p == NULL) { dprintk("NFS: FH truncated\n"); *entry = old; return ERR_PTR(-EAGAIN); } - } else { - /* If we don't get a file handle, the attrs - * aren't worth a lot. */ - entry->fattr.valid = 0; - } + } else + memset((u8*)(entry->fh), 0, sizeof(*entry->fh)); } entry->eof = !p[0] && p[1]; diff -Nru a/fs/nfs/write.c b/fs/nfs/write.c --- a/fs/nfs/write.c Thu Aug 1 14:17:37 2002 +++ b/fs/nfs/write.c Thu Aug 1 14:17:37 2002 @@ -808,8 +808,15 @@ * If wsize is smaller than page size, update and write * page synchronously. */ - if (NFS_SERVER(inode)->wsize < PAGE_CACHE_SIZE || IS_SYNC(inode)) - return nfs_writepage_sync(file, inode, page, offset, count); + if (NFS_SERVER(inode)->wsize < PAGE_CACHE_SIZE || IS_SYNC(inode)) { + status = nfs_writepage_sync(file, inode, page, offset, count); + if (status > 0) { + if (offset == 0 && status == PAGE_CACHE_SIZE) + SetPageUptodate(page); + return 0; + } + return status; + } /* * Try to find an NFS request corresponding to this page diff -Nru a/fs/ntfs/file.c b/fs/ntfs/file.c --- a/fs/ntfs/file.c Thu Aug 1 14:17:41 2002 +++ b/fs/ntfs/file.c Thu Aug 1 14:17:41 2002 @@ -52,6 +52,7 @@ llseek: generic_file_llseek, /* Seek inside file. */ read: generic_file_read, /* Read from file. */ mmap: generic_file_mmap, /* Mmap file. */ + sendfile: generic_file_sendfile, /* Zero-copy data send */ open: ntfs_file_open, /* Open file. */ }; diff -Nru a/fs/partitions/Config.in b/fs/partitions/Config.in --- a/fs/partitions/Config.in Thu Aug 1 14:17:39 2002 +++ b/fs/partitions/Config.in Thu Aug 1 14:17:39 2002 @@ -25,7 +25,7 @@ bool ' Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION bool ' Unixware slices support' CONFIG_UNIXWARE_DISKLABEL fi - dep_bool ' Windows Logical Disk Manager (Dynamic Disk) support' CONFIG_LDM_PARTITION + bool ' Windows Logical Disk Manager (Dynamic Disk) support' CONFIG_LDM_PARTITION if [ "$CONFIG_LDM_PARTITION" = "y" ]; then bool ' Windows LDM extra logging' CONFIG_LDM_DEBUG fi diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c --- a/fs/partitions/check.c Thu Aug 1 14:17:40 2002 +++ b/fs/partitions/check.c Thu Aug 1 14:17:40 2002 @@ -107,11 +107,13 @@ const char *maj = hd->major_name; unsigned int unit = (minor >> hd->minor_shift); unsigned int part = (minor & ((1 << hd->minor_shift) -1 )); + struct hd_struct *p = hd->part + minor - hd->first_minor; - if ((unit < hd->nr_real) && hd->part[minor].de) { + if ((((minor - hd->first_minor) >> hd->minor_shift) < hd->nr_real) && + p->de) { int pos; - pos = devfs_generate_path (hd->part[minor].de, buf, 64); + pos = devfs_generate_path(p->de, buf, 64); if (pos >= 0) return buf + pos; } @@ -210,33 +212,25 @@ kdev.value=(int)(long)driverfs_dev->driver_data; return off ? 0 : sprintf (page, "%x\n",kdev.value); } -static struct driver_file_entry partition_device_kdev_file = { - name: "kdev", - mode: S_IRUGO, - show: partition_device_kdev_read, -}; +static DEVICE_ATTR(kdev,"kdev",S_IRUGO,partition_device_kdev_read,NULL); static ssize_t partition_device_type_read(struct device *driverfs_dev, char *page, size_t count, loff_t off) { return off ? 0 : sprintf (page, "BLK\n"); } -static struct driver_file_entry partition_device_type_file = { - name: "type", - mode: S_IRUGO, - show: partition_device_type_read, -}; +static DEVICE_ATTR(type,"type",S_IRUGO,partition_device_type_read,NULL); void driverfs_create_partitions(struct gendisk *hd, int minor) { int pos = -1; - int devnum = minor >> hd->minor_shift; + int devnum = (minor - hd->first_minor) >> hd->minor_shift; char dirname[256]; struct device *parent = 0; int max_p; int part; devfs_handle_t dir = 0; - struct hd_struct *p = hd->part + minor; + struct hd_struct *p = hd->part + minor - hd->first_minor; /* get parent driverfs device structure */ if (hd->driverfs_dev_arr) @@ -296,9 +290,9 @@ if (parent) current_driverfs_dev->bus = parent->bus; device_register(current_driverfs_dev); device_create_file(current_driverfs_dev, - &partition_device_type_file); + &dev_attr_type); device_create_file(current_driverfs_dev, - &partition_device_kdev_file); + &dev_attr_kdev); } } } @@ -308,7 +302,7 @@ int max_p; int part; struct device * current_driverfs_dev; - struct hd_struct *p = hd->part + minor; + struct hd_struct *p = hd->part + minor - hd->first_minor; max_p=(1 << hd->minor_shift); @@ -317,17 +311,17 @@ if ((p[part].nr_sects >= 1)) { current_driverfs_dev = &p[part].hd_driverfs_dev; device_remove_file(current_driverfs_dev, - partition_device_type_file.name); + &dev_attr_type); device_remove_file(current_driverfs_dev, - partition_device_kdev_file.name); + &dev_attr_kdev); put_device(current_driverfs_dev); } } current_driverfs_dev = &p->hd_driverfs_dev; - device_remove_file(current_driverfs_dev, - partition_device_type_file.name); - device_remove_file(current_driverfs_dev, - partition_device_kdev_file.name); + device_remove_file(current_driverfs_dev, + &dev_attr_type); + device_remove_file(current_driverfs_dev, + &dev_attr_kdev); put_device(current_driverfs_dev); return; } @@ -335,31 +329,17 @@ static void check_partition(struct gendisk *hd, kdev_t dev) { devfs_handle_t de = NULL; - unsigned long first_sector; struct block_device *bdev; char buf[64]; struct parsed_partitions *state; int i; - first_sector = hd->part[minor(dev)].start_sect; - - /* - * This is a kludge to allow the partition check to be - * skipped for specific drives (e.g. IDE CD-ROM drives) - */ - if ((int)first_sector == -1) { - hd->part[minor(dev)].start_sect = 0; - return; - } - if (first_sector != 0) - BUG(); - state = kmalloc(sizeof(struct parsed_partitions), GFP_KERNEL); if (!state) return; if (hd->de_arr) - de = hd->de_arr[minor(dev) >> hd->minor_shift]; + de = hd->de_arr[(minor(dev)-hd->first_minor)>>hd->minor_shift]; i = devfs_generate_path (de, buf, sizeof buf); if (i >= 0) { printk(KERN_INFO " /dev/%s:", buf + i); @@ -377,6 +357,7 @@ state->limit = 1<minor_shift; for (i = 0; check_part[i]; i++) { int res, j; + struct hd_struct *p; memset(&state->parts, 0, sizeof(state->parts)); res = check_part[i](state, bdev); if (!res) @@ -385,12 +366,11 @@ if (warn_no_part) printk(" unable to read partition table\n"); goto setup_devfs; - } + } + p = hd->part + minor(dev) - hd->first_minor; for (j = 1; j < state->limit; j++) { - hd->part[j + minor(dev)].start_sect = - state->parts[j].from; - hd->part[j + minor(dev)].nr_sects = - state->parts[j].size; + p[j].start_sect = state->parts[j].from; + p[j].nr_sects = state->parts[j].size; #if CONFIG_BLK_DEV_MD if (!state->parts[j].flags) continue; @@ -404,34 +384,31 @@ setup_devfs: blkdev_put(bdev, BDEV_RAW); out: - /* Setup driverfs tree */ - if (hd->sizes) - driverfs_create_partitions(hd, minor(dev)); - else - driverfs_remove_partitions(hd, minor(dev)); - - devfs_register_partitions (hd, minor(dev), hd->sizes ? 0 : 1); + driverfs_create_partitions(hd, minor(dev)); + devfs_register_partitions (hd, minor(dev), 0); } #ifdef CONFIG_DEVFS_FS static void devfs_register_partition (struct gendisk *dev, int minor, int part) { - int devnum = minor >> dev->minor_shift; + int devnum = (minor - dev->first_minor) >> dev->minor_shift; devfs_handle_t dir; unsigned int devfs_flags = DEVFS_FL_DEFAULT; + struct hd_struct *p = dev->part + minor - dev->first_minor; char devname[16]; - if (dev->part[minor + part].de) return; - dir = devfs_get_parent (dev->part[minor].de); - if (!dir) return; + if (p[part].de) + return; + dir = devfs_get_parent(p[0].de); + if (!dir) + return; if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) ) devfs_flags |= DEVFS_FL_REMOVABLE; sprintf (devname, "part%d", part); - dev->part[minor + part].de = - devfs_register (dir, devname, devfs_flags, - dev->major, minor + part, - S_IFBLK | S_IRUSR | S_IWUSR, - dev->fops, NULL); + p[part].de = devfs_register (dir, devname, devfs_flags, + dev->major, minor + part, + S_IFBLK | S_IRUSR | S_IWUSR, + dev->fops, NULL); } static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER; @@ -439,38 +416,40 @@ static void devfs_register_disc (struct gendisk *dev, int minor) { int pos = 0; - int devnum = minor >> dev->minor_shift; + int devnum = (minor - dev->first_minor) >> dev->minor_shift; devfs_handle_t dir, slave; unsigned int devfs_flags = DEVFS_FL_DEFAULT; char dirname[64], symlink[16]; static devfs_handle_t devfs_handle; + struct hd_struct *p = dev->part + minor - dev->first_minor; - if (dev->part[minor].de) return; + if (p[0].de) + return; if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) ) devfs_flags |= DEVFS_FL_REMOVABLE; if (dev->de_arr) { dir = dev->de_arr[devnum]; if (!dir) /* Aware driver wants to block disc management */ return; - pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3); - if (pos < 0) return; - strncpy (dirname + pos, "../", 3); - } - else { + pos = devfs_generate_path(dir, dirname + 3, sizeof dirname-3); + if (pos < 0) + return; + strncpy(dirname + pos, "../", 3); + } else { /* Unaware driver: construct "real" directory */ - sprintf (dirname, "../%s/disc%d", dev->major_name, devnum); - dir = devfs_mk_dir (NULL, dirname + 3, NULL); + sprintf(dirname, "../%s/disc%d", dev->major_name, + (dev->first_minor >> dev->minor_shift) + devnum); + dir = devfs_mk_dir(NULL, dirname + 3, NULL); } if (!devfs_handle) - devfs_handle = devfs_mk_dir (NULL, "discs", NULL); - dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace); - sprintf (symlink, "disc%d", dev->part[minor].number); + devfs_handle = devfs_mk_dir(NULL, "discs", NULL); + p[0].number = devfs_alloc_unique_number (&disc_numspace); + sprintf(symlink, "disc%d", p[0].number); devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT, dirname + pos, &slave, NULL); - dev->part[minor].de = - devfs_register (dir, "disc", devfs_flags, dev->major, minor, + p[0].de = devfs_register (dir, "disc", devfs_flags, dev->major, minor, S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); - devfs_auto_unregister (dev->part[minor].de, slave); + devfs_auto_unregister(p[0].de, slave); if (!dev->de_arr) devfs_auto_unregister (slave, dir); } @@ -480,23 +459,23 @@ { #ifdef CONFIG_DEVFS_FS int part, max_p; + struct hd_struct *p = dev->part + minor - dev->first_minor; if (!unregister) devfs_register_disc (dev, minor); max_p = (1 << dev->minor_shift); for (part = 1; part < max_p; part++) { - if ( unregister || (dev->part[part + minor].nr_sects < 1) ) { - devfs_unregister (dev->part[part + minor].de); - dev->part[part + minor].de = NULL; + if ( unregister || (p[part].nr_sects < 1) ) { + devfs_unregister(p[part].de); + dev->part[p].de = NULL; continue; } devfs_register_partition (dev, minor, part); } if (unregister) { - devfs_unregister (dev->part[minor].de); - dev->part[minor].de = NULL; - devfs_dealloc_unique_number (&disc_numspace, - dev->part[minor].number); + devfs_unregister(p[0].de); + p[0].de = NULL; + devfs_dealloc_unique_number(&disc_numspace, p[0].number); } #endif /* CONFIG_DEVFS_FS */ } @@ -521,8 +500,9 @@ void grok_partitions(kdev_t dev, long size) { - int i, minors, first_minor, end_minor; + int minors, first_minor, end_minor; struct gendisk *g = get_gendisk(dev); + struct hd_struct *p; if (!g) return; @@ -536,36 +516,18 @@ } end_minor = first_minor + minors; - if (!g->sizes) - blk_size[g->major] = NULL; - - g->part[first_minor].nr_sects = size; + p = g->part + first_minor - g->first_minor; + p[0].nr_sects = size; /* No minors to use for partitions */ if (minors == 1) return; - if (g->sizes) { - g->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9); - for (i = first_minor + 1; i < end_minor; i++) - g->sizes[i] = 0; - } - blk_size[g->major] = g->sizes; - /* No such device (e.g., media were just removed) */ if (!size) return; check_partition(g, mk_kdev(g->major, first_minor)); - - /* - * We need to set the sizes array before we will be able to access - * any of the partitions on this device. - */ - if (g->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */ - for (i = first_minor; i < end_minor; i++) - g->sizes[i] = g->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9); - } } unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p) @@ -596,6 +558,7 @@ struct gendisk *g; kdev_t devp; int p, major, minor, minor0, max_p, res; + struct hd_struct *part; g = get_gendisk(dev); if (g == NULL) @@ -608,19 +571,20 @@ if (minor0 != minor) /* for now only whole-disk reread */ return -EINVAL; /* %%% later.. */ + part = g->part + minor - g->first_minor; /* invalidate stuff */ for (p = max_p - 1; p >= 0; p--) { minor = minor0 + p; devp = mk_kdev(major,minor); #if 0 /* %%% superfluous? */ - if (g->part[minor].nr_sects == 0) + if (part[p].nr_sects == 0) continue; #endif res = invalidate_device(devp, 1); if (res) return res; - g->part[minor].start_sect = 0; - g->part[minor].nr_sects = 0; + part[p].start_sect = 0; + part[p].nr_sects = 0; } return 0; } diff -Nru a/fs/partitions/msdos.c b/fs/partitions/msdos.c --- a/fs/partitions/msdos.c Thu Aug 1 14:17:36 2002 +++ b/fs/partitions/msdos.c Thu Aug 1 14:17:36 2002 @@ -385,87 +385,6 @@ {SOLARIS_X86_PARTITION, parse_solaris_x86}, {0, NULL}, }; -/* - * Look for various forms of IDE disk geometry translation - */ -static int handle_ide_mess(struct block_device *bdev) -{ -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - Sector sect; - unsigned char *data; - kdev_t dev = to_kdev_t(bdev->bd_dev); - unsigned int sig; - int heads = 0; - struct partition *p; - int i; -#ifdef CONFIG_BLK_DEV_IDE_MODULE - if (!ide_xlate_1024) - return 1; -#endif - /* - * The i386 partition handling programs very often - * make partitions end on cylinder boundaries. - * There is no need to do so, and Linux fdisk doesn't always - * do this, and Windows NT on Alpha doesn't do this either, - * but still, this helps to guess #heads. - */ - data = read_dev_sector(bdev, 0, §); - if (!data) - return -1; - if (!msdos_magic_present(data + 510)) { - put_dev_sector(sect); - return 0; - } - sig = le16_to_cpu(*(unsigned short *)(data + 2)); - p = (struct partition *) (data + 0x1be); - for (i = 0; i < 4; i++) { - struct partition *q = &p[i]; - if (NR_SECTS(q)) { - if ((q->sector & 63) == 1 && - (q->end_sector & 63) == 63) - heads = q->end_head + 1; - break; - } - } - if (SYS_IND(p) == EZD_PARTITION) { - /* - * Accesses to sector 0 must go to sector 1 instead. - */ - if (ide_xlate_1024(dev, -1, heads, " [EZD]")) - goto reread; - } else if (SYS_IND(p) == DM6_PARTITION) { - - /* - * Everything on the disk is offset by 63 sectors, - * including a "new" MBR with its own partition table. - */ - if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]")) - goto reread; - } else if (sig <= 0x1ae && - data[sig] == 0xAA && data[sig+1] == 0x55 && - (data[sig+2] & 1)) { - /* DM6 signature in MBR, courtesy of OnTrack */ - (void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]"); - } else if (SYS_IND(p) == DM6_AUX1PARTITION || - SYS_IND(p) == DM6_AUX3PARTITION) { - /* - * DM6 on other than the first (boot) drive - */ - (void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]"); - } else { - (void) ide_xlate_1024(dev, 2, heads, " [PTBL]"); - } - put_dev_sector(sect); - return 1; - -reread: - put_dev_sector(sect); - /* Flush the cache */ - invalidate_bdev(bdev, 1); - truncate_inode_pages(bdev->bd_inode->i_mapping, 0); -#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */ - return 1; -} int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) { @@ -474,11 +393,7 @@ unsigned char *data; struct partition *p; int slot; - int err; - err = handle_ide_mess(bdev); - if (err <= 0) - return err; data = read_dev_sector(bdev, 0, §); if (!data) return -1; @@ -524,21 +439,6 @@ state->parts[slot].flags = 1; } - /* - * Check for old-style Disk Manager partition table - */ - if (msdos_magic_present(data + 0xfc)) { - p = (struct partition *) (0x1be + data); - for (slot = 4 ; slot < 16 ; slot++, state->next++) { - p--; - if (state->next == state->limit) - break; - if (!(START_SECT(p) && NR_SECTS(p))) - continue; - put_partition(state, state->next, - START_SECT(p), NR_SECTS(p)); - } - } printk("\n"); /* second pass - output for each on a separate line */ @@ -556,7 +456,7 @@ if (!subtypes[n].parse) continue; subtypes[n].parse(state, bdev, START_SECT(p)*sector_size, - NR_SECTS(p)*sector_size, n); + NR_SECTS(p)*sector_size, slot); } put_dev_sector(sect); return 1; diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c --- a/fs/proc/proc_misc.c Thu Aug 1 14:17:36 2002 +++ b/fs/proc/proc_misc.c Thu Aug 1 14:17:36 2002 @@ -126,11 +126,13 @@ return proc_calc_metrics(page, start, off, count, eof, len); } +extern atomic_t vm_committed_space; + static int meminfo_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { struct sysinfo i; - int len; + int len, committed; struct page_state ps; get_page_state(&ps); @@ -140,6 +142,7 @@ #define K(x) ((x) << (PAGE_SHIFT - 10)) si_meminfo(&i); si_swapinfo(&i); + committed = atomic_read(&vm_committed_space); /* * Tagged format, for easy grepping and expansion. @@ -160,9 +163,9 @@ "SwapFree: %8lu kB\n" "Dirty: %8lu kB\n" "Writeback: %8lu kB\n" + "Committed_AS: %8u kB\n" "PageTables: %8lu kB\n" - "PteChainTot: %8lu kB\n" - "PteChainUsed: %8lu kB\n", + "ReverseMaps: %8lu\n", K(i.totalram), K(i.freeram), K(i.sharedram), @@ -178,9 +181,9 @@ K(i.freeswap), K(ps.nr_dirty), K(ps.nr_writeback), + K(committed), K(ps.nr_page_table_pages), - K(ps.nr_pte_chain_pages), - ps.used_pte_chains_bytes >> 10 + ps.nr_reverse_maps ); return proc_calc_metrics(page, start, off, count, eof, len); diff -Nru a/fs/qnx4/file.c b/fs/qnx4/file.c --- a/fs/qnx4/file.c Thu Aug 1 14:17:40 2002 +++ b/fs/qnx4/file.c Thu Aug 1 14:17:40 2002 @@ -33,6 +33,7 @@ #ifdef CONFIG_QNX4FS_RW fsync: qnx4_sync_file, #endif + sendfile: generic_file_sendfile, }; struct inode_operations qnx4_file_inode_operations = diff -Nru a/fs/ramfs/inode.c b/fs/ramfs/inode.c --- a/fs/ramfs/inode.c Thu Aug 1 14:17:40 2002 +++ b/fs/ramfs/inode.c Thu Aug 1 14:17:40 2002 @@ -276,6 +276,7 @@ write: generic_file_write, mmap: generic_file_mmap, fsync: ramfs_sync_file, + sendfile: generic_file_sendfile, }; static struct inode_operations ramfs_dir_inode_operations = { diff -Nru a/fs/read_write.c b/fs/read_write.c --- a/fs/read_write.c Thu Aug 1 14:17:41 2002 +++ b/fs/read_write.c Thu Aug 1 14:17:41 2002 @@ -19,6 +19,7 @@ llseek: generic_file_llseek, read: generic_file_read, mmap: generic_file_mmap, + sendfile: generic_file_sendfile, }; loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) @@ -184,8 +185,6 @@ return -EBADF; if (!file->f_op || !file->f_op->read) return -EINVAL; - if (pos < 0) - return -EINVAL; ret = locks_verify_area(FLOCK_VERIFY_READ, inode, file, *pos, count); if (!ret) { @@ -209,8 +208,6 @@ return -EBADF; if (!file->f_op || !file->f_op->write) return -EINVAL; - if (pos < 0) - return -EINVAL; ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, *pos, count); if (!ret) { @@ -253,12 +250,15 @@ return ret; } -asmlinkage ssize_t sys_pread(unsigned int fd, char *buf, +asmlinkage ssize_t sys_pread64(unsigned int fd, char *buf, size_t count, loff_t pos) { struct file *file; ssize_t ret = -EBADF; + if (pos < 0) + return -EINVAL; + file = fget(fd); if (file) { ret = vfs_read(file, buf, count, &pos); @@ -268,12 +268,15 @@ return ret; } -asmlinkage ssize_t sys_pwrite(unsigned int fd, const char *buf, +asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char *buf, size_t count, loff_t pos) { struct file *file; ssize_t ret = -EBADF; + if (pos < 0) + return -EINVAL; + file = fget(fd); if (file) { ret = vfs_write(file, buf, count, &pos); @@ -435,4 +438,114 @@ bad_file: return ret; +} + +static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, + size_t count, loff_t max) +{ + struct file * in_file, * out_file; + struct inode * in_inode, * out_inode; + loff_t pos; + ssize_t retval; + + /* + * Get input file, and verify that it is ok.. + */ + retval = -EBADF; + in_file = fget(in_fd); + if (!in_file) + goto out; + if (!(in_file->f_mode & FMODE_READ)) + goto fput_in; + retval = -EINVAL; + in_inode = in_file->f_dentry->d_inode; + if (!in_inode) + goto fput_in; + if (!in_file->f_op || !in_file->f_op->sendfile) + goto fput_in; + retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, in_file->f_pos, count); + if (retval) + goto fput_in; + + /* + * Get output file, and verify that it is ok.. + */ + retval = -EBADF; + out_file = fget(out_fd); + if (!out_file) + goto fput_in; + if (!(out_file->f_mode & FMODE_WRITE)) + goto fput_out; + retval = -EINVAL; + if (!out_file->f_op || !out_file->f_op->sendpage) + goto fput_out; + out_inode = out_file->f_dentry->d_inode; + retval = locks_verify_area(FLOCK_VERIFY_WRITE, out_inode, out_file, out_file->f_pos, count); + if (retval) + goto fput_out; + + if (!ppos) + ppos = &in_file->f_pos; + + if (!max) + max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); + + pos = *ppos; + retval = -EINVAL; + if (unlikely(pos < 0)) + goto fput_out; + if (unlikely(pos + count > max)) { + retval = -EOVERFLOW; + if (pos >= max) + goto fput_out; + count = max - pos; + } + + retval = in_file->f_op->sendfile(out_file, in_file, ppos, count); + + if (*ppos > max) + retval = -EOVERFLOW; + +fput_out: + fput(out_file); +fput_in: + fput(in_file); +out: + return retval; +} + +asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count) +{ + loff_t pos; + off_t off; + ssize_t ret; + + if (offset) { + if (unlikely(get_user(off, offset))) + return -EFAULT; + pos = off; + ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS); + if (unlikely(put_user(pos, offset))) + return -EFAULT; + return ret; + } + + return do_sendfile(out_fd, in_fd, NULL, count, MAX_NON_LFS); +} + +asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count) +{ + loff_t pos; + ssize_t ret; + + if (offset) { + if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t)))) + return -EFAULT; + ret = do_sendfile(out_fd, in_fd, &pos, count, 0); + if (unlikely(put_user(pos, offset))) + return -EFAULT; + return ret; + } + + return do_sendfile(out_fd, in_fd, NULL, count, 0); } diff -Nru a/fs/reiserfs/file.c b/fs/reiserfs/file.c --- a/fs/reiserfs/file.c Thu Aug 1 14:17:36 2002 +++ b/fs/reiserfs/file.c Thu Aug 1 14:17:36 2002 @@ -147,6 +147,7 @@ mmap: generic_file_mmap, release: reiserfs_file_release, fsync: reiserfs_sync_file, + sendfile: generic_file_sendfile, }; diff -Nru a/fs/smbfs/file.c b/fs/smbfs/file.c --- a/fs/smbfs/file.c Thu Aug 1 14:17:41 2002 +++ b/fs/smbfs/file.c Thu Aug 1 14:17:41 2002 @@ -105,9 +105,9 @@ int error; struct dentry *dentry = file->f_dentry; - get_page(page); + page_cache_get(page); error = smb_readpage_sync(dentry, page); - put_page(page); + page_cache_release(page); return error; } @@ -194,11 +194,11 @@ if (page->index >= end_index+1 || !offset) return -EIO; do_it: - get_page(page); + page_cache_get(page); err = smb_writepage_sync(inode, page, 0, offset); SetPageUptodate(page); unlock_page(page); - put_page(page); + page_cache_release(page); return err; } diff -Nru a/fs/smbfs/smbiod.c b/fs/smbfs/smbiod.c --- a/fs/smbfs/smbiod.c Thu Aug 1 14:17:41 2002 +++ b/fs/smbfs/smbiod.c Thu Aug 1 14:17:41 2002 @@ -269,6 +269,7 @@ set_bit(SMBIOD_DATA_READY, &smbiod_flags); out: + return; } /* diff -Nru a/fs/sysv/file.c b/fs/sysv/file.c --- a/fs/sysv/file.c Thu Aug 1 14:17:41 2002 +++ b/fs/sysv/file.c Thu Aug 1 14:17:41 2002 @@ -25,6 +25,7 @@ write: generic_file_write, mmap: generic_file_mmap, fsync: sysv_sync_file, + sendfile: generic_file_sendfile, }; struct inode_operations sysv_file_inode_operations = { diff -Nru a/fs/udf/file.c b/fs/udf/file.c --- a/fs/udf/file.c Thu Aug 1 14:17:36 2002 +++ b/fs/udf/file.c Thu Aug 1 14:17:36 2002 @@ -365,6 +365,7 @@ write: udf_file_write, release: udf_release_file, fsync: udf_fsync_file, + sendfile: generic_file_sendfile, }; struct inode_operations udf_file_inode_operations = { diff -Nru a/fs/ufs/file.c b/fs/ufs/file.c --- a/fs/ufs/file.c Thu Aug 1 14:17:39 2002 +++ b/fs/ufs/file.c Thu Aug 1 14:17:39 2002 @@ -47,6 +47,7 @@ write: generic_file_write, mmap: generic_file_mmap, open: generic_file_open, + sendfile: generic_file_sendfile, }; struct inode_operations ufs_file_inode_operations = { diff -Nru a/fs/ufs/super.c b/fs/ufs/super.c --- a/fs/ufs/super.c Thu Aug 1 14:17:36 2002 +++ b/fs/ufs/super.c Thu Aug 1 14:17:36 2002 @@ -673,7 +673,7 @@ } if (uspi->s_bsize < 4096) { printk("ufs_read_super: block size %u is too small\n", - uspi->s_fsize); + uspi->s_bsize); goto failed; } if (uspi->s_bsize / uspi->s_fsize > 8) { diff -Nru a/include/asm-alpha/processor.h b/include/asm-alpha/processor.h --- a/include/asm-alpha/processor.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-alpha/processor.h Thu Aug 1 14:17:41 2002 @@ -74,7 +74,7 @@ #define KSTK_ESP(tsk) \ ((tsk) == current ? rdusp() : (tsk)->thread_info->pcb.usp) -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() #define ARCH_HAS_PREFETCH #define ARCH_HAS_PREFETCHW diff -Nru a/include/asm-alpha/socket.h b/include/asm-alpha/socket.h --- a/include/asm-alpha/socket.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-alpha/socket.h Thu Aug 1 14:17:41 2002 @@ -3,7 +3,7 @@ #include -/* For setsockoptions(2) */ +/* For setsockopt(2) */ /* * Note: we only bother about making the SOL_SOCKET options * same as OSF/1, as that's all that "normal" programs are diff -Nru a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h --- a/include/asm-alpha/unistd.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-alpha/unistd.h Thu Aug 1 14:17:40 2002 @@ -286,8 +286,8 @@ #define __NR_pciconfig_write 346 #define __NR_query_module 347 #define __NR_prctl 348 -#define __NR_pread 349 -#define __NR_pwrite 350 +#define __NR_pread64 349 +#define __NR_pwrite64 350 #define __NR_rt_sigreturn 351 #define __NR_rt_sigaction 352 #define __NR_rt_sigprocmask 353 diff -Nru a/include/asm-arm/arch-ebsa285/keyboard.h b/include/asm-arm/arch-ebsa285/keyboard.h --- a/include/asm-arm/arch-ebsa285/keyboard.h Thu Aug 1 14:17:39 2002 +++ b/include/asm-arm/arch-ebsa285/keyboard.h Thu Aug 1 14:17:40 2002 @@ -6,63 +6,4 @@ * Copyright (C) 1998-2001 Russell King * (C) 1998 Phil Blundell */ -#include -#include -#include -#include - -#define KEYBOARD_IRQ IRQ_ISA_KEYBOARD -#define NR_SCANCODES 128 - -#define kbd_disable_irq() do { } while (0) -#define kbd_enable_irq() do { } while (0) - -extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); -extern int pckbd_getkeycode(unsigned int scancode); -extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode); -extern char pckbd_unexpected_up(unsigned char keycode); -extern void pckbd_leds(unsigned char leds); -extern void pckbd_init_hw(void); -extern unsigned char pckbd_sysrq_xlate[128]; - -static inline void kbd_init_hw(void) -{ - if (have_isa_bridge) { - k_setkeycode = pckbd_setkeycode; - k_getkeycode = pckbd_getkeycode; - k_translate = pckbd_translate; - k_unexpected_up = pckbd_unexpected_up; - k_leds = pckbd_leds; -#ifdef CONFIG_MAGIC_SYSRQ - k_sysrq_key = 0x54; - k_sysrq_xlate = pckbd_sysrq_xlate; -#endif - pckbd_init_hw(); - } -} - - -/* - * The rest of this file is to do with supporting pc_keyb.c - */ - -/* resource allocation */ -#define kbd_request_region() request_region(0x60, 16, "keyboard") -#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \ - "keyboard", NULL) - -/* How to access the keyboard macros on this platform. */ -#define kbd_read_input() inb(KBD_DATA_REG) -#define kbd_read_status() inb(KBD_STATUS_REG) -#define kbd_write_output(val) outb(val, KBD_DATA_REG) -#define kbd_write_command(val) outb(val, KBD_CNTL_REG) - -/* Some stoneage hardware needs delays after some operations. */ -#define kbd_pause() do { } while(0) - -#define aux_request_irq(hand, dev_id) \ - request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id) - -#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id) - +#define kbd_init_hw() do { } while (0) diff -Nru a/include/asm-arm/arch-integrator/keyboard.h b/include/asm-arm/arch-integrator/keyboard.h --- a/include/asm-arm/arch-integrator/keyboard.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-arm/arch-integrator/keyboard.h Thu Aug 1 14:17:40 2002 @@ -17,13 +17,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Keyboard driver definitions for the Integrator architecture + * Now using the input subsystem... */ -#include - -#define NR_SCANCODES 128 - -extern int kmi_kbd_init(void); - -#define kbd_disable_irq() disable_irq(IRQ_KMIINT0) -#define kbd_enable_irq() enable_irq(IRQ_KMIINT0) -#define kbd_init_hw() kmi_kbd_init() +#define kbd_init_hw() do { } while (0) diff -Nru a/include/asm-arm/arch-rpc/keyboard.h b/include/asm-arm/arch-rpc/keyboard.h --- a/include/asm-arm/arch-rpc/keyboard.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-arm/arch-rpc/keyboard.h Thu Aug 1 14:17:40 2002 @@ -8,13 +8,6 @@ * published by the Free Software Foundation. * * Keyboard driver definitions for RiscPC architecture + * Now using the input subsystem... */ -#include - -#define NR_SCANCODES 128 - -extern int ps2kbd_init_hw(void); - -#define kbd_disable_irq() disable_irq(IRQ_KEYBOARDRX) -#define kbd_enable_irq() enable_irq(IRQ_KEYBOARDRX) -#define kbd_init_hw() ps2kbd_init_hw() +#define kbd_init_hw() do { } while (0) diff -Nru a/include/asm-arm/arch-sa1100/hardware.h b/include/asm-arm/arch-sa1100/hardware.h --- a/include/asm-arm/arch-sa1100/hardware.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-arm/arch-sa1100/hardware.h Thu Aug 1 14:17:40 2002 @@ -13,8 +13,6 @@ #define __ASM_ARCH_HARDWARE_H #include -#include - /* Flushing areas */ #define FLUSH_BASE_PHYS 0xe0000000 /* SA1100 zero bank */ diff -Nru a/include/asm-arm/arch-sa1100/keyboard.h b/include/asm-arm/arch-sa1100/keyboard.h --- a/include/asm-arm/arch-sa1100/keyboard.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-arm/arch-sa1100/keyboard.h Thu Aug 1 14:17:40 2002 @@ -8,21 +8,13 @@ #include #include -#include -#define kbd_disable_irq() do { } while(0) -#define kbd_enable_irq() do { } while(0) - -extern int sa1111_kbd_init_hw(void); extern void gc_kbd_init_hw(void); extern void smartio_kbd_init_hw(void); extern void cerf_kbd_init_hw(void); static inline void kbd_init_hw(void) { - if ((machine_is_assabet() && machine_has_neponset()) || - machine_is_graphicsmaster()) - sa1111_kbd_init_hw(); if (machine_is_graphicsclient()) gc_kbd_init_hw(); if (machine_is_adsbitsy()) @@ -30,11 +22,6 @@ #ifdef CONFIG_SA1100_CERF_CPLD if (machine_is_cerf()) cerf_kbd_init_hw(); -#endif -#ifdef CONFIG_SA1100_PT_SYSTEM3 - /* TODO: add system 3 board specific functions here */ - if (machine_is_pt_system3()) - sa1111_kbd_init_hw(); #endif } diff -Nru a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h --- a/include/asm-arm/atomic.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-arm/atomic.h Thu Aug 1 14:17:36 2002 @@ -36,7 +36,7 @@ { unsigned long flags; - local_save_flags_cli(flags); + local_irq_save(flags); v->counter += i; local_irq_restore(flags); } @@ -45,7 +45,7 @@ { unsigned long flags; - local_save_flags_cli(flags); + local_irq_save(flags); v->counter -= i; local_irq_restore(flags); } @@ -54,7 +54,7 @@ { unsigned long flags; - local_save_flags_cli(flags); + local_irq_save(flags); v->counter += 1; local_irq_restore(flags); } @@ -63,7 +63,7 @@ { unsigned long flags; - local_save_flags_cli(flags); + local_irq_save(flags); v->counter -= 1; local_irq_restore(flags); } @@ -73,7 +73,7 @@ unsigned long flags; int val; - local_save_flags_cli(flags); + local_irq_save(flags); val = v->counter; v->counter = val -= 1; local_irq_restore(flags); @@ -86,7 +86,7 @@ unsigned long flags; int val; - local_save_flags_cli(flags); + local_irq_save(flags); val = v->counter; v->counter = val += i; local_irq_restore(flags); @@ -98,7 +98,7 @@ { unsigned long flags; - local_save_flags_cli(flags); + local_irq_save(flags); *addr &= ~mask; local_irq_restore(flags); } diff -Nru a/include/asm-arm/hardirq.h b/include/asm-arm/hardirq.h --- a/include/asm-arm/hardirq.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-arm/hardirq.h Thu Aug 1 14:17:40 2002 @@ -17,27 +17,70 @@ #include /* Standard mappings for irq_cpustat_t above */ /* - * Are we in an interrupt context? Either doing bottom half - * or hardware interrupt processing? + * We put the hardirq and softirq counter into the preemption + * counter. The bitmask has the following meaning: + * + * - bits 0-7 are the preemption count (max depth: 256) + * - bits 8-15 are the softirq count (max # of softirqs: 256) + * - bits 16-23 are the hardirq count (max # of hardirqs: 256) + * - bit 26 is the PREEMPT_ACTIVE flag */ -#define in_interrupt() ({ const int __cpu = smp_processor_id(); \ - (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); }) - -#define in_irq() (local_irq_count(smp_processor_id()) != 0) - -#ifndef CONFIG_SMP +#define PREEMPT_BITS 8 +#define SOFTIRQ_BITS 8 +#define HARDIRQ_BITS 8 + +#define PREEMPT_SHIFT 0 +#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS) +#define HARDIRQ_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS) + +#define __MASK(x) ((1UL << (x))-1) + +#define PREEMPT_MASK (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT) +#define HARDIRQ_MASK (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT) +#define SOFTIRQ_MASK (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) + +#define hardirq_count() (preempt_count() & HARDIRQ_MASK) +#define softirq_count() (preempt_count() & SOFTIRQ_MASK) +#define irq_count() (preempt_count() & (HARDIRQ_MASK|SOFTIRQ_MASK)) + +#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT) +#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT) +#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT) + +/* + * The hardirq mask has to be large enough to have space + * for potentially all IRQ sources in the system nesting + * on a single CPU: + */ +#if (1 << HARDIRQ_BITS) < NR_IRQS +# error HARDIRQ_BITS is too low! +#endif + +/* + * Are we doing bottom half or hardware interrupt processing? + * Are we in a softirq context? Interrupt context? + */ +#define in_irq() (hardirq_count()) +#define in_softirq() (softirq_count()) +#define in_interrupt() (irq_count()) -#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0) -#define hardirq_endlock(cpu) do { } while (0) +#define hardirq_trylock() (!in_interrupt()) +#define hardirq_endlock() do { } while (0) -#define irq_enter(cpu,irq) (local_irq_count(cpu)++) -#define irq_exit(cpu,irq) (local_irq_count(cpu)--) +#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) -#define synchronize_irq() do { } while (0) -#define release_irqlock(cpu) do { } while (0) +#ifndef CONFIG_SMP +#define irq_exit() \ + do { \ + preempt_count() -= HARDIRQ_OFFSET; \ + if (!in_interrupt() && softirq_pending(smp_processor_id())) \ + __asm__("bl%? __do_softirq": : : "lr");/* out of line */\ + preempt_enable_no_resched(); \ + } while (0) +#define synchronize_irq(irq) barrier() #else #error SMP not supported -#endif /* CONFIG_SMP */ +#endif #endif /* __ASM_HARDIRQ_H */ diff -Nru a/include/asm-arm/hardware/sa1111.h b/include/asm-arm/hardware/sa1111.h --- a/include/asm-arm/hardware/sa1111.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-arm/hardware/sa1111.h Thu Aug 1 14:17:40 2002 @@ -529,120 +529,31 @@ * */ -#define _KBD( x ) _SA1111( 0x0A00 ) -#define _MSE( x ) _SA1111( 0x0C00 ) +#define SA1111_KBD 0x0a00 +#define SA1111_MSE 0x0c00 -#define _KBDCR _SA1111( 0x0A00 ) -#define _KBDSTAT _SA1111( 0x0A04 ) -#define _KBDDATA _SA1111( 0x0A08 ) -#define _KBDCLKDIV _SA1111( 0x0A0C ) -#define _KBDPRECNT _SA1111( 0x0A10 ) -#define _MSECR _SA1111( 0x0C00 ) -#define _MSESTAT _SA1111( 0x0C04 ) -#define _MSEDATA _SA1111( 0x0C08 ) -#define _MSECLKDIV _SA1111( 0x0C0C ) -#define _MSEPRECNT _SA1111( 0x0C10 ) - -#if ( LANGUAGE == C ) - -#define KBDCR __CCREG(0x0a00) -#define KBDSTAT __CCREG(0x0a04) -#define KBDDATA __CCREG(0x0a08) -#define KBDCLKDIV __CCREG(0x0a0c) -#define KBDPRECNT __CCREG(0x0a10) -#define MSECR __CCREG(0x0c00) -#define MSESTAT __CCREG(0x0c04) -#define MSEDATA __CCREG(0x0c08) -#define MSECLKDIV __CCREG(0x0c0c) -#define MSEPRECNT __CCREG(0x0c10) - -#define KBDCR_ENA 0x08 -#define KBDCR_FKD 0x02 -#define KBDCR_FKC 0x01 - -#define KBDSTAT_TXE 0x80 -#define KBDSTAT_TXB 0x40 -#define KBDSTAT_RXF 0x20 -#define KBDSTAT_RXB 0x10 -#define KBDSTAT_ENA 0x08 -#define KBDSTAT_RXP 0x04 -#define KBDSTAT_KBD 0x02 -#define KBDSTAT_KBC 0x01 - -#define KBDCLKDIV_DivVal Fld(4,0) - -#define MSECR_ENA 0x08 -#define MSECR_FKD 0x02 -#define MSECR_FKC 0x01 - -#define MSESTAT_TXE 0x80 -#define MSESTAT_TXB 0x40 -#define MSESTAT_RXF 0x20 -#define MSESTAT_RXB 0x10 -#define MSESTAT_ENA 0x08 -#define MSESTAT_RXP 0x04 -#define MSESTAT_MSD 0x02 -#define MSESTAT_MSC 0x01 - -#define MSECLKDIV_DivVal Fld(4,0) - -#define KBDTEST1_CD 0x80 -#define KBDTEST1_RC1 0x40 -#define KBDTEST1_MC 0x20 -#define KBDTEST1_C Fld(2,3) -#define KBDTEST1_T2 0x40 -#define KBDTEST1_T1 0x20 -#define KBDTEST1_T0 0x10 -#define KBDTEST2_TICBnRES 0x08 -#define KBDTEST2_RKC 0x04 -#define KBDTEST2_RKD 0x02 -#define KBDTEST2_SEL 0x01 -#define KBDTEST3_ms_16 0x80 -#define KBDTEST3_us_64 0x40 -#define KBDTEST3_us_16 0x20 -#define KBDTEST3_DIV8 0x10 -#define KBDTEST3_DIn 0x08 -#define KBDTEST3_CIn 0x04 -#define KBDTEST3_KD 0x02 -#define KBDTEST3_KC 0x01 -#define KBDTEST4_BC12 0x80 -#define KBDTEST4_BC11 0x40 -#define KBDTEST4_TRES 0x20 -#define KBDTEST4_CLKOE 0x10 -#define KBDTEST4_CRES 0x08 -#define KBDTEST4_RXB 0x04 -#define KBDTEST4_TXB 0x02 -#define KBDTEST4_SRX 0x01 - -#define MSETEST1_CD 0x80 -#define MSETEST1_RC1 0x40 -#define MSETEST1_MC 0x20 -#define MSETEST1_C Fld(2,3) -#define MSETEST1_T2 0x40 -#define MSETEST1_T1 0x20 -#define MSETEST1_T0 0x10 -#define MSETEST2_TICBnRES 0x08 -#define MSETEST2_RKC 0x04 -#define MSETEST2_RKD 0x02 -#define MSETEST2_SEL 0x01 -#define MSETEST3_ms_16 0x80 -#define MSETEST3_us_64 0x40 -#define MSETEST3_us_16 0x20 -#define MSETEST3_DIV8 0x10 -#define MSETEST3_DIn 0x08 -#define MSETEST3_CIn 0x04 -#define MSETEST3_KD 0x02 -#define MSETEST3_KC 0x01 -#define MSETEST4_BC12 0x80 -#define MSETEST4_BC11 0x40 -#define MSETEST4_TRES 0x20 -#define MSETEST4_CLKOE 0x10 -#define MSETEST4_CRES 0x08 -#define MSETEST4_RXB 0x04 -#define MSETEST4_TXB 0x02 -#define MSETEST4_SRX 0x01 - -#endif /* LANGUAGE == C */ +/* + * These are offsets from the above bases. + */ +#define SA1111_PS2CR 0x0000 +#define SA1111_PS2STAT 0x0004 +#define SA1111_PS2DATA 0x0008 +#define SA1111_PS2CLKDIV 0x000c +#define SA1111_PS2PRECNT 0x0010 + +#define PS2CR_ENA 0x08 +#define PS2CR_FKD 0x02 +#define PS2CR_FKC 0x01 + +#define PS2STAT_STP 0x0100 +#define PS2STAT_TXE 0x0080 +#define PS2STAT_TXB 0x0040 +#define PS2STAT_RXF 0x0020 +#define PS2STAT_RXB 0x0010 +#define PS2STAT_ENA 0x0008 +#define PS2STAT_RXP 0x0004 +#define PS2STAT_KBD 0x0002 +#define PS2STAT_KBC 0x0001 /* * PCMCIA Interface diff -Nru a/include/asm-arm/io.h b/include/asm-arm/io.h --- a/include/asm-arm/io.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-arm/io.h Thu Aug 1 14:17:40 2002 @@ -29,6 +29,13 @@ #include /* + * ISA I/O bus memory addresses are 1:1 with the physical address. + */ +#define isa_virt_to_bus virt_to_phys +#define isa_page_to_bus page_to_phys +#define isa_bus_to_virt phys_to_virt + +/* * Generic IO read/write. These perform native-endian accesses. Note * that some architectures will want to re-define __raw_{read,write}w. */ diff -Nru a/include/asm-arm/proc-armv/rmap.h b/include/asm-arm/proc-armv/rmap.h --- a/include/asm-arm/proc-armv/rmap.h Thu Aug 1 14:17:36 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,51 +0,0 @@ -#ifndef _ARMV_RMAP_H -#define _ARMV_RMAP_H -/* - * linux/include/asm-arm/proc-armv/rmap.h - * - * Architecture dependant parts of the reverse mapping code, - * - * ARM is different since hardware page tables are smaller than - * the page size and Linux uses a "duplicate" one with extra info. - * For rmap this means that the first 2 kB of a page are the hardware - * page tables and the last 2 kB are the software page tables. - */ - -static inline void pgtable_add_rmap(pte_t * ptep, struct mm_struct * mm, unsigned long address) -{ - struct page * page = virt_to_page(ptep); - - page->mm = mm; - page->index = address & ~((PTRS_PER_PTE * PAGE_SIZE) - 1); - inc_page_state(nr_page_table_pages); -} - -static inline void pgtable_remove_rmap(pte_t * ptep) -{ - struct page * page = virt_to_page(ptep); - - page->mm = NULL; - page->index = 0; - dec_page_state(nr_page_table_pages); -} - -static inline struct mm_struct * ptep_to_mm(pte_t * ptep) -{ - struct page * page = virt_to_page(ptep); - - return page->mm; -} - -/* The page table takes half of the page */ -#define PTE_MASK ((PAGE_SIZE / 2) - 1) - -static inline unsigned long ptep_to_address(pte_t * ptep) -{ - struct page * page = virt_to_page(ptep); - unsigned long low_bits; - - low_bits = ((unsigned long)ptep & PTE_MASK) * PTRS_PER_PTE; - return page->index + low_bits; -} - -#endif /* _ARMV_RMAP_H */ diff -Nru a/include/asm-arm/proc-armv/system.h b/include/asm-arm/proc-armv/system.h --- a/include/asm-arm/proc-armv/system.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-arm/proc-armv/system.h Thu Aug 1 14:17:36 2002 @@ -43,17 +43,23 @@ #endif /* - * A couple of speedups for the ARM + * Save the current interrupt enable state. */ +#define local_save_flags(x) \ + ({ \ + __asm__ __volatile__( \ + "mrs %0, cpsr @ local_save_flags" \ + : "=r" (x) : : "memory"); \ + }) /* * Save the current interrupt enable state & disable IRQs */ -#define local_save_flags_cli(x) \ +#define local_irq_save(x) \ ({ \ unsigned long temp; \ __asm__ __volatile__( \ - "mrs %0, cpsr @ save_flags_cli\n" \ + "mrs %0, cpsr @ local_irq_save\n" \ " orr %1, %0, #128\n" \ " msr cpsr_c, %1" \ : "=r" (x), "=r" (temp) \ @@ -64,11 +70,11 @@ /* * Enable IRQs */ -#define local_irq_enable() \ +#define local_irq_enable() \ ({ \ unsigned long temp; \ __asm__ __volatile__( \ - "mrs %0, cpsr @ sti\n" \ + "mrs %0, cpsr @ local_irq_enable\n" \ " bic %0, %0, #128\n" \ " msr cpsr_c, %0" \ : "=r" (temp) \ @@ -79,11 +85,11 @@ /* * Disable IRQs */ -#define local_irq_disable() \ +#define local_irq_disable() \ ({ \ unsigned long temp; \ __asm__ __volatile__( \ - "mrs %0, cpsr @ cli\n" \ + "mrs %0, cpsr @ local_irq_disable\n" \ " orr %0, %0, #128\n" \ " msr cpsr_c, %0" \ : "=r" (temp) \ @@ -122,21 +128,11 @@ }) /* - * save current IRQ & FIQ state - */ -#define local_save_flags(x) \ - __asm__ __volatile__( \ - "mrs %0, cpsr @ save_flags\n" \ - : "=r" (x) \ - : \ - : "memory") - -/* * restore saved IRQ & FIQ state */ #define local_irq_restore(x) \ __asm__ __volatile__( \ - "msr cpsr_c, %0 @ restore_flags\n" \ + "msr cpsr_c, %0 @ local_irq_restore\n" \ : \ : "r" (x) \ : "memory") @@ -168,14 +164,14 @@ switch (size) { #ifdef swp_is_buggy case 1: - local_save_flags_cli(flags); + local_irq_save(flags); ret = *(volatile unsigned char *)ptr; *(volatile unsigned char *)ptr = x; local_irq_restore(flags); break; case 4: - local_save_flags_cli(flags); + local_irq_save(flags); ret = *(volatile unsigned long *)ptr; *(volatile unsigned long *)ptr = x; local_irq_restore(flags); diff -Nru a/include/asm-arm/processor.h b/include/asm-arm/processor.h --- a/include/asm-arm/processor.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-arm/processor.h Thu Aug 1 14:17:40 2002 @@ -59,7 +59,7 @@ unsigned long get_wchan(struct task_struct *p); -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() /* * Create a new kernel thread diff -Nru a/include/asm-arm/rmap.h b/include/asm-arm/rmap.h --- a/include/asm-arm/rmap.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-arm/rmap.h Thu Aug 1 14:17:36 2002 @@ -1,6 +1,6 @@ #ifndef _ARM_RMAP_H #define _ARM_RMAP_H -#include +#include #endif /* _ARM_RMAP_H */ diff -Nru a/include/asm-arm/socket.h b/include/asm-arm/socket.h --- a/include/asm-arm/socket.h Thu Aug 1 14:17:39 2002 +++ b/include/asm-arm/socket.h Thu Aug 1 14:17:39 2002 @@ -3,7 +3,7 @@ #include -/* For setsockoptions(2) */ +/* For setsockopt(2) */ #define SOL_SOCKET 1 #define SO_DEBUG 1 diff -Nru a/include/asm-arm/softirq.h b/include/asm-arm/softirq.h --- a/include/asm-arm/softirq.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-arm/softirq.h Thu Aug 1 14:17:40 2002 @@ -1,26 +1,20 @@ #ifndef __ASM_SOFTIRQ_H #define __ASM_SOFTIRQ_H -#include +#include #include -#define __cpu_bh_enable(cpu) \ - do { barrier(); local_bh_count(cpu)--; preempt_enable(); } while (0) -#define cpu_bh_disable(cpu) \ - do { preempt_disable(); local_bh_count(cpu)++; barrier(); } while (0) +#define local_bh_disable() \ + do { preempt_count() += SOFTIRQ_OFFSET; barrier(); } while (0) +#define __local_bh_enable() \ + do { barrier(); preempt_count() -= SOFTIRQ_OFFSET; } while (0) -#define local_bh_disable() cpu_bh_disable(smp_processor_id()) -#define __local_bh_enable() __cpu_bh_enable(smp_processor_id()) - -#define in_softirq() (local_bh_count(smp_processor_id()) != 0) - -#define _local_bh_enable() \ +#define local_bh_enable() \ do { \ - unsigned int *ptr = &local_bh_count(smp_processor_id()); \ - if (!--*ptr && ptr[-2]) \ + __local_bh_enable(); \ + if (unlikely(!in_interrupt() && softirq_pending(smp_processor_id()))) \ __asm__("bl%? __do_softirq": : : "lr");/* out of line */\ + preempt_check_resched(); \ } while (0) - -#define local_bh_enable() do { _local_bh_enable(); preempt_enable(); } while (0) #endif /* __ASM_SOFTIRQ_H */ diff -Nru a/include/asm-arm/system.h b/include/asm-arm/system.h --- a/include/asm-arm/system.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-arm/system.h Thu Aug 1 14:17:36 2002 @@ -64,20 +64,12 @@ struct thread_info; extern struct task_struct *__switch_to(struct thread_info *, struct thread_info *); -#define prepare_arch_schedule(prev) do { } while(0) -#define finish_arch_schedule(prev) do { } while(0) -#define prepare_arch_switch(rq) do { } while(0) -#define finish_arch_switch(rq) spin_unlock_irq(&(rq)->lock) - #define switch_to(prev,next,last) \ do { \ __switch_to(prev->thread_info,next->thread_info); \ mb(); \ } while (0) -/* For spinlocks etc */ -#define local_irq_save(x) local_save_flags_cli(x) - #ifdef CONFIG_SMP #error SMP not supported @@ -91,12 +83,8 @@ #define smp_rmb() barrier() #define smp_wmb() barrier() -#define cli() local_irq_disable() -#define sti() local_irq_enable() #define clf() __clf() #define stf() __stf() -#define save_flags(x) local_save_flags(x) -#define restore_flags(x) local_irq_restore(x) #endif /* CONFIG_SMP */ diff -Nru a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h --- a/include/asm-arm/unistd.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-arm/unistd.h Thu Aug 1 14:17:41 2002 @@ -200,8 +200,8 @@ #define __NR_rt_sigtimedwait (__NR_SYSCALL_BASE+177) #define __NR_rt_sigqueueinfo (__NR_SYSCALL_BASE+178) #define __NR_rt_sigsuspend (__NR_SYSCALL_BASE+179) -#define __NR_pread (__NR_SYSCALL_BASE+180) -#define __NR_pwrite (__NR_SYSCALL_BASE+181) +#define __NR_pread64 (__NR_SYSCALL_BASE+180) +#define __NR_pwrite64 (__NR_SYSCALL_BASE+181) #define __NR_chown (__NR_SYSCALL_BASE+182) #define __NR_getcwd (__NR_SYSCALL_BASE+183) #define __NR_capget (__NR_SYSCALL_BASE+184) diff -Nru a/include/asm-cris/processor.h b/include/asm-cris/processor.h --- a/include/asm-cris/processor.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-cris/processor.h Thu Aug 1 14:17:40 2002 @@ -142,6 +142,6 @@ #define init_task (init_task_union.task) #define init_stack (init_task_union.stack) -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() #endif /* __ASM_CRIS_PROCESSOR_H */ diff -Nru a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h --- a/include/asm-cris/unistd.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-cris/unistd.h Thu Aug 1 14:17:40 2002 @@ -185,8 +185,8 @@ #define __NR_rt_sigtimedwait 177 #define __NR_rt_sigqueueinfo 178 #define __NR_rt_sigsuspend 179 -#define __NR_pread 180 -#define __NR_pwrite 181 +#define __NR_pread64 180 +#define __NR_pwrite64 181 #define __NR_chown 182 #define __NR_getcwd 183 #define __NR_capget 184 diff -Nru a/include/asm-i386/desc.h b/include/asm-i386/desc.h --- a/include/asm-i386/desc.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-i386/desc.h Thu Aug 1 14:17:36 2002 @@ -86,11 +86,9 @@ _set_tssldt_desc(&cpu_gdt_table[cpu][LDT_ENTRY], (int)addr, ((size << 3)-1), 0x82); } -#define TLS_FLAGS_MASK 0x00000007 +#define TLS_FLAGS_MASK 0x00000001 -#define TLS_FLAG_LIMIT_IN_PAGES 0x00000001 -#define TLS_FLAG_WRITABLE 0x00000002 -#define TLS_FLAG_CLEAR 0x00000004 +#define TLS_FLAG_WRITABLE 0x00000001 static inline void load_TLS_desc(struct thread_struct *t, unsigned int cpu) { diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h --- a/include/asm-i386/processor.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-i386/processor.h Thu Aug 1 14:17:36 2002 @@ -376,8 +376,7 @@ unsigned long v86flags, v86mask, v86mode, saved_esp0; /* IO permissions */ unsigned long *ts_io_bitmap; -/* TLS info and cached descriptor */ - unsigned int tls_base, tls_limit, tls_flags; +/* TLS cached descriptor */ struct desc_struct tls_desc; }; @@ -456,7 +455,7 @@ /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ static inline void rep_nop(void) { - __asm__ __volatile__("rep;nop"); + __asm__ __volatile__("rep;nop": : :"memory"); } #define cpu_relax() rep_nop() diff -Nru a/include/asm-i386/rwsem.h b/include/asm-i386/rwsem.h --- a/include/asm-i386/rwsem.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-i386/rwsem.h Thu Aug 1 14:17:40 2002 @@ -118,6 +118,29 @@ } /* + * trylock for reading -- returns 1 if successful, 0 if contention + */ +static inline int __down_read_trylock(struct rw_semaphore *sem) +{ + __s32 result, tmp; + __asm__ __volatile__( + "# beginning __down_read_trylock\n\t" + " movl %0,%1\n\t" + "1:\n\t" + " movl %1,%2\n\t" + " addl %3,%2\n\t" + " jle 2f\n\t" +LOCK_PREFIX " cmpxchgl %2,%0\n\t" + " jnz 1b\n\t" + "2:\n\t" + "# ending __down_read_trylock\n\t" + : "+m"(sem->count), "=&a"(result), "=&r"(tmp) + : "i"(RWSEM_ACTIVE_READ_BIAS) + : "memory", "cc"); + return result>=0 ? 1 : 0; +} + +/* * lock for writing */ static inline void __down_write(struct rw_semaphore *sem) @@ -142,6 +165,19 @@ : "=m"(sem->count), "=d"(tmp) : "a"(sem), "1"(tmp), "m"(sem->count) : "memory", "cc"); +} + +/* + * trylock for writing -- returns 1 if successful, 0 if contention + */ +static inline int __down_write_trylock(struct rw_semaphore *sem) +{ + signed long ret = cmpxchg(&sem->count, + RWSEM_UNLOCKED_VALUE, + RWSEM_ACTIVE_WRITE_BIAS); + if (ret == RWSEM_UNLOCKED_VALUE) + return 1; + return 0; } /* diff -Nru a/include/asm-i386/smp.h b/include/asm-i386/smp.h --- a/include/asm-i386/smp.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-i386/smp.h Thu Aug 1 14:17:36 2002 @@ -85,7 +85,9 @@ */ #define smp_processor_id() (current_thread_info()->cpu) -#define cpu_possible(cpu) (phys_cpu_present_map & (1<<(cpu))) +extern volatile unsigned long cpu_callout_map; + +#define cpu_possible(cpu) (cpu_callout_map & (1<<(cpu))) #define cpu_online(cpu) (cpu_online_map & (1<<(cpu))) extern inline unsigned int num_online_cpus(void) @@ -113,7 +115,6 @@ return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR)); } -extern volatile unsigned long cpu_callout_map; /* We don't mark CPUs online until __cpu_up(), so we need another measure */ static inline int num_booting_cpus(void) { diff -Nru a/include/asm-i386/socket.h b/include/asm-i386/socket.h --- a/include/asm-i386/socket.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-i386/socket.h Thu Aug 1 14:17:36 2002 @@ -3,7 +3,7 @@ #include -/* For setsockoptions(2) */ +/* For setsockopt(2) */ #define SOL_SOCKET 1 #define SO_DEBUG 1 diff -Nru a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h --- a/include/asm-i386/spinlock.h Thu Aug 1 14:17:39 2002 +++ b/include/asm-i386/spinlock.h Thu Aug 1 14:17:39 2002 @@ -39,7 +39,7 @@ * We make no fairness assumptions. They have a cost. */ -#define spin_is_locked(x) (*(volatile char *)(&(x)->lock) <= 0) +#define spin_is_locked(x) (*(volatile signed char *)(&(x)->lock) <= 0) #define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x)) #define spin_lock_string \ diff -Nru a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h --- a/include/asm-i386/unistd.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-i386/unistd.h Thu Aug 1 14:17:41 2002 @@ -184,8 +184,8 @@ #define __NR_rt_sigtimedwait 177 #define __NR_rt_sigqueueinfo 178 #define __NR_rt_sigsuspend 179 -#define __NR_pread 180 -#define __NR_pwrite 181 +#define __NR_pread64 180 +#define __NR_pwrite64 181 #define __NR_chown 182 #define __NR_getcwd 183 #define __NR_capget 184 @@ -247,6 +247,7 @@ #define __NR_futex 240 #define __NR_sched_setaffinity 241 #define __NR_sched_getaffinity 242 +#define __NR_set_thread_area 243 /* user-visible error numbers are in the range -1 - -124: see */ diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h --- a/include/asm-ia64/processor.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-ia64/processor.h Thu Aug 1 14:17:40 2002 @@ -616,7 +616,7 @@ asm volatile ("mov cr.lrr0=%0;; srlz.d" :: "r"(val) : "memory"); } -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() static inline void diff -Nru a/include/asm-ia64/socket.h b/include/asm-ia64/socket.h --- a/include/asm-ia64/socket.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-ia64/socket.h Thu Aug 1 14:17:36 2002 @@ -10,7 +10,7 @@ #include -/* For setsockoptions(2) */ +/* For setsockopt(2) */ #define SOL_SOCKET 1 #define SO_DEBUG 1 diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h --- a/include/asm-ia64/unistd.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-ia64/unistd.h Thu Aug 1 14:17:36 2002 @@ -137,8 +137,8 @@ #define __NR_flock 1145 #define __NR_readv 1146 #define __NR_writev 1147 -#define __NR_pread 1148 -#define __NR_pwrite 1149 +#define __NR_pread64 1148 +#define __NR_pwrite64 1149 #define __NR__sysctl 1150 #define __NR_mmap 1151 #define __NR_munmap 1152 diff -Nru a/include/asm-m68k/processor.h b/include/asm-m68k/processor.h --- a/include/asm-m68k/processor.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-m68k/processor.h Thu Aug 1 14:17:41 2002 @@ -137,6 +137,6 @@ eip; }) #define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() #endif diff -Nru a/include/asm-m68k/socket.h b/include/asm-m68k/socket.h --- a/include/asm-m68k/socket.h Thu Aug 1 14:17:39 2002 +++ b/include/asm-m68k/socket.h Thu Aug 1 14:17:39 2002 @@ -3,7 +3,7 @@ #include -/* For setsockoptions(2) */ +/* For setsockopt(2) */ #define SOL_SOCKET 1 #define SO_DEBUG 1 diff -Nru a/include/asm-m68k/unistd.h b/include/asm-m68k/unistd.h --- a/include/asm-m68k/unistd.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-m68k/unistd.h Thu Aug 1 14:17:40 2002 @@ -184,8 +184,8 @@ #define __NR_rt_sigtimedwait 177 #define __NR_rt_sigqueueinfo 178 #define __NR_rt_sigsuspend 179 -#define __NR_pread 180 -#define __NR_pwrite 181 +#define __NR_pread64 180 +#define __NR_pwrite64 181 #define __NR_lchown 182 #define __NR_getcwd 183 #define __NR_capget 184 diff -Nru a/include/asm-mips/processor.h b/include/asm-mips/processor.h --- a/include/asm-mips/processor.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-mips/processor.h Thu Aug 1 14:17:36 2002 @@ -259,7 +259,7 @@ #define init_task (init_task_union.task) #define init_stack (init_task_union.stack) -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() #endif /* !defined (_LANGUAGE_ASSEMBLY) */ #endif /* __KERNEL__ */ diff -Nru a/include/asm-mips/socket.h b/include/asm-mips/socket.h --- a/include/asm-mips/socket.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-mips/socket.h Thu Aug 1 14:17:41 2002 @@ -4,7 +4,7 @@ #include /* - * For setsockoptions(2) + * For setsockopt(2) * * This defines are ABI conformant as far as Linux supports these ... */ diff -Nru a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h --- a/include/asm-mips/unistd.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-mips/unistd.h Thu Aug 1 14:17:36 2002 @@ -212,8 +212,8 @@ #define __NR_rt_sigtimedwait (__NR_Linux + 197) #define __NR_rt_sigqueueinfo (__NR_Linux + 198) #define __NR_rt_sigsuspend (__NR_Linux + 199) -#define __NR_pread (__NR_Linux + 200) -#define __NR_pwrite (__NR_Linux + 201) +#define __NR_pread64 (__NR_Linux + 200) +#define __NR_pwrite64 (__NR_Linux + 201) #define __NR_chown (__NR_Linux + 202) #define __NR_getcwd (__NR_Linux + 203) #define __NR_capget (__NR_Linux + 204) diff -Nru a/include/asm-mips64/processor.h b/include/asm-mips64/processor.h --- a/include/asm-mips64/processor.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-mips64/processor.h Thu Aug 1 14:17:40 2002 @@ -290,7 +290,7 @@ #define init_task (init_task_union.task) #define init_stack (init_task_union.stack) -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() #endif /* !defined (_LANGUAGE_ASSEMBLY) */ #endif /* __KERNEL__ */ diff -Nru a/include/asm-mips64/socket.h b/include/asm-mips64/socket.h --- a/include/asm-mips64/socket.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-mips64/socket.h Thu Aug 1 14:17:36 2002 @@ -12,7 +12,7 @@ #include /* - * For setsockoptions(2) + * For setsockopt(2) * * This defines are ABI conformant as far as Linux supports these ... */ diff -Nru a/include/asm-mips64/unistd.h b/include/asm-mips64/unistd.h --- a/include/asm-mips64/unistd.h Thu Aug 1 14:17:39 2002 +++ b/include/asm-mips64/unistd.h Thu Aug 1 14:17:39 2002 @@ -447,8 +447,8 @@ #define __NR_rt_sigtimedwait (__NR_Linux + 197) #define __NR_rt_sigqueueinfo (__NR_Linux + 198) #define __NR_rt_sigsuspend (__NR_Linux + 199) -#define __NR_pread (__NR_Linux + 200) -#define __NR_pwrite (__NR_Linux + 201) +#define __NR_pread64 (__NR_Linux + 200) +#define __NR_pwrite64 (__NR_Linux + 201) #define __NR_chown (__NR_Linux + 202) #define __NR_getcwd (__NR_Linux + 203) #define __NR_capget (__NR_Linux + 204) diff -Nru a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h --- a/include/asm-parisc/processor.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-parisc/processor.h Thu Aug 1 14:17:40 2002 @@ -333,7 +333,7 @@ #define init_task (init_task_union.task) #define init_stack (init_task_union.stack) -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() #endif /* __ASM_PARISC_PROCESSOR_H */ diff -Nru a/include/asm-parisc/socket.h b/include/asm-parisc/socket.h --- a/include/asm-parisc/socket.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-parisc/socket.h Thu Aug 1 14:17:41 2002 @@ -3,7 +3,7 @@ #include -/* For setsockoptions(2) */ +/* For setsockopt(2) */ #define SOL_SOCKET 0xffff #define SO_DEBUG 0x0001 diff -Nru a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h --- a/include/asm-parisc/unistd.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-parisc/unistd.h Thu Aug 1 14:17:36 2002 @@ -598,8 +598,8 @@ #define __NR_getitimer (__NR_Linux + 105) #define __NR_capget (__NR_Linux + 106) #define __NR_capset (__NR_Linux + 107) -#define __NR_pread (__NR_Linux + 108) -#define __NR_pwrite (__NR_Linux + 109) +#define __NR_pread64 (__NR_Linux + 108) +#define __NR_pwrite64 (__NR_Linux + 109) #define __NR_getcwd (__NR_Linux + 110) #define __NR_vhangup (__NR_Linux + 111) #define __NR_idle (__NR_Linux + 112) diff -Nru a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h --- a/include/asm-ppc/hardirq.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-ppc/hardirq.h Thu Aug 1 14:17:36 2002 @@ -15,8 +15,6 @@ */ typedef struct { unsigned long __softirq_pending; /* set_bit is used on this */ - unsigned int __local_irq_count; - unsigned int __local_bh_count; unsigned int __syscall_count; struct task_struct * __ksoftirqd_task; unsigned int __last_jiffy_stamp; @@ -25,91 +23,87 @@ #include /* Standard mappings for irq_cpustat_t above */ #define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp) + /* - * Are we in an interrupt context? Either doing bottom half - * or hardware interrupt processing? + * We put the hardirq and softirq counter into the preemption + * counter. The bitmask has the following meaning: + * + * - bits 0-7 are the preemption count (max preemption depth: 256) + * - bits 8-15 are the softirq count (max # of softirqs: 256) + * - bits 16-23 are the hardirq count (max # of hardirqs: 256) + * + * - ( bit 26 is the PREEMPT_ACTIVE flag. ) + * + * PREEMPT_MASK: 0x000000ff + * HARDIRQ_MASK: 0x0000ff00 + * SOFTIRQ_MASK: 0x00ff0000 */ -#define in_interrupt() ({ int __cpu = smp_processor_id(); \ - (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); }) - -#define in_irq() (local_irq_count(smp_processor_id()) != 0) -#ifndef CONFIG_SMP +#define PREEMPT_BITS 8 +#define SOFTIRQ_BITS 8 +#define HARDIRQ_BITS 8 + +#define PREEMPT_SHIFT 0 +#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS) +#define HARDIRQ_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS) + +#define __MASK(x) ((1UL << (x))-1) + +#define PREEMPT_MASK (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT) +#define HARDIRQ_MASK (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT) +#define SOFTIRQ_MASK (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) + +#define hardirq_count() (preempt_count() & HARDIRQ_MASK) +#define softirq_count() (preempt_count() & SOFTIRQ_MASK) +#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK)) + +#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT) +#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT) +#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT) -#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0) -#define hardirq_endlock(cpu) do { } while (0) +/* + * The hardirq mask has to be large enough to have + * space for potentially all IRQ sources in the system + * nesting on a single CPU: + */ +#if (1 << HARDIRQ_BITS) < NR_IRQS +# error HARDIRQ_BITS is too low! +#endif -#define hardirq_enter(cpu) do { preempt_disable(); local_irq_count(cpu)++; } while (0) -#define hardirq_exit(cpu) do { local_irq_count(cpu)--; preempt_enable(); } while (0) +/* + * Are we doing bottom half or hardware interrupt processing? + * Are we in a softirq context? Interrupt context? + */ +#define in_irq() (hardirq_count()) +#define in_softirq() (softirq_count()) +#define in_interrupt() (irq_count()) -#define synchronize_irq() do { } while (0) -#define release_irqlock(cpu) do { } while (0) -#else /* CONFIG_SMP */ - -#include - -extern unsigned char global_irq_holder; -extern unsigned volatile long global_irq_lock; - -static inline int irqs_running (void) -{ - int i; - - for (i = 0; i < NR_CPUS; i++) - if (local_irq_count(i)) - return 1; - return 0; -} - -static inline void release_irqlock(int cpu) -{ - /* if we didn't own the irq lock, just ignore.. */ - if (global_irq_holder == (unsigned char) cpu) { - global_irq_holder = NO_PROC_ID; - clear_bit(0,&global_irq_lock); - } -} - -static inline void hardirq_enter(int cpu) -{ - unsigned int loops = 10000000; - - preempt_disable(); - ++local_irq_count(cpu); - while (test_bit(0,&global_irq_lock)) { - if (cpu == global_irq_holder) { - printk("uh oh, interrupt while we hold global irq lock! (CPU %d)\n", cpu); -#ifdef CONFIG_XMON - xmon(0); -#endif - break; - } - if (loops-- == 0) { - printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder); -#ifdef CONFIG_XMON - xmon(0); -#endif - } - } -} - -static inline void hardirq_exit(int cpu) -{ - --local_irq_count(cpu); - preempt_enable(); -} - -static inline int hardirq_trylock(int cpu) -{ - return !test_bit(0,&global_irq_lock); -} +#define hardirq_trylock() (!in_interrupt()) +#define hardirq_endlock() do { } while (0) -#define hardirq_endlock(cpu) do { } while (0) +#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) -extern void synchronize_irq(void); +#if CONFIG_PREEMPT +# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1) +#else +# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET +#endif +#define irq_exit() \ +do { \ + preempt_count() -= IRQ_EXIT_OFFSET; \ + if (!in_interrupt() && softirq_pending(smp_processor_id())) \ + do_softirq(); \ + preempt_enable_no_resched(); \ +} while (0) +#ifndef CONFIG_SMP +# define synchronize_irq(irq) barrier() +#else + extern void synchronize_irq(unsigned int irq); #endif /* CONFIG_SMP */ + +extern void show_stack(unsigned long *sp); #endif /* __ASM_HARDIRQ_H */ #endif /* __KERNEL__ */ diff -Nru a/include/asm-ppc/hw_irq.h b/include/asm-ppc/hw_irq.h --- a/include/asm-ppc/hw_irq.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-ppc/hw_irq.h Thu Aug 1 14:17:41 2002 @@ -8,21 +8,18 @@ #ifndef _PPC_HW_IRQ_H #define _PPC_HW_IRQ_H -extern unsigned long timer_interrupt_intercept; -extern unsigned long do_IRQ_intercept; -extern int timer_interrupt(struct pt_regs *); +extern void timer_interrupt(struct pt_regs *); extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); #define INLINE_IRQS -#ifdef INLINE_IRQS - #define mfmsr() ({unsigned int rval; \ asm volatile("mfmsr %0" : "=r" (rval)); rval;}) #define mtmsr(v) asm volatile("mtmsr %0" : : "r" (v)) -#define local_save_flags(flags) ((flags) = mfmsr()) -#define local_irq_restore(flags) mtmsr(flags) +#define irqs_disabled() ((mfmsr() & MSR_EE) == 0) + +#ifdef INLINE_IRQS static inline void local_irq_disable(void) { @@ -40,7 +37,7 @@ mtmsr(msr | MSR_EE); } -static inline void __do_save_and_cli(unsigned long *flags) +static inline void local_irq_save_ptr(unsigned long *flags) { unsigned long msr; msr = mfmsr(); @@ -49,7 +46,9 @@ __asm__ __volatile__("": : :"memory"); } -#define local_irq_save(flags) __do_save_and_cli(&flags) +#define local_save_flags(flags) ((flags) = mfmsr()) +#define local_irq_save(flags) local_irq_save_ptr(&flags) +#define local_irq_restore(flags) mtmsr(flags) #else @@ -57,9 +56,8 @@ extern void local_irq_disable(void); extern void local_irq_restore(unsigned long); extern void local_save_flags_ptr(unsigned long *); -extern unsigned long local_irq_enable_end, local_irq_disable_end, local_irq_restore_end, local_save_flags_ptr_end; -#define local_save_flags(flags) local_save_flags_ptr((unsigned long *)&flags) +#define local_save_flags(flags) local_save_flags_ptr(&flags) #define local_irq_save(flags) ({local_save_flags(flags);local_irq_disable();}) #endif diff -Nru a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h --- a/include/asm-ppc/pgtable.h Thu Aug 1 14:17:37 2002 +++ b/include/asm-ppc/pgtable.h Thu Aug 1 14:17:37 2002 @@ -246,6 +246,23 @@ #define _PAGE_KERNEL _PAGE_BASE | _PAGE_WRENABLE | _PAGE_SHARED | _PAGE_HWEXEC #define _PAGE_IO _PAGE_KERNEL | _PAGE_NO_CACHE | _PAGE_GUARDED +#define _PAGE_RAM _PAGE_KERNEL + +#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) +/* 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 +#else +#ifdef CONFIG_PPC_STD_MMU +/* On standard PPC MMU, no user access implies kernel read/write + * access, so to write-protect the kernel text we must turn on user + * access */ +#define _PAGE_RAM_TEXT (_PAGE_RAM & ~_PAGE_WRENABLE) | _PAGE_USER +#else +#define _PAGE_RAM_TEXT (_PAGE_RAM & ~_PAGE_WRENABLE) +#endif +#endif + #define PAGE_NONE __pgprot(_PAGE_BASE) #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) #define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) diff -Nru a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h --- a/include/asm-ppc/processor.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-ppc/processor.h Thu Aug 1 14:17:36 2002 @@ -771,7 +771,7 @@ #define have_of (_machine == _MACH_chrp || _machine == _MACH_Pmac) -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() /* * Prefetch macros. diff -Nru a/include/asm-ppc/rwsem.h b/include/asm-ppc/rwsem.h --- a/include/asm-ppc/rwsem.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-ppc/rwsem.h Thu Aug 1 14:17:41 2002 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.rwsem.h 1.6 05/17/01 18:14:25 cort + * BK Id: %F% %I% %G% %U% %#% */ /* * include/asm-ppc/rwsem.h: R/W semaphores for PPC using the stuff @@ -55,6 +55,7 @@ extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); static inline void init_rwsem(struct rw_semaphore *sem) { @@ -122,6 +123,19 @@ static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) { atomic_add(delta, (atomic_t *)(&sem->count)); +} + +/* + * downgrade write lock to read lock + */ +static inline void __downgrade_write(struct rw_semaphore *sem) +{ + int tmp; + + smp_wmb(); + tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count)); + if (tmp < 0) + rwsem_downgrade_wake(sem); } /* diff -Nru a/include/asm-ppc/smplock.h b/include/asm-ppc/smplock.h --- a/include/asm-ppc/smplock.h Thu Aug 1 14:17:39 2002 +++ b/include/asm-ppc/smplock.h Thu Aug 1 14:17:39 2002 @@ -18,7 +18,7 @@ #ifdef CONFIG_SMP #define kernel_locked() spin_is_locked(&kernel_flag) #elif defined(CONFIG_PREEMPT) -#define kernel_locked() preempt_get_count() +#define kernel_locked() preempt_count() #endif /* diff -Nru a/include/asm-ppc/socket.h b/include/asm-ppc/socket.h --- a/include/asm-ppc/socket.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-ppc/socket.h Thu Aug 1 14:17:40 2002 @@ -12,7 +12,7 @@ #define SIOCATMARK 0x8905 #define SIOCGSTAMP 0x8906 /* Get stamp */ -/* For setsockoptions(2) */ +/* For setsockopt(2) */ #define SOL_SOCKET 1 #define SO_DEBUG 1 diff -Nru a/include/asm-ppc/softirq.h b/include/asm-ppc/softirq.h --- a/include/asm-ppc/softirq.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-ppc/softirq.h Thu Aug 1 14:17:41 2002 @@ -5,34 +5,30 @@ #ifndef __ASM_SOFTIRQ_H #define __ASM_SOFTIRQ_H -#include +#include #include #define local_bh_disable() \ do { \ - preempt_disable(); \ - local_bh_count(smp_processor_id())++; \ + preempt_count() += SOFTIRQ_OFFSET; \ barrier(); \ } while (0) #define __local_bh_enable() \ do { \ barrier(); \ - local_bh_count(smp_processor_id())--; \ - preempt_enable(); \ + preempt_count() -= SOFTIRQ_OFFSET; \ } while (0) -#define local_bh_enable() \ -do { \ - barrier(); \ - if (!--local_bh_count(smp_processor_id()) \ - && softirq_pending(smp_processor_id())) { \ - do_softirq(); \ - } \ - preempt_enable(); \ +#define local_bh_enable() \ +do { \ + __local_bh_enable(); \ + if (unlikely(!in_interrupt() \ + && softirq_pending(smp_processor_id()))) \ + do_softirq(); \ + if (preempt_count() == 0) \ + preempt_check_resched(); \ } while (0) - -#define in_softirq() (local_bh_count(smp_processor_id()) != 0) #endif /* __ASM_SOFTIRQ_H */ #endif /* __KERNEL__ */ diff -Nru a/include/asm-ppc/system.h b/include/asm-ppc/system.h --- a/include/asm-ppc/system.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-ppc/system.h Thu Aug 1 14:17:40 2002 @@ -96,27 +96,6 @@ struct pt_regs; extern void dump_regs(struct pt_regs *); -#ifndef CONFIG_SMP - -#define cli() local_irq_disable() -#define sti() local_irq_enable() -#define save_flags(flags) local_save_flags(flags) -#define restore_flags(flags) local_irq_restore(flags) -#define save_and_cli(flags) local_irq_save(flags) - -#else /* CONFIG_SMP */ - -extern void __global_cli(void); -extern void __global_sti(void); -extern unsigned long __global_save_flags(void); -extern void __global_restore_flags(unsigned long); -#define cli() __global_cli() -#define sti() __global_sti() -#define save_flags(x) ((x)=__global_save_flags()) -#define restore_flags(x) __global_restore_flags(x) - -#endif /* !CONFIG_SMP */ - static __inline__ unsigned long xchg_u32(volatile void *p, unsigned long val) { diff -Nru a/include/asm-ppc/thread_info.h b/include/asm-ppc/thread_info.h --- a/include/asm-ppc/thread_info.h Thu Aug 1 14:17:37 2002 +++ b/include/asm-ppc/thread_info.h Thu Aug 1 14:17:37 2002 @@ -22,24 +22,24 @@ struct exec_domain *exec_domain; /* execution domain */ unsigned long flags; /* low level flags */ int cpu; /* cpu we're on */ - int preempt_count; /* not used at present */ - int softirq_count; - int hardirq_count; + int preempt_count; }; -/* - * macros/functions for gaining access to the thread information structure - */ #define INIT_THREAD_INFO(tsk) \ { \ - task: &tsk, \ - exec_domain: &default_exec_domain, \ - flags: 0, \ - cpu: 0, \ + .task = &tsk, \ + .exec_domain = &default_exec_domain, \ + .flags = 0, \ + .cpu = 0, \ + .preempt_count = 1 \ } #define init_thread_info (init_thread_union.thread_info) #define init_stack (init_thread_union.stack) + +/* + * macros/functions for gaining access to the thread information structure + */ /* how to get the thread information struct from C */ static inline struct thread_info *current_thread_info(void) diff -Nru a/include/asm-ppc/tlb.h b/include/asm-ppc/tlb.h --- a/include/asm-ppc/tlb.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-ppc/tlb.h Thu Aug 1 14:17:36 2002 @@ -1,4 +1,61 @@ /* - * BK Id: SCCS/s.tlb.h 1.5 05/17/01 18:14:26 cort + * TLB shootdown specifics for PPC + * + * Copyright (C) 2002 Paul Mackerras, IBM Corp. + * + * 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. */ +#ifndef _PPC_TLB_H +#define _PPC_TLB_H + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PPC_STD_MMU +/* Classic PPC with hash-table based MMU... */ + +struct free_pte_ctx; +extern void tlb_flush(struct free_pte_ctx *tlb); + +/* Get the generic bits... */ #include + +/* Nothing needed here in fact... */ +#define tlb_start_vma(tlb, vma) do { } while (0) +#define tlb_end_vma(tlb, vma) do { } while (0) + +extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, + unsigned long address); + +static inline void tlb_remove_tlb_entry(mmu_gather_t *tlb, pte_t *ptep, + unsigned long address) +{ + if (pte_val(*ptep) & _PAGE_HASHPTE) + flush_hash_entry(tlb->mm, ptep, address); +} + +#else +/* Embedded PPC with software-loaded TLB, very simple... */ + +struct flush_tlb_arch { }; + +#define tlb_init_arch(tlb, full_flush) do { } while (0) +#define tlb_finish_arch(tlb) do { } while (0) +#define tlb_start_vma(tlb, vma) do { } while (0) +#define tlb_end_vma(tlb, vma) do { } while (0) +#define tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) +#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) + +/* Get the generic bits... */ +#include + +#endif /* CONFIG_PPC_STD_MMU */ + +#endif /* __PPC_TLB_H */ diff -Nru a/include/asm-ppc/tlbflush.h b/include/asm-ppc/tlbflush.h --- a/include/asm-ppc/tlbflush.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-ppc/tlbflush.h Thu Aug 1 14:17:36 2002 @@ -22,8 +22,6 @@ #if defined(CONFIG_4xx) -static inline void flush_tlb_all(void) - { _tlbia(); } static inline void flush_tlb_mm(struct mm_struct *mm) { _tlbia(); } static inline void flush_tlb_page(struct vm_area_struct *vma, @@ -40,8 +38,6 @@ #elif defined(CONFIG_8xx) #define __tlbia() asm volatile ("tlbia; sync" : : : "memory") -static inline void flush_tlb_all(void) - { __tlbia(); } static inline void flush_tlb_mm(struct mm_struct *mm) { __tlbia(); } static inline void flush_tlb_page(struct vm_area_struct *vma, @@ -58,7 +54,6 @@ #else /* 6xx, 7xx, 7xxx cpus */ struct mm_struct; struct vm_area_struct; -extern void flush_tlb_all(void); extern void flush_tlb_mm(struct mm_struct *mm); extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, diff -Nru a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h --- a/include/asm-ppc/unistd.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-ppc/unistd.h Thu Aug 1 14:17:36 2002 @@ -186,8 +186,8 @@ #define __NR_rt_sigtimedwait 176 #define __NR_rt_sigqueueinfo 177 #define __NR_rt_sigsuspend 178 -#define __NR_pread 179 -#define __NR_pwrite 180 +#define __NR_pread64 179 +#define __NR_pwrite64 180 #define __NR_chown 181 #define __NR_getcwd 182 #define __NR_capget 183 diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h --- a/include/asm-ppc64/processor.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-ppc64/processor.h Thu Aug 1 14:17:36 2002 @@ -692,7 +692,7 @@ #define KSTK_EIP(tsk) ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0) #define KSTK_ESP(tsk) ((tsk)->thread.regs? (tsk)->thread.regs->gpr[1]: 0) -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() /* * Prefetch macros. diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h --- a/include/asm-ppc64/unistd.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-ppc64/unistd.h Thu Aug 1 14:17:36 2002 @@ -188,8 +188,8 @@ #define __NR_rt_sigtimedwait 176 #define __NR_rt_sigqueueinfo 177 #define __NR_rt_sigsuspend 178 -#define __NR_pread 179 -#define __NR_pwrite 180 +#define __NR_pread64 179 +#define __NR_pwrite64 180 #define __NR_chown 181 #define __NR_getcwd 182 #define __NR_capget 183 diff -Nru a/include/asm-s390/processor.h b/include/asm-s390/processor.h --- a/include/asm-s390/processor.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-s390/processor.h Thu Aug 1 14:17:40 2002 @@ -134,7 +134,7 @@ #define KSTK_EIP(tsk) (__KSTK_PTREGS(tsk)->psw.addr) #define KSTK_ESP(tsk) (__KSTK_PTREGS(tsk)->gprs[15]) -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() /* * Set of msr bits that gdb can change on behalf of a process. diff -Nru a/include/asm-s390/socket.h b/include/asm-s390/socket.h --- a/include/asm-s390/socket.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-s390/socket.h Thu Aug 1 14:17:36 2002 @@ -11,7 +11,7 @@ #include -/* For setsockoptions(2) */ +/* For setsockopt(2) */ #define SOL_SOCKET 1 #define SO_DEBUG 1 diff -Nru a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h --- a/include/asm-s390/unistd.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-s390/unistd.h Thu Aug 1 14:17:41 2002 @@ -170,8 +170,8 @@ #define __NR_rt_sigtimedwait 177 #define __NR_rt_sigqueueinfo 178 #define __NR_rt_sigsuspend 179 -#define __NR_pread 180 -#define __NR_pwrite 181 +#define __NR_pread64 180 +#define __NR_pwrite64 181 #define __NR_chown 182 #define __NR_getcwd 183 #define __NR_capget 184 diff -Nru a/include/asm-s390x/processor.h b/include/asm-s390x/processor.h --- a/include/asm-s390x/processor.h Thu Aug 1 14:17:39 2002 +++ b/include/asm-s390x/processor.h Thu Aug 1 14:17:39 2002 @@ -151,7 +151,7 @@ #define KSTK_EIP(tsk) (__KSTK_PTREGS(tsk)->psw.addr) #define KSTK_ESP(tsk) (__KSTK_PTREGS(tsk)->gprs[15]) -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() /* * Set of msr bits that gdb can change on behalf of a process. diff -Nru a/include/asm-s390x/unistd.h b/include/asm-s390x/unistd.h --- a/include/asm-s390x/unistd.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-s390x/unistd.h Thu Aug 1 14:17:36 2002 @@ -147,8 +147,8 @@ #define __NR_rt_sigtimedwait 177 #define __NR_rt_sigqueueinfo 178 #define __NR_rt_sigsuspend 179 -#define __NR_pread 180 -#define __NR_pwrite 181 +#define __NR_pread64 180 +#define __NR_pwrite64 181 #define __NR_getcwd 183 #define __NR_capget 184 #define __NR_capset 185 diff -Nru a/include/asm-sh/processor.h b/include/asm-sh/processor.h --- a/include/asm-sh/processor.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-sh/processor.h Thu Aug 1 14:17:40 2002 @@ -222,6 +222,6 @@ #define init_task (init_task_union.task) #define init_stack (init_task_union.stack) -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() #endif /* __ASM_SH_PROCESSOR_H */ diff -Nru a/include/asm-sh/socket.h b/include/asm-sh/socket.h --- a/include/asm-sh/socket.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-sh/socket.h Thu Aug 1 14:17:40 2002 @@ -3,7 +3,7 @@ #include -/* For setsockoptions(2) */ +/* For setsockopt(2) */ #define SOL_SOCKET 1 #define SO_DEBUG 1 diff -Nru a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h --- a/include/asm-sh/unistd.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-sh/unistd.h Thu Aug 1 14:17:41 2002 @@ -189,8 +189,8 @@ #define __NR_rt_sigtimedwait 177 #define __NR_rt_sigqueueinfo 178 #define __NR_rt_sigsuspend 179 -#define __NR_pread 180 -#define __NR_pwrite 181 +#define __NR_pread64 180 +#define __NR_pwrite64 181 #define __NR_chown 182 #define __NR_getcwd 183 #define __NR_capget 184 diff -Nru a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h --- a/include/asm-sparc/processor.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-sparc/processor.h Thu Aug 1 14:17:41 2002 @@ -201,7 +201,7 @@ #define init_task (init_task_union.task) #define init_stack (init_task_union.stack) -#define cpu_relax() do { } while (0) +#define cpu_relax() barrier() #endif diff -Nru a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h --- a/include/asm-sparc/socket.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-sparc/socket.h Thu Aug 1 14:17:41 2002 @@ -4,7 +4,7 @@ #include -/* For setsockoptions(2) */ +/* For setsockopt(2) */ #define SOL_SOCKET 0xffff #define SO_DEBUG 0x0001 diff -Nru a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h --- a/include/asm-sparc/unistd.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-sparc/unistd.h Thu Aug 1 14:17:36 2002 @@ -82,8 +82,8 @@ #define __NR_getpagesize 64 /* Common */ #define __NR_msync 65 /* Common in newer 1.3.x revs... */ #define __NR_vfork 66 /* Common */ -#define __NR_pread 67 /* Linux Specific */ -#define __NR_pwrite 68 /* Linux Specific */ +#define __NR_pread64 67 /* Linux Specific */ +#define __NR_pwrite64 68 /* Linux Specific */ #define __NR_geteuid32 69 /* Linux sparc32, sbrk under SunOS */ #define __NR_getegid32 70 /* Linux sparc32, sstk under SunOS */ #define __NR_mmap 71 /* Common */ diff -Nru a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h --- a/include/asm-sparc64/processor.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-sparc64/processor.h Thu Aug 1 14:17:36 2002 @@ -225,7 +225,7 @@ #define KSTK_EIP(tsk) ((tsk)->thread_info->kregs->tpc) #define KSTK_ESP(tsk) ((tsk)->thread_info->kregs->u_regs[UREG_FP]) -#define cpu_relax() udelay(1 + smp_processor_id()) +#define cpu_relax() do { udelay(1 + smp_processor_id()); barrier(); } while (0) #endif /* !(__ASSEMBLY__) */ diff -Nru a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h --- a/include/asm-sparc64/socket.h Thu Aug 1 14:17:40 2002 +++ b/include/asm-sparc64/socket.h Thu Aug 1 14:17:40 2002 @@ -4,7 +4,7 @@ #include -/* For setsockoptions(2) */ +/* For setsockopt(2) */ #define SOL_SOCKET 0xffff #define SO_DEBUG 0x0001 diff -Nru a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h --- a/include/asm-sparc64/unistd.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-sparc64/unistd.h Thu Aug 1 14:17:36 2002 @@ -82,8 +82,8 @@ #define __NR_getpagesize 64 /* Common */ #define __NR_msync 65 /* Common in newer 1.3.x revs... */ #define __NR_vfork 66 /* Common */ -#define __NR_pread 67 /* Linux Specific */ -#define __NR_pwrite 68 /* Linux Specific */ +#define __NR_pread64 67 /* Linux Specific */ +#define __NR_pwrite64 68 /* Linux Specific */ /* #define __NR_geteuid32 69 Linux sparc32, sbrk under SunOS */ /* #define __NR_getegid32 70 Linux sparc32, sstk under SunOS */ #define __NR_mmap 71 /* Common */ diff -Nru a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h --- a/include/asm-x86_64/processor.h Thu Aug 1 14:17:41 2002 +++ b/include/asm-x86_64/processor.h Thu Aug 1 14:17:41 2002 @@ -367,7 +367,7 @@ /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ extern inline void rep_nop(void) { - __asm__ __volatile__("rep;nop"); + __asm__ __volatile__("rep;nop": : :"memory"); } #define cpu_has_fpu 1 diff -Nru a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h --- a/include/asm-x86_64/unistd.h Thu Aug 1 14:17:36 2002 +++ b/include/asm-x86_64/unistd.h Thu Aug 1 14:17:36 2002 @@ -48,10 +48,10 @@ #define __NR_ioctl 16 __SYSCALL(__NR_ioctl, sys_ioctl) -#define __NR_pread 17 -__SYSCALL(__NR_pread, sys_pread) -#define __NR_pwrite 18 -__SYSCALL(__NR_pwrite, sys_pwrite) +#define __NR_pread64 17 +__SYSCALL(__NR_pread64, sys_pread64) +#define __NR_pwrite64 18 +__SYSCALL(__NR_pwrite64, sys_pwrite64) #define __NR_readv 19 __SYSCALL(__NR_readv, sys_readv) #define __NR_writev 20 diff -Nru a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h --- a/include/linux/devfs_fs_kernel.h Thu Aug 1 14:17:41 2002 +++ b/include/linux/devfs_fs_kernel.h Thu Aug 1 14:17:41 2002 @@ -74,9 +74,9 @@ extern devfs_handle_t devfs_get_handle (devfs_handle_t dir, const char *name, unsigned int major,unsigned int minor, char type, int traverse_symlinks); -extern devfs_handle_t devfs_find_handle (devfs_handle_t dir, const char *name, - unsigned int major,unsigned int minor, - char type, int traverse_symlinks); +extern void devfs_find_and_unregister (devfs_handle_t dir, const char *name, + unsigned int major, unsigned int minor, + char type, int traverse_symlinks); extern int devfs_get_flags (devfs_handle_t de, unsigned int *flags); extern int devfs_set_flags (devfs_handle_t de, unsigned int flags); extern int devfs_get_maj_min (devfs_handle_t de, @@ -94,12 +94,7 @@ extern void devfs_auto_unregister (devfs_handle_t master,devfs_handle_t slave); extern devfs_handle_t devfs_get_unregister_slave (devfs_handle_t master); extern const char *devfs_get_name (devfs_handle_t de, unsigned int *namelen); -extern int devfs_register_chrdev (unsigned int major, const char *name, - struct file_operations *fops); -extern int devfs_register_blkdev (unsigned int major, const char *name, - struct block_device_operations *bdops); -extern int devfs_unregister_chrdev (unsigned int major, const char *name); -extern int devfs_unregister_blkdev (unsigned int major, const char *name); +extern int devfs_only (void); extern void devfs_register_tape (devfs_handle_t de); extern void devfs_register_series (devfs_handle_t dir, const char *format, @@ -164,14 +159,12 @@ { return NULL; } -static inline devfs_handle_t devfs_find_handle (devfs_handle_t dir, - const char *name, - unsigned int major, - unsigned int minor, - char type, - int traverse_symlinks) +static inline void devfs_find_and_unregister (devfs_handle_t dir, + const char *name, + unsigned int major, + unsigned int minor, + char type, int traverse_symlinks) { - return NULL; } static inline int devfs_get_flags (devfs_handle_t de, unsigned int *flags) { @@ -241,23 +234,9 @@ { return NULL; } -static inline int devfs_register_chrdev (unsigned int major, const char *name, - struct file_operations *fops) -{ - return register_chrdev (major, name, fops); -} -static inline int devfs_register_blkdev (unsigned int major, const char *name, - struct block_device_operations *bdops) -{ - return register_blkdev (major, name, bdops); -} -static inline int devfs_unregister_chrdev (unsigned int major,const char *name) -{ - return unregister_chrdev (major, name); -} -static inline int devfs_unregister_blkdev (unsigned int major,const char *name) +static inline int devfs_only (void) { - return unregister_blkdev (major, name); + return 0; } static inline void devfs_register_tape (devfs_handle_t de) diff -Nru a/include/linux/device.h b/include/linux/device.h --- a/include/linux/device.h Thu Aug 1 14:17:40 2002 +++ b/include/linux/device.h Thu Aug 1 14:17:40 2002 @@ -160,8 +160,6 @@ void (*release)(struct device * dev); }; -#define to_device(d) container_of(d, struct device, dir) - static inline struct device * list_to_dev(struct list_head *node) { @@ -179,8 +177,24 @@ */ extern int device_register(struct device * dev); -extern int device_create_file(struct device *device, struct driver_file_entry * entry); -extern void device_remove_file(struct device * dev, const char * name); + +/* driverfs interface for exporting device attributes */ + +struct device_attribute { + struct attribute attr; + ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off); + ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off); +}; + +#define DEVICE_ATTR(_name,_str,_mode,_show,_store) \ +struct device_attribute dev_attr_##_name = { \ + .attr = {.name = _str, .mode = _mode }, \ + .show = _show, \ + .store = _store, \ +}; + +extern int device_create_file(struct device *device, struct device_attribute * entry); +extern void device_remove_file(struct device * dev, struct device_attribute * attr); /* * Platform "fixup" functions - allow the platform to have their say diff -Nru a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h --- a/include/linux/dqblk_xfs.h Thu Aug 1 14:17:41 2002 +++ b/include/linux/dqblk_xfs.h Thu Aug 1 14:17:41 2002 @@ -30,8 +30,8 @@ * * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ -#ifndef _LINUX_XQM_H -#define _LINUX_XQM_H +#ifndef _LINUX_DQBLK_XFS_H +#define _LINUX_DQBLK_XFS_H #include @@ -156,4 +156,4 @@ __u16 qs_iwarnlimit; /* limit for num warnings */ } fs_quota_stat_t; -#endif /* _LINUX_XQM_H */ +#endif /* _LINUX_DQBLK_XFS_H */ diff -Nru a/include/linux/driverfs_fs.h b/include/linux/driverfs_fs.h --- a/include/linux/driverfs_fs.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/driverfs_fs.h Thu Aug 1 14:17:36 2002 @@ -26,24 +26,26 @@ #ifndef _DRIVER_FS_H_ #define _DRIVER_FS_H_ +struct driver_dir_entry; +struct attribute; + +struct driverfs_ops { + int (*open)(struct driver_dir_entry *); + int (*close)(struct driver_dir_entry *); + ssize_t (*show)(struct driver_dir_entry *, struct attribute *,char *, size_t, loff_t); + ssize_t (*store)(struct driver_dir_entry *,struct attribute *,const char *, size_t, loff_t); +}; + struct driver_dir_entry { char * name; struct dentry * dentry; mode_t mode; - struct list_head files; + struct driverfs_ops * ops; }; -struct device; - -struct driver_file_entry { - struct driver_dir_entry * parent; - struct list_head node; +struct attribute { char * name; mode_t mode; - struct dentry * dentry; - - ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off); - ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off); }; extern int @@ -53,13 +55,12 @@ driverfs_remove_dir(struct driver_dir_entry * entry); extern int -driverfs_create_file(struct driver_file_entry * entry, +driverfs_create_file(struct attribute * attr, struct driver_dir_entry * parent); extern int driverfs_create_symlink(struct driver_dir_entry * parent, - struct driver_file_entry * entry, - char * target); + char * name, char * target); extern void driverfs_remove_file(struct driver_dir_entry *, const char * name); diff -Nru a/include/linux/elevator.h b/include/linux/elevator.h --- a/include/linux/elevator.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/elevator.h Thu Aug 1 14:17:36 2002 @@ -6,13 +6,14 @@ typedef void (elevator_merge_cleanup_fn) (request_queue_t *, struct request *, int); -typedef void (elevator_merge_req_fn) (struct request *, struct request *); +typedef void (elevator_merge_req_fn) (request_queue_t *, struct request *, 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 int (elevator_queue_empty_fn) (request_queue_t *); typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *); +typedef struct list_head *(elevator_get_sort_head_fn) (request_queue_t *, struct request *); typedef int (elevator_init_fn) (request_queue_t *, elevator_t *); typedef void (elevator_exit_fn) (request_queue_t *, elevator_t *); @@ -28,6 +29,7 @@ elevator_remove_req_fn *elevator_remove_req_fn; elevator_queue_empty_fn *elevator_queue_empty_fn; + elevator_get_sort_head_fn *elevator_get_sort_head_fn; elevator_init_fn *elevator_init_fn; elevator_exit_fn *elevator_exit_fn; @@ -45,6 +47,8 @@ extern void elv_merge_requests(request_queue_t *, struct request *, struct request *); extern void elv_remove_request(request_queue_t *, struct request *); +extern int elv_queue_empty(request_queue_t *); +extern inline struct list_head *elv_get_sort_head(request_queue_t *, struct request *); /* * noop I/O scheduler. always merges, always inserts new request at tail @@ -72,6 +76,10 @@ extern int elevator_init(request_queue_t *, elevator_t *, elevator_t); extern void elevator_exit(request_queue_t *, elevator_t *); +extern inline int bio_rq_in_between(struct bio *, struct request *, struct list_head *); +extern inline int elv_rq_merge_ok(struct request *, struct bio *); +extern inline int elv_try_merge(struct request *, struct bio *); +extern inline int elv_try_last_merge(request_queue_t *, struct request **, struct bio *); /* * Return values from elevator merger @@ -79,11 +87,5 @@ #define ELEVATOR_NO_MERGE 0 #define ELEVATOR_FRONT_MERGE 1 #define ELEVATOR_BACK_MERGE 2 - -/* - * will change once we move to a more complex data structure than a simple - * list for pending requests - */ -#define elv_queue_empty(q) list_empty(&(q)->queue_head) #endif diff -Nru a/include/linux/fs.h b/include/linux/fs.h --- a/include/linux/fs.h Thu Aug 1 14:17:39 2002 +++ b/include/linux/fs.h Thu Aug 1 14:17:39 2002 @@ -211,7 +211,11 @@ extern void files_init(unsigned long); struct buffer_head; -typedef int (get_block_t)(struct inode*,sector_t,struct buffer_head*,int); +typedef int (get_block_t)(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create); +typedef int (get_blocks_t)(struct inode *inode, sector_t iblock, + unsigned long max_blocks, + struct buffer_head *bh_result, int create); #include /* #include */ @@ -757,6 +761,7 @@ int (*lock) (struct file *, int, struct file_lock *); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); + ssize_t (*sendfile) (struct file *, struct file *, loff_t *, size_t); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); }; @@ -1234,11 +1239,12 @@ extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *); extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *); +extern ssize_t generic_file_sendfile(struct file *, struct file *, loff_t *, size_t); extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t); ssize_t generic_file_direct_IO(int rw, struct inode *inode, char *buf, loff_t offset, size_t count); int generic_direct_IO(int rw, struct inode *inode, char *buf, - loff_t offset, size_t count, get_block_t *get_block); + loff_t offset, size_t count, get_blocks_t *get_blocks); extern loff_t no_llseek(struct file *file, loff_t offset, int origin); extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin); diff -Nru a/include/linux/genhd.h b/include/linux/genhd.h --- a/include/linux/genhd.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/genhd.h Thu Aug 1 14:17:36 2002 @@ -70,12 +70,12 @@ struct gendisk { int major; /* major number of driver */ + int first_minor; const char *major_name; /* name of major driver */ int minor_shift; /* number of times minor is shifted to get real minor */ struct hd_struct *part; /* [indexed by minor] */ - int *sizes; /* [idem], device size in blocks */ int nr_real; /* number of real devices */ struct gendisk *next; diff -Nru a/include/linux/hdreg.h b/include/linux/hdreg.h --- a/include/linux/hdreg.h Thu Aug 1 14:17:40 2002 +++ b/include/linux/hdreg.h Thu Aug 1 14:17:40 2002 @@ -2,279 +2,18 @@ #define _LINUX_HDREG_H /* - * This file contains some defines for the AT-hd-controller. - * Various sources. - */ - -#define HD_IRQ 14 /* the standard disk interrupt */ - -/* ide.c has its own port definitions in "ide.h" */ - -/* Hd controller regs. Ref: IBM AT Bios-listing */ -#define HD_DATA 0x1f0 /* _CTL when writing */ -#define HD_ERROR 0x1f1 /* see err-bits */ -#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */ -#define HD_SECTOR 0x1f3 /* starting sector */ -#define HD_LCYL 0x1f4 /* starting cylinder */ -#define HD_HCYL 0x1f5 /* high byte of starting cyl */ -#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */ -#define HD_STATUS 0x1f7 /* see status-bits */ -#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */ -#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */ -#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */ - -#define HD_CMD 0x3f6 /* used for resets */ -#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */ - -/* remainder is shared between hd.c, ide.c, ide-cd.c, and the hdparm utility */ - -/* Bits of HD_STATUS */ -#define ERR_STAT 0x01 -#define INDEX_STAT 0x02 -#define ECC_STAT 0x04 /* Corrected error */ -#define DRQ_STAT 0x08 -#define SEEK_STAT 0x10 -#define SERVICE_STAT SEEK_STAT -#define WRERR_STAT 0x20 -#define READY_STAT 0x40 -#define BUSY_STAT 0x80 - -/* Bits for HD_ERROR */ -#define MARK_ERR 0x01 /* Bad address mark */ -#define TRK0_ERR 0x02 /* couldn't find track 0 */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define MCR_ERR 0x08 /* media change request */ -#define ID_ERR 0x10 /* ID field not found */ -#define MC_ERR 0x20 /* media changed */ -#define ECC_ERR 0x40 /* Uncorrectable ECC error */ -#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ -#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ - -/* - * sector count bits - */ -#define NSEC_CD 0x01 -#define NSEC_IO 0x02 -#define NSEC_REL 0x04 - -/* * Command Header sizes for IOCTL commands */ - #define HDIO_DRIVE_CMD_HDR_SIZE (4 * sizeof(u8)) #define HDIO_DRIVE_HOB_HDR_SIZE (8 * sizeof(u8)) -#define IDE_DRIVE_TASK_INVALID -1 -#define IDE_DRIVE_TASK_NO_DATA 0 -#define IDE_DRIVE_TASK_SET_XFER 1 - -#define IDE_DRIVE_TASK_IN 2 - -#define IDE_DRIVE_TASK_OUT 3 -#define IDE_DRIVE_TASK_RAW_WRITE 4 - -struct hd_drive_task_hdr { - u8 feature; - u8 sector_count; - u8 sector_number; - u8 low_cylinder; - u8 high_cylinder; - u8 device_head; -} __attribute__((packed)); - -/* - * Define standard taskfile in/out register - */ -#define IDE_TASKFILE_STD_OUT_FLAGS 0xFE -#define IDE_TASKFILE_STD_IN_FLAGS 0xFE -#define IDE_HOB_STD_OUT_FLAGS 0xC0 -#define IDE_HOB_STD_IN_FLAGS 0xC0 - -#define TASKFILE_INVALID 0x7fff -#define TASKFILE_48 0x8000 - -#define TASKFILE_NO_DATA 0x0000 - -#define TASKFILE_IN 0x0001 -#define TASKFILE_MULTI_IN 0x0002 - -#define TASKFILE_OUT 0x0004 -#define TASKFILE_MULTI_OUT 0x0008 -#define TASKFILE_IN_OUT 0x0010 - -#define TASKFILE_IN_DMA 0x0020 -#define TASKFILE_OUT_DMA 0x0040 -#define TASKFILE_IN_DMAQ 0x0080 -#define TASKFILE_OUT_DMAQ 0x0100 - -#define TASKFILE_P_IN 0x0200 -#define TASKFILE_P_OUT 0x0400 -#define TASKFILE_P_IN_DMA 0x0800 -#define TASKFILE_P_OUT_DMA 0x1000 -#define TASKFILE_P_IN_DMAQ 0x2000 -#define TASKFILE_P_OUT_DMAQ 0x4000 - -/* ATA/ATAPI Commands pre T13 Spec */ -#define WIN_NOP 0x00 -#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ -#define WIN_SRST 0x08 /* ATAPI soft reset command */ -#define WIN_DEVICE_RESET 0x08 -#define WIN_RESTORE 0x10 -#define WIN_READ 0x20 /* 28-Bit */ -#define WIN_READ_EXT 0x24 /* 48-Bit */ -#define WIN_READDMA_EXT 0x25 /* 48-Bit */ -#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */ -#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ -#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ -#define WIN_WRITE 0x30 /* 28-Bit */ -#define WIN_WRITE_EXT 0x34 /* 48-Bit */ -#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ -#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ -#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ -#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ -#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ -#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */ -#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ -#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ -#define WIN_FORMAT 0x50 -#define WIN_INIT 0x60 -#define WIN_SEEK 0x70 -#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ -#define WIN_DIAGNOSE 0x90 -#define WIN_SPECIFY 0x91 /* set drive geometry translation */ -#define WIN_DOWNLOAD_MICROCODE 0x92 -#define WIN_STANDBYNOW2 0x94 -#define WIN_SETIDLE2 0x97 -#define WIN_CHECKPOWERMODE2 0x98 -#define WIN_SLEEPNOW2 0x99 -#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ -#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ -#define WIN_QUEUED_SERVICE 0xA2 -#define WIN_SMART 0xB0 /* self-monitoring and reporting */ -#define CFA_ERASE_SECTORS 0xC0 -#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ -#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ -#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ -#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */ -#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ -#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ -#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */ -#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ -#define WIN_GETMEDIASTATUS 0xDA -#define WIN_DOORLOCK 0xDE /* lock door on removable drives */ -#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */ -#define WIN_STANDBYNOW1 0xE0 -#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ -#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ -#define WIN_SETIDLE1 0xE3 -#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ -#define WIN_CHECKPOWERMODE1 0xE5 -#define WIN_SLEEPNOW1 0xE6 -#define WIN_FLUSH_CACHE 0xE7 -#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ -#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ -#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ -#define WIN_MEDIAEJECT 0xED -#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */ -#define WIN_SETFEATURES 0xEF /* set special drive features */ -#define EXABYTE_ENABLE_NEST 0xF0 -#define WIN_SECURITY_SET_PASS 0xF1 -#define WIN_SECURITY_UNLOCK 0xF2 -#define WIN_SECURITY_ERASE_PREPARE 0xF3 -#define WIN_SECURITY_ERASE_UNIT 0xF4 -#define WIN_SECURITY_FREEZE_LOCK 0xF5 -#define WIN_SECURITY_DISABLE 0xF6 -#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ -#define WIN_SET_MAX 0xF9 -#define DISABLE_SEAGATE 0xFB - -/* WIN_SMART sub-commands */ - -#define SMART_READ_VALUES 0xD0 -#define SMART_READ_THRESHOLDS 0xD1 -#define SMART_AUTOSAVE 0xD2 -#define SMART_SAVE 0xD3 -#define SMART_IMMEDIATE_OFFLINE 0xD4 -#define SMART_READ_LOG_SECTOR 0xD5 -#define SMART_WRITE_LOG_SECTOR 0xD6 -#define SMART_WRITE_THRESHOLDS 0xD7 -#define SMART_ENABLE 0xD8 -#define SMART_DISABLE 0xD9 -#define SMART_STATUS 0xDA -#define SMART_AUTO_OFFLINE 0xDB - -/* Password used in TF4 & TF5 executing SMART commands */ - -#define SMART_LCYL_PASS 0x4F -#define SMART_HCYL_PASS 0xC2 - -/* WIN_SETFEATURES sub-commands */ - -#define SETFEATURES_EN_WCACHE 0x02 /* Enable write cache */ -#define SETFEATURES_XFER 0x03 /* Set transfer mode */ -# define XFER_UDMA_7 0x47 /* 0100|0111 */ -# define XFER_UDMA_6 0x46 /* 0100|0110 */ -# define XFER_UDMA_5 0x45 /* 0100|0101 */ -# define XFER_UDMA_4 0x44 /* 0100|0100 */ -# define XFER_UDMA_3 0x43 /* 0100|0011 */ -# define XFER_UDMA_2 0x42 /* 0100|0010 */ -# define XFER_UDMA_1 0x41 /* 0100|0001 */ -# define XFER_UDMA_0 0x40 /* 0100|0000 */ -# define XFER_MW_DMA_2 0x22 /* 0010|0010 */ -# define XFER_MW_DMA_1 0x21 /* 0010|0001 */ -# define XFER_MW_DMA_0 0x20 /* 0010|0000 */ -# define XFER_SW_DMA_2 0x12 /* 0001|0010 */ -# define XFER_SW_DMA_1 0x11 /* 0001|0001 */ -# define XFER_SW_DMA_0 0x10 /* 0001|0000 */ -# define XFER_PIO_4 0x0C /* 0000|1100 */ -# define XFER_PIO_3 0x0B /* 0000|1011 */ -# define XFER_PIO_2 0x0A /* 0000|1010 */ -# define XFER_PIO_1 0x09 /* 0000|1001 */ -# define XFER_PIO_0 0x08 /* 0000|1000 */ -# define XFER_PIO_SLOW 0x00 /* 0000|0000 */ -#define SETFEATURES_DIS_DEFECT 0x04 /* Disable Defect Management */ -#define SETFEATURES_EN_APM 0x05 /* Enable advanced power management */ -#define SETFEATURES_DIS_MSN 0x31 /* Disable Media Status Notification */ -#define SETFEATURES_EN_AAM 0x42 /* Enable Automatic Acoustic Management */ -#define SETFEATURES_DIS_RLA 0x55 /* Disable read look-ahead feature */ -#define SETFEATURES_EN_RI 0x5D /* Enable release interrupt */ -#define SETFEATURES_EN_SI 0x5E /* Enable SERVICE interrupt */ -#define SETFEATURES_DIS_RPOD 0x66 /* Disable reverting to power on defaults */ -#define SETFEATURES_DIS_WCACHE 0x82 /* Disable write cache */ -#define SETFEATURES_EN_DEFECT 0x84 /* Enable Defect Management */ -#define SETFEATURES_DIS_APM 0x85 /* Disable advanced power management */ -#define SETFEATURES_EN_MSN 0x95 /* Enable Media Status Notification */ -#define SETFEATURES_EN_RLA 0xAA /* Enable read look-ahead feature */ -#define SETFEATURES_PREFETCH 0xAB /* Sets drive prefetch value */ -#define SETFEATURES_DIS_AAM 0xC2 /* Disable Automatic Acoustic Management */ -#define SETFEATURES_EN_RPOD 0xCC /* Enable reverting to power on defaults */ -#define SETFEATURES_DIS_RI 0xDD /* Disable release interrupt */ -#define SETFEATURES_DIS_SI 0xDE /* Disable SERVICE interrupt */ - -/* WIN_SECURITY sub-commands */ - -#define SECURITY_SET_PASSWORD 0xBA -#define SECURITY_UNLOCK 0xBB -#define SECURITY_ERASE_PREPARE 0xBC -#define SECURITY_ERASE_UNIT 0xBD -#define SECURITY_FREEZE_LOCK 0xBE -#define SECURITY_DISABLE_PASSWORD 0xBF - struct hd_geometry { - u8 heads; - u8 sectors; - u16 cylinders; + __u8 heads; + __u8 sectors; + __u16 cylinders; unsigned long start; }; -/* BIG GEOMETRY - dying, used only by HDIO_GETGEO_BIG_RAW */ -struct hd_big_geometry { - u8 heads; - u8 sectors; - u32 cylinders; - unsigned long start; -}; - /* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x030n/0x031n */ #define HDIO_GETGEO 0x0301 /* get device geometry */ #define HDIO_GET_UNMASKINTR 0x0302 /* get current unmask setting */ @@ -306,263 +45,8 @@ #define HDIO_SET_QDMA 0x032e /* change use-qdma flag */ #define HDIO_SET_ADDRESS 0x032f /* change lba addressing modes */ -/* bus states */ -enum { - BUSSTATE_OFF = 0, - BUSSTATE_ON, - BUSSTATE_TRISTATE -}; - /* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x033n/0x033n */ /* 0x330 is reserved - used to be HDIO_GETGEO_BIG */ #define HDIO_GETGEO_BIG_RAW 0x0331 /* */ - -#define __NEW_HD_DRIVE_ID - -/* - * Structure returned by HDIO_GET_IDENTITY, as per ANSI NCITS ATA6 rev.1b spec. - * - * If you change something here, please remember to update fix_driveid() in - * ide/probe.c. - */ -struct hd_driveid { - u16 config; /* lots of obsolete bit flags */ - u16 cyls; /* Obsolete, "physical" cyls */ - u16 reserved2; /* reserved (word 2) */ - u16 heads; /* Obsolete, "physical" heads */ - u16 track_bytes; /* unformatted bytes per track */ - u16 sector_bytes; /* unformatted bytes per sector */ - u16 sectors; /* Obsolete, "physical" sectors per track */ - u16 vendor0; /* vendor unique */ - u16 vendor1; /* vendor unique */ - u16 vendor2; /* Retired vendor unique */ - u8 serial_no[20]; /* 0 = not_specified */ - u16 buf_type; /* Retired */ - u16 buf_size; /* Retired, 512 byte increments - * 0 = not_specified - */ - u16 ecc_bytes; /* for r/w long cmds; 0 = not_specified */ - u8 fw_rev[8]; /* 0 = not_specified */ - char model[40]; /* 0 = not_specified */ - u8 max_multsect; /* 0=not_implemented */ - u8 vendor3; /* vendor unique */ - u16 dword_io; /* 0=not_implemented; 1=implemented */ - u8 vendor4; /* vendor unique */ - u8 capability; /* (upper byte of word 49) - * 3: IORDYsup - * 2: IORDYsw - * 1: LBA - * 0: DMA - */ - u16 reserved50; /* reserved (word 50) */ - u8 vendor5; /* Obsolete, vendor unique */ - u8 tPIO; /* Obsolete, 0=slow, 1=medium, 2=fast */ - u8 vendor6; /* Obsolete, vendor unique */ - u8 tDMA; /* Obsolete, 0=slow, 1=medium, 2=fast */ - u16 field_valid; /* (word 53) - * 2: ultra_ok word 88 - * 1: eide_ok words 64-70 - * 0: cur_ok words 54-58 - */ - u16 cur_cyls; /* Obsolete, logical cylinders */ - u16 cur_heads; /* Obsolete, l heads */ - u16 cur_sectors; /* Obsolete, l sectors per track */ - u16 cur_capacity0; /* Obsolete, l total sectors on drive */ - u16 cur_capacity1; /* Obsolete, (2 words, misaligned int) */ - u8 multsect; /* current multiple sector count */ - u8 multsect_valid; /* when (bit0==1) multsect is ok */ - u32 lba_capacity; /* Obsolete, total number of sectors */ - u16 dma_1word; /* Obsolete, single-word dma info */ - u16 dma_mword; /* multiple-word dma info */ - u16 eide_pio_modes; /* bits 0:mode3 1:mode4 */ - u16 eide_dma_min; /* min mword dma cycle time (ns) */ - u16 eide_dma_time; /* recommended mword dma cycle time (ns) */ - u16 eide_pio; /* min cycle time (ns), no IORDY */ - u16 eide_pio_iordy; /* min cycle time (ns), with IORDY */ - u16 words69_70[2]; /* reserved words 69-70 - * future command overlap and queuing - */ - /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */ - u16 words71_74[4]; /* reserved words 71-74 - * for IDENTIFY PACKET DEVICE command - */ - u16 queue_depth; /* (word 75) - * 15:5 reserved - * 4:0 Maximum queue depth -1 - */ - u16 words76_79[4]; /* reserved words 76-79 */ - u16 major_rev_num; /* (word 80) */ - u16 minor_rev_num; /* (word 81) */ - u16 command_set_1; /* (word 82) supported - * 15: Obsolete - * 14: NOP command - * 13: READ_BUFFER - * 12: WRITE_BUFFER - * 11: Obsolete - * 10: Host Protected Area - * 9: DEVICE Reset - * 8: SERVICE Interrupt - * 7: Release Interrupt - * 6: look-ahead - * 5: write cache - * 4: PACKET Command - * 3: Power Management Feature Set - * 2: Removable Feature Set - * 1: Security Feature Set - * 0: SMART Feature Set - */ - u16 command_set_2; /* (word 83) - * 15: Shall be ZERO - * 14: Shall be ONE - * 13: FLUSH CACHE EXT - * 12: FLUSH CACHE - * 11: Device Configuration Overlay - * 10: 48-bit Address Feature Set - * 9: Automatic Acoustic Management - * 8: SET MAX security - * 7: reserved 1407DT PARTIES - * 6: SetF sub-command Power-Up - * 5: Power-Up in Standby Feature Set - * 4: Removable Media Notification - * 3: APM Feature Set - * 2: CFA Feature Set - * 1: READ/WRITE DMA QUEUED - * 0: Download MicroCode - */ - u16 cfsse; /* (word 84) - * cmd set-feature supported extensions - * 15: Shall be ZERO - * 14: Shall be ONE - * 13:3 reserved - * 2: Media Serial Number Valid - * 1: SMART selt-test supported - * 0: SMART error logging - */ - u16 cfs_enable_1; /* (word 85) - * command set-feature enabled - * 15: Obsolete - * 14: NOP command - * 13: READ_BUFFER - * 12: WRITE_BUFFER - * 11: Obsolete - * 10: Host Protected Area - * 9: DEVICE Reset - * 8: SERVICE Interrupt - * 7: Release Interrupt - * 6: look-ahead - * 5: write cache - * 4: PACKET Command - * 3: Power Management Feature Set - * 2: Removable Feature Set - * 1: Security Feature Set - * 0: SMART Feature Set - */ - u16 cfs_enable_2; /* (word 86) - * command set-feature enabled - * 15: Shall be ZERO - * 14: Shall be ONE - * 13: FLUSH CACHE EXT - * 12: FLUSH CACHE - * 11: Device Configuration Overlay - * 10: 48-bit Address Feature Set - * 9: Automatic Acoustic Management - * 8: SET MAX security - * 7: reserved 1407DT PARTIES - * 6: SetF sub-command Power-Up - * 5: Power-Up in Standby Feature Set - * 4: Removable Media Notification - * 3: APM Feature Set - * 2: CFA Feature Set - * 1: READ/WRITE DMA QUEUED - * 0: Download MicroCode - */ - u16 csf_default; /* (word 87) - * command set-feature default - * 15: Shall be ZERO - * 14: Shall be ONE - * 13:3 reserved - * 2: Media Serial Number Valid - * 1: SMART selt-test supported - * 0: SMART error logging - */ - u16 dma_ultra; /* (word 88) */ - u16 word89; /* reserved (word 89) */ - u16 word90; /* reserved (word 90) */ - u16 CurAPMvalues; /* current APM values */ - u16 word92; /* reserved (word 92) */ - u16 hw_config; /* hardware config (word 93) - * 15: - * 14: - * 13: - * 12: - * 11: - * 10: - * 9: - * 8: - * 7: - * 6: - * 5: - * 4: - * 3: - * 2: - * 1: - * 0: - */ - u16 acoustic; /* (word 94) - * 15:8 Vendor's recommended value - * 7:0 current value - */ - u16 words95_99[5]; /* reserved words 95-99 */ - u64 lba_capacity_2; /* 48-bit total number of sectors */ - u16 words104_125[22];/* reserved words 104-125 */ - u16 last_lun; /* (word 126) */ - u16 word127; /* (word 127) Feature Set - * Removable Media Notification - * 15:2 reserved - * 1:0 00 = not supported - * 01 = supported - * 10 = reserved - * 11 = reserved - */ - u16 dlf; /* (word 128) - * device lock function - * 15:9 reserved - * 8 security level 1:max 0:high - * 7:6 reserved - * 5 enhanced erase - * 4 expire - * 3 frozen - * 2 locked - * 1 en/disabled - * 0 capability - */ - u16 csfo; /* (word 129) - * current set features options - * 15:4 reserved - * 3: auto reassign - * 2: reverting - * 1: read-look-ahead - * 0: write cache - */ - u16 words130_155[26];/* reserved vendor words 130-155 */ - u16 word156; /* reserved vendor word 156 */ - u16 words157_159[3];/* reserved vendor words 157-159 */ - u16 cfa_power; /* (word 160) CFA Power Mode - * 15 word 160 supported - * 14 reserved - * 13 - * 12 - * 11:0 - */ - u16 words161_175[14];/* Reserved for CFA */ - u16 words176_205[31];/* Current Media Serial Number */ - u16 words206_254[48];/* reserved words 206-254 */ - u16 integrity_word; /* (word 255) - * 15:8 Checksum - * 7:0 Signature - */ -} __attribute__((packed)); - -#define IDE_NICE_DSC_OVERLAP (0) /* per the DSC overlap protocol */ #endif diff -Nru a/include/linux/ide.h b/include/linux/ide.h --- a/include/linux/ide.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/ide.h Thu Aug 1 14:17:37 2002 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -51,7 +50,460 @@ * "No user-serviceable parts" beyond this point *****************************************************************************/ -typedef unsigned char byte; /* used everywhere */ + +/* ATA/ATAPI Commands pre T13 Spec */ +#define WIN_NOP 0x00 +#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ +#define WIN_SRST 0x08 /* ATAPI soft reset command */ +#define WIN_DEVICE_RESET 0x08 +#define WIN_RESTORE 0x10 +#define WIN_READ 0x20 /* 28-Bit */ +#define WIN_READ_EXT 0x24 /* 48-Bit */ +#define WIN_READDMA_EXT 0x25 /* 48-Bit */ +#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */ +#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ +#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ +#define WIN_WRITE 0x30 /* 28-Bit */ +#define WIN_WRITE_EXT 0x34 /* 48-Bit */ +#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ +#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ +#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ +#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ +#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ +#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */ +#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ +#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ +#define WIN_FORMAT 0x50 +#define WIN_INIT 0x60 +#define WIN_SEEK 0x70 +#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ +#define WIN_DIAGNOSE 0x90 +#define WIN_SPECIFY 0x91 /* set drive geometry translation */ +#define WIN_DOWNLOAD_MICROCODE 0x92 +#define WIN_STANDBYNOW2 0x94 +#define WIN_SETIDLE2 0x97 +#define WIN_CHECKPOWERMODE2 0x98 +#define WIN_SLEEPNOW2 0x99 +#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ +#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ +#define WIN_QUEUED_SERVICE 0xA2 +#define WIN_SMART 0xB0 /* self-monitoring and reporting */ +#define CFA_ERASE_SECTORS 0xC0 +#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ +#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ +#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ +#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */ +#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ +#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ +#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */ +#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ +#define WIN_GETMEDIASTATUS 0xDA +#define WIN_DOORLOCK 0xDE /* lock door on removable drives */ +#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */ +#define WIN_STANDBYNOW1 0xE0 +#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ +#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ +#define WIN_SETIDLE1 0xE3 +#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ +#define WIN_CHECKPOWERMODE1 0xE5 +#define WIN_SLEEPNOW1 0xE6 +#define WIN_FLUSH_CACHE 0xE7 +#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ +#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ +#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ +#define WIN_MEDIAEJECT 0xED +#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */ +#define WIN_SETFEATURES 0xEF /* set special drive features */ +#define EXABYTE_ENABLE_NEST 0xF0 +#define WIN_SECURITY_SET_PASS 0xF1 +#define WIN_SECURITY_UNLOCK 0xF2 +#define WIN_SECURITY_ERASE_PREPARE 0xF3 +#define WIN_SECURITY_ERASE_UNIT 0xF4 +#define WIN_SECURITY_FREEZE_LOCK 0xF5 +#define WIN_SECURITY_DISABLE 0xF6 +#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ +#define WIN_SET_MAX 0xF9 +#define DISABLE_SEAGATE 0xFB + +/* WIN_SMART sub-commands */ + +#define SMART_READ_VALUES 0xD0 +#define SMART_READ_THRESHOLDS 0xD1 +#define SMART_AUTOSAVE 0xD2 +#define SMART_SAVE 0xD3 +#define SMART_IMMEDIATE_OFFLINE 0xD4 +#define SMART_READ_LOG_SECTOR 0xD5 +#define SMART_WRITE_LOG_SECTOR 0xD6 +#define SMART_WRITE_THRESHOLDS 0xD7 +#define SMART_ENABLE 0xD8 +#define SMART_DISABLE 0xD9 +#define SMART_STATUS 0xDA +#define SMART_AUTO_OFFLINE 0xDB + +/* Password used in TF4 & TF5 executing SMART commands */ + +#define SMART_LCYL_PASS 0x4F +#define SMART_HCYL_PASS 0xC2 + +/* WIN_SETFEATURES sub-commands */ + +#define SETFEATURES_EN_WCACHE 0x02 /* Enable write cache */ + +#define SETFEATURES_XFER 0x03 /* Set transfer mode */ +# define XFER_UDMA_7 0x47 /* 0100|0111 */ +# define XFER_UDMA_6 0x46 /* 0100|0110 */ +# define XFER_UDMA_5 0x45 /* 0100|0101 */ +# define XFER_UDMA_4 0x44 /* 0100|0100 */ +# define XFER_UDMA_3 0x43 /* 0100|0011 */ +# define XFER_UDMA_2 0x42 /* 0100|0010 */ +# define XFER_UDMA_1 0x41 /* 0100|0001 */ +# define XFER_UDMA_0 0x40 /* 0100|0000 */ +# define XFER_MW_DMA_2 0x22 /* 0010|0010 */ +# define XFER_MW_DMA_1 0x21 /* 0010|0001 */ +# define XFER_MW_DMA_0 0x20 /* 0010|0000 */ +# define XFER_SW_DMA_2 0x12 /* 0001|0010 */ +# define XFER_SW_DMA_1 0x11 /* 0001|0001 */ +# define XFER_SW_DMA_0 0x10 /* 0001|0000 */ +# define XFER_PIO_4 0x0C /* 0000|1100 */ +# define XFER_PIO_3 0x0B /* 0000|1011 */ +# define XFER_PIO_2 0x0A /* 0000|1010 */ +# define XFER_PIO_1 0x09 /* 0000|1001 */ +# define XFER_PIO_0 0x08 /* 0000|1000 */ +# define XFER_PIO_SLOW 0x00 /* 0000|0000 */ + +#define SETFEATURES_DIS_DEFECT 0x04 /* Disable Defect Management */ +#define SETFEATURES_EN_APM 0x05 /* Enable advanced power management */ +#define SETFEATURES_DIS_MSN 0x31 /* Disable Media Status Notification */ +#define SETFEATURES_EN_AAM 0x42 /* Enable Automatic Acoustic Management */ +#define SETFEATURES_DIS_RLA 0x55 /* Disable read look-ahead feature */ +#define SETFEATURES_EN_RI 0x5D /* Enable release interrupt */ +#define SETFEATURES_EN_SI 0x5E /* Enable SERVICE interrupt */ +#define SETFEATURES_DIS_RPOD 0x66 /* Disable reverting to power on defaults */ +#define SETFEATURES_DIS_WCACHE 0x82 /* Disable write cache */ +#define SETFEATURES_EN_DEFECT 0x84 /* Enable Defect Management */ +#define SETFEATURES_DIS_APM 0x85 /* Disable advanced power management */ +#define SETFEATURES_EN_MSN 0x95 /* Enable Media Status Notification */ +#define SETFEATURES_EN_RLA 0xAA /* Enable read look-ahead feature */ +#define SETFEATURES_PREFETCH 0xAB /* Sets drive prefetch value */ +#define SETFEATURES_DIS_AAM 0xC2 /* Disable Automatic Acoustic Management */ +#define SETFEATURES_EN_RPOD 0xCC /* Enable reverting to power on defaults */ +#define SETFEATURES_DIS_RI 0xDD /* Disable release interrupt */ +#define SETFEATURES_DIS_SI 0xDE /* Disable SERVICE interrupt */ + +/* WIN_SECURITY sub-commands */ + +#define SECURITY_SET_PASSWORD 0xBA +#define SECURITY_UNLOCK 0xBB +#define SECURITY_ERASE_PREPARE 0xBC +#define SECURITY_ERASE_UNIT 0xBD +#define SECURITY_FREEZE_LOCK 0xBE +#define SECURITY_DISABLE_PASSWORD 0xBF + + +/* Taskfile related constants. + */ +#define IDE_DRIVE_TASK_INVALID -1 +#define IDE_DRIVE_TASK_NO_DATA 0 +#define IDE_DRIVE_TASK_SET_XFER 1 + +#define IDE_DRIVE_TASK_IN 2 + +#define IDE_DRIVE_TASK_OUT 3 +#define IDE_DRIVE_TASK_RAW_WRITE 4 + +struct hd_drive_task_hdr { + u8 feature; + u8 sector_count; + u8 sector_number; + u8 low_cylinder; + u8 high_cylinder; + u8 device_head; +} __attribute__((packed)); + +/* + * Define standard taskfile in/out register + */ +#define IDE_TASKFILE_STD_OUT_FLAGS 0xFE +#define IDE_TASKFILE_STD_IN_FLAGS 0xFE +#define IDE_HOB_STD_OUT_FLAGS 0xC0 +#define IDE_HOB_STD_IN_FLAGS 0xC0 + +#define TASKFILE_INVALID 0x7fff +#define TASKFILE_48 0x8000 + +#define TASKFILE_NO_DATA 0x0000 + +#define TASKFILE_IN 0x0001 +#define TASKFILE_MULTI_IN 0x0002 + +#define TASKFILE_OUT 0x0004 +#define TASKFILE_MULTI_OUT 0x0008 +#define TASKFILE_IN_OUT 0x0010 + +#define TASKFILE_IN_DMA 0x0020 +#define TASKFILE_OUT_DMA 0x0040 +#define TASKFILE_IN_DMAQ 0x0080 +#define TASKFILE_OUT_DMAQ 0x0100 + +#define TASKFILE_P_IN 0x0200 +#define TASKFILE_P_OUT 0x0400 +#define TASKFILE_P_IN_DMA 0x0800 +#define TASKFILE_P_OUT_DMA 0x1000 +#define TASKFILE_P_IN_DMAQ 0x2000 +#define TASKFILE_P_OUT_DMAQ 0x4000 + +/* bus states */ +enum { + BUSSTATE_OFF = 0, + BUSSTATE_ON, + BUSSTATE_TRISTATE +}; + +/* + * Structure returned by HDIO_GET_IDENTITY, as per ANSI NCITS ATA6 rev.1b spec. + * + * If you change something here, please remember to update fix_driveid() in + * ide/probe.c. + */ +struct hd_driveid { + u16 config; /* lots of obsolete bit flags */ + u16 cyls; /* Obsolete, "physical" cyls */ + u16 reserved2; /* reserved (word 2) */ + u16 heads; /* Obsolete, "physical" heads */ + u16 track_bytes; /* unformatted bytes per track */ + u16 sector_bytes; /* unformatted bytes per sector */ + u16 sectors; /* Obsolete, "physical" sectors per track */ + u16 vendor0; /* vendor unique */ + u16 vendor1; /* vendor unique */ + u16 vendor2; /* Retired vendor unique */ + u8 serial_no[20]; /* 0 = not_specified */ + u16 buf_type; /* Retired */ + u16 buf_size; /* Retired, 512 byte increments + * 0 = not_specified + */ + u16 ecc_bytes; /* for r/w long cmds; 0 = not_specified */ + u8 fw_rev[8]; /* 0 = not_specified */ + char model[40]; /* 0 = not_specified */ + u8 max_multsect; /* 0=not_implemented */ + u8 vendor3; /* vendor unique */ + u16 dword_io; /* 0=not_implemented; 1=implemented */ + u8 vendor4; /* vendor unique */ + u8 capability; /* (upper byte of word 49) + * 3: IORDYsup + * 2: IORDYsw + * 1: LBA + * 0: DMA + */ + u16 reserved50; /* reserved (word 50) */ + u8 vendor5; /* Obsolete, vendor unique */ + u8 tPIO; /* Obsolete, 0=slow, 1=medium, 2=fast */ + u8 vendor6; /* Obsolete, vendor unique */ + u8 tDMA; /* Obsolete, 0=slow, 1=medium, 2=fast */ + u16 field_valid; /* (word 53) + * 2: ultra_ok word 88 + * 1: eide_ok words 64-70 + * 0: cur_ok words 54-58 + */ + u16 cur_cyls; /* Obsolete, logical cylinders */ + u16 cur_heads; /* Obsolete, l heads */ + u16 cur_sectors; /* Obsolete, l sectors per track */ + u16 cur_capacity0; /* Obsolete, l total sectors on drive */ + u16 cur_capacity1; /* Obsolete, (2 words, misaligned int) */ + u8 multsect; /* current multiple sector count */ + u8 multsect_valid; /* when (bit0==1) multsect is ok */ + u32 lba_capacity; /* Obsolete, total number of sectors */ + u16 dma_1word; /* Obsolete, single-word dma info */ + u16 dma_mword; /* multiple-word dma info */ + u16 eide_pio_modes; /* bits 0:mode3 1:mode4 */ + u16 eide_dma_min; /* min mword dma cycle time (ns) */ + u16 eide_dma_time; /* recommended mword dma cycle time (ns) */ + u16 eide_pio; /* min cycle time (ns), no IORDY */ + u16 eide_pio_iordy; /* min cycle time (ns), with IORDY */ + u16 words69_70[2]; /* reserved words 69-70 + * future command overlap and queuing + */ + /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */ + u16 words71_74[4]; /* reserved words 71-74 + * for IDENTIFY PACKET DEVICE command + */ + u16 queue_depth; /* (word 75) + * 15:5 reserved + * 4:0 Maximum queue depth -1 + */ + u16 words76_79[4]; /* reserved words 76-79 */ + u16 major_rev_num; /* (word 80) */ + u16 minor_rev_num; /* (word 81) */ + u16 command_set_1; /* (word 82) supported + * 15: Obsolete + * 14: NOP command + * 13: READ_BUFFER + * 12: WRITE_BUFFER + * 11: Obsolete + * 10: Host Protected Area + * 9: DEVICE Reset + * 8: SERVICE Interrupt + * 7: Release Interrupt + * 6: look-ahead + * 5: write cache + * 4: PACKET Command + * 3: Power Management Feature Set + * 2: Removable Feature Set + * 1: Security Feature Set + * 0: SMART Feature Set + */ + u16 command_set_2; /* (word 83) + * 15: Shall be ZERO + * 14: Shall be ONE + * 13: FLUSH CACHE EXT + * 12: FLUSH CACHE + * 11: Device Configuration Overlay + * 10: 48-bit Address Feature Set + * 9: Automatic Acoustic Management + * 8: SET MAX security + * 7: reserved 1407DT PARTIES + * 6: SetF sub-command Power-Up + * 5: Power-Up in Standby Feature Set + * 4: Removable Media Notification + * 3: APM Feature Set + * 2: CFA Feature Set + * 1: READ/WRITE DMA QUEUED + * 0: Download MicroCode + */ + u16 cfsse; /* (word 84) + * cmd set-feature supported extensions + * 15: Shall be ZERO + * 14: Shall be ONE + * 13:3 reserved + * 2: Media Serial Number Valid + * 1: SMART selt-test supported + * 0: SMART error logging + */ + u16 cfs_enable_1; /* (word 85) + * command set-feature enabled + * 15: Obsolete + * 14: NOP command + * 13: READ_BUFFER + * 12: WRITE_BUFFER + * 11: Obsolete + * 10: Host Protected Area + * 9: DEVICE Reset + * 8: SERVICE Interrupt + * 7: Release Interrupt + * 6: look-ahead + * 5: write cache + * 4: PACKET Command + * 3: Power Management Feature Set + * 2: Removable Feature Set + * 1: Security Feature Set + * 0: SMART Feature Set + */ + u16 cfs_enable_2; /* (word 86) + * command set-feature enabled + * 15: Shall be ZERO + * 14: Shall be ONE + * 13: FLUSH CACHE EXT + * 12: FLUSH CACHE + * 11: Device Configuration Overlay + * 10: 48-bit Address Feature Set + * 9: Automatic Acoustic Management + * 8: SET MAX security + * 7: reserved 1407DT PARTIES + * 6: SetF sub-command Power-Up + * 5: Power-Up in Standby Feature Set + * 4: Removable Media Notification + * 3: APM Feature Set + * 2: CFA Feature Set + * 1: READ/WRITE DMA QUEUED + * 0: Download MicroCode + */ + u16 csf_default; /* (word 87) + * command set-feature default + * 15: Shall be ZERO + * 14: Shall be ONE + * 13:3 reserved + * 2: Media Serial Number Valid + * 1: SMART selt-test supported + * 0: SMART error logging + */ + u16 dma_ultra; /* (word 88) */ + u16 word89; /* reserved (word 89) */ + u16 word90; /* reserved (word 90) */ + u16 CurAPMvalues; /* current APM values */ + u16 word92; /* reserved (word 92) */ + u16 hw_config; /* hardware config (word 93) + * 15: + * 14: + * 13: + * 12: + * 11: + * 10: + * 9: + * 8: + * 7: + * 6: + * 5: + * 4: + * 3: + * 2: + * 1: + * 0: + */ + u16 acoustic; /* (word 94) + * 15:8 Vendor's recommended value + * 7:0 current value + */ + u16 words95_99[5]; /* reserved words 95-99 */ + u64 lba_capacity_2; /* 48-bit total number of sectors */ + u16 words104_125[22];/* reserved words 104-125 */ + u16 last_lun; /* (word 126) */ + u16 word127; /* (word 127) Feature Set + * Removable Media Notification + * 15:2 reserved + * 1:0 00 = not supported + * 01 = supported + * 10 = reserved + * 11 = reserved + */ + u16 dlf; /* (word 128) + * device lock function + * 15:9 reserved + * 8 security level 1:max 0:high + * 7:6 reserved + * 5 enhanced erase + * 4 expire + * 3 frozen + * 2 locked + * 1 en/disabled + * 0 capability + */ + u16 csfo; /* (word 129) + * current set features options + * 15:4 reserved + * 3: auto reassign + * 2: reverting + * 1: read-look-ahead + * 0: write cache + */ + u16 words130_155[26];/* reserved vendor words 130-155 */ + u16 word156; /* reserved vendor word 156 */ + u16 words157_159[3];/* reserved vendor words 157-159 */ + u16 cfa_power; /* (word 160) CFA Power Mode + * 15 word 160 supported + * 14 reserved + * 13 + * 12 + * 11:0 + */ + u16 words161_175[14];/* Reserved for CFA */ + u16 words176_205[31];/* Current Media Serial Number */ + u16 words206_254[48];/* reserved words 206-254 */ + u16 integrity_word; /* (word 255) + * 15:8 Checksum + * 7:0 Signature + */ +} __attribute__((packed)); + +#define IDE_NICE_DSC_OVERLAP (0) /* per the DSC overlap protocol */ /* * Probably not wise to fiddle with these @@ -105,6 +557,35 @@ #define GET_ALTSTAT() IN_BYTE(drive->channel->io_ports[IDE_CONTROL_OFFSET]) #define GET_FEAT() IN_BYTE(IDE_NSECTOR_REG) +/* Bits of HD_STATUS */ +#define ERR_STAT 0x01 +#define INDEX_STAT 0x02 +#define ECC_STAT 0x04 /* Corrected error */ +#define DRQ_STAT 0x08 +#define SEEK_STAT 0x10 +#define SERVICE_STAT SEEK_STAT +#define WRERR_STAT 0x20 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 + +/* Bits for HD_ERROR */ +#define MARK_ERR 0x01 /* Bad address mark */ +#define TRK0_ERR 0x02 /* couldn't find track 0 */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* media change request */ +#define ID_ERR 0x10 /* ID field not found */ +#define MC_ERR 0x20 /* media changed */ +#define ECC_ERR 0x40 /* Uncorrectable ECC error */ +#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ +#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ + +/* + * sector count bits + */ +#define NSEC_CD 0x01 +#define NSEC_IO 0x02 +#define NSEC_REL 0x04 + #define BAD_R_STAT (BUSY_STAT | ERR_STAT) #define BAD_W_STAT (BAD_R_STAT | WRERR_STAT) #define BAD_STAT (BAD_R_STAT | DRQ_STAT) @@ -283,8 +764,6 @@ request_queue_t queue; /* per device request queue */ struct request *rq; /* current request */ - unsigned long sleep; /* sleep until this time */ - u8 retry_pio; /* retrying dma capable host in pio */ u8 state; /* retry state */ @@ -304,7 +783,6 @@ unsigned atapi_overlap : 1; /* flag: ATAPI overlap (not supported) */ unsigned doorlocking : 1; /* flag: for removable only: door lock/unlock works */ unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */ - unsigned remap_0_to_1 : 2; /* 0=remap if ezdrive, 1=remap, 2=noremap */ unsigned ata_flash : 1; /* 1=present, 0=default */ unsigned addressing; /* : 2; 0=28-bit, 1=48-bit, 2=64-bit */ u8 scsi; /* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */ @@ -316,7 +794,6 @@ u8 mult_count; /* current multiple sector setting */ u8 bad_wstat; /* used for ignoring WRERR_STAT */ u8 nowerr; /* used for ignoring WRERR_STAT */ - u8 sect0; /* offset of first sector for DM6:DDO */ u8 head; /* "real" number of heads */ u8 sect; /* "real" sectors per track */ u8 bios_head; /* BIOS/fdisk/LILO number of heads */ @@ -417,7 +894,7 @@ struct pci_dev *pci_dev; /* for pci chipsets */ #endif struct ata_device drives[MAX_DRIVES]; /* drive info */ - struct gendisk *gd; /* gendisk structure */ + struct gendisk *gd[MAX_DRIVES]; /* gendisk structure */ /* * Routines to tune PIO and DMA mode for drives. @@ -466,6 +943,8 @@ void (*udma_timeout) (struct ata_device *); void (*udma_irq_lost) (struct ata_device *); + unsigned long seg_boundary_mask; + unsigned int max_segment_size; unsigned int *dmatable_cpu; /* dma physical region descriptor table (cpu view) */ dma_addr_t dmatable_dma; /* dma physical region descriptor table (dma view) */ struct scatterlist *sg_table; /* Scatter-gather list used to build the above */ @@ -665,23 +1144,23 @@ */ extern int ideprobe_init(void); #ifdef CONFIG_BLK_DEV_IDEDISK -extern int idedisk_init (void); +extern int idedisk_init(void); #endif #ifdef CONFIG_BLK_DEV_IDECD -extern int ide_cdrom_init (void); +extern int ide_cdrom_init(void); #endif #ifdef CONFIG_BLK_DEV_IDETAPE -extern int idetape_init (void); +extern int idetape_init(void); #endif #ifdef CONFIG_BLK_DEV_IDEFLOPPY -extern int idefloppy_init (void); +extern int idefloppy_init(void); #endif #ifdef CONFIG_BLK_DEV_IDESCSI -extern int idescsi_init (void); +extern int idescsi_init(void); #endif -extern int ide_register_subdriver(struct ata_device *, struct ata_operations *); -extern int ide_unregister_subdriver(struct ata_device *drive); +extern int ata_register_device(struct ata_device *, struct ata_operations *); +extern int ata_unregister_device(struct ata_device *drive); extern int ata_revalidate(kdev_t i_rdev); extern void ide_driver_module(void); diff -Nru a/include/linux/input.h b/include/linux/input.h --- a/include/linux/input.h Thu Aug 1 14:17:40 2002 +++ b/include/linux/input.h Thu Aug 1 14:17:40 2002 @@ -41,9 +41,9 @@ struct input_event { struct timeval time; - unsigned short type; - unsigned short code; - unsigned int value; + __u16 type; + __u16 code; + __s32 value; }; /* @@ -63,6 +63,14 @@ __u16 version; }; +struct input_absinfo { + __s32 value; + __s32 minimum; + __s32 maximum; + __s32 fuzz; + __s32 flat; +}; + #define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */ #define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */ #define EVIOCGREP _IOR('E', 0x03, int[2]) /* get repeat settings */ @@ -79,8 +87,8 @@ #define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) /* get all sounds status */ #define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + ev, len) /* get event bits */ -#define EVIOCGABS(abs) _IOR('E', 0x40 + abs, int[5]) /* get abs value/limits */ -#define EVIOCSABS(abs) _IOW('E', 0xc0 + abs, int[5]) /* set abs value/limits */ +#define EVIOCGABS(abs) _IOR('E', 0x40 + abs, struct input_absinfo) /* get abs value/limits */ +#define EVIOCSABS(abs) _IOW('E', 0xc0 + abs, struct input_absinfo) /* set abs value/limits */ #define EVIOCSFF _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect)) /* send a force effect to a force feedback device */ #define EVIOCRMFF _IOW('E', 0x81, int) /* Erase a force effect */ @@ -473,11 +481,11 @@ #define KEY_RESTART 0x198 #define KEY_SLOW 0x199 #define KEY_SHUFFLE 0x19a -#define KEY_BREAK 0x1ab +#define KEY_BREAK 0x19b #define KEY_PREVIOUS 0x19c #define KEY_DIGITS 0x19d #define KEY_TEEN 0x19e -#define KEY_TWEN 0x1af +#define KEY_TWEN 0x19f #define KEY_MAX 0x1ff diff -Nru a/include/linux/jffs2.h b/include/linux/jffs2.h --- a/include/linux/jffs2.h Thu Aug 1 14:17:41 2002 +++ b/include/linux/jffs2.h Thu Aug 1 14:17:41 2002 @@ -5,33 +5,10 @@ * * Created by David Woodhouse * - * The original JFFS, from which the design for JFFS2 was derived, - * was designed and implemented by Axis Communications AB. + * For licensing information, see the file 'LICENCE' in the + * jffs2 directory. * - * The contents of this file are subject to the Red Hat eCos Public - * License Version 1.1 (the "Licence"); you may not use this file - * except in compliance with the Licence. You may obtain a copy of - * the Licence at http://www.redhat.com/ - * - * Software distributed under the Licence is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the Licence for the specific language governing rights and - * limitations under the Licence. - * - * The Original Code is JFFS2 - Journalling Flash File System, version 2 - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the RHEPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the RHEPL or the GPL. - * - * $Id: jffs2.h,v 1.23 2002/02/21 17:03:45 dwmw2 Exp $ + * $Id: jffs2.h,v 1.24 2002/05/20 14:56:37 dwmw2 Exp $ * */ diff -Nru a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h --- a/include/linux/jffs2_fs_sb.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/jffs2_fs_sb.h Thu Aug 1 14:17:36 2002 @@ -1,16 +1,15 @@ -/* $Id: jffs2_fs_sb.h,v 1.26 2002/03/17 10:18:42 dwmw2 Exp $ */ +/* $Id: jffs2_fs_sb.h,v 1.32 2002/07/23 14:35:34 dwmw2 Exp $ */ #ifndef _JFFS2_FS_SB #define _JFFS2_FS_SB #include #include +#include #include #include #include -#define INOCACHE_HASHSIZE 14 - #define JFFS2_SB_FLAG_RO 1 #define JFFS2_SB_FLAG_MOUNTING 2 @@ -33,6 +32,9 @@ out-of-order writing of nodes. And GC. */ + uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER + (i.e. zero for OOB CLEANMARKER */ + uint32_t flash_size; uint32_t used_size; uint32_t dirty_size; @@ -52,6 +54,7 @@ struct jffs2_eraseblock *gcblock; /* The block we're currently garbage-collecting */ struct list_head clean_list; /* Blocks 100% full of clean data */ + struct list_head very_dirty_list; /* Blocks with lots of dirty space */ struct list_head dirty_list; /* Blocks with some dirty space */ struct list_head erasable_list; /* Blocks which are completely dirty, and need erasing */ struct list_head erasable_pending_wbuf_list; /* Blocks which need erasing but only after the current wbuf is flushed */ @@ -66,10 +69,8 @@ against erase completion handler */ wait_queue_head_t erase_wait; /* For waiting for erases to complete */ - struct jffs2_inode_cache *inocache_list[INOCACHE_HASHSIZE]; + struct jffs2_inode_cache **inocache_list; spinlock_t inocache_lock; - /* This _really_ speeds up mounts. */ - struct jffs2_inode_cache *inocache_last; /* Sem to allow jffs2_garbage_collect_deletion_dirent to drop the erase_completion_lock while it's holding a pointer @@ -81,6 +82,8 @@ uint32_t wbuf_ofs; uint32_t wbuf_len; uint32_t wbuf_pagesize; + struct tq_struct wbuf_task; /* task for timed wbuf flush */ + struct timer_list wbuf_timer; /* timer for flushing wbuf */ /* OS-private pointer for getting back to master superblock info */ void *os_priv; diff -Nru a/include/linux/list.h b/include/linux/list.h --- a/include/linux/list.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/list.h Thu Aug 1 14:17:36 2002 @@ -156,9 +156,7 @@ */ static inline void list_splice(list_t *list, list_t *head) { - list_t *first = list->next; - - if (first != list) + if (!list_empty(list)) __list_splice(list, head); } diff -Nru a/include/linux/mm.h b/include/linux/mm.h --- a/include/linux/mm.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/mm.h Thu Aug 1 14:17:36 2002 @@ -103,8 +103,9 @@ #define VM_DONTCOPY 0x00020000 /* Do not copy this vma on fork */ #define VM_DONTEXPAND 0x00040000 /* Cannot expand with mremap() */ #define VM_RESERVED 0x00080000 /* Don't unmap it from swap_out */ +#define VM_ACCOUNT 0x00100000 /* Is a VM accounted object */ -#define VM_STACK_FLAGS (0x00000100 | VM_DATA_DEFAULT_FLAGS) +#define VM_STACK_FLAGS (0x00000100 | VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT) #define VM_READHINTMASK (VM_SEQ_READ | VM_RAND_READ) #define VM_ClearReadHint(v) (v)->vm_flags &= ~VM_READHINTMASK @@ -149,12 +150,12 @@ * TODO: make this structure smaller, it could be as small as 32 bytes. */ struct page { + unsigned long flags; /* atomic flags, some possibly + updated asynchronously */ + atomic_t count; /* Usage count, see below. */ struct list_head list; /* ->mapping has some page lists. */ struct address_space *mapping; /* The inode (or ...) we belong to. */ unsigned long index; /* Our offset within mapping. */ - atomic_t count; /* Usage count, see below. */ - unsigned long flags; /* atomic flags, some possibly - updated asynchronously */ struct list_head lru; /* Pageout list, eg. active_list; protected by pagemap_lru_lock !! */ union { @@ -327,11 +328,10 @@ extern struct page *mem_map; extern void show_free_areas(void); -extern void show_free_areas_node(pg_data_t *pgdat); extern int fail_writepage(struct page *); struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int unused); -struct file *shmem_file_setup(char * name, loff_t size); +struct file *shmem_file_setup(char * name, loff_t size, unsigned long flags); extern void shmem_lock(struct file * file, int lock); extern int shmem_zero_setup(struct vm_area_struct *); @@ -401,8 +401,6 @@ extern int can_share_swap_page(struct page *); extern int remove_exclusive_swap_page(struct page *); -extern void __free_pte(pte_t); - /* mmap.c */ extern void lock_vma_mappings(struct vm_area_struct *); extern void unlock_vma_mappings(struct vm_area_struct *); @@ -472,31 +470,8 @@ void page_cache_readaround(struct file *file, unsigned long offset); void handle_ra_miss(struct file *file); -/* vma is the first one with address < vma->vm_end, - * and even address < vma->vm_start. Have to extend vma. */ -static inline int expand_stack(struct vm_area_struct * vma, unsigned long address) -{ - unsigned long grow; - - /* - * vma->vm_start/vm_end cannot change under us because the caller is required - * to hold the mmap_sem in write mode. We need to get the spinlock only - * before relocating the vma range ourself. - */ - address &= PAGE_MASK; - grow = (vma->vm_start - address) >> PAGE_SHIFT; - if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur || - ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur) - return -ENOMEM; - spin_lock(&vma->vm_mm->page_table_lock); - vma->vm_start = address; - vma->vm_pgoff -= grow; - vma->vm_mm->total_vm += grow; - if (vma->vm_flags & VM_LOCKED) - vma->vm_mm->locked_vm += grow; - spin_unlock(&vma->vm_mm->page_table_lock); - return 0; -} +/* Do stack extension */ +extern int expand_stack(struct vm_area_struct * vma, unsigned long address); /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ extern struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr); diff -Nru a/include/linux/mman.h b/include/linux/mman.h --- a/include/linux/mman.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/mman.h Thu Aug 1 14:17:36 2002 @@ -6,4 +6,7 @@ #define MREMAP_MAYMOVE 1 #define MREMAP_FIXED 2 +extern int vm_enough_memory(long pages); +extern void vm_unacct_memory(long pages); + #endif /* _LINUX_MMAN_H */ diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h --- a/include/linux/mmzone.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/mmzone.h Thu Aug 1 14:17:36 2002 @@ -136,7 +136,7 @@ unsigned long node_start_mapnr; unsigned long node_size; int node_id; - struct pglist_data *node_next; + struct pglist_data *pgdat_next; } pg_data_t; extern int numnodes; @@ -162,6 +162,57 @@ struct page *pmap); extern pg_data_t contig_page_data; + +/** + * for_each_pgdat - helper macro to iterate over all nodes + * @pgdat - pointer to a pg_data_t variable + * + * Meant to help with common loops of the form + * pgdat = pgdat_list; + * while(pgdat) { + * ... + * pgdat = pgdat->pgdat_next; + * } + */ +#define for_each_pgdat(pgdat) \ + for (pgdat = pgdat_list; pgdat; pgdat = pgdat->pgdat_next) + +/* + * next_zone - helper magic for for_each_zone() + * Thanks to William Lee Irwin III for this piece of ingenuity. + */ +static inline zone_t * next_zone(zone_t * zone) +{ + pg_data_t *pgdat = zone->zone_pgdat; + + if (zone - pgdat->node_zones < MAX_NR_ZONES - 1) + zone++; + else if (pgdat->pgdat_next) { + pgdat = pgdat->pgdat_next; + zone = pgdat->node_zones; + } else + zone = NULL; + + return zone; +} + +/** + * for_each_zone - helper macro to iterate over all memory zones + * @zone - pointer to zone_t variable + * + * The user only needs to declare the zone variable, for_each_zone + * fills it in. This basically means for_each_zone() is an + * easier to read version of this piece of code: + * + * for (pgdat = pgdat_list; pgdat; pgdat = pgdat->node_next) + * for (i = 0; i < MAX_NR_ZONES; ++i) { + * zone_t * z = pgdat->node_zones + i; + * ... + * } + * } + */ +#define for_each_zone(zone) \ + for (zone = pgdat_list->node_zones; zone; zone = next_zone(zone)) #ifndef CONFIG_DISCONTIGMEM diff -Nru a/include/linux/n_r3964.h b/include/linux/n_r3964.h --- a/include/linux/n_r3964.h Thu Aug 1 14:17:41 2002 +++ b/include/linux/n_r3964.h Thu Aug 1 14:17:41 2002 @@ -13,6 +13,12 @@ * L. Haag * * $Log: r3964.h,v $ + * Revision 1.3 2001/03/18 13:02:24 dwmw2 + * Fix timer usage, use spinlocks properly. + * + * Revision 1.2 2001/03/18 12:53:15 dwmw2 + * Merge changes in 2.4.2 + * * Revision 1.1.1.1 1998/10/13 16:43:14 dwmw2 * This'll screw the version control * @@ -103,8 +109,9 @@ struct r3964_message; struct r3964_client_info { + spinlock_t lock; pid_t pid; - unsigned int sig_flags; + unsigned int sig_flags; struct r3964_client_info *next; @@ -186,6 +193,7 @@ struct r3964_info { + spinlock_t lock; struct tty_struct *tty; unsigned char priority; unsigned char *rx_buf; /* ring buffer */ @@ -209,11 +217,8 @@ unsigned int state; unsigned int flags; - int count_down; - int nRetry; - - struct tq_struct bh_1; - struct tq_struct bh_2; + struct timer_list tmr; + int nRetry; }; #endif diff -Nru a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h --- a/include/linux/nfs_fs.h Thu Aug 1 14:17:40 2002 +++ b/include/linux/nfs_fs.h Thu Aug 1 14:17:40 2002 @@ -225,8 +225,15 @@ #define NFS_FILEID(inode) (NFS_I(inode)->fileid) -/* Inode Flags */ -#define NFS_USE_READDIRPLUS(inode) ((NFS_FLAGS(inode) & NFS_INO_ADVISE_RDPLUS) ? 1 : 0) +static inline int nfs_server_capable(struct inode *inode, int cap) +{ + return NFS_SERVER(inode)->caps & cap; +} + +static inline int NFS_USE_READDIRPLUS(struct inode *inode) +{ + return NFS_FLAGS(inode) & NFS_INO_ADVISE_RDPLUS; +} static inline loff_t page_offset(struct page *page) diff -Nru a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h --- a/include/linux/nfs_fs_sb.h Thu Aug 1 14:17:41 2002 +++ b/include/linux/nfs_fs_sb.h Thu Aug 1 14:17:41 2002 @@ -10,6 +10,7 @@ struct rpc_clnt * client; /* RPC client handle */ struct nfs_rpc_ops * rpc_ops; /* NFS protocol vector */ int flags; /* various flags */ + unsigned int caps; /* server capabilities */ unsigned int rsize; /* read size */ unsigned int rpages; /* read size (in pages) */ unsigned int wsize; /* write size */ @@ -30,5 +31,8 @@ struct nfs_fh fh; struct sockaddr_in addr; }; + +/* Server capabilities */ +#define NFS_CAP_READDIRPLUS (1) #endif diff -Nru a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h --- a/include/linux/nfs_xdr.h Thu Aug 1 14:17:39 2002 +++ b/include/linux/nfs_xdr.h Thu Aug 1 14:17:39 2002 @@ -27,6 +27,7 @@ __u64 atime; __u64 mtime; __u64 ctime; + unsigned long timestamp; }; #define NFS_ATTR_WCC 0x0001 /* pre-op WCC data */ @@ -109,8 +110,8 @@ const char * name; unsigned int len; int eof; - struct nfs_fh fh; - struct nfs_fattr fattr; + struct nfs_fh * fh; + struct nfs_fattr * fattr; }; /* diff -Nru a/include/linux/page-flags.h b/include/linux/page-flags.h --- a/include/linux/page-flags.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/page-flags.h Thu Aug 1 14:17:36 2002 @@ -79,8 +79,7 @@ unsigned long nr_active; /* on active_list LRU */ unsigned long nr_inactive; /* on inactive_list LRU */ unsigned long nr_page_table_pages; - unsigned long nr_pte_chain_pages; - unsigned long used_pte_chains_bytes; + unsigned long nr_reverse_maps; } ____cacheline_aligned_in_smp page_states[NR_CPUS]; extern void get_page_state(struct page_state *ret); @@ -241,16 +240,20 @@ * attempt to acquire the lock bit. */ preempt_disable(); +#ifdef CONFIG_SMP while (test_and_set_bit(PG_chainlock, &page->flags)) { while (test_bit(PG_chainlock, &page->flags)) cpu_relax(); } +#endif } static inline void pte_chain_unlock(struct page *page) { +#ifdef CONFIG_SMP smp_mb__before_clear_bit(); clear_bit(PG_chainlock, &page->flags); +#endif preempt_enable(); } diff -Nru a/include/linux/pci.h b/include/linux/pci.h --- a/include/linux/pci.h Thu Aug 1 14:17:40 2002 +++ b/include/linux/pci.h Thu Aug 1 14:17:40 2002 @@ -567,6 +567,10 @@ int pci_write_config_word(struct pci_dev *dev, int where, u16 val); int pci_write_config_dword(struct pci_dev *dev, int where, u32 val); +extern spinlock_t pci_lock; + +extern spinlock_t pci_lock; + int pci_enable_device(struct pci_dev *dev); void pci_disable_device(struct pci_dev *dev); void pci_set_master(struct pci_dev *dev); diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h --- a/include/linux/pci_ids.h Thu Aug 1 14:17:40 2002 +++ b/include/linux/pci_ids.h Thu Aug 1 14:17:40 2002 @@ -506,13 +506,18 @@ #define PCI_DEVICE_ID_HP_TACHLITE 0x1029 #define PCI_DEVICE_ID_HP_J2585A 0x1030 #define PCI_DEVICE_ID_HP_J2585B 0x1031 -#define PCI_DEVICE_ID_HP_SAS 0x1048 -#define PCI_DEVICE_ID_HP_DIVA1 0x1049 -#define PCI_DEVICE_ID_HP_DIVA2 0x104A -#define PCI_DEVICE_ID_HP_SP2_0 0x104B +#define PCI_DEVICE_ID_HP_DIVA 0x1048 +#define PCI_DEVICE_ID_HP_DIVA_TOSCA1 0x1049 +#define PCI_DEVICE_ID_HP_DIVA_TOSCA2 0x104A +#define PCI_DEVICE_ID_HP_DIVA_MAESTRO 0x104B +#define PCI_DEVICE_ID_HP_DIVA_HALFDOME 0x1223 +#define PCI_DEVICE_ID_HP_DIVA_KEYSTONE 0x1226 +#define PCI_DEVICE_ID_HP_DIVA_POWERBAR 0x1227 #define PCI_DEVICE_ID_HP_ZX1_SBA 0x1229 #define PCI_DEVICE_ID_HP_ZX1_IOC 0x122a #define PCI_DEVICE_ID_HP_ZX1_LBA 0x122e +#define PCI_DEVICE_ID_HP_DIVA_EVEREST 0x1282 +#define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290 #define PCI_VENDOR_ID_PCTECH 0x1042 #define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000 diff -Nru a/include/linux/rwsem-spinlock.h b/include/linux/rwsem-spinlock.h --- a/include/linux/rwsem-spinlock.h Thu Aug 1 14:17:40 2002 +++ b/include/linux/rwsem-spinlock.h Thu Aug 1 14:17:40 2002 @@ -54,9 +54,12 @@ extern void FASTCALL(init_rwsem(struct rw_semaphore *sem)); extern void FASTCALL(__down_read(struct rw_semaphore *sem)); +extern int FASTCALL(__down_read_trylock(struct rw_semaphore *sem)); extern void FASTCALL(__down_write(struct rw_semaphore *sem)); +extern int FASTCALL(__down_write_trylock(struct rw_semaphore *sem)); extern void FASTCALL(__up_read(struct rw_semaphore *sem)); extern void FASTCALL(__up_write(struct rw_semaphore *sem)); +extern void FASTCALL(__downgrade_write(struct rw_semaphore *sem)); #endif /* __KERNEL__ */ #endif /* _LINUX_RWSEM_SPINLOCK_H */ diff -Nru a/include/linux/rwsem.h b/include/linux/rwsem.h --- a/include/linux/rwsem.h Thu Aug 1 14:17:40 2002 +++ b/include/linux/rwsem.h Thu Aug 1 14:17:40 2002 @@ -46,6 +46,18 @@ } /* + * trylock for reading -- returns 1 if successful, 0 if contention + */ +static inline int down_read_trylock(struct rw_semaphore *sem) +{ + int ret; + rwsemtrace(sem,"Entering down_read_trylock"); + ret = __down_read_trylock(sem); + rwsemtrace(sem,"Leaving down_read_trylock"); + return ret; +} + +/* * lock for writing */ static inline void down_write(struct rw_semaphore *sem) @@ -56,6 +68,18 @@ } /* + * trylock for writing -- returns 1 if successful, 0 if contention + */ +static inline int down_write_trylock(struct rw_semaphore *sem) +{ + int ret; + rwsemtrace(sem,"Entering down_write_trylock"); + ret = __down_write_trylock(sem); + rwsemtrace(sem,"Leaving down_write_trylock"); + return ret; +} + +/* * release a read lock */ static inline void up_read(struct rw_semaphore *sem) @@ -84,7 +108,6 @@ __downgrade_write(sem); rwsemtrace(sem,"Leaving downgrade_write"); } - #endif /* __KERNEL__ */ #endif /* _LINUX_RWSEM_H */ diff -Nru a/include/linux/sched.h b/include/linux/sched.h --- a/include/linux/sched.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/sched.h Thu Aug 1 14:17:36 2002 @@ -393,7 +393,7 @@ #define PF_FREEZE 0x00010000 /* this task should be frozen for suspend */ #define PF_IOTHREAD 0x00020000 /* this thread is needed for doing I/O to swap */ #define PF_FROZEN 0x00040000 /* frozen for system suspend */ -#define PF_INVALIDATE 0x00080000 /* debug: unmounting an fs. killme. */ + /* * Ptrace flags */ diff -Nru a/include/linux/security.h b/include/linux/security.h --- a/include/linux/security.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/security.h Thu Aug 1 14:17:36 2002 @@ -407,7 +407,6 @@ * @file contains the file structure. * @cmd contains the posix-translated lock operation to perform * (e.g. F_RDLCK, F_WRLCK). - * @blocking indicates if the request is for a blocking lock. * Return 0 if permission is granted. * @file_fcntl: * Check permission before allowing the file operation specified by @cmd @@ -753,7 +752,7 @@ int (*file_mmap) (struct file * file, unsigned long prot, unsigned long flags); int (*file_mprotect) (struct vm_area_struct * vma, unsigned long prot); - int (*file_lock) (struct file * file, unsigned int cmd, int blocking); + int (*file_lock) (struct file * file, unsigned int cmd); int (*file_fcntl) (struct file * file, unsigned int cmd, unsigned long arg); int (*file_set_fowner) (struct file * file); diff -Nru a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h --- a/include/linux/shmem_fs.h Thu Aug 1 14:17:41 2002 +++ b/include/linux/shmem_fs.h Thu Aug 1 14:17:41 2002 @@ -16,7 +16,7 @@ swp_entry_t i_direct[SHMEM_NR_DIRECT]; /* for the first blocks */ void **i_indirect; /* indirect blocks */ unsigned long swapped; - int locked; /* into memory */ + unsigned long flags; struct list_head list; struct inode vfs_inode; }; diff -Nru a/include/linux/signal.h b/include/linux/signal.h --- a/include/linux/signal.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/signal.h Thu Aug 1 14:17:36 2002 @@ -221,6 +221,7 @@ extern long do_sigpending(void *, unsigned long); #ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER +struct pt_regs; extern int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs); #endif diff -Nru a/include/linux/slab.h b/include/linux/slab.h --- a/include/linux/slab.h Thu Aug 1 14:17:40 2002 +++ b/include/linux/slab.h Thu Aug 1 14:17:40 2002 @@ -57,6 +57,7 @@ extern int kmem_cache_shrink(kmem_cache_t *); extern void *kmem_cache_alloc(kmem_cache_t *, int); extern void kmem_cache_free(kmem_cache_t *, void *); +extern unsigned int kmem_cache_size(kmem_cache_t *); extern void *kmalloc(size_t, int); extern void kfree(const void *); diff -Nru a/include/linux/smp.h b/include/linux/smp.h --- a/include/linux/smp.h Thu Aug 1 14:17:40 2002 +++ b/include/linux/smp.h Thu Aug 1 14:17:40 2002 @@ -101,9 +101,13 @@ #define this_cpu(var) var /* Need to know about CPUs going up/down? */ -#define register_cpu_notifier(nb) 0 -#define unregister_cpu_notifier(nb) do { } while(0) - +static inline int register_cpu_notifier(struct notifier_block *nb) +{ + return 0; +} +static inline void unregister_cpu_notifier(struct notifier_block *nb) +{ +} #endif /* !SMP */ #define get_cpu() ({ preempt_disable(); smp_processor_id(); }) diff -Nru a/include/linux/swap.h b/include/linux/swap.h --- a/include/linux/swap.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/swap.h Thu Aug 1 14:17:36 2002 @@ -176,10 +176,7 @@ /* linux/mm/page_alloc.c */ /* linux/mm/swap_state.c */ -#define SWAP_CACHE_INFO -#ifdef SWAP_CACHE_INFO extern void show_swap_cache_info(void); -#endif extern int add_to_swap_cache(struct page *, swp_entry_t); extern int add_to_swap(struct page *); extern void __delete_from_swap_cache(struct page *page); diff -Nru a/include/linux/swapctl.h b/include/linux/swapctl.h --- a/include/linux/swapctl.h Thu Aug 1 14:17:36 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,13 +0,0 @@ -#ifndef _LINUX_SWAPCTL_H -#define _LINUX_SWAPCTL_H - -typedef struct pager_daemon_v1 -{ - unsigned int tries_base; - unsigned int tries_min; - unsigned int swap_cluster; -} pager_daemon_v1; -typedef pager_daemon_v1 pager_daemon_t; -extern pager_daemon_t pager_daemon; - -#endif /* _LINUX_SWAPCTL_H */ diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h --- a/include/linux/sysctl.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/sysctl.h Thu Aug 1 14:17:36 2002 @@ -136,12 +136,12 @@ VM_UNUSED1=1, /* was: struct: Set vm swapping control */ VM_UNUSED2=2, /* was; int: Linear or sqrt() swapout for hogs */ VM_UNUSED3=3, /* was: struct: Set free page thresholds */ - VM_BDFLUSH_UNUSED=4, /* Spare */ + VM_UNUSED4=4, /* Spare */ VM_OVERCOMMIT_MEMORY=5, /* Turn off the virtual memory safety limit */ - VM_UNUSED4=6, /* was: struct: Set buffer memory thresholds */ - VM_UNUSED5=7, /* was: struct: Set cache memory thresholds */ - VM_PAGERDAEMON=8, /* struct: Control kswapd behaviour */ - VM_UNUSED6=9, /* was: struct: Set page table cache parameters */ + VM_UNUSED5=6, /* was: struct: Set buffer memory thresholds */ + VM_UNUSED7=7, /* was: struct: Set cache memory thresholds */ + VM_UNUSED8=8, /* was: struct: Control kswapd behaviour */ + VM_UNUSED9=9, /* was: struct: Set page table cache parameters */ VM_PAGE_CLUSTER=10, /* int: set number of pages to swap together */ VM_DIRTY_BACKGROUND=11, /* dirty_background_ratio */ VM_DIRTY_ASYNC=12, /* dirty_async_ratio */ @@ -149,6 +149,7 @@ VM_DIRTY_WB_CS=14, /* dirty_writeback_centisecs */ VM_DIRTY_EXPIRE_CS=15, /* dirty_expire_centisecs */ VM_NR_PDFLUSH_THREADS=16, /* nr_pdflush_threads */ + VM_OVERCOMMIT_RATIO=17, /* percent of RAM to allow overcommit in */ }; @@ -171,7 +172,6 @@ NET_TR=14, NET_DECNET=15, NET_ECONET=16, - NET_KHTTPD=17 }; /* /proc/sys/kernel/random */ @@ -491,23 +491,6 @@ NET_DECNET_CONF = 10, NET_DECNET_NO_FC_MAX_CWND = 11, NET_DECNET_DEBUG_LEVEL = 255 -}; - -/* /proc/sys/net/khttpd/ */ -enum { - NET_KHTTPD_DOCROOT = 1, - NET_KHTTPD_START = 2, - NET_KHTTPD_STOP = 3, - NET_KHTTPD_UNLOAD = 4, - NET_KHTTPD_CLIENTPORT = 5, - NET_KHTTPD_PERMREQ = 6, - NET_KHTTPD_PERMFORBID = 7, - NET_KHTTPD_LOGGING = 8, - NET_KHTTPD_SERVERPORT = 9, - NET_KHTTPD_DYNAMICSTRING= 10, - NET_KHTTPD_SLOPPYMIME = 11, - NET_KHTTPD_THREADS = 12, - NET_KHTTPD_MAXCONNECT = 13 }; /* /proc/sys/net/decnet/conf/ */ diff -Nru a/include/linux/timer.h b/include/linux/timer.h --- a/include/linux/timer.h Thu Aug 1 14:17:36 2002 +++ b/include/linux/timer.h Thu Aug 1 14:17:36 2002 @@ -2,6 +2,7 @@ #define _LINUX_TIMER_H #include +#include #include /* diff -Nru a/init/do_mounts.c b/init/do_mounts.c --- a/init/do_mounts.c Thu Aug 1 14:17:40 2002 +++ b/init/do_mounts.c Thu Aug 1 14:17:40 2002 @@ -356,11 +356,12 @@ if (!do_devfs) return sys_mknod(name, S_IFBLK|0600, dev); - handle = devfs_find_handle(NULL, !dev ? devfs_name : NULL, - MAJOR(dev), MINOR(dev), DEVFS_SPECIAL_BLK, 1); + handle = devfs_get_handle(NULL, !dev ? devfs_name : NULL, + MAJOR(dev), MINOR(dev), DEVFS_SPECIAL_BLK, 1); if (!handle) return -1; n = devfs_generate_path(handle, path + 5, sizeof (path) - 5); + devfs_put(handle); if (n < 0) return -1; return sys_symlink(path + n + 5, name); diff -Nru a/init/main.c b/init/main.c --- a/init/main.c Thu Aug 1 14:17:36 2002 +++ b/init/main.c Thu Aug 1 14:17:36 2002 @@ -70,7 +70,7 @@ extern void sysctl_init(void); extern void signals_init(void); extern void buffer_init(void); - +extern void pte_chain_init(void); extern void radix_tree_init(void); extern void free_initmem(void); @@ -432,7 +432,7 @@ mem_init(); kmem_cache_sizes_init(); pgtable_cache_init(); - + pte_chain_init(); mempages = num_physpages; fork_init(mempages); @@ -524,6 +524,17 @@ do_initcalls(); } +static void do_pre_smp_initcalls(void) +{ + extern int spawn_ksoftirqd(void); +#ifdef CONFIG_SMP + extern int migration_init(void); + + migration_init(); +#endif + spawn_ksoftirqd(); +} + extern void prepare_namespace(void); static int init(void * unused) @@ -533,6 +544,9 @@ lock_kernel(); /* Sets up cpus_possible() */ smp_prepare_cpus(max_cpus); + + do_pre_smp_initcalls(); + smp_init(); do_basic_setup(); diff -Nru a/ipc/shm.c b/ipc/shm.c --- a/ipc/shm.c Thu Aug 1 14:17:40 2002 +++ b/ipc/shm.c Thu Aug 1 14:17:40 2002 @@ -186,7 +186,7 @@ shp->shm_flags = (shmflg & S_IRWXUGO); sprintf (name, "SYSV%08x", key); - file = shmem_file_setup(name, size); + file = shmem_file_setup(name, size, VM_ACCOUNT); error = PTR_ERR(file); if (IS_ERR(file)) goto no_file; diff -Nru a/kernel/fork.c b/kernel/fork.c --- a/kernel/fork.c Thu Aug 1 14:17:36 2002 +++ b/kernel/fork.c Thu Aug 1 14:17:36 2002 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -181,6 +182,7 @@ { struct vm_area_struct * mpnt, *tmp, **pprev; int retval; + unsigned long charge = 0; flush_cache_mm(current->mm); mm->locked_vm = 0; @@ -208,6 +210,12 @@ retval = -ENOMEM; if(mpnt->vm_flags & VM_DONTCOPY) continue; + if (mpnt->vm_flags & VM_ACCOUNT) { + unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; + if (!vm_enough_memory(len)) + goto fail_nomem; + charge += len; + } tmp = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); if (!tmp) goto fail_nomem; @@ -248,9 +256,12 @@ retval = 0; build_mmap_rb(mm); -fail_nomem: +out: flush_tlb_mm(current->mm); return retval; +fail_nomem: + vm_unacct_memory(charge); + goto out; } spinlock_t mmlist_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; @@ -597,22 +608,20 @@ } /* - * Ok, this is the main fork-routine. It copies the system process - * information (task[nr]) and sets up the necessary registers. It also - * copies the data segment in its entirety. The "stack_start" and - * "stack_top" arguments are simply passed along to the platform - * specific copy_thread() routine. Most platforms ignore stack_top. - * For an example that's using stack_top, see - * arch/ia64/kernel/process.c. + * This creates a new process as a copy of the old one, + * but does not actually start it yet. + * + * It copies the registers, and all the appropriate + * parts of the process environment (as per the clone + * flags). The actual kick-off is left to the caller. */ -struct task_struct *do_fork(unsigned long clone_flags, +static struct task_struct *copy_process(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size) { int retval; struct task_struct *p = NULL; - struct completion vfork; if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) return ERR_PTR(-EINVAL); @@ -669,10 +678,6 @@ INIT_LIST_HEAD(&p->sibling); init_waitqueue_head(&p->wait_chldexit); p->vfork_done = NULL; - if (clone_flags & CLONE_VFORK) { - p->vfork_done = &vfork; - init_completion(&vfork); - } spin_lock_init(&p->alloc_lock); spin_lock_init(&p->switch_lock); @@ -792,20 +797,6 @@ hash_pid(p); nr_threads++; write_unlock_irq(&tasklist_lock); - - if (p->ptrace & PT_PTRACED) - send_sig(SIGSTOP, p, 1); - - wake_up_forked_process(p); /* do this last */ - ++total_forks; - if (clone_flags & CLONE_VFORK) - wait_for_completion(&vfork); - else - /* - * Let the child process run first, to avoid most of the - * COW overhead when the child exec()s afterwards. - */ - set_need_resched(); retval = 0; fork_out: @@ -837,6 +828,45 @@ bad_fork_free: put_task_struct(p); goto fork_out; +} + +/* + * Ok, this is the main fork-routine. + * + * It copies the process, and if successful kick-starts + * it and waits for it to finish using the VM if required. + */ +struct task_struct *do_fork(unsigned long clone_flags, + unsigned long stack_start, + struct pt_regs *regs, + unsigned long stack_size) +{ + struct task_struct *p; + + p = copy_process(clone_flags, stack_start, regs, stack_size); + if (!IS_ERR(p)) { + struct completion vfork; + + if (clone_flags & CLONE_VFORK) { + p->vfork_done = &vfork; + init_completion(&vfork); + } + + if (p->ptrace & PT_PTRACED) + send_sig(SIGSTOP, p, 1); + + wake_up_forked_process(p); /* do this last */ + ++total_forks; + if (clone_flags & CLONE_VFORK) + wait_for_completion(&vfork); + else + /* + * Let the child process run first, to avoid most of the + * COW overhead when the child exec()s afterwards. + */ + set_need_resched(); + } + return p; } /* SLAB cache for signal_struct structures (tsk->sig) */ diff -Nru a/kernel/futex.c b/kernel/futex.c --- a/kernel/futex.c Thu Aug 1 14:17:39 2002 +++ b/kernel/futex.c Thu Aug 1 14:17:39 2002 @@ -245,8 +245,8 @@ } static struct file_operations futex_fops = { - release: futex_close, - poll: futex_poll, + .release = futex_close, + .poll = futex_poll, }; /* Signal allows caller to avoid the race which would occur if they @@ -357,8 +357,8 @@ } static struct file_system_type futex_fs_type = { - name: "futexfs", - get_sb: futexfs_get_sb, + .name = "futexfs", + .get_sb = futexfs_get_sb, }; static int __init init(void) diff -Nru a/kernel/kmod.c b/kernel/kmod.c --- a/kernel/kmod.c Thu Aug 1 14:17:39 2002 +++ b/kernel/kmod.c Thu Aug 1 14:17:39 2002 @@ -346,15 +346,15 @@ { DECLARE_COMPLETION(work); struct subprocess_info sub_info = { - complete: &work, - path: path, - argv: argv, - envp: envp, - retval: 0, + .complete = &work, + .path = path, + .argv = argv, + .envp = envp, + .retval = 0, }; struct tq_struct tqs = { - routine: __call_usermodehelper, - data: &sub_info, + .routine = __call_usermodehelper, + .data = &sub_info, }; if (path[0] == '\0') diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c --- a/kernel/ksyms.c Thu Aug 1 14:17:36 2002 +++ b/kernel/ksyms.c Thu Aug 1 14:17:36 2002 @@ -105,6 +105,7 @@ EXPORT_SYMBOL(kmem_cache_shrink); EXPORT_SYMBOL(kmem_cache_alloc); EXPORT_SYMBOL(kmem_cache_free); +EXPORT_SYMBOL(kmem_cache_size); EXPORT_SYMBOL(kmalloc); EXPORT_SYMBOL(kfree); EXPORT_SYMBOL(vfree); @@ -218,6 +219,7 @@ EXPORT_SYMBOL(block_truncate_page); EXPORT_SYMBOL(generic_block_bmap); EXPORT_SYMBOL(generic_file_read); +EXPORT_SYMBOL(generic_file_sendfile); EXPORT_SYMBOL(do_generic_file_read); EXPORT_SYMBOL(generic_file_write); EXPORT_SYMBOL(generic_file_mmap); @@ -340,6 +342,7 @@ EXPORT_SYMBOL(read_dev_sector); EXPORT_SYMBOL(init_buffer); EXPORT_SYMBOL(wipe_partitions); +EXPORT_SYMBOL(generic_file_direct_IO); /* tty routines */ EXPORT_SYMBOL(tty_hangup); diff -Nru a/kernel/module.c b/kernel/module.c --- a/kernel/module.c Thu Aug 1 14:17:36 2002 +++ b/kernel/module.c Thu Aug 1 14:17:36 2002 @@ -44,15 +44,15 @@ struct module kernel_module = { - size_of_struct: sizeof(struct module), - name: "", - uc: {ATOMIC_INIT(1)}, - flags: MOD_RUNNING, - syms: __start___ksymtab, - ex_table_start: __start___ex_table, - ex_table_end: __stop___ex_table, - kallsyms_start: __start___kallsyms, - kallsyms_end: __stop___kallsyms, + .size_of_struct = sizeof(struct module), + .name = "", + .uc = {ATOMIC_INIT(1)}, + .flags = MOD_RUNNING, + .syms = __start___ksymtab, + .ex_table_start = __start___ex_table, + .ex_table_end = __stop___ex_table, + .kallsyms_start = __start___kallsyms, + .kallsyms_end = __stop___kallsyms, }; struct module *module_list = &kernel_module; @@ -1132,10 +1132,10 @@ return 0; } struct seq_operations modules_op = { - start: m_start, - next: m_next, - stop: m_stop, - show: m_show + .start = m_start, + .next = m_next, + .stop = m_stop, + .show = m_show }; /* @@ -1214,10 +1214,10 @@ } struct seq_operations ksyms_op = { - start: s_start, - next: s_next, - stop: s_stop, - show: s_show + .start = s_start, + .next = s_next, + .stop = s_stop, + .show = s_show }; #else /* CONFIG_MODULES */ diff -Nru a/kernel/platform.c b/kernel/platform.c --- a/kernel/platform.c Thu Aug 1 14:17:40 2002 +++ b/kernel/platform.c Thu Aug 1 14:17:40 2002 @@ -23,13 +23,13 @@ } static struct platform_t default_platform = { - name: "Default Platform", - suspend_states: 0, - reboot: default_reboot, - halt: default_halt, - power_off: default_halt, - suspend: default_suspend, - idle: default_idle, + .name = "Default Platform", + .suspend_states = 0, + .reboot = default_reboot, + .halt = default_halt, + .power_off = default_halt, + .suspend = default_suspend, + .idle = default_idle, }; struct platform_t * platform = &default_platform; diff -Nru a/kernel/ptrace.c b/kernel/ptrace.c --- a/kernel/ptrace.c Thu Aug 1 14:17:41 2002 +++ b/kernel/ptrace.c Thu Aug 1 14:17:41 2002 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -156,7 +157,7 @@ flush_page_to_ram(page); } kunmap(page); - put_page(page); + page_cache_release(page); len -= bytes; buf += bytes; addr += bytes; diff -Nru a/kernel/sched.c b/kernel/sched.c --- a/kernel/sched.c Thu Aug 1 14:17:39 2002 +++ b/kernel/sched.c Thu Aug 1 14:17:39 2002 @@ -107,9 +107,9 @@ * BASE_TIMESLICE scales user-nice values [ -20 ... 19 ] * to time slice values. * - * The higher a process's priority, the bigger timeslices + * The higher a thread's priority, the bigger timeslices * it gets during one round of execution. But even the lowest - * priority process gets MIN_TIMESLICE worth of execution time. + * priority thread gets MIN_TIMESLICE worth of execution time. * * task_timeslice() is the interface that is used by the scheduler. */ @@ -140,7 +140,7 @@ * This is the main, per-CPU runqueue data structure. * * Locking rule: those places that want to lock multiple runqueues - * (such as the load balancing or the process migration code), lock + * (such as the load balancing or the thread migration code), lock * acquire operations must be ordered by ascending &runqueue. */ struct runqueue { @@ -237,21 +237,24 @@ p->array = array; } +/* + * effective_prio - return the priority that is based on the static + * priority but is modified by bonuses/penalties. + * + * We scale the actual sleep average [0 .... MAX_SLEEP_AVG] + * into the -5 ... 0 ... +5 bonus/penalty range. + * + * We use 25% of the full 0...39 priority range so that: + * + * 1) nice +19 interactive tasks do not preempt nice 0 CPU hogs. + * 2) nice -20 CPU hogs do not get preempted by nice 0 tasks. + * + * Both properties are important to certain workloads. + */ static inline int effective_prio(task_t *p) { int bonus, prio; - /* - * Here we scale the actual sleep average [0 .... MAX_SLEEP_AVG] - * into the -5 ... 0 ... +5 bonus/penalty range. - * - * We use 25% of the full 0...39 priority range so that: - * - * 1) nice +19 interactive tasks do not preempt nice 0 CPU hogs. - * 2) nice -20 CPU hogs do not get preempted by nice 0 tasks. - * - * Both properties are important to certain workloads. - */ bonus = MAX_USER_PRIO*PRIO_BONUS_RATIO*p->sleep_avg/MAX_SLEEP_AVG/100 - MAX_USER_PRIO*PRIO_BONUS_RATIO/100/2; @@ -263,6 +266,12 @@ return prio; } +/* + * activate_task - move a task to the runqueue. + + * Also update all the scheduling statistics stuff. (sleep average + * calculation, priority modifiers, etc.) + */ static inline void activate_task(task_t *p, runqueue_t *rq) { unsigned long sleep_time = jiffies - p->sleep_timestamp; @@ -285,6 +294,9 @@ rq->nr_running++; } +/* + * deactivate_task - remove a task from the runqueue. + */ static inline void deactivate_task(struct task_struct *p, runqueue_t *rq) { rq->nr_running--; @@ -294,6 +306,13 @@ p->array = NULL; } +/* + * resched_task - mark a task 'to be rescheduled now'. + * + * On UP this means the setting of the need_resched flag, on SMP it + * might also involve a cross-CPU call to trigger the scheduler on + * the target CPU. + */ static inline void resched_task(task_t *p) { #ifdef CONFIG_SMP @@ -316,8 +335,10 @@ #ifdef CONFIG_SMP /* - * Wait for a process to unschedule. This is used by the exit() and - * ptrace() code. + * wait_task_inactive - wait for a thread to unschedule. + * + * The caller must ensure that the task *will* unschedule sometime soon, + * else this function might spin for a *long* time. */ void wait_task_inactive(task_t * p) { @@ -349,9 +370,10 @@ #endif /* - * Kick the remote CPU if the task is running currently, - * this code is used by the signal code to signal tasks - * which are in user-mode as quickly as possible. + * kick_if_running - kick the remote CPU if the task is running currently. + * + * This code is used by the signal code to signal tasks + * which are in user-mode, as quickly as possible. * * (Note that we do this lockless - if the task does anything * while the message is in flight then it will notice the @@ -363,13 +385,16 @@ resched_task(p); } -/* - * Wake up a process. Put it on the run-queue if it's not - * already there. The "current" process is always on the - * run-queue (except when the actual re-schedule is in - * progress), and as such you're allowed to do the simpler - * "current->state = TASK_RUNNING" to mark yourself runnable - * without the overhead of this. +/*** + * try_to_wake_up - wake up a thread + * @p: the to-be-woken-up thread + * @sync: do a synchronous wakeup? + * + * Put it on the run-queue if it's not already there. The "current" + * thread is always on the run-queue (except when the actual + * re-schedule is in progress), and as such you're allowed to do + * the simpler "current->state = TASK_RUNNING" to mark yourself + * runnable without the overhead of this. * * returns failure only if the task is already active. */ @@ -415,6 +440,12 @@ return try_to_wake_up(p, 0); } +/* + * wake_up_forked_process - wake up a freshly forked process. + * + * This function will do some initial scheduler statistics housekeeping + * that must be done for every newly created process. + */ void wake_up_forked_process(task_t * p) { runqueue_t *rq = this_rq_lock(); @@ -439,7 +470,7 @@ /* * Potentially available exiting-child timeslices are * retrieved here - this way the parent does not get - * penalized for creating too many processes. + * penalized for creating too many threads. * * (this cannot be used to 'generate' timeslices * artificially, because any timeslice recovered here @@ -463,6 +494,10 @@ p->sleep_avg) / (EXIT_WEIGHT + 1); } +/** + * schedule_tail - first thing a freshly forked thread must call. + * @prev: the thread we just switched away from. + */ #if CONFIG_SMP || CONFIG_PREEMPT asmlinkage void schedule_tail(task_t *prev) { @@ -470,6 +505,10 @@ } #endif +/* + * context_switch - switch to the new MM and the new + * thread's register state. + */ static inline task_t * context_switch(task_t *prev, task_t *next) { struct mm_struct *mm = next->mm; @@ -493,6 +532,13 @@ return prev; } +/* + * nr_running, nr_uninterruptible and nr_context_switches: + * + * externally visible scheduler statistics: current number of runnable + * threads, current number of uninterruptible-sleeping threads, total + * number of context switches performed since bootup. + */ unsigned long nr_running(void) { unsigned long i, sum = 0; @@ -560,8 +606,10 @@ #if CONFIG_SMP /* - * Lock the busiest runqueue as well, this_rq is locked already. - * Recalculate nr_running if we have to drop the runqueue lock. + * double_lock_balance - lock the busiest runqueue + * + * this_rq is locked already. Recalculate nr_running if we have to + * drop the runqueue lock. */ static inline unsigned int double_lock_balance(runqueue_t *this_rq, runqueue_t *busiest, int this_cpu, int idle, unsigned int nr_running) @@ -582,6 +630,9 @@ return nr_running; } +/* + * find_busiest_queue - find the busiest runqueue. + */ static inline runqueue_t *find_busiest_queue(runqueue_t *this_rq, int this_cpu, int idle, int *imbalance) { int nr_running, load, max_load, i; @@ -658,7 +709,7 @@ } /* - * Move a task from a remote runqueue to the local runqueue. + * pull_task - move a task from a remote runqueue to the local runqueue. * Both runqueues must be locked. */ static inline void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p, runqueue_t *this_rq, int this_cpu) @@ -762,8 +813,8 @@ } /* - * One of the idle_cpu_tick() or the busy_cpu_tick() function will - * gets called every timer tick, on every CPU. Our balancing action + * One of the idle_cpu_tick() and busy_cpu_tick() functions will + * get called every timer tick, on every CPU. Our balancing action * frequency and balancing agressivity depends on whether the CPU is * idle or not. * @@ -848,7 +899,7 @@ /* * The task was running during this tick - update the * time slice counter and the sleep average. Note: we - * do not update a process's priority until it either + * do not update a thread's priority until it either * goes to sleep or uses up its timeslice. This makes * it possible for interactive tasks to use up their * timeslices at their highest priority levels. @@ -880,7 +931,7 @@ void scheduling_functions_start_here(void) { } /* - * 'schedule()' is the main scheduler function. + * schedule() is the main scheduler function. */ asmlinkage void schedule(void) { @@ -1034,6 +1085,12 @@ } } +/** + * __wake_up - wake up threads blocked on a waitqueue. + * @q: the waitqueue + * @mode: which threads + * @nr_exclusive: how many wake-one or wake-many threads to wake up + */ void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive) { unsigned long flags; @@ -1056,6 +1113,17 @@ #if CONFIG_SMP +/** + * __wake_up - sync- wake up threads blocked on a waitqueue. + * @q: the waitqueue + * @mode: which threads + * @nr_exclusive: how many wake-one or wake-many threads to wake up + * + * The sync wakeup differs that the waker knows that it will schedule + * away soon, so while the target thread will be woken up, it will not + * be migrated to another CPU - ie. the two threads are 'synchronized' + * with each other. This can prevent needless bouncing between CPUs. + */ void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive) { unsigned long flags; @@ -1207,11 +1275,12 @@ #ifndef __alpha__ /* - * This has been replaced by sys_setpriority. Maybe it should be - * moved into the arch dependent tree for those ports that require - * it for backward compatibility? + * sys_nice - change the priority of the current process. + * @increment: priority increment + * + * sys_setpriority is a more generic, but much slower function that + * does similar things. */ - asmlinkage long sys_nice(int increment) { int retval; @@ -1247,9 +1316,11 @@ #endif -/* - * This is the priority value as seen by users in /proc +/** + * task_prio - return the priority value of a given task. + * @p: the task in question. * + * This is the priority value as seen by users in /proc. * RT tasks are offset by -200. Normal tasks are centered * around 0, value goes from -16 to +15. */ @@ -1258,21 +1329,36 @@ return p->prio - MAX_USER_RT_PRIO; } +/** + * task_nice - return the nice value of a given task. + * @p: the task in question. + */ int task_nice(task_t *p) { return TASK_NICE(p); } +/** + * idle_cpu - is a given cpu idle currently? + * @cpu: the processor in question. + */ int idle_cpu(int cpu) { return cpu_curr(cpu) == cpu_rq(cpu)->idle; } +/** + * find_process_by_pid - find a process with a matching PID value. + * @pid: the pid in question. + */ static inline task_t *find_process_by_pid(pid_t pid) { return pid ? find_task_by_pid(pid) : current; } +/* + * setscheduler - change the scheduling policy and/or RT priority of a thread. + */ static int setscheduler(pid_t pid, int policy, struct sched_param *param) { struct sched_param lp; @@ -1359,17 +1445,32 @@ return retval; } +/** + * sys_sched_setscheduler - set/change the scheduler policy and RT priority + * @pid: the pid in question. + * @policy: new policy + * @param: structure containing the new RT priority. + */ asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, struct sched_param *param) { return setscheduler(pid, policy, param); } +/** + * sys_sched_setparam - set/change the RT priority of a thread + * @pid: the pid in question. + * @param: structure containing the new RT priority. + */ asmlinkage long sys_sched_setparam(pid_t pid, struct sched_param *param) { return setscheduler(pid, -1, param); } +/** + * sys_sched_getscheduler - get the policy (scheduling class) of a thread + * @pid: the pid in question. + */ asmlinkage long sys_sched_getscheduler(pid_t pid) { int retval = -EINVAL; @@ -1392,6 +1493,11 @@ return retval; } +/** + * sys_sched_getscheduler - get the RT priority of a thread + * @pid: the pid in question. + * @param: structure containing the RT priority. + */ asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param *param) { struct sched_param lp; @@ -1516,6 +1622,13 @@ return real_len; } +/** + * sys_sched_yield - yield the current processor to other threads. + * + * this function yields the current CPU by moving the calling thread + * to the expired array. If there are no other threads running on this + * CPU then this function will return. + */ asmlinkage long sys_sched_yield(void) { runqueue_t *rq = this_rq_lock(); @@ -1553,12 +1666,25 @@ schedule(); } +/** + * yield - yield the current processor to other threads. + * + * this is a shortcut for kernel-space yielding - it marks the + * thread runnable and calls sys_sched_yield(). + */ void yield(void) { set_current_state(TASK_RUNNING); sys_sched_yield(); } +/** + * sys_sched_get_priority_max - return maximum RT priority. + * @policy: scheduling class. + * + * this syscall returns the maximum rt_priority that can be used + * by a given scheduling class. + */ asmlinkage long sys_sched_get_priority_max(int policy) { int ret = -EINVAL; @@ -1575,6 +1701,13 @@ return ret; } +/** + * sys_sched_get_priority_mix - return minimum RT priority. + * @policy: scheduling class. + * + * this syscall returns the minimum rt_priority that can be used + * by a given scheduling class. + */ asmlinkage long sys_sched_get_priority_min(int policy) { int ret = -EINVAL; @@ -1590,6 +1723,14 @@ return ret; } +/** + * sys_sched_rr_get_interval - return the default timeslice of a process. + * @pid: pid of the process. + * @interval: userspace pointer to the timeslice value. + * + * this syscall writes the default timeslice value of a given process + * into the user-space timespec buffer. A value of '0' means infinity. + */ asmlinkage long sys_sched_rr_get_interval(pid_t pid, struct timespec *interval) { int retval = -EINVAL; @@ -1765,7 +1906,7 @@ } migration_req_t; /* - * Change a given task's CPU affinity. Migrate the process to a + * Change a given task's CPU affinity. Migrate the thread to a * proper CPU and schedule it away if the CPU it's executing on * is removed from the allowed bitmask. * @@ -1790,7 +1931,7 @@ p->cpus_allowed = new_mask; /* * Can the task run on the task's current CPU? If not then - * migrate the process off to a proper CPU. + * migrate the thread off to a proper CPU. */ if (new_mask & (1UL << task_cpu(p))) { task_rq_unlock(rq, &flags); @@ -1816,10 +1957,14 @@ preempt_enable(); } -static int migration_thread(void * bind_cpu) +/* + * migration_thread - this is a highprio system thread that performs + * thread migration by 'pulling' threads into the target runqueue. + */ +static int migration_thread(void * data) { - int cpu = (int) (long) bind_cpu; - struct sched_param param = { sched_priority: MAX_RT_PRIO-1 }; + struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; + int cpu = (long) data; runqueue_t *rq; int ret; @@ -1828,6 +1973,14 @@ set_fs(KERNEL_DS); set_cpus_allowed(current, 1UL << cpu); + + /* + * Migration can happen without a migration thread on the + * target CPU because here we remove the thread from the + * runqueue and the helper thread then moves this thread + * to the target CPU - we'll wake up there. + */ + if (smp_processor_id() != cpu) printk("migration_task %d on cpu=%d\n", cpu, smp_processor_id()); ret = setscheduler(0, SCHED_FIFO, ¶m); @@ -1884,6 +2037,10 @@ } } +/* + * migration_call - callback that gets triggered when a CPU is added. + * Here we can start up the necessary migration thread for the new CPU. + */ static int migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) @@ -1894,6 +2051,8 @@ (long)hcpu); kernel_thread(migration_thread, hcpu, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); + while (!cpu_rq((long)hcpu)->migration_thread) + yield(); break; } return NOTIFY_OK; @@ -1901,7 +2060,7 @@ static struct notifier_block migration_notifier = { &migration_call, NULL, 0 }; -int __init migration_init(void) +__init int migration_init(void) { /* Start one for boot CPU. */ migration_call(&migration_notifier, CPU_ONLINE, @@ -1910,7 +2069,6 @@ return 0; } -__initcall(migration_init); #endif extern void init_timervecs(void); @@ -1944,7 +2102,7 @@ } /* * We have to do a little magic to get the first - * process right in SMP mode. + * thread right in SMP mode. */ rq = this_rq(); rq->curr = current; diff -Nru a/kernel/softirq.c b/kernel/softirq.c --- a/kernel/softirq.c Thu Aug 1 14:17:39 2002 +++ b/kernel/softirq.c Thu Aug 1 14:17:39 2002 @@ -410,11 +410,9 @@ static struct notifier_block cpu_nfb = { &cpu_callback, NULL, 0 }; -static __init int spawn_ksoftirqd(void) +__init int spawn_ksoftirqd(void) { cpu_callback(&cpu_nfb, CPU_ONLINE, (void *)smp_processor_id()); register_cpu_notifier(&cpu_nfb); return 0; } - -__initcall(spawn_ksoftirqd); diff -Nru a/kernel/suspend.c b/kernel/suspend.c --- a/kernel/suspend.c Thu Aug 1 14:17:39 2002 +++ b/kernel/suspend.c Thu Aug 1 14:17:39 2002 @@ -36,7 +36,6 @@ #include #include -#include #include #include #include @@ -66,6 +65,7 @@ #include extern void signal_wake_up(struct task_struct *t); +extern int sys_sync(void); unsigned char software_suspend_enabled = 0; @@ -815,17 +815,17 @@ PRINTK(KERN_WARNING "%sLeaving do_magic_suspend_2...\n", name_suspend); } -/* - * We try to swap out as much as we can then make a copy of the - * occupied pages in memory so we can make a copy of kernel state - * atomically, the I/O needed by saving won't bother us anymore. - */ void do_software_suspend(void) { arch_prepare_suspend(); if (prepare_suspend_console()) printk( "%sCan't allocate a console... proceeding\n", name_suspend); if (!prepare_suspend_processes()) { + + /* At this point, all user processes and "dangerous" + kernel threads are stopped. Free some memory, as we + need half of memory free. */ + free_some_memory(); /* No need to invalidate any vfsmnt list -- they will be valid after resume, anyway. @@ -835,8 +835,19 @@ */ PRINTK("Syncing disks before copy\n"); do_suspend_sync(); + + /* Save state of all device drivers, and stop them. */ if(drivers_suspend()==0) - do_magic(0); /* This function returns after machine woken up from resume */ + /* If stopping device drivers worked, we proceed basically into + * suspend_save_image. + * + * do_magic(0) returns after system is resumed. + * + * do_magic() copies all "used" memory to "free" memory, then + * unsuspends all device drivers, and writes memory to disk + * using normal kernel mechanism. + */ + do_magic(0); PRINTK("Restarting processes...\n"); thaw_processes(); } @@ -1004,8 +1015,8 @@ static int bdev_write_page(struct block_device *bdev, long pos, void *buf) { - struct buffer_head *bh; #if 0 + struct buffer_head *bh; BUG_ON (pos%PAGE_SIZE); bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE); if (!bh || (!bh->b_data)) { diff -Nru a/kernel/sys.c b/kernel/sys.c --- a/kernel/sys.c Thu Aug 1 14:17:36 2002 +++ b/kernel/sys.c Thu Aug 1 14:17:36 2002 @@ -391,7 +391,7 @@ void ctrl_alt_del(void) { static struct tq_struct cad_tq = { - routine: deferred_cad, + .routine = deferred_cad, }; if (C_A_D) diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c --- a/kernel/sysctl.c Thu Aug 1 14:17:36 2002 +++ b/kernel/sysctl.c Thu Aug 1 14:17:36 2002 @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -45,6 +44,7 @@ extern int panic_timeout; extern int C_A_D; extern int sysctl_overcommit_memory; +extern int sysctl_overcommit_ratio; extern int max_threads; extern atomic_t nr_queued_signals; extern int max_queued_signals; @@ -126,12 +126,12 @@ static int proc_sys_permission(struct inode *, int); struct file_operations proc_sys_file_operations = { - read: proc_readsys, - write: proc_writesys, + .read = proc_readsys, + .write = proc_writesys, }; static struct inode_operations proc_sys_inode_operations = { - permission: proc_sys_permission, + .permission = proc_sys_permission, }; extern struct proc_dir_entry *proc_sys_root; @@ -268,8 +268,9 @@ static ctl_table vm_table[] = { {VM_OVERCOMMIT_MEMORY, "overcommit_memory", &sysctl_overcommit_memory, sizeof(sysctl_overcommit_memory), 0644, NULL, &proc_dointvec}, - {VM_PAGERDAEMON, "kswapd", - &pager_daemon, sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec}, + {VM_OVERCOMMIT_RATIO, "overcommit_ratio", + &sysctl_overcommit_ratio, sizeof(sysctl_overcommit_ratio), 0644, + NULL, &proc_dointvec}, {VM_PAGE_CLUSTER, "page-cluster", &page_cluster, sizeof(int), 0644, NULL, &proc_dointvec}, {VM_DIRTY_BACKGROUND, "dirty_background_ratio", diff -Nru a/kernel/user.c b/kernel/user.c --- a/kernel/user.c Thu Aug 1 14:17:40 2002 +++ b/kernel/user.c Thu Aug 1 14:17:40 2002 @@ -28,9 +28,9 @@ static spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED; struct user_struct root_user = { - __count: ATOMIC_INIT(1), - processes: ATOMIC_INIT(1), - files: ATOMIC_INIT(0) + .__count = ATOMIC_INIT(1), + .processes = ATOMIC_INIT(1), + .files = ATOMIC_INIT(0) }; /* diff -Nru a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c --- a/lib/rwsem-spinlock.c Thu Aug 1 14:17:36 2002 +++ b/lib/rwsem-spinlock.c Thu Aug 1 14:17:36 2002 @@ -46,8 +46,9 @@ * - the 'waiting count' is non-zero * - the spinlock must be held by the caller * - woken process blocks are discarded from the list after having flags zeroised + * - writers are only woken if wakewrite is non-zero */ -static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem) +static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int wakewrite) { struct rwsem_waiter *waiter; int woken; @@ -56,7 +57,14 @@ waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list); - /* try to grant a single write lock if there's a writer at the front of the queue + if (!wakewrite) { + if (waiter->flags & RWSEM_WAITING_FOR_WRITE) + goto out; + goto dont_wake_writers; + } + + /* if we are allowed to wake writers try to grant a single write lock if there's a + * writer at the front of the queue * - we leave the 'waiting count' incremented to signify potential contention */ if (waiter->flags & RWSEM_WAITING_FOR_WRITE) { @@ -68,16 +76,19 @@ } /* grant an infinite number of read locks to the readers at the front of the queue */ + dont_wake_writers: woken = 0; - do { + while (waiter->flags&RWSEM_WAITING_FOR_READ) { + struct list_head *next = waiter->list.next; + list_del(&waiter->list); waiter->flags = 0; wake_up_process(waiter->task); woken++; if (list_empty(&sem->wait_list)) break; - waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list); - } while (waiter->flags&RWSEM_WAITING_FOR_READ); + waiter = list_entry(next,struct rwsem_waiter,list); + } sem->activity += woken; @@ -149,6 +160,28 @@ } /* + * trylock for reading -- returns 1 if successful, 0 if contention + */ +int __down_read_trylock(struct rw_semaphore *sem) +{ + int ret = 0; + rwsemtrace(sem,"Entering __down_read_trylock"); + + spin_lock(&sem->wait_lock); + + if (sem->activity>=0 && list_empty(&sem->wait_list)) { + /* granted */ + sem->activity++; + ret = 1; + } + + spin_unlock(&sem->wait_lock); + + rwsemtrace(sem,"Leaving __down_read_trylock"); + return ret; +} + +/* * get a write lock on the semaphore * - note that we increment the waiting count anyway to indicate an exclusive lock */ @@ -195,6 +228,28 @@ } /* + * trylock for writing -- returns 1 if successful, 0 if contention + */ +int __down_write_trylock(struct rw_semaphore *sem) +{ + int ret = 0; + rwsemtrace(sem,"Entering __down_write_trylock"); + + spin_lock(&sem->wait_lock); + + if (sem->activity==0 && list_empty(&sem->wait_list)) { + /* granted */ + sem->activity = -1; + ret = 1; + } + + spin_unlock(&sem->wait_lock); + + rwsemtrace(sem,"Leaving __down_write_trylock"); + return ret; +} + +/* * release a read lock on the semaphore */ void __up_read(struct rw_semaphore *sem) @@ -222,18 +277,40 @@ sem->activity = 0; if (!list_empty(&sem->wait_list)) - sem = __rwsem_do_wake(sem); + sem = __rwsem_do_wake(sem, 1); spin_unlock(&sem->wait_lock); rwsemtrace(sem,"Leaving __up_write"); } +/* + * downgrade a write lock into a read lock + * - just wake up any readers at the front of the queue + */ +void __downgrade_write(struct rw_semaphore *sem) +{ + rwsemtrace(sem,"Entering __rwsem_downgrade"); + + spin_lock(&sem->wait_lock); + + sem->activity = 1; + if (!list_empty(&sem->wait_list)) + sem = __rwsem_do_wake(sem,0); + + spin_unlock(&sem->wait_lock); + + rwsemtrace(sem,"Leaving __rwsem_downgrade"); +} + EXPORT_SYMBOL(init_rwsem); EXPORT_SYMBOL(__down_read); +EXPORT_SYMBOL(__down_read_trylock); EXPORT_SYMBOL(__down_write); +EXPORT_SYMBOL(__down_write_trylock); EXPORT_SYMBOL(__up_read); EXPORT_SYMBOL(__up_write); +EXPORT_SYMBOL(__downgrade_write); #if RWSEM_DEBUG EXPORT_SYMBOL(rwsemtrace); #endif diff -Nru a/lib/rwsem.c b/lib/rwsem.c --- a/lib/rwsem.c Thu Aug 1 14:17:36 2002 +++ b/lib/rwsem.c Thu Aug 1 14:17:36 2002 @@ -236,6 +236,7 @@ EXPORT_SYMBOL_NOVERS(rwsem_down_read_failed); EXPORT_SYMBOL_NOVERS(rwsem_down_write_failed); EXPORT_SYMBOL_NOVERS(rwsem_wake); +EXPORT_SYMBOL_NOVERS(rwsem_downgrade_wake); #if RWSEM_DEBUG EXPORT_SYMBOL(rwsemtrace); #endif diff -Nru a/mm/bootmem.c b/mm/bootmem.c --- a/mm/bootmem.c Thu Aug 1 14:17:39 2002 +++ b/mm/bootmem.c Thu Aug 1 14:17:39 2002 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -49,7 +48,7 @@ bootmem_data_t *bdata = pgdat->bdata; unsigned long mapsize = ((end - start)+7)/8; - pgdat->node_next = pgdat_list; + pgdat->pgdat_next = pgdat_list; pgdat_list = pgdat; mapsize = (mapsize + (sizeof(long) - 1UL)) & ~(sizeof(long) - 1UL); @@ -339,12 +338,11 @@ pg_data_t *pgdat = pgdat_list; void *ptr; - while (pgdat) { + for_each_pgdat(pgdat) if ((ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal))) return(ptr); - pgdat = pgdat->node_next; - } + /* * Whoops, we cannot satisfy the allocation request. */ diff -Nru a/mm/filemap.c b/mm/filemap.c --- a/mm/filemap.c Thu Aug 1 14:17:40 2002 +++ b/mm/filemap.c Thu Aug 1 14:17:40 2002 @@ -173,17 +173,16 @@ } /* - * AKPM: the PagePrivate test here seems a bit bogus. It bypasses the - * mapping's ->invalidatepage, which may still want to be called. + * If truncate can remove the fs-private metadata from the page, it + * removes the page from the LRU immediately. This because some other thread + * of control (eg, sendfile) may have a reference to the page. But dropping + * the final reference to an LRU page in interrupt context is illegal - it may + * deadlock over pagemap_lru_lock. */ static void truncate_complete_page(struct page *page) { - /* Drop fs-specific data so the page might become freeable. */ - if (PagePrivate(page) && !do_invalidatepage(page, 0)) { - if (current->flags & PF_INVALIDATE) - printk("%s: buffer heads were leaked\n", - current->comm); - } + if (!PagePrivate(page) || do_invalidatepage(page, 0)) + lru_cache_del(page); ClearPageDirty(page); ClearPageUptodate(page); @@ -1119,127 +1118,23 @@ return written; } -static ssize_t common_sendfile(int out_fd, int in_fd, loff_t *offset, size_t count, loff_t max) +ssize_t generic_file_sendfile(struct file *in_file, struct file *out_file, + loff_t *ppos, size_t count) { - ssize_t retval; - struct file * in_file, * out_file; - struct inode * in_inode, * out_inode; - - /* - * Get input file, and verify that it is ok.. - */ - retval = -EBADF; - in_file = fget(in_fd); - if (!in_file) - goto out; - if (!(in_file->f_mode & FMODE_READ)) - goto fput_in; - retval = -EINVAL; - in_inode = in_file->f_dentry->d_inode; - if (!in_inode) - goto fput_in; - if (!in_inode->i_mapping->a_ops->readpage) - goto fput_in; - retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, in_file->f_pos, count); - if (retval) - goto fput_in; - - retval = security_ops->file_permission (in_file, MAY_READ); - if (retval) - goto fput_in; - - /* - * Get output file, and verify that it is ok.. - */ - retval = -EBADF; - out_file = fget(out_fd); - if (!out_file) - goto fput_in; - if (!(out_file->f_mode & FMODE_WRITE)) - goto fput_out; - retval = -EINVAL; - if (!out_file->f_op || !out_file->f_op->sendpage) - goto fput_out; - out_inode = out_file->f_dentry->d_inode; - retval = locks_verify_area(FLOCK_VERIFY_WRITE, out_inode, out_file, out_file->f_pos, count); - if (retval) - goto fput_out; - - retval = security_ops->file_permission (out_file, MAY_WRITE); - if (retval) - goto fput_out; - - retval = 0; - if (count) { - read_descriptor_t desc; - loff_t pos; - - if (!offset) - offset = &in_file->f_pos; + read_descriptor_t desc; - pos = *offset; - retval = -EINVAL; - if (unlikely(pos < 0)) - goto fput_out; - if (unlikely(pos + count > max)) { - retval = -EOVERFLOW; - if (pos >= max) - goto fput_out; - count = max - pos; - } - - desc.written = 0; - desc.count = count; - desc.buf = (char *) out_file; - desc.error = 0; - do_generic_file_read(in_file, offset, &desc, file_send_actor); - - retval = desc.written; - if (!retval) - retval = desc.error; - pos = *offset; - if (pos > max) - retval = -EOVERFLOW; - } - -fput_out: - fput(out_file); -fput_in: - fput(in_file); -out: - return retval; -} + if (!count) + return 0; -asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count) -{ - loff_t pos, *ppos = NULL; - ssize_t ret; - if (offset) { - off_t off; - if (unlikely(get_user(off, offset))) - return -EFAULT; - pos = off; - ppos = &pos; - } - ret = common_sendfile(out_fd, in_fd, ppos, count, MAX_NON_LFS); - if (offset && put_user(pos, offset)) - ret = -EFAULT; - return ret; -} - -asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count) -{ - loff_t pos, *ppos = NULL; - ssize_t ret; - if (offset) { - if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t)))) - return -EFAULT; - ppos = &pos; - } - ret = common_sendfile(out_fd, in_fd, ppos, count, MAX_LFS_FILESIZE); - if (offset && put_user(pos, offset)) - ret = -EFAULT; - return ret; + desc.written = 0; + desc.count = count; + desc.buf = (char *)out_file; + desc.error = 0; + + do_generic_file_read(in_file, ppos, &desc, file_send_actor); + if (desc.written) + return desc.written; + return desc.error; } static ssize_t @@ -1451,7 +1346,7 @@ } static struct vm_operations_struct generic_file_vm_ops = { - nopage: filemap_nopage, + .nopage = filemap_nopage, }; /* This is used for a general mmap of a disk file */ @@ -2056,8 +1951,6 @@ mark_inode_dirty(inode); } *ppos = end; - if (mapping->nrpages) - invalidate_inode_pages2(mapping); } /* * Sync the fs metadata but not the minor inode changes and diff -Nru a/mm/memory.c b/mm/memory.c --- a/mm/memory.c Thu Aug 1 14:17:40 2002 +++ b/mm/memory.c Thu Aug 1 14:17:40 2002 @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -863,18 +862,19 @@ static inline int remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size, unsigned long phys_addr, pgprot_t prot) { - unsigned long end; + unsigned long base, end; + base = address & PGDIR_MASK; address &= ~PGDIR_MASK; end = address + size; if (end > PGDIR_SIZE) end = PGDIR_SIZE; phys_addr -= address; do { - pte_t * pte = pte_alloc_map(mm, pmd, address); + pte_t * pte = pte_alloc_map(mm, pmd, base + address); if (!pte) return -ENOMEM; - remap_pte_range(pte, address, end - address, address + phys_addr, prot); + remap_pte_range(pte, base + address, end - address, address + phys_addr, prot); pte_unmap(pte); address = (address + PMD_SIZE) & PMD_MASK; pmd++; @@ -1096,23 +1096,20 @@ do_expand: limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit != RLIM_INFINITY) { - if (inode->i_size >= limit) { - send_sig(SIGXFSZ, current, 0); - goto out; - } - if (offset > limit) { - send_sig(SIGXFSZ, current, 0); - offset = limit; - } - } + if (limit != RLIM_INFINITY && offset > limit) + goto out_sig; + if (offset > inode->i_sb->s_maxbytes) + goto out; inode->i_size = offset; out_truncate: if (inode->i_op && inode->i_op->truncate) inode->i_op->truncate(inode); -out: return 0; +out_sig: + send_sig(SIGXFSZ, current, 0); +out: + return -EFBIG; } /* diff -Nru a/mm/mmap.c b/mm/mmap.c --- a/mm/mmap.c Thu Aug 1 14:17:36 2002 +++ b/mm/mmap.c Thu Aug 1 14:17:36 2002 @@ -1,14 +1,16 @@ /* - * linux/mm/mmap.c + * mm/mmap.c * * Written by obz. + * + * Address space accounting code */ + #include #include #include #include #include -#include #include #include #include @@ -49,52 +51,84 @@ __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111 }; -int sysctl_overcommit_memory; +int sysctl_overcommit_memory = 0; /* default is heuristic overcommit */ +int sysctl_overcommit_ratio = 50; /* default is 50% */ +atomic_t vm_committed_space = ATOMIC_INIT(0); + +inline void vm_unacct_memory(long pages) +{ + atomic_sub(pages, &vm_committed_space); +} -/* Check that a process has enough memory to allocate a - * new virtual mapping. +/* + * Check that a process has enough memory to allocate a new virtual + * mapping. 1 means there is enough memory for the allocation to + * succeed and 0 implies there is not. + * + * We currently support three overcommit policies, which are set via the + * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-acounting + * + * Strict overcommit modes added 2002 Feb 26 by Alan Cox. + * Additional code 2002 Jul 20 by Robert Love. */ int vm_enough_memory(long pages) { - /* Stupid algorithm to decide if we have enough memory: while - * simple, it hopefully works in most obvious cases.. Easy to - * fool it, but this should catch most mistakes. - */ - /* 23/11/98 NJC: Somewhat less stupid version of algorithm, - * which tries to do "TheRightThing". Instead of using half of - * (buffers+cache), use the minimum values. Allow an extra 2% - * of num_physpages for safety margin. - */ + unsigned long free, allowed; + struct sysinfo i; - unsigned long free; - - /* Sometimes we want to use more memory than we have. */ - if (sysctl_overcommit_memory) - return 1; - - /* The page cache contains buffer pages these days.. */ - free = get_page_cache_size(); - free += nr_free_pages(); - free += nr_swap_pages; + atomic_add(pages, &vm_committed_space); - /* - * This double-counts: the nrpages are both in the page-cache - * and in the swapper space. At the same time, this compensates - * for the swap-space over-allocation (ie "nr_swap_pages" being - * too small. + /* + * Sometimes we want to use more memory than we have */ - free += swapper_space.nrpages; + if (sysctl_overcommit_memory == 1) + return 1; + + if (sysctl_overcommit_memory == 0) { + free = get_page_cache_size(); + free += nr_free_pages(); + free += nr_swap_pages; + + /* + * This double-counts: the nrpages are both in the + * page-cache and in the swapper space. At the same time, + * this compensates for the swap-space over-allocation + * (ie "nr_swap_pages" being too small). + */ + free += swapper_space.nrpages; + + /* + * The code below doesn't account for free space in the + * inode and dentry slab cache, slab cache fragmentation, + * inodes and dentries which will become freeable under + * VM load, etc. Lets just hope all these (complex) + * factors balance out... + */ + free += (dentry_stat.nr_unused * sizeof(struct dentry)) >> + PAGE_SHIFT; + free += (inodes_stat.nr_unused * sizeof(struct inode)) >> + PAGE_SHIFT; + + if (free > pages) + return 1; + vm_unacct_memory(pages); + return 0; + } /* - * The code below doesn't account for free space in the inode - * and dentry slab cache, slab cache fragmentation, inodes and - * dentries which will become freeable under VM load, etc. - * Lets just hope all these (complex) factors balance out... + * FIXME: need to add arch hooks to get the bits we need + * without this higher overhead crap */ - free += (dentry_stat.nr_unused * sizeof(struct dentry)) >> PAGE_SHIFT; - free += (inodes_stat.nr_unused * sizeof(struct inode)) >> PAGE_SHIFT; + si_meminfo(&i); + allowed = i.totalram * sysctl_overcommit_ratio / 100; + allowed += total_swap_pages; + + if (atomic_read(&vm_committed_space) < allowed) + return 1; + + vm_unacct_memory(pages); - return free > pages; + return 0; } /* Remove one vm structure from the inode's i_mapping address space. */ @@ -177,10 +211,6 @@ if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) goto out; - /* Check if we have enough memory.. */ - if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) - goto out; - /* Ok, looks good - let it rip. */ if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk) goto out; @@ -386,8 +416,9 @@ return 0; } -unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, unsigned long pgoff) +unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flags, unsigned long pgoff) { struct mm_struct * mm = current->mm; struct vm_area_struct * vma, * prev; @@ -395,6 +426,7 @@ int correct_wcount = 0; int error; rb_node_t ** rb_link, * rb_parent; + unsigned long charged = 0; if (file && (!file->f_op || !file->f_op->mmap)) return -ENODEV; @@ -495,11 +527,18 @@ > current->rlim[RLIMIT_AS].rlim_cur) return -ENOMEM; - /* Private writable mapping? Check memory availability.. */ - if ((vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE && - !(flags & MAP_NORESERVE) && - !vm_enough_memory(len >> PAGE_SHIFT)) - return -ENOMEM; + if (!(flags & MAP_NORESERVE) || sysctl_overcommit_memory > 1) { + if (vm_flags & VM_SHARED) { + /* Check memory availability in shmem_file_setup? */ + vm_flags |= VM_ACCOUNT; + } else if (vm_flags & VM_WRITE) { + /* Private writable mapping: check memory availability */ + charged = len >> PAGE_SHIFT; + if (!vm_enough_memory(charged)) + return -ENOMEM; + vm_flags |= VM_ACCOUNT; + } + } /* Can we just expand an old anonymous mapping? */ if (!file && !(vm_flags & VM_SHARED) && rb_parent) @@ -511,8 +550,9 @@ * not unmapped, but the maps are removed from the list. */ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + error = -ENOMEM; if (!vma) - return -ENOMEM; + goto unacct_error; vma->vm_mm = mm; vma->vm_start = addr; @@ -540,12 +580,20 @@ error = file->f_op->mmap(file, vma); if (error) goto unmap_and_free_vma; - } else if (flags & MAP_SHARED) { + } else if (vm_flags & VM_SHARED) { error = shmem_zero_setup(vma); if (error) goto free_vma; } + /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform + * shmem_zero_setup (perhaps called through /dev/zero's ->mmap) + * that memory reservation must be checked; but that reservation + * belongs to shared memory object, not to vma: so now clear it. + */ + if ((vm_flags & (VM_SHARED|VM_ACCOUNT)) == (VM_SHARED|VM_ACCOUNT)) + vma->vm_flags &= ~VM_ACCOUNT; + /* Can addr have changed?? * * Answer: Yes, several device drivers can do it in their @@ -575,6 +623,9 @@ zap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start); free_vma: kmem_cache_free(vm_area_cachep, vma); +unacct_error: + if (charged) + vm_unacct_memory(charged); return error; } @@ -704,6 +755,45 @@ return prev ? prev->vm_next : vma; } +/* + * vma is the first one with address < vma->vm_end, + * and even address < vma->vm_start. Have to extend vma. + */ +int expand_stack(struct vm_area_struct * vma, unsigned long address) +{ + unsigned long grow; + + /* + * vma->vm_start/vm_end cannot change under us because the caller + * is required to hold the mmap_sem in write mode. We need to get + * the spinlock only before relocating the vma range ourself. + */ + address &= PAGE_MASK; + spin_lock(&vma->vm_mm->page_table_lock); + grow = (vma->vm_start - address) >> PAGE_SHIFT; + + /* Overcommit.. */ + if(!vm_enough_memory(grow)) { + spin_unlock(&vma->vm_mm->page_table_lock); + return -ENOMEM; + } + + if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur || + ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > + current->rlim[RLIMIT_AS].rlim_cur) { + spin_unlock(&vma->vm_mm->page_table_lock); + vm_unacct_memory(grow); + return -ENOMEM; + } + vma->vm_start = address; + vma->vm_pgoff -= grow; + vma->vm_mm->total_vm += grow; + if (vma->vm_flags & VM_LOCKED) + vma->vm_mm->locked_vm += grow; + spin_unlock(&vma->vm_mm->page_table_lock); + return 0; +} + #ifdef ARCH_STACK_GROWSUP struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long addr) { @@ -829,7 +919,6 @@ kmem_cache_free(vm_area_cachep, area); } - /* * Update the VMA and inode share lists. * @@ -863,12 +952,17 @@ tlb = tlb_gather_mmu(mm, 0); do { - unsigned long from, to; + unsigned long from, to, len; from = start < mpnt->vm_start ? mpnt->vm_start : start; to = end > mpnt->vm_end ? mpnt->vm_end : end; unmap_page_range(tlb, mpnt, from, to); + + if (mpnt->vm_flags & VM_ACCOUNT) { + len = to - from; + vm_unacct_memory(len >> PAGE_SHIFT); + } } while ((mpnt = mpnt->vm_next) != NULL); free_pgtables(tlb, prev, start, end); @@ -1058,7 +1152,7 @@ if (!vm_enough_memory(len >> PAGE_SHIFT)) return -ENOMEM; - flags = VM_DATA_DEFAULT_FLAGS | mm->def_flags; + flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; /* Can we just expand an old anonymous mapping? */ if (rb_parent && vma_merge(mm, prev, rb_parent, addr, addr + len, flags)) @@ -1068,8 +1162,10 @@ * create a vma struct for an anonymous mapping */ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); - if (!vma) + if (!vma) { + vm_unacct_memory(len >> PAGE_SHIFT); return -ENOMEM; + } vma->vm_mm = mm; vma->vm_start = addr; @@ -1124,6 +1220,13 @@ while (mpnt) { unsigned long start = mpnt->vm_start; unsigned long end = mpnt->vm_end; + + /* + * If the VMA has been charged for, account for its + * removal + */ + if (mpnt->vm_flags & VM_ACCOUNT) + vm_unacct_memory((end - start) >> PAGE_SHIFT); mm->map_count--; unmap_page_range(tlb, mpnt, start, end); diff -Nru a/mm/mprotect.c b/mm/mprotect.c --- a/mm/mprotect.c Thu Aug 1 14:17:40 2002 +++ b/mm/mprotect.c Thu Aug 1 14:17:40 2002 @@ -1,7 +1,10 @@ /* - * linux/mm/mprotect.c + * mm/mprotect.c * * (C) Copyright 1994 Linus Torvalds + * + * Address space accounting code + * (C) Copyright 2002 Red Hat Inc, All Rights Reserved */ #include #include @@ -248,11 +251,28 @@ { pgprot_t newprot; int error; + unsigned long charged = 0; if (newflags == vma->vm_flags) { *pprev = vma; return 0; } + + /* + * If we make a private mapping writable we increase our commit; + * but (without finer accounting) cannot reduce our commit if we + * make it unwritable again. + * + * FIXME? We haven't defined a VM_NORESERVE flag, so mprotecting + * a MAP_NORESERVE private mapping to writable will now reserve. + */ + if ((newflags & VM_WRITE) && + !(vma->vm_flags & (VM_ACCOUNT|VM_WRITE|VM_SHARED))) { + charged = (end - start) >> PAGE_SHIFT; + if (!vm_enough_memory(charged)) + return -ENOMEM; + newflags |= VM_ACCOUNT; + } newprot = protection_map[newflags & 0xf]; if (start == vma->vm_start) { if (end == vma->vm_end) @@ -263,10 +283,10 @@ error = mprotect_fixup_end(vma, pprev, start, newflags, newprot); else error = mprotect_fixup_middle(vma, pprev, start, end, newflags, newprot); - - if (error) + if (error) { + vm_unacct_memory(charged); return error; - + } change_protection(vma, start, end, newprot); return 0; } diff -Nru a/mm/mremap.c b/mm/mremap.c --- a/mm/mremap.c Thu Aug 1 14:17:40 2002 +++ b/mm/mremap.c Thu Aug 1 14:17:40 2002 @@ -1,7 +1,10 @@ /* - * linux/mm/remap.c + * mm/remap.c * * (C) Copyright 1996 Linus Torvalds + * + * Address space accounting code + * (C) Copyright 2002 Red Hat Inc, All Rights Reserved */ #include @@ -18,8 +21,6 @@ #include #include -extern int vm_enough_memory(long pages); - static inline pte_t *get_one_pte_map_nested(struct mm_struct *mm, unsigned long addr) { pgd_t * pgd; @@ -149,6 +150,7 @@ struct mm_struct * mm = vma->vm_mm; struct vm_area_struct * new_vma, * next, * prev; int allocated_vma; + int split = 0; new_vma = NULL; next = find_vma_prev(mm, new_addr, &prev); @@ -209,7 +211,26 @@ new_vma->vm_ops->open(new_vma); insert_vm_struct(current->mm, new_vma); } + + /* Conceal VM_ACCOUNT so old reservation is not undone */ + if (vma->vm_flags & VM_ACCOUNT) { + vma->vm_flags &= ~VM_ACCOUNT; + if (addr > vma->vm_start) { + if (addr + old_len < vma->vm_end) + split = 1; + } else if (addr + old_len == vma->vm_end) + vma = NULL; /* it will be removed */ + } else + vma = NULL; /* nothing more to do */ + do_munmap(current->mm, addr, old_len); + + /* Restore VM_ACCOUNT if one or two pieces of vma left */ + if (vma) { + vma->vm_flags |= VM_ACCOUNT; + if (split) + vma->vm_next->vm_flags |= VM_ACCOUNT; + } current->mm->total_vm += new_len >> PAGE_SHIFT; if (new_vma->vm_flags & VM_LOCKED) { current->mm->locked_vm += new_len >> PAGE_SHIFT; @@ -237,6 +258,7 @@ { struct vm_area_struct *vma; unsigned long ret = -EINVAL; + unsigned long charged = 0; if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE)) goto out; @@ -272,12 +294,14 @@ /* * Always allow a shrinking remap: that just unmaps * the unnecessary pages.. + * do_munmap does all the needed commit accounting */ ret = addr; if (old_len >= new_len) { do_munmap(current->mm, addr+new_len, old_len - new_len); if (!(flags & MREMAP_FIXED) || (new_addr == addr)) goto out; + old_len = new_len; } /* @@ -305,11 +329,12 @@ if ((current->mm->total_vm << PAGE_SHIFT) + (new_len - old_len) > current->rlim[RLIMIT_AS].rlim_cur) goto out; - /* Private writable mapping? Check memory availability.. */ - if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE && - !(flags & MAP_NORESERVE) && - !vm_enough_memory((new_len - old_len) >> PAGE_SHIFT)) - goto out; + + if (vma->vm_flags & VM_ACCOUNT) { + charged = (new_len - old_len) >> PAGE_SHIFT; + if (!vm_enough_memory(charged)) + goto out_nc; + } /* old_len exactly to the end of the area.. * And we're not relocating the area. @@ -356,6 +381,9 @@ ret = move_vma(vma, addr, old_len, new_len, new_addr); } out: + if (ret & ~PAGE_MASK) + vm_unacct_memory(charged); +out_nc: return ret; } diff -Nru a/mm/numa.c b/mm/numa.c --- a/mm/numa.c Thu Aug 1 14:17:39 2002 +++ b/mm/numa.c Thu Aug 1 14:17:39 2002 @@ -12,7 +12,7 @@ int numnodes = 1; /* Initialized for UMA platforms */ static bootmem_data_t contig_bootmem_data; -pg_data_t contig_page_data = { bdata: &contig_bootmem_data }; +pg_data_t contig_page_data = { .bdata = &contig_bootmem_data }; #ifndef CONFIG_DISCONTIGMEM @@ -44,17 +44,6 @@ #define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1)) -static spinlock_t node_lock = SPIN_LOCK_UNLOCKED; - -void show_free_areas_node(pg_data_t *pgdat) -{ - unsigned long flags; - - spin_lock_irqsave(&node_lock, flags); - show_free_areas_core(pgdat); - spin_unlock_irqrestore(&node_lock, flags); -} - /* * Nodes can be initialized parallely, in no particular order. */ @@ -106,23 +95,22 @@ #ifdef CONFIG_NUMA temp = NODE_DATA(numa_node_id()); #else - spin_lock_irqsave(&node_lock, flags); - if (!next) next = pgdat_list; + if (!next) + next = pgdat_list; temp = next; - next = next->node_next; - spin_unlock_irqrestore(&node_lock, flags); + next = next->pgdat_next; #endif start = temp; while (temp) { if ((ret = alloc_pages_pgdat(temp, gfp_mask, order))) return(ret); - temp = temp->node_next; + temp = temp->pgdat_next; } temp = pgdat_list; while (temp != start) { if ((ret = alloc_pages_pgdat(temp, gfp_mask, order))) return(ret); - temp = temp->node_next; + temp = temp->pgdat_next; } return(0); } diff -Nru a/mm/oom_kill.c b/mm/oom_kill.c --- a/mm/oom_kill.c Thu Aug 1 14:17:36 2002 +++ b/mm/oom_kill.c Thu Aug 1 14:17:36 2002 @@ -18,7 +18,6 @@ #include #include #include -#include #include /* #define DEBUG */ diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c --- a/mm/page_alloc.c Thu Aug 1 14:17:36 2002 +++ b/mm/page_alloc.c Thu Aug 1 14:17:36 2002 @@ -477,22 +477,21 @@ */ unsigned int nr_free_pages(void) { - unsigned int i, sum = 0; - pg_data_t *pgdat; + unsigned int sum = 0; + zone_t *zone; - for (pgdat = pgdat_list; pgdat; pgdat = pgdat->node_next) - for (i = 0; i < MAX_NR_ZONES; ++i) - sum += pgdat->node_zones[i].free_pages; + for_each_zone(zone) + sum += zone->free_pages; return sum; } static unsigned int nr_free_zone_pages(int offset) { - pg_data_t *pgdat = pgdat_list; + pg_data_t *pgdat; unsigned int sum = 0; - do { + for_each_pgdat(pgdat) { zonelist_t *zonelist = pgdat->node_zonelists + offset; zone_t **zonep = zonelist->zones; zone_t *zone; @@ -503,9 +502,7 @@ if (size > high) sum += size - high; } - - pgdat = pgdat->node_next; - } while (pgdat); + } return sum; } @@ -529,13 +526,12 @@ #if CONFIG_HIGHMEM unsigned int nr_free_highpages (void) { - pg_data_t *pgdat = pgdat_list; + pg_data_t *pgdat; unsigned int pages = 0; - while (pgdat) { + for_each_pgdat(pgdat) pages += pgdat->node_zones[ZONE_HIGHMEM].free_pages; - pgdat = pgdat->node_next; - } + return pages; } #endif @@ -566,8 +562,7 @@ ret->nr_active += ps->nr_active; ret->nr_inactive += ps->nr_inactive; ret->nr_page_table_pages += ps->nr_page_table_pages; - ret->nr_pte_chain_pages += ps->nr_pte_chain_pages; - ret->used_pte_chains_bytes += ps->used_pte_chains_bytes; + ret->nr_reverse_maps += ps->nr_reverse_maps; } } @@ -602,12 +597,11 @@ * We also calculate the percentage fragmentation. We do this by counting the * memory on each free list with the exception of the first item on the list. */ -void show_free_areas_core(pg_data_t *pgdat) +void show_free_areas(void) { - unsigned int order; - unsigned type; - pg_data_t *tmpdat = pgdat; + pg_data_t *pgdat; struct page_state ps; + int type; get_page_state(&ps); @@ -615,20 +609,20 @@ K(nr_free_pages()), K(nr_free_highpages())); - while (tmpdat) { - zone_t *zone; - for (zone = tmpdat->node_zones; - zone < tmpdat->node_zones + MAX_NR_ZONES; zone++) - printk("Zone:%s freepages:%6lukB min:%6lukB low:%6lukB " - "high:%6lukB\n", - zone->name, - K(zone->free_pages), - K(zone->pages_min), - K(zone->pages_low), - K(zone->pages_high)); - - tmpdat = tmpdat->node_next; - } + for (pgdat = pgdat_list; pgdat; pgdat = pgdat->pgdat_next) + for (type = 0; type < MAX_NR_ZONES; ++type) { + zone_t *zone = &pgdat->node_zones[type]; + printk("Zone:%s " + "freepages:%6lukB " + "min:%6lukB " + "low:%6lukB " + "high:%6lukB\n", + zone->name, + K(zone->free_pages), + K(zone->pages_min), + K(zone->pages_low), + K(zone->pages_high)); + } printk("( Active:%lu inactive:%lu dirty:%lu writeback:%lu free:%u )\n", ps.nr_active, @@ -637,40 +631,28 @@ ps.nr_writeback, nr_free_pages()); - for (type = 0; type < MAX_NR_ZONES; type++) { - struct list_head *head, *curr; - zone_t *zone = pgdat->node_zones + type; - unsigned long nr, total, flags; + for (pgdat = pgdat_list; pgdat; pgdat = pgdat->pgdat_next) + for (type = 0; type < MAX_NR_ZONES; type++) { + list_t *elem; + zone_t *zone = &pgdat->node_zones[type]; + unsigned long nr, flags, order, total = 0; + + if (!zone->size) + continue; - total = 0; - if (zone->size) { spin_lock_irqsave(&zone->lock, flags); - for (order = 0; order < MAX_ORDER; order++) { - head = &(zone->free_area + order)->free_list; - curr = head; + for (order = 0; order < MAX_ORDER; order++) { nr = 0; - for (;;) { - curr = curr->next; - if (curr == head) - break; - nr++; - } - total += nr * (1 << order); + list_for_each(elem, &zone->free_area[order].free_list) + ++nr; + total += nr << order; printk("%lu*%lukB ", nr, K(1UL) << order); } spin_unlock_irqrestore(&zone->lock, flags); + printk("= %lukB)\n", K(total)); } - printk("= %lukB)\n", K(total)); - } -#ifdef SWAP_CACHE_INFO show_swap_cache_info(); -#endif -} - -void show_free_areas(void) -{ - show_free_areas_core(pgdat_list); } /* diff -Nru a/mm/page_io.c b/mm/page_io.c --- a/mm/page_io.c Thu Aug 1 14:17:36 2002 +++ b/mm/page_io.c Thu Aug 1 14:17:36 2002 @@ -132,11 +132,11 @@ } struct address_space_operations swap_aops = { - vm_writeback: swap_vm_writeback, - writepage: swap_writepage, - readpage: swap_readpage, - sync_page: block_sync_page, - set_page_dirty: __set_page_dirty_nobuffers, + .vm_writeback = swap_vm_writeback, + .writepage = swap_writepage, + .readpage = swap_readpage, + .sync_page = block_sync_page, + .set_page_dirty = __set_page_dirty_nobuffers, }; /* diff -Nru a/mm/readahead.c b/mm/readahead.c --- a/mm/readahead.c Thu Aug 1 14:17:36 2002 +++ b/mm/readahead.c Thu Aug 1 14:17:36 2002 @@ -14,8 +14,8 @@ #include struct backing_dev_info default_backing_dev_info = { - ra_pages: (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE, - state: 0, + .ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE, + .state = 0, }; /* diff -Nru a/mm/rmap.c b/mm/rmap.c --- a/mm/rmap.c Thu Aug 1 14:17:41 2002 +++ b/mm/rmap.c Thu Aug 1 14:17:41 2002 @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -50,10 +52,10 @@ pte_t * ptep; }; +static kmem_cache_t *pte_chain_cache; static inline struct pte_chain * pte_chain_alloc(void); static inline void pte_chain_free(struct pte_chain *, struct pte_chain *, struct page *); -static void alloc_new_pte_chains(void); /** * page_referenced - test if the page was referenced @@ -148,6 +150,7 @@ } pte_chain_unlock(page); + inc_page_state(nr_reverse_maps); } /** @@ -208,9 +211,9 @@ #endif out: + dec_page_state(nr_reverse_maps); pte_chain_unlock(page); return; - } /** @@ -355,27 +358,6 @@ ** functions. **/ -struct pte_chain * pte_chain_freelist; -spinlock_t pte_chain_freelist_lock = SPIN_LOCK_UNLOCKED; - -/* Maybe we should have standard ops for singly linked lists ... - Rik */ -static inline void pte_chain_push(struct pte_chain * pte_chain) -{ - pte_chain->ptep = NULL; - pte_chain->next = pte_chain_freelist; - pte_chain_freelist = pte_chain; -} - -static inline struct pte_chain * pte_chain_pop(void) -{ - struct pte_chain *pte_chain; - - pte_chain = pte_chain_freelist; - pte_chain_freelist = pte_chain->next; - pte_chain->next = NULL; - - return pte_chain; -} /** * pte_chain_free - free pte_chain structure @@ -391,15 +373,12 @@ static inline void pte_chain_free(struct pte_chain * pte_chain, struct pte_chain * prev_pte_chain, struct page * page) { - mod_page_state(used_pte_chains_bytes, -sizeof(struct pte_chain)); if (prev_pte_chain) prev_pte_chain->next = pte_chain->next; else if (page) page->pte.chain = pte_chain->next; - spin_lock(&pte_chain_freelist_lock); - pte_chain_push(pte_chain); - spin_unlock(&pte_chain_freelist_lock); + kmem_cache_free(pte_chain_cache, pte_chain); } /** @@ -409,47 +388,20 @@ * pte_chain structures as required. * Caller needs to hold the page's pte_chain_lock. */ -static inline struct pte_chain * pte_chain_alloc() +static inline struct pte_chain *pte_chain_alloc(void) { - struct pte_chain * pte_chain; - - spin_lock(&pte_chain_freelist_lock); - - /* Allocate new pte_chain structs as needed. */ - if (!pte_chain_freelist) - alloc_new_pte_chains(); - - /* Grab the first pte_chain from the freelist. */ - pte_chain = pte_chain_pop(); - - spin_unlock(&pte_chain_freelist_lock); - - mod_page_state(used_pte_chains_bytes, sizeof(struct pte_chain)); - return pte_chain; + return kmem_cache_alloc(pte_chain_cache, GFP_ATOMIC); } -/** - * alloc_new_pte_chains - convert a free page to pte_chain structures - * - * Grabs a free page and converts it to pte_chain structures. We really - * should pre-allocate these earlier in the pagefault path or come up - * with some other trick. - * - * Note that we cannot use the slab cache because the pte_chain structure - * is way smaller than the minimum size of a slab cache allocation. - * Caller needs to hold the pte_chain_freelist_lock - */ -static void alloc_new_pte_chains() +void __init pte_chain_init(void) { - struct pte_chain * pte_chain = (void *) get_zeroed_page(GFP_ATOMIC); - int i = PAGE_SIZE / sizeof(struct pte_chain); + pte_chain_cache = kmem_cache_create( "pte_chain", + sizeof(struct pte_chain), + 0, + 0, + NULL, + NULL); - if (pte_chain) { - inc_page_state(nr_pte_chain_pages); - for (; i-- > 0; pte_chain++) - pte_chain_push(pte_chain); - } else { - /* Yeah yeah, I'll fix the pte_chain allocation ... */ - panic("Fix pte_chain allocation, you lazy bastard!\n"); - } + if (!pte_chain_cache) + panic("failed to create pte_chain cache!\n"); } diff -Nru a/mm/shmem.c b/mm/shmem.c --- a/mm/shmem.c Thu Aug 1 14:17:40 2002 +++ b/mm/shmem.c Thu Aug 1 14:17:40 2002 @@ -5,7 +5,8 @@ * 2000 Transmeta Corp. * 2000-2001 Christoph Rohland * 2000-2001 SAP AG - * + * 2002 Red Hat Inc. + * * This file is released under the GPL. */ @@ -21,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +37,12 @@ #define TMPFS_MAGIC 0x01021994 #define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long)) +#define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512) + +#define SHMEM_MAX_INDEX (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE * (ENTRIES_PER_PAGE/2) * (ENTRIES_PER_PAGE+1)) +#define SHMEM_MAX_BYTES ((unsigned long long)SHMEM_MAX_INDEX << PAGE_CACHE_SHIFT) + +#define VM_ACCT(size) (((size) + PAGE_CACHE_SIZE - 1) >> PAGE_SHIFT) static inline struct shmem_sb_info *SHMEM_SB(struct super_block *sb) { @@ -54,8 +62,6 @@ static struct page *shmem_getpage_locked(struct shmem_inode_info *, struct inode *, unsigned long); -#define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512) - /* * shmem_recalc_inode - recalculate the size of an inode * @@ -131,9 +137,6 @@ * +-> 48-51 * +-> 52-55 */ - -#define SHMEM_MAX_BLOCKS (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE * ENTRIES_PER_PAGE/2*(ENTRIES_PER_PAGE+1)) - static swp_entry_t * shmem_swp_entry (struct shmem_inode_info *info, unsigned long index, unsigned long page) { unsigned long offset; @@ -186,7 +189,7 @@ unsigned long page = 0; swp_entry_t * res; - if (index >= SHMEM_MAX_BLOCKS) + if (index >= SHMEM_MAX_INDEX) return ERR_PTR(-EFBIG); if (info->next_index <= index) @@ -358,15 +361,46 @@ up(&info->sem); } +static int shmem_notify_change(struct dentry * dentry, struct iattr *attr) +{ + struct inode *inode = dentry->d_inode; + long change = 0; + int error; + + if ((attr->ia_valid & ATTR_SIZE) && (attr->ia_size <= SHMEM_MAX_BYTES)) { + /* + * Account swap file usage based on new file size, + * but just let vmtruncate fail on out-of-range sizes. + */ + change = VM_ACCT(attr->ia_size) - VM_ACCT(inode->i_size); + if (change > 0) { + if (!vm_enough_memory(change)) + return -ENOMEM; + } else + vm_unacct_memory(-change); + } + + error = inode_change_ok(inode, attr); + if (!error) + error = inode_setattr(inode, attr); + if (error) + vm_unacct_memory(change); + return error; +} + + static void shmem_delete_inode(struct inode * inode) { struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); + struct shmem_inode_info *info = SHMEM_I(inode); - inode->i_size = 0; - if (inode->i_op->truncate == shmem_truncate){ - spin_lock (&shmem_ilock); - list_del (&SHMEM_I(inode)->list); - spin_unlock (&shmem_ilock); + if (inode->i_op->truncate == shmem_truncate) { + spin_lock(&shmem_ilock); + list_del(&info->list); + spin_unlock(&shmem_ilock); + if (info->flags & VM_ACCOUNT) + vm_unacct_memory(VM_ACCT(inode->i_size)); + inode->i_size = 0; shmem_truncate (inode); } spin_lock (&sbinfo->stat_lock); @@ -494,7 +528,7 @@ index = page->index; inode = mapping->host; info = SHMEM_I(inode); - if (info->locked) + if (info->flags & VM_LOCKED) return fail_writepage(page); swap = get_swap_page(); if (!swap.val) @@ -711,9 +745,12 @@ struct inode * inode = file->f_dentry->d_inode; struct shmem_inode_info * info = SHMEM_I(inode); - down(&info->sem); - info->locked = lock; - up(&info->sem); + spin_lock(&info->lock); + if (lock) + info->flags |= VM_LOCKED; + else + info->flags &= ~VM_LOCKED; + spin_unlock(&info->lock); } static int shmem_mmap(struct file * file, struct vm_area_struct * vma) @@ -760,7 +797,7 @@ memset (info->i_direct, 0, sizeof(info->i_direct)); info->i_indirect = NULL; info->swapped = 0; - info->locked = 0; + info->flags = VM_ACCOUNT; switch (mode & S_IFMT) { default: init_special_inode(inode, mode, dev); @@ -824,6 +861,7 @@ unsigned long written; long status; int err; + loff_t maxpos; if ((ssize_t) count < 0) return -EINVAL; @@ -836,12 +874,12 @@ pos = *ppos; err = -EINVAL; if (pos < 0) - goto out; + goto out_nc; err = file->f_error; if (err) { file->f_error = 0; - goto out; + goto out_nc; } written = 0; @@ -849,6 +887,17 @@ if (file->f_flags & O_APPEND) pos = inode->i_size; + maxpos = inode->i_size; + if (pos + count > inode->i_size) { + maxpos = pos + count; + if (maxpos > SHMEM_MAX_BYTES) + maxpos = SHMEM_MAX_BYTES; + if (!vm_enough_memory(VM_ACCT(maxpos) - VM_ACCT(inode->i_size))) { + err = -ENOMEM; + goto out_nc; + } + } + /* * Check whether we've reached the file size limit. */ @@ -938,6 +987,10 @@ err = written ? written : status; out: + /* Short writes give back address space */ + if (inode->i_size != maxpos) + vm_unacct_memory(VM_ACCT(maxpos) - VM_ACCT(inode->i_size)); +out_nc: up(&inode->i_sem); return err; fail_write: @@ -1191,10 +1244,15 @@ memcpy(info, symname, len); inode->i_op = &shmem_symlink_inline_operations; } else { + if (!vm_enough_memory(VM_ACCT(1))) { + iput(inode); + return -ENOMEM; + } down(&info->sem); page = shmem_getpage_locked(info, inode, 0); if (IS_ERR(page)) { up(&info->sem); + vm_unacct_memory(VM_ACCT(1)); iput(inode); return PTR_ERR(page); } @@ -1254,14 +1312,14 @@ } static struct inode_operations shmem_symlink_inline_operations = { - readlink: shmem_readlink_inline, - follow_link: shmem_follow_link_inline, + .readlink = shmem_readlink_inline, + .follow_link = shmem_follow_link_inline, }; static struct inode_operations shmem_symlink_inode_operations = { - truncate: shmem_truncate, - readlink: shmem_readlink, - follow_link: shmem_follow_link, + .truncate = shmem_truncate, + .readlink = shmem_readlink, + .follow_link = shmem_follow_link, }; static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long * blocks, unsigned long *inodes) @@ -1383,7 +1441,7 @@ sbinfo->free_blocks = blocks; sbinfo->max_inodes = inodes; sbinfo->free_inodes = inodes; - sb->s_maxbytes = (unsigned long long) SHMEM_MAX_BLOCKS << PAGE_CACHE_SHIFT; + sb->s_maxbytes = SHMEM_MAX_BYTES; sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = TMPFS_MAGIC; @@ -1462,51 +1520,52 @@ } static struct address_space_operations shmem_aops = { - writepage: shmem_writepage, - set_page_dirty: __set_page_dirty_nobuffers, + .writepage = shmem_writepage, + .set_page_dirty = __set_page_dirty_nobuffers, }; static struct file_operations shmem_file_operations = { - mmap: shmem_mmap, + .mmap = shmem_mmap, #ifdef CONFIG_TMPFS - read: shmem_file_read, - write: shmem_file_write, - fsync: shmem_sync_file, + .read = shmem_file_read, + .write = shmem_file_write, + .fsync = shmem_sync_file, #endif }; static struct inode_operations shmem_inode_operations = { - truncate: shmem_truncate, + .truncate = shmem_truncate, + .setattr = shmem_notify_change, }; static struct inode_operations shmem_dir_inode_operations = { #ifdef CONFIG_TMPFS - create: shmem_create, - lookup: simple_lookup, - link: shmem_link, - unlink: shmem_unlink, - symlink: shmem_symlink, - mkdir: shmem_mkdir, - rmdir: shmem_rmdir, - mknod: shmem_mknod, - rename: shmem_rename, + .create = shmem_create, + .lookup = simple_lookup, + .link = shmem_link, + .unlink = shmem_unlink, + .symlink = shmem_symlink, + .mkdir = shmem_mkdir, + .rmdir = shmem_rmdir, + .mknod = shmem_mknod, + .rename = shmem_rename, #endif }; static struct super_operations shmem_ops = { - alloc_inode: shmem_alloc_inode, - destroy_inode: shmem_destroy_inode, + .alloc_inode = shmem_alloc_inode, + .destroy_inode = shmem_destroy_inode, #ifdef CONFIG_TMPFS - statfs: shmem_statfs, - remount_fs: shmem_remount_fs, + .statfs = shmem_statfs, + .remount_fs = shmem_remount_fs, #endif - delete_inode: shmem_delete_inode, - drop_inode: generic_delete_inode, - put_super: shmem_put_super, + .delete_inode = shmem_delete_inode, + .drop_inode = generic_delete_inode, + .put_super = shmem_put_super, }; static struct vm_operations_struct shmem_vm_ops = { - nopage: shmem_nopage, + .nopage = shmem_nopage, }; static struct super_block *shmem_get_sb(struct file_system_type *fs_type, @@ -1518,17 +1577,17 @@ #ifdef CONFIG_TMPFS /* type "shm" will be tagged obsolete in 2.5 */ static struct file_system_type shmem_fs_type = { - owner: THIS_MODULE, - name: "shmem", - get_sb: shmem_get_sb, - kill_sb: kill_litter_super, + .owner = THIS_MODULE, + .name = "shmem", + .get_sb = shmem_get_sb, + .kill_sb = kill_litter_super, }; #endif static struct file_system_type tmpfs_fs_type = { - owner: THIS_MODULE, - name: "tmpfs", - get_sb: shmem_get_sb, - kill_sb: kill_litter_super, + .owner = THIS_MODULE, + .name = "tmpfs", + .get_sb = shmem_get_sb, + .kill_sb = kill_litter_super, }; static struct vfsmount *shm_mnt; @@ -1598,28 +1657,28 @@ * @size: size to be set for the file * */ -struct file *shmem_file_setup(char * name, loff_t size) +struct file *shmem_file_setup(char * name, loff_t size, unsigned long flags) { int error; struct file *file; struct inode * inode; struct dentry *dentry, *root; struct qstr this; - int vm_enough_memory(long pages); - if (size > (unsigned long long) SHMEM_MAX_BLOCKS << PAGE_CACHE_SHIFT) + if (size > SHMEM_MAX_BYTES) return ERR_PTR(-EINVAL); - if (!vm_enough_memory((size) >> PAGE_CACHE_SHIFT)) + if ((flags & VM_ACCOUNT) && !vm_enough_memory(VM_ACCT(size))) return ERR_PTR(-ENOMEM); + error = -ENOMEM; this.name = name; this.len = strlen(name); this.hash = 0; /* will go */ root = shm_mnt->mnt_root; dentry = d_alloc(root, &this); if (!dentry) - return ERR_PTR(-ENOMEM); + goto put_memory; error = -ENFILE; file = get_empty_filp(); @@ -1631,22 +1690,26 @@ if (!inode) goto close_file; + SHMEM_I(inode)->flags &= flags; d_instantiate(dentry, inode); - dentry->d_inode->i_size = size; - shmem_truncate(inode); + inode->i_size = size; + inode->i_nlink = 0; /* It is unlinked */ file->f_vfsmnt = mntget(shm_mnt); file->f_dentry = dentry; file->f_op = &shmem_file_operations; file->f_mode = FMODE_WRITE | FMODE_READ; - inode->i_nlink = 0; /* It is unlinked */ return(file); close_file: put_filp(file); put_dentry: dput (dentry); +put_memory: + if (flags & VM_ACCOUNT) + vm_unacct_memory(VM_ACCT(size)); return ERR_PTR(error); } + /* * shmem_zero_setup - setup a shared anonymous mapping * @@ -1657,7 +1720,7 @@ struct file *file; loff_t size = vma->vm_end - vma->vm_start; - file = shmem_file_setup("dev/zero", size); + file = shmem_file_setup("dev/zero", size, vma->vm_flags); if (IS_ERR(file)) return PTR_ERR(file); diff -Nru a/mm/slab.c b/mm/slab.c --- a/mm/slab.c Thu Aug 1 14:17:41 2002 +++ b/mm/slab.c Thu Aug 1 14:17:41 2002 @@ -126,7 +126,7 @@ * Bufctl's are used for linking objs within a slab * linked offsets. * - * This implementaion relies on "struct page" for locating the cache & + * This implementation relies on "struct page" for locating the cache & * slab an object belongs to. * This allows the bufctl structure to be small (one int), but limits * the number of objects a slab (not a cache) can contain when off-slab @@ -384,14 +384,14 @@ /* internal cache of cache description objs */ static kmem_cache_t cache_cache = { - slabs_full: LIST_HEAD_INIT(cache_cache.slabs_full), - slabs_partial: LIST_HEAD_INIT(cache_cache.slabs_partial), - slabs_free: LIST_HEAD_INIT(cache_cache.slabs_free), - objsize: sizeof(kmem_cache_t), - flags: SLAB_NO_REAP, - spinlock: SPIN_LOCK_UNLOCKED, - colour_off: L1_CACHE_BYTES, - name: "kmem_cache", + .slabs_full = LIST_HEAD_INIT(cache_cache.slabs_full), + .slabs_partial = LIST_HEAD_INIT(cache_cache.slabs_partial), + .slabs_free = LIST_HEAD_INIT(cache_cache.slabs_free), + .objsize = sizeof(kmem_cache_t), + .flags = SLAB_NO_REAP, + .spinlock = SPIN_LOCK_UNLOCKED, + .colour_off = L1_CACHE_BYTES, + .name = "kmem_cache", }; /* Guard access to the cache-chain. */ @@ -1647,6 +1647,15 @@ local_irq_restore(flags); } +unsigned int kmem_cache_size(kmem_cache_t *cachep) +{ +#if DEBUG + if (cachep->flags & SLAB_RED_ZONE) + return (cachep->objsize - 2*BYTES_PER_WORD); +#endif + return cachep->objsize; +} + kmem_cache_t * kmem_find_general_cachep (size_t size, int gfpflags) { cache_sizes_t *csizep = cache_sizes; @@ -2044,10 +2053,10 @@ */ struct seq_operations slabinfo_op = { - start: s_start, - next: s_next, - stop: s_stop, - show: s_show + .start = s_start, + .next = s_next, + .stop = s_stop, + .show = s_show, }; #define MAX_SLABINFO_WRITE 128 diff -Nru a/mm/swap.c b/mm/swap.c --- a/mm/swap.c Thu Aug 1 14:17:40 2002 +++ b/mm/swap.c Thu Aug 1 14:17:40 2002 @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -26,12 +25,6 @@ /* How many pages do we try to swap or page in/out together? */ int page_cluster; - -pager_daemon_t pager_daemon = { - 512, /* base number for calculating the number of tries */ - SWAP_CLUSTER_MAX, /* minimum number of tries */ - 8, /* do swap I/O in clusters of this size */ -}; /* * Move an inactive page to the active list. diff -Nru a/mm/swap_state.c b/mm/swap_state.c --- a/mm/swap_state.c Thu Aug 1 14:17:40 2002 +++ b/mm/swap_state.c Thu Aug 1 14:17:40 2002 @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -23,27 +22,26 @@ * avoid some special-casing in other parts of the kernel. */ static struct inode swapper_inode = { - i_mapping: &swapper_space, + .i_mapping = &swapper_space, }; extern struct address_space_operations swap_aops; struct address_space swapper_space = { - page_tree: RADIX_TREE_INIT(GFP_ATOMIC), - page_lock: RW_LOCK_UNLOCKED, - clean_pages: LIST_HEAD_INIT(swapper_space.clean_pages), - dirty_pages: LIST_HEAD_INIT(swapper_space.dirty_pages), - io_pages: LIST_HEAD_INIT(swapper_space.io_pages), - locked_pages: LIST_HEAD_INIT(swapper_space.locked_pages), - host: &swapper_inode, - a_ops: &swap_aops, - i_shared_lock: SPIN_LOCK_UNLOCKED, - private_lock: SPIN_LOCK_UNLOCKED, - private_list: LIST_HEAD_INIT(swapper_space.private_list), + .page_tree = RADIX_TREE_INIT(GFP_ATOMIC), + .page_lock = RW_LOCK_UNLOCKED, + .clean_pages = LIST_HEAD_INIT(swapper_space.clean_pages), + .dirty_pages = LIST_HEAD_INIT(swapper_space.dirty_pages), + .io_pages = LIST_HEAD_INIT(swapper_space.io_pages), + .locked_pages = LIST_HEAD_INIT(swapper_space.locked_pages), + .host = &swapper_inode, + .a_ops = &swap_aops, + .i_shared_lock = SPIN_LOCK_UNLOCKED, + .private_lock = SPIN_LOCK_UNLOCKED, + .private_list = LIST_HEAD_INIT(swapper_space.private_list), }; -#ifdef SWAP_CACHE_INFO -#define INC_CACHE_INFO(x) (swap_cache_info.x++) +#define INC_CACHE_INFO(x) do { swap_cache_info.x++; } while (0) static struct { unsigned long add_total; @@ -61,9 +59,6 @@ swap_cache_info.find_success, swap_cache_info.find_total, swap_cache_info.noent_race, swap_cache_info.exist_race); } -#else -#define INC_CACHE_INFO(x) do { } while (0) -#endif int add_to_swap_cache(struct page *page, swp_entry_t entry) { diff -Nru a/mm/swapfile.c b/mm/swapfile.c --- a/mm/swapfile.c Thu Aug 1 14:17:37 2002 +++ b/mm/swapfile.c Thu Aug 1 14:17:37 2002 @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff -Nru a/mm/vmscan.c b/mm/vmscan.c --- a/mm/vmscan.c Thu Aug 1 14:17:36 2002 +++ b/mm/vmscan.c Thu Aug 1 14:17:36 2002 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -200,8 +199,8 @@ * so the direct writes to the page cannot get lost. */ int (*writeback)(struct page *, int *); - const int nr_pages = SWAP_CLUSTER_MAX; - int nr_to_write = nr_pages; + const int cluster_size = SWAP_CLUSTER_MAX; + int nr_to_write = cluster_size; writeback = mapping->a_ops->vm_writeback; if (writeback == NULL) @@ -209,7 +208,7 @@ page_cache_get(page); spin_unlock(&pagemap_lru_lock); (*writeback)(page, &nr_to_write); - max_scan -= (nr_pages - nr_to_write); + max_scan -= (cluster_size - nr_to_write); page_cache_release(page); spin_lock(&pagemap_lru_lock); continue; @@ -471,7 +470,7 @@ pgdat = pgdat_list; do need_more_balance |= kswapd_balance_pgdat(pgdat); - while ((pgdat = pgdat->node_next)); + while ((pgdat = pgdat->pgdat_next)); } while (need_more_balance); } @@ -499,7 +498,7 @@ if (kswapd_can_sleep_pgdat(pgdat)) continue; return 0; - } while ((pgdat = pgdat->node_next)); + } while ((pgdat = pgdat->pgdat_next)); return 1; } diff -Nru a/net/802/Makefile b/net/802/Makefile --- a/net/802/Makefile Thu Aug 1 14:17:40 2002 +++ b/net/802/Makefile Thu Aug 1 14:17:40 2002 @@ -6,6 +6,7 @@ obj-y := p8023.o +# Check the p8022 selections against net/core/Makefile. obj-$(CONFIG_SYSCTL) += sysctl_net_802.o obj-$(CONFIG_LLC) += p8022.o psnap.o llc_sendpdu.o llc_utility.o \ cl2llc.o llc_macinit.o diff -Nru a/net/Config.in b/net/Config.in --- a/net/Config.in Thu Aug 1 14:17:39 2002 +++ b/net/Config.in Thu Aug 1 14:17:39 2002 @@ -26,9 +26,6 @@ source net/ipv6/Config.in fi fi - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - source net/khttpd/Config.in - fi fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'Asynchronous Transfer Mode (ATM) (EXPERIMENTAL)' CONFIG_ATM diff -Nru a/net/Makefile b/net/Makefile --- a/net/Makefile Thu Aug 1 14:17:40 2002 +++ b/net/Makefile Thu Aug 1 14:17:40 2002 @@ -16,7 +16,6 @@ obj-$(CONFIG_INET) += ipv4/ obj-$(CONFIG_UNIX) += unix/ obj-$(CONFIG_IPV6) += ipv6/ -obj-$(CONFIG_KHTTPD) += khttpd/ obj-$(CONFIG_PACKET) += packet/ obj-$(CONFIG_NET_SCHED) += sched/ obj-$(CONFIG_BRIDGE) += bridge/ diff -Nru a/net/core/Makefile b/net/core/Makefile --- a/net/core/Makefile Thu Aug 1 14:17:41 2002 +++ b/net/core/Makefile Thu Aug 1 14:17:41 2002 @@ -2,7 +2,7 @@ # Makefile for the Linux networking core. # -export-objs := ext8022.o netfilter.o profile.o +export-objs := ext8022.o obj-y := sock.o skbuff.o iovec.o datagram.o scm.o @@ -16,7 +16,8 @@ obj-$(CONFIG_NET) += dev.o dev_mcast.o dst.o neighbour.o rtnetlink.o utils.o -ifneq ($(CONFIG_LLC),n) +# See p8022 in net/802/Makefile for config options to check +ifneq ($(CONFIG_LLC)$(CONFIG_TR)$(CONFIG_IPX)$(CONFIG_ATALK),) obj-y += ext8022.o endif diff -Nru a/net/ipv4/Makefile b/net/ipv4/Makefile --- a/net/ipv4/Makefile Thu Aug 1 14:17:39 2002 +++ b/net/ipv4/Makefile Thu Aug 1 14:17:39 2002 @@ -2,8 +2,6 @@ # Makefile for the Linux TCP/IP (INET) layer. # -export-objs = ipip.o ip_gre.o - obj-y := utils.o route.o inetpeer.o proc.o protocol.o \ ip_input.o ip_fragment.o ip_forward.o ip_options.o \ ip_output.o ip_sockglue.o \ diff -Nru a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c --- a/net/ipv4/ipconfig.c Thu Aug 1 14:17:36 2002 +++ b/net/ipv4/ipconfig.c Thu Aug 1 14:17:36 2002 @@ -469,7 +469,7 @@ /* - * Send RARP request packet over a signle interface. + * Send RARP request packet over a single interface. */ static void __init ic_rarp_send_if(struct ic_device *d) { diff -Nru a/net/ipx/Makefile b/net/ipx/Makefile --- a/net/ipx/Makefile Thu Aug 1 14:17:37 2002 +++ b/net/ipx/Makefile Thu Aug 1 14:17:37 2002 @@ -2,7 +2,7 @@ # Makefile for the Linux IPX layer. # -export-objs = af_ipx.o af_spx.o +export-objs = af_ipx.o obj-$(CONFIG_IPX) += ipx.o diff -Nru a/net/khttpd/Config.help b/net/khttpd/Config.help --- a/net/khttpd/Config.help Thu Aug 1 14:17:40 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,18 +0,0 @@ -CONFIG_KHTTPD - The kernel httpd acceleration daemon (kHTTPd) is a (limited) web - server built into the kernel. It is limited since it can only serve - files from the file system and cannot deal with executable content - such as CGI scripts. Serving files is sped up if you use kHTTPd. - If kHTTPd is not able to fulfill a request, it can transparently - pass it through to a user space web server such as apache. - - Saying "M" here builds the kHTTPd module; this is NOT enough to have - a working kHTTPd. For safety reasons, the module has to be activated - by doing a "echo 1 > /proc/sys/net/khttpd/start" after inserting the - module. - - Before using this, read the README in net/khttpd ! - - The kHTTPd is experimental. Be careful when using it on a production - machine. Also note that kHTTPd doesn't support virtual servers yet. - diff -Nru a/net/khttpd/Config.in b/net/khttpd/Config.in --- a/net/khttpd/Config.in Thu Aug 1 14:17:41 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,4 +0,0 @@ -# -# kHTTPd -# -tristate ' Kernel httpd acceleration (EXPERIMENTAL)' CONFIG_KHTTPD diff -Nru a/net/khttpd/Makefile b/net/khttpd/Makefile --- a/net/khttpd/Makefile Thu Aug 1 14:17:41 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,22 +0,0 @@ -# -# Makefile for kHTTPd -# - -obj-$(CONFIG_KHTTPD) += khttpd.o - -khttpd-objs := main.o accept.o datasending.o logging.o misc.o rfc.o \ - rfc_time.o security.o sockets.o sysctl.o userspace.o \ - waitheaders.o - -host-progs := make_times_h - -include $(TOPDIR)/Rules.make - -# Dependencies on generated files need to be listed explicitly - -$(obj)/rfc_time.o: $(obj)/times.h - -# Generated files - -$(obj)/times.h: $(obj)/make_times_h - $(obj)/make_times_h >$@ diff -Nru a/net/khttpd/README b/net/khttpd/README --- a/net/khttpd/README Thu Aug 1 14:17:41 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,224 +0,0 @@ -===== - -kHTTPd - Kernel httpd accelerator - -(C) 1999 by Arjan van de Ven -Licensed under the terms of the GNU General Public License - -===== - - -1. Introduction ---------------- - kHTTPd is a http-daemon (webserver) for Linux. kHTTPd is different from - other webservers in that it runs from within the Linux-kernel as a module - (device-driver). - - kHTTPd handles only static (file based) web-pages, and passes all requests - for non-static information to a regular userspace-webserver such as Apache or - Zeus. The userspace-daemon doesn't have to be altered in any way. - - Static web-pages are not a very complex thing to serve, but these are very - important nevertheless, since virtually all images are static, and a large - portion of the html-pages are static also. A "regular" webserver has little - added value for static pages, it is simply a "copy file to network"-operation. - This can be done very efficiently from within the Linux-kernel, for example - the nfs (network file system) daemon performs a similar task and also runs - in the kernel. - - By "accelerating" the simple case within the kernel, userspace daemons can - do what they are very good at: Generating user-specific, dynamic content. - - Note: This document sometimes uses "Apache" instead of "any webserver you - ever might want to use", just for reasons of readability. - - -2. Quick Start --------------- - - 1) compile and load the module - 2) configure the module in /proc/sys/net/khttpd if needed - 3) echo 1 > /proc/sys/net/khttpd/start - - unloading: - - echo 1 > /proc/sys/net/khttpd/stop - echo 1 > /proc/sys/net/khttpd/unload - rmmod khttpd - - - -3. Configuration ----------------- - - Modes of operation - ================== - - - There are two recommended modes of operation: - - 1) "Apache" is main webserver, kHTTPd is assistant - clientport -> 80 - serverport -> 8080 (or whatever) - - 2) kHTTPd is main webserver, "Apache" is assistant - clientport -> 8080 (or whatever) - serverport -> 80 - - - Configuring kHTTPd - ================== - - Before you can start using kHTTPd, you have to configure it. This - is done through the /proc filesystem, and can thus be done from inside - a script. Most parameters can only be set when kHTTPd is not active. - - The following things need configuration: - - 1) The port where kHTTPd should listen for requests - 2) The port (on "localhost") where "Apache" is listening - 3) The location of the documents (documentroot) - 4) The strings that indicate dynamic content (optional) - [ "cgi-bin" is added by default ] - - It is very important that the documentroot for kHTTPd matches the - documentroot for the userspace-daemon, as kHTTPd might "redirect" - any request to this userspace-daemon. - - A typical script (for the first mode of operation) to do this would - look like: - -#!/bin/sh -modprobe khttpd -echo 80 > /proc/sys/net/khttpd/clientport -echo 8080 > /proc/sys/net/khttpd/serverport -echo /var/www > /proc/sys/net/khttpd/documentroot -echo php3 > /proc/sys/net/khttpd/dynamic -echo shtml > /proc/sys/net/khttpd/dynamic -echo 1 > /proc/sys/net/khttpd/start - - For the second mode of operation, this would be: - -#!/bin/sh -modprobe khttpd -echo 8080 > /proc/sys/net/khttpd/clientport -echo 80 > /proc/sys/net/khttpd/serverport -echo /var/www > /proc/sys/net/khttpd/documentroot -echo php3 > /proc/sys/net/khttpd/dynamic -echo shtml > /proc/sys/net/khttpd/dynamic -echo 1 > /proc/sys/net/khttpd/start - - In this case, you also have to change the configuration of the - userspace-daemon. For Apache, you do this by changing - - Port 80 - - to - - Port 8080 - - - - Stopping kHTTPd - =============== - In order to change the configuration, you should stop kHTTPd by typing - echo 1 > /proc/sys/net/khttpd/stop - on a command-prompt. - - If you want to unload the module, you should type - echo 1 > /proc/sys/net/khttpd/unload - after stopping kHTTPd first. - - If this doesn't work fast enough for you (the commands above can wait for - a remote connection to close down), you can send the daemons a "HUP" - signal after you told them to stop. This will cause the daemon-threads to - stop immediately. - - Note that the daemons will restart immediately if they are not told to - stop. - - - -4. Permissions --------------- - The security model of kHTTPd is very strict. It can be, since there is a - userspace daemon that can handle the complex exceptions. - - kHTTPd only serves a file if - - 1) There is no "?" in the URL - 2) The URL starts with a "/" - 3) The file indicated by the URL exists - 4) The file is world-readable (*) - 5) The file is not a directory, executable or has the Sticky-bit - set (*) - 6) The URL doesn't contain any "forbidden" substrings such as ".." - and "cgi-bin" (*) - 7) The mime-type is known (*) - - The items marked with a (*) are configurable through the - sysctl-parameters in /proc/sys/net/khttpd. - - - In all cases where any of the above conditions isn't met, the - userspace-daemon is handed the request. - - - -5. Parameters -------------- - The following parameters are settable through /proc/sys/net/khttpd: - - Name Default Description - - serverport 8080 The port where kHTTPd listens on - - clientport 80 The port of the userspace - http-daemon - - threads 2 The number of server-threads. Should - be 1 per CPU for small websites, 2 - per CPU for big (the active files - do not fit in the RAM) websites. - - documentroot /var/www the directory where the - document-files are - - start 0 Set to 1 to start kHTTPd - (this also resets "stop" to 0) - - stop 0 Set to 1 to stop kHTTPd - (this also resets "start" to 0) - - unload 0 Set to 1 to prepare kHTTPd for - unloading of the module - - sloppymime 0 If set to 1, unknown mime-types are - set to text/html. If set to 0, - files with unknown mime-types are - handled by the userspace daemon - - perm_required S_IROTH Minimum permissions required - (for values see "man 2 stat") - - perm_forbid dir+sticky+ Permission-mask with "forbidden" - execute permissions. - (for values see "man 2 stat") - - dynamic cgi-bin .. Strings that, if they are a subset - of the URL, indicate "dynamic - content" - - maxconnect 1000 Maximum number of concurrent - connections - -6. More information -------------------- - More information about the architecture of kHTTPd, the mailinglist and - configuration-examples can be found at the kHTTPd homepage: - - http://www.fenrus.demon.nl - - Bugreports, patches, etc can be send to the mailinglist - (khttpd-users@zgp.org) or to khttpd@fenrus.demon.nl - diff -Nru a/net/khttpd/accept.c b/net/khttpd/accept.c --- a/net/khttpd/accept.c Thu Aug 1 14:17:36 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,129 +0,0 @@ -/* - -kHTTPd -- the next generation - -Accept connections - -*/ -/**************************************************************** - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ****************************************************************/ - -#include "structure.h" -#include "prototypes.h" -#include "sysctl.h" - -#include - -/* - -Purpose: - -AcceptConnections puts all "accepted" connections in the -"WaitForHeader" queue. - -Return value: - The number of accepted connections -*/ - - -int AcceptConnections(const int CPUNR, struct socket *Socket) -{ - struct tcp_opt *tp; - struct http_request *NewRequest; - struct socket *NewSock; - int count = 0; - int error; - - EnterFunction("AcceptConnections"); - - if (atomic_read(&ConnectCount)>sysctl_khttpd_maxconnect) - { - LeaveFunction("AcceptConnections - to many active connections"); - return 0; - } - - if (Socket==NULL) return 0; - - tp = tcp_sk(Socket->sk); - /* - Quick test to see if there are connections on the queue. - This is cheaper than accept() itself because this saves us - the allocation of a new socket. (Which doesn't seem to be - used anyway) - */ - if (tp->accept_queue==NULL) - { - return 0; - } - - error = 0; - while (error>=0) - { - NewSock = sock_alloc(); - if (NewSock==NULL) - break; - - - NewSock->type = Socket->type; - NewSock->ops = Socket->ops; - - - error = Socket->ops->accept(Socket,NewSock,O_NONBLOCK); - - - if (error<0) - { - sock_release(NewSock); - break; - } - - if (NewSock->sk->state==TCP_CLOSE) - { - sock_release(NewSock); - continue; - } - - /* Allocate a request-entry for the connection */ - NewRequest = kmalloc(sizeof(struct http_request),(int)GFP_KERNEL); - - if (NewRequest == NULL) - { - Send50x(NewSock); /* Service not available. Try again later */ - sock_release(NewSock); - break; - } - memset(NewRequest,0,sizeof(struct http_request)); - - NewRequest->sock = NewSock; - - NewRequest->Next = threadinfo[CPUNR].WaitForHeaderQueue; - - init_waitqueue_entry(&NewRequest->sleep,current); - - add_wait_queue(NewSock->sk->sleep,&(NewRequest->sleep)); - - threadinfo[CPUNR].WaitForHeaderQueue = NewRequest; - - atomic_inc(&ConnectCount); - - - count++; - } - - LeaveFunction("AcceptConnections"); - return count; -} diff -Nru a/net/khttpd/datasending.c b/net/khttpd/datasending.c --- a/net/khttpd/datasending.c Thu Aug 1 14:17:39 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,242 +0,0 @@ -/* - -kHTTPd -- the next generation - -Send actual file-data to the connections - -*/ -/**************************************************************** - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ****************************************************************/ - -/* - -Purpose: - -DataSending does the actual sending of file-data to the socket. - -Note: Since asynchronous reads do not -yet- exists, this might block! - -Return value: - The number of requests that changed status (ie: made some progress) -*/ - -#include -#include -#include - -#include - -#include -#include - -#include "structure.h" -#include "prototypes.h" - -static char *Block[CONFIG_KHTTPD_NUMCPU]; - -/* - -This send_actor is for use with do_generic_file_read (ie sendfile()) -It sends the data to the socket indicated by desc->buf. - -*/ -static int sock_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size) -{ - int written; - char *kaddr; - unsigned long count = desc->count; - struct socket *sock = (struct socket *) desc->buf; - mm_segment_t old_fs; - - if (size > count) - size = count; - old_fs = get_fs(); - set_fs(KERNEL_DS); - - kaddr = kmap(page); - written = SendBuffer_async(sock, kaddr + offset, size); - kunmap(page); - set_fs(old_fs); - if (written < 0) { - desc->error = written; - written = 0; - } - desc->count = count - written; - desc->written += written; - return written; -} - - - - -int DataSending(const int CPUNR) -{ - struct http_request *CurrentRequest,**Prev; - int count = 0; - - EnterFunction("DataSending"); - - Prev = &(threadinfo[CPUNR].DataSendingQueue); - CurrentRequest = threadinfo[CPUNR].DataSendingQueue; - while (CurrentRequest!=NULL) - { - int ReadSize,Space; - int retval; - - - /* First, test if the socket has any buffer-space left. - If not, no need to actually try to send something. */ - - - Space = sock_wspace(CurrentRequest->sock->sk); - - ReadSize = min_t(int, 4 * 4096, CurrentRequest->FileLength - CurrentRequest->BytesSent); - ReadSize = min_t(int, ReadSize, Space); - - if (ReadSize>0) - { - struct inode *inode; - - inode = CurrentRequest->filp->f_dentry->d_inode; - - if (inode->i_mapping->a_ops->readpage) { - /* This does the actual transfer using sendfile */ - read_descriptor_t desc; - loff_t *ppos; - - CurrentRequest->filp->f_pos = CurrentRequest->BytesSent; - - ppos = &CurrentRequest->filp->f_pos; - - desc.written = 0; - desc.count = ReadSize; - desc.buf = (char *) CurrentRequest->sock; - desc.error = 0; - do_generic_file_read(CurrentRequest->filp, ppos, &desc, sock_send_actor); - if (desc.written>0) - { - CurrentRequest->BytesSent += desc.written; - count++; - } - } - else /* FS doesn't support sendfile() */ - { - mm_segment_t oldfs; - CurrentRequest->filp->f_pos = CurrentRequest->BytesSent; - - oldfs = get_fs(); set_fs(KERNEL_DS); - retval = CurrentRequest->filp->f_op->read(CurrentRequest->filp, Block[CPUNR], ReadSize, &CurrentRequest->filp->f_pos); - set_fs(oldfs); - - if (retval>0) - { - retval = SendBuffer_async(CurrentRequest->sock,Block[CPUNR],(size_t)retval); - if (retval>0) - { - CurrentRequest->BytesSent += retval; - count++; - } - } - } - - } - - /* - If end-of-file or closed connection: Finish this request - by moving it to the "logging" queue. - */ - if ((CurrentRequest->BytesSent>=CurrentRequest->FileLength)|| - (CurrentRequest->sock->sk->state!=TCP_ESTABLISHED - && CurrentRequest->sock->sk->state!=TCP_CLOSE_WAIT)) - { - struct http_request *Next; - Next = CurrentRequest->Next; - - lock_sock(CurrentRequest->sock->sk); - if (CurrentRequest->sock->sk->state == TCP_ESTABLISHED || - CurrentRequest->sock->sk->state == TCP_CLOSE_WAIT) - { - struct tcp_opt *tp = - tcp_sk(CurrentRequest->sock->sk); - tp->nonagle = 0; - tcp_push_pending_frames(CurrentRequest->sock->sk, tp); - } - release_sock(CurrentRequest->sock->sk); - - (*Prev) = CurrentRequest->Next; - - CurrentRequest->Next = threadinfo[CPUNR].LoggingQueue; - threadinfo[CPUNR].LoggingQueue = CurrentRequest; - - CurrentRequest = Next; - continue; - - } - - - Prev = &(CurrentRequest->Next); - CurrentRequest = CurrentRequest->Next; - } - - LeaveFunction("DataSending"); - return count; -} - -int InitDataSending(int ThreadCount) -{ - int I,I2; - - EnterFunction("InitDataSending"); - I=0; - while (INext; - CleanUpRequest(CurrentRequest); - CurrentRequest=Next; - } - - threadinfo[CPUNR].DataSendingQueue = NULL; - - free_page( (unsigned long)Block[CPUNR]); - LeaveFunction("StopDataSending"); -} diff -Nru a/net/khttpd/logging.c b/net/khttpd/logging.c --- a/net/khttpd/logging.c Thu Aug 1 14:17:37 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,95 +0,0 @@ -/* - -kHTTPd -- the next generation - -logging.c takes care of shutting down a connection. - -*/ -/**************************************************************** - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ****************************************************************/ - -#include -#include -#include -#include -#include -#include "structure.h" -#include "prototypes.h" - -/* - -Purpose: - -Logging() terminates "finished" connections and will eventually log them to a -userspace daemon. - -Return value: - The number of requests that changed status, thus the number of connections - that shut down. -*/ - - -int Logging(const int CPUNR) -{ - struct http_request *CurrentRequest,*Req; - int count = 0; - - EnterFunction("Logging"); - - CurrentRequest = threadinfo[CPUNR].LoggingQueue; - - /* For now, all requests are removed immediatly, but this changes - when userspace-logging is added. */ - - while (CurrentRequest!=NULL) - { - - Req = CurrentRequest->Next; - - CleanUpRequest(CurrentRequest); - - threadinfo[CPUNR].LoggingQueue = Req; - - CurrentRequest = Req; - - count++; - - } - - LeaveFunction("Logging"); - return count; -} - - - -void StopLogging(const int CPUNR) -{ - struct http_request *CurrentRequest,*Next; - - EnterFunction("StopLogging"); - CurrentRequest = threadinfo[CPUNR].LoggingQueue; - - while (CurrentRequest!=NULL) - { - Next=CurrentRequest->Next; - CleanUpRequest(CurrentRequest); - CurrentRequest=Next; - } - - threadinfo[CPUNR].LoggingQueue = NULL; - LeaveFunction("StopLogging"); -} diff -Nru a/net/khttpd/main.c b/net/khttpd/main.c --- a/net/khttpd/main.c Thu Aug 1 14:17:36 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,394 +0,0 @@ -/* - -kHTTPd -- the next generation - -Main program - - -kHTTPd TNG consists of 1 thread, this main-thread handles ALL connections -simultanious. It does this by keeping queues with the requests in different -stages. - -The stages are - - - TCP/IP connection is not accepted yet -WaitForHeaders - Connection is accepted, waiting for headers -DataSending - Headers decoded, sending file-data -Userspace - Requires userspace daemon -Logging - The request is finished, cleanup and logging - -A typical flow for a request would be: - - -WaitForHeaders -DataSending -Logging - -or - - -WaitForHeaders -Userspace - - - -*/ -/**************************************************************** - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ****************************************************************/ - - -static int errno; -#define __KERNEL_SYSCALLS__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "structure.h" -#include "prototypes.h" -#include "sysctl.h" - -struct khttpd_threadinfo threadinfo[CONFIG_KHTTPD_NUMCPU]; /* The actual work-queues */ - - -atomic_t ConnectCount; -atomic_t DaemonCount; - -static int ActualThreads; /* The number of actual, active threads */ - - -static int ConnectionsPending(int CPUNR) -{ - if (threadinfo[CPUNR].DataSendingQueue!=NULL) return O_NONBLOCK; - if (threadinfo[CPUNR].WaitForHeaderQueue!=NULL) return O_NONBLOCK; - if (threadinfo[CPUNR].LoggingQueue!=NULL) return O_NONBLOCK; - if (threadinfo[CPUNR].UserspaceQueue!=NULL) return O_NONBLOCK; - return 0; -} - - - -static wait_queue_head_t DummyWQ[CONFIG_KHTTPD_NUMCPU]; -static atomic_t Running[CONFIG_KHTTPD_NUMCPU]; - -static int MainDaemon(void *cpu_pointer) -{ - int CPUNR; - sigset_t tmpsig; - - DECLARE_WAITQUEUE(main_wait,current); - - MOD_INC_USE_COUNT; - - - CPUNR=0; - if (cpu_pointer!=NULL) - CPUNR=(int)*(int*)cpu_pointer; - - sprintf(current->comm,"khttpd - %i",CPUNR); - daemonize(); - - init_waitqueue_head(&(DummyWQ[CPUNR])); - - - /* Block all signals except SIGKILL, SIGSTOP and SIGHUP */ - spin_lock_irq(¤t->sigmask_lock); - tmpsig = current->blocked; - siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP)| sigmask(SIGHUP)); - recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); - - - if (MainSocket->sk==NULL) - return 0; - add_wait_queue_exclusive(MainSocket->sk->sleep,&(main_wait)); - atomic_inc(&DaemonCount); - atomic_set(&Running[CPUNR],1); - - while (sysctl_khttpd_stop==0) - { - int changes = 0; - - - - changes +=AcceptConnections(CPUNR,MainSocket); - if (ConnectionsPending(CPUNR)) - { - changes +=WaitForHeaders(CPUNR); - changes +=DataSending(CPUNR); - changes +=Userspace(CPUNR); - changes +=Logging(CPUNR); - /* Test for incoming connections _again_, because it is possible - one came in during the other steps, and the wakeup doesn't happen - then. - */ - changes +=AcceptConnections(CPUNR,MainSocket); - } - - if (changes==0) - { - (void)interruptible_sleep_on_timeout(&(DummyWQ[CPUNR]),1); - if (CPUNR==0) - UpdateCurrentDate(); - } - - if (signal_pending(current)!=0) - { - (void)printk(KERN_NOTICE "kHTTPd: Ring Ring - signal received\n"); - break; - } - - } - - remove_wait_queue(MainSocket->sk->sleep,&(main_wait)); - - StopWaitingForHeaders(CPUNR); - StopDataSending(CPUNR); - StopUserspace(CPUNR); - StopLogging(CPUNR); - - atomic_set(&Running[CPUNR],0); - atomic_dec(&DaemonCount); - (void)printk(KERN_NOTICE "kHTTPd: Daemon %i has ended\n",CPUNR); - MOD_DEC_USE_COUNT; - return 0; -} - -static int CountBuf[CONFIG_KHTTPD_NUMCPU]; - - - -/* - -The ManagementDaemon has a very simple task: Start the real daemons when the user wants us -to, and cleanup when the users wants to unload the module. - -Initially, kHTTPd didn't have this thread, but it is the only way to have "delayed activation", -a feature required to prevent accidental activations resulting in unexpected backdoors. - -*/ -static int ManagementDaemon(void *unused) -{ - sigset_t tmpsig; - int waitpid_result; - - DECLARE_WAIT_QUEUE_HEAD(WQ); - - - sprintf(current->comm,"khttpd manager"); - daemonize(); - - - /* Block all signals except SIGKILL and SIGSTOP */ - spin_lock_irq(¤t->sigmask_lock); - tmpsig = current->blocked; - siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP) ); - recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); - - - /* main loop */ - while (sysctl_khttpd_unload==0) - { - int I; - - - /* First : wait for activation */ - - sysctl_khttpd_start = 0; - - while ( (sysctl_khttpd_start==0) && (!signal_pending(current)) && (sysctl_khttpd_unload==0) ) - { - current->state = TASK_INTERRUPTIBLE; - interruptible_sleep_on_timeout(&WQ,HZ); - } - - if ( (signal_pending(current)) || (sysctl_khttpd_unload!=0) ) - break; - - /* Then start listening and spawn the daemons */ - - if (StartListening(sysctl_khttpd_serverport)==0) - { - continue; - } - - ActualThreads = sysctl_khttpd_threads; - if (ActualThreads<1) - ActualThreads = 1; - - if (ActualThreads>CONFIG_KHTTPD_NUMCPU) - ActualThreads = CONFIG_KHTTPD_NUMCPU; - - /* Write back the actual value */ - - sysctl_khttpd_threads = ActualThreads; - - InitUserspace(ActualThreads); - - if (InitDataSending(ActualThreads)!=0) - { - StopListening(); - continue; - } - if (InitWaitHeaders(ActualThreads)!=0) - { - I=0; - while (I0) - interruptible_sleep_on_timeout(&WQ,HZ); - StopListening(); - } - - - - } - - sysctl_khttpd_stop = 1; - - /* Wait for the daemons to stop, one second per iteration */ - while (atomic_read(&DaemonCount)>0) - interruptible_sleep_on_timeout(&WQ,HZ); - - - waitpid_result = 1; - /* reap the zombie-daemons */ - while (waitpid_result>0) - waitpid_result = waitpid(-1,NULL,__WCLONE|WNOHANG); - - StopListening(); - - - (void)printk(KERN_NOTICE "kHTTPd: Management daemon stopped. \n You can unload the module now.\n"); - - MOD_DEC_USE_COUNT; - - return 0; -} - -int __init khttpd_init(void) -{ - int I; - - MOD_INC_USE_COUNT; - - I=0; - while (I -#include - -static time_t GetDay(int D,int M,int Y) -{ - struct tm TM; - - TM.tm_sec = 0; - TM.tm_min = 0; - TM.tm_hour = 0; - TM.tm_mday = D; - TM.tm_mon = M; - TM.tm_wday = 0; - TM.tm_yday = 0; - TM.tm_year = Y-1900; - TM.tm_isdst = 0; - - return mktime(&TM); - -} -static int WeekGetDay(int D,int M,int Y) -{ - struct tm TM; - - TM.tm_sec = 0; - TM.tm_min = 0; - TM.tm_hour = 0; - TM.tm_mday = D; - TM.tm_mon = M; - TM.tm_year = Y-1900; - TM.tm_isdst = 0; - TM.tm_wday = 0; - TM.tm_yday = 0; - - (void)mktime(&TM); - - return TM.tm_wday; - -} - -int main(void) -{ - int M,Y; - - printf("static time_t TimeDays[10][13] = { \n"); - - Y=1997; - while (Y<2007) - { - M=0; - printf(" { "); - while (M<12) - { - printf("%i",(int)GetDay(1,M,Y)); - printf(",\t"); - - M++; - } - - printf("%i } ",(int)GetDay(1,0,Y+1)); - if (Y!=2006) printf(","); - printf("\n"); - Y++; - } - printf("};\n"); - - printf("static int WeekDays[10][13] = { \n"); - - Y=1997; - while (Y<2007) - { - M=0; - printf(" { "); - while (M<12) - { - printf("%i",(int)WeekGetDay(1,M,Y)); - printf(",\t"); - - M++; - } - - printf("%i } ",(int)WeekGetDay(1,0,Y+1)); - if (Y!=2006) printf(","); - printf("\n"); - Y++; - } - printf("};\n"); - printf("#define KHTTPD_YEAROFFSET 1997\n"); - printf("#define KHTTPD_NUMYEARS 10\n"); - - return 0; -} diff -Nru a/net/khttpd/misc.c b/net/khttpd/misc.c --- a/net/khttpd/misc.c Thu Aug 1 14:17:40 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,242 +0,0 @@ -/* - -kHTTPd -- the next generation - -General functions - -*/ -/**************************************************************** - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ****************************************************************/ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include "structure.h" -#include "prototypes.h" - -#ifndef ECONNRESET -#define ECONNRESET 102 -#endif - - -/* - -Readrest reads and discards all pending input on a socket. This is required -before closing the socket. - -*/ -static void ReadRest(struct socket *sock) -{ - struct msghdr msg; - struct iovec iov; - int len; - - mm_segment_t oldfs; - - - EnterFunction("ReadRest"); - - - if (sock->sk==NULL) - return; - - len = 1; - - while (len>0) - { - static char Buffer[1024]; /* Never read, so doesn't need to - be SMP safe */ - - msg.msg_name = 0; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = MSG_DONTWAIT; - - msg.msg_iov->iov_base = &Buffer[0]; - msg.msg_iov->iov_len = (__kernel_size_t)1024; - - len = 0; - oldfs = get_fs(); set_fs(KERNEL_DS); - len = sock_recvmsg(sock,&msg,1024,MSG_DONTWAIT); - set_fs(oldfs); - } - LeaveFunction("ReadRest"); -} - - -/* - -CleanUpRequest takes care of shutting down the connection, closing the file-pointer -and releasing the memory of the request-structure. Do not try to access it afterwards! - -*/ -void CleanUpRequest(struct http_request *Req) -{ - EnterFunction("CleanUpRequest"); - - /* Close the socket ....*/ - if ((Req->sock!=NULL)&&(Req->sock->sk!=NULL)) - { - ReadRest(Req->sock); - remove_wait_queue(Req->sock->sk->sleep,&(Req->sleep)); - sock_release(Req->sock); - } - - /* ... and the file-pointer ... */ - if (Req->filp!=NULL) - { - fput(Req->filp); - Req->filp = NULL; - } - - - /* ... and release the memory for the structure. */ - kfree(Req); - - atomic_dec(&ConnectCount); - LeaveFunction("CleanUpRequest"); -} - - -/* - -SendBuffer and Sendbuffer_async send "Length" bytes from "Buffer" to the "sock"et. -The _async-version is non-blocking. - -A positive return-value indicates the number of bytes sent, a negative value indicates -an error-condition. - -*/ -int SendBuffer(struct socket *sock, const char *Buffer,const size_t Length) -{ - struct msghdr msg; - mm_segment_t oldfs; - struct iovec iov; - int len; - - EnterFunction("SendBuffer"); - - msg.msg_name = 0; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = MSG_NOSIGNAL; - msg.msg_iov->iov_len = (__kernel_size_t)Length; - msg.msg_iov->iov_base = (char*) Buffer; - - - len = 0; - - oldfs = get_fs(); set_fs(KERNEL_DS); - len = sock_sendmsg(sock,&msg,(size_t)(Length-len)); - set_fs(oldfs); - LeaveFunction("SendBuffer"); - return len; -} - -int SendBuffer_async(struct socket *sock, const char *Buffer,const size_t Length) -{ - struct msghdr msg; - mm_segment_t oldfs; - struct iovec iov; - int len; - - EnterFunction("SendBuffer_async"); - msg.msg_name = 0; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = MSG_DONTWAIT|MSG_NOSIGNAL; - msg.msg_iov->iov_base = (char*) Buffer; - msg.msg_iov->iov_len = (__kernel_size_t)Length; - - - if (sock->sk) - { - oldfs = get_fs(); set_fs(KERNEL_DS); - len = sock_sendmsg(sock,&msg,(size_t)(Length)); - set_fs(oldfs); - } else - { - return -ECONNRESET; - } - - LeaveFunction("SendBuffer_async"); - return len; -} - - - - -/* - -HTTP header shortcuts. Hardcoded since these might be called in a low-memory -situation, and they don't change anyhow. - -*/ - -static char NoPerm[] = "HTTP/1.0 403 Forbidden\r\nServer: kHTTPd 0.1.6\r\n\r\n"; -static char TryLater[] = "HTTP/1.0 503 Service Unavailable\r\nServer: kHTTPd 0.1.6\r\nContent-Length: 15\r\n\r\nTry again later"; -static char NotModified[] = "HTTP/1.0 304 Not Modified\r\nServer: kHTTPd 0.1.6\r\n\r\n"; - - -void Send403(struct socket *sock) -{ - EnterFunction("Send403"); - (void)SendBuffer(sock,NoPerm,strlen(NoPerm)); - LeaveFunction("Send403"); -} - -void Send304(struct socket *sock) -{ - EnterFunction("Send304"); - (void)SendBuffer(sock,NotModified,strlen(NotModified)); - LeaveFunction("Send304"); -} - -void Send50x(struct socket *sock) -{ - EnterFunction("Send50x"); - (void)SendBuffer(sock,TryLater,strlen(TryLater)); - LeaveFunction("Send50x"); -} - diff -Nru a/net/khttpd/prototypes.h b/net/khttpd/prototypes.h --- a/net/khttpd/prototypes.h Thu Aug 1 14:17:41 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,121 +0,0 @@ -#ifndef _INCLUDE_GUARD_PROTOTYPES_H -#define _INCLUDE_GUARD_PROTOTYPES_H - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "structure.h" - - -/* General defines and stuff */ - - -#define CONFIG_KHTTPD_NUMCPU 16 /* Maximum number of threads */ - -#ifdef OOPSTRACE -#define EnterFunction(x) printk("Enter: %s, %s line %i\n",x,__FILE__,__LINE__) -#define LeaveFunction(x) printk("Leave: %s, %s line %i\n",x,__FILE__,__LINE__) -#else -#define EnterFunction(x) do {} while (0) -#define LeaveFunction(x) do {} while (0) -#endif - - - -/* sockets.c */ -int StartListening(const int Port); -void StopListening(void); - -extern struct socket *MainSocket; - - -/* sysctl.c */ -void StartSysctl(void); -void EndSysctl(void); - -extern int sysctl_khttpd_stop; - - -/* main.c */ - - -extern struct khttpd_threadinfo threadinfo[CONFIG_KHTTPD_NUMCPU]; -extern char CurrentTime[]; -extern atomic_t ConnectCount; -extern struct wait_queue main_wait[CONFIG_KHTTPD_NUMCPU]; - -/* misc.c */ - -void CleanUpRequest(struct http_request *Req); -int SendBuffer(struct socket *sock, const char *Buffer,const size_t Length); -int SendBuffer_async(struct socket *sock, const char *Buffer,const size_t Length); -void Send403(struct socket *sock); -void Send304(struct socket *sock); -void Send50x(struct socket *sock); - -/* accept.c */ - -int AcceptConnections(const int CPUNR,struct socket *Socket); - -/* waitheaders.c */ - -int WaitForHeaders(const int CPUNR); -void StopWaitingForHeaders(const int CPUNR); -int InitWaitHeaders(int ThreadCount); - -/* datasending.c */ - -int DataSending(const int CPUNR); -void StopDataSending(const int CPUNR); -int InitDataSending(int ThreadCount); - - -/* userspace.c */ - -int Userspace(const int CPUNR); -void StopUserspace(const int CPUNR); -void InitUserspace(const int CPUNR); - - -/* rfc_time.c */ - -void time_Unix2RFC(const time_t Zulu,char *Buffer); -void UpdateCurrentDate(void); -time_t mimeTime_to_UnixTime(char *Q); -extern int CurrentTime_i; - -/* rfc.c */ - -void ParseHeader(char *Buffer,const int length, struct http_request *Head); -char *ResolveMimeType(const char *File,__kernel_size_t *Len); -void AddMimeType(const char *Ident,const char *Type); -void SendHTTPHeader(struct http_request *Request); - - - -/* security.c */ - -struct file *OpenFileForSecurity(char *Filename); -void AddDynamicString(const char *String); -void GetSecureString(char *String); - - -/* logging.c */ - -int Logging(const int CPUNR); -void StopLogging(const int CPUNR); - - -/* Other prototypes */ - - - -#endif diff -Nru a/net/khttpd/rfc.c b/net/khttpd/rfc.c --- a/net/khttpd/rfc.c Thu Aug 1 14:17:40 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,374 +0,0 @@ -/* - -kHTTPd -- the next generation - -RFC related functions (headers and stuff) - -*/ - -/**************************************************************** - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ****************************************************************/ - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - - -#include "prototypes.h" -#include "structure.h" -#include "sysctl.h" - - -#define KHTTPD_NUMMIMETYPES 40 - -static atomic_t MimeCount; - -struct MimeType -{ - __u32 identifier; - char type[64-sizeof(__u32)-sizeof(__kernel_size_t)]; - __kernel_size_t len; -}; - -static struct MimeType MimeTypes[KHTTPD_NUMMIMETYPES]; - - -void AddMimeType(const char *Ident,const char *Type) -{ - __u32 *I; - - EnterFunction("AddMimeType"); - - if (strlen(Ident)!=4) - { - (void)printk(KERN_ERR "httpd: Only 4-byte mime-identifiers are accepted\n"); - return; - } - - if (strlen(Type)>(64-sizeof(__u32)-sizeof(__kernel_size_t) ) ) - { - (void)printk(KERN_ERR "httpd: Mime-string too long.\n"); - return; - } - - I=(__u32*)Ident; - - /* FIXME: Need to lock-down all access to the mime-structure here */ - /* For now, just don't add mime-types after initialisation */ - - - MimeTypes[atomic_read(&MimeCount)].identifier=*I; - strncpy(MimeTypes[atomic_read(&MimeCount)].type,Type,(64-sizeof(__u32)-sizeof(__kernel_size_t))); - MimeTypes[atomic_read(&MimeCount)].len = strlen(Type); - - atomic_inc(&MimeCount); - LeaveFunction("AddMimeType"); -} - - -char *ResolveMimeType(const char *File,__kernel_size_t *Len) -/* - - The returned string is for READ ONLY, ownership of the memory is NOT - transferred. - -*/ -{ - __u32 *I; - int pos,lc,filelen; - - EnterFunction("ResolveMimeType"); - - *Len = 0; - - if (File==NULL) - return NULL; - - filelen = (int)strlen(File); - - if (filelen<4) - { - return NULL; - } - - /* The Merced-people are NOT going to like this! So this has to be fixed - in a later stage. */ - - pos = filelen-4; - I=(__u32*)(File+pos); - - lc=0; - - while (lcMimeType; - iov[2].iov_len = Request->MimeLength; - - iov[3].iov_base = HeaderPart7; - iov[3].iov_len = 18; - - - sprintf(Request->LengthS,"%i",Request->FileLength); - iov[4].iov_base = Request->LengthS; - iov[4].iov_len = strlen(Request->LengthS); - iov[5].iov_base = HeaderPart9; - iov[5].iov_len = 4; - - len2=15+16+18+iov[2].iov_len+iov[4].iov_len+4; - - - len = 0; - - - oldfs = get_fs(); set_fs(KERNEL_DS); - len = sock_sendmsg(Request->sock,&msg,len2); - set_fs(oldfs); - - - return; -} -#else -void SendHTTPHeader(struct http_request *Request) -{ - struct msghdr msg; - mm_segment_t oldfs; - struct iovec iov[9]; - int len,len2; - __kernel_size_t slen; - - EnterFunction("SendHTTPHeader"); - - msg.msg_name = 0; - msg.msg_namelen = 0; - msg.msg_iov = &(iov[0]); - msg.msg_iovlen = 9; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; /* Synchronous for now */ - - iov[0].iov_base = HeaderPart1; - iov[0].iov_len = 45; - iov[1].iov_base = CurrentTime; - iov[1].iov_len = 29; - iov[2].iov_base = HeaderPart3; - iov[2].iov_len = 16; - - iov[3].iov_base = Request->MimeType; - iov[3].iov_len = Request->MimeLength; - - iov[4].iov_base = HeaderPart5; - iov[4].iov_len = 17; - iov[5].iov_base = &(Request->TimeS[0]); - iov[5].iov_len = 29; - iov[6].iov_base = HeaderPart7; - iov[6].iov_len = 18; - iov[7].iov_base = &(Request->LengthS[0]); - slen = strlen(Request->LengthS); - iov[7].iov_len = slen; - iov[8].iov_base = HeaderPart9; - iov[8].iov_len = 4; - - len2=45+2*29+16+17+18+slen+4+iov[3].iov_len; - - len = 0; - - oldfs = get_fs(); set_fs(KERNEL_DS); - len = sock_sendmsg(Request->sock,&msg,len2); - set_fs(oldfs); - LeaveFunction("SendHTTPHeader"); - - - return; -} -#endif - - - -/* - -Parse a HTTP-header. Be careful for buffer-overflows here, this is the most important -place for this, since the remote-user controls the data. - -*/ -void ParseHeader(char *Buffer,const int length, struct http_request *Head) -{ - char *Endval,*EOL,*tmp; - - EnterFunction("ParseHeader"); - Endval = Buffer + length; - - /* We want to parse only the first header if multiple headers are present */ - tmp = strstr(Buffer,"\r\n\r\n"); - if (tmp!=NULL) - Endval = tmp; - - - while (BufferHTTPVER = 9; - } else - Head->HTTPVER = 10; - - if (tmp>Endval) continue; - - strncpy(Head->FileName,sysctl_khttpd_docroot,sizeof(Head->FileName)); - PrefixLen = strlen(sysctl_khttpd_docroot); - Head->FileNameLength = min_t(unsigned int, 255, tmp - Buffer + PrefixLen); - - strncat(Head->FileName,Buffer,min_t(unsigned int, 255 - PrefixLen, tmp - Buffer)); - - Buffer=EOL+1; -#ifdef BENCHMARK - break; -#endif - continue; - } -#ifndef BENCHMARK - if (strncmp("If-Modified-Since: ",Buffer,19)==0) - { - Buffer+=19; - - strncpy(Head->IMS,Buffer,min_t(unsigned int, 127,EOL-Buffer-1)); - - Buffer=EOL+1; - continue; - } - - if (strncmp("User-Agent: ",Buffer,12)==0) - { - Buffer+=12; - - strncpy(Head->Agent,Buffer,min_t(unsigned int, 127,EOL-Buffer-1)); - - Buffer=EOL+1; - continue; - } - - - if (strncmp("Host: ",Buffer,6)==0) - { - Buffer+=6; - - strncpy(Head->Host,Buffer,min_t(unsigned int, 127,EOL-Buffer-1)); - - Buffer=EOL+1; - continue; - } -#endif - Buffer = EOL+1; /* Skip line */ - } - LeaveFunction("ParseHeader"); -} diff -Nru a/net/khttpd/rfc_time.c b/net/khttpd/rfc_time.c --- a/net/khttpd/rfc_time.c Thu Aug 1 14:17:36 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,227 +0,0 @@ -/* - -Functions related to time: - -1) rfc (string) time to unix-time -2) unix-time to rfc (string) time -3) current time to rfc (string) time for the "Date:" header - -*/ - -/**************************************************************** - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ****************************************************************/ - -#include -#include -#include -#include - - -#include "times.h" -#include "prototypes.h" -static char *dayName[7] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - -static char *monthName[12] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - - -char CurrentTime[64]; -int CurrentTime_i; - - -static char itoa_h[60]={'0','0','0','0','0','0','0','0','0','0', - '1','1','1','1','1','1','1','1','1','1', - '2','2','2','2','2','2','2','2','2','2', - '3','3','3','3','3','3','3','3','3','3', - '4','4','4','4','4','4','4','4','4','4', - '5','5','5','5','5','5','5','5','5','5'}; - -static char itoa_l[60]={'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','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'}; -void time_Unix2RFC(const time_t Zulu,char *Buffer) -{ - int Y=0,M=0,D=0; - int H=0,Min=0,S=0,WD=0; - int I,I2; - time_t rest; - - - - I=0; - while (IZulu) - break; - I++; - } - - Y=--I; - if (I<0) - { - Y=0; - goto BuildYear; - } - I2=0; - while (I2<=12) - { - if (TimeDays[I][I2]>Zulu) - break; - I2++; - } - - M=I2-1; - - rest=Zulu - TimeDays[Y][M]; - WD=WeekDays[Y][M]; - D=rest/86400; - rest=rest%86400; - WD+=D; - WD=WD%7; - H=rest/3600; - rest=rest%3600; - Min=rest/60; - rest=rest%60; - S=rest; - -BuildYear: - Y+=KHTTPD_YEAROFFSET; - - - /* Format: Day, 01 Mon 1999 01:01:01 GMT */ - -/* - We want to do - - sprintf( Buffer, "%s, %02i %s %04i %02i:%02i:%02i GMT", - dayName[ WD ], D+1, monthName[ M ], Y, - H, Min, S - ); - - but this is very expensive. Since the string is fixed length, - it is filled manually. -*/ - Buffer[0]=dayName[WD][0]; - Buffer[1]=dayName[WD][1]; - Buffer[2]=dayName[WD][2]; - Buffer[3]=','; - Buffer[4]=' '; - Buffer[5]=itoa_h[D+1]; - Buffer[6]=itoa_l[D+1]; - Buffer[7]=' '; - Buffer[8]=monthName[M][0]; - Buffer[9]=monthName[M][1]; - Buffer[10]=monthName[M][2]; - Buffer[11]=' '; - Buffer[12]=itoa_l[Y/1000]; - Buffer[13]=itoa_l[(Y/100)%10]; - Buffer[14]=itoa_l[(Y/10)%10]; - Buffer[15]=itoa_l[Y%10]; - Buffer[16]=' '; - Buffer[17]=itoa_h[H]; - Buffer[18]=itoa_l[H]; - Buffer[19]=':'; - Buffer[20]=itoa_h[Min]; - Buffer[21]=itoa_l[Min]; - Buffer[22]=':'; - Buffer[23]=itoa_h[S]; - Buffer[24]=itoa_l[S]; - Buffer[25]=' '; - Buffer[26]='G'; - Buffer[27]='M'; - Buffer[28]='T'; - Buffer[29]=0; - - - - -} - -void UpdateCurrentDate(void) -{ - struct timeval tv; - - do_gettimeofday(&tv); - if (CurrentTime_i!=tv.tv_sec) - time_Unix2RFC(tv.tv_sec,CurrentTime); - - CurrentTime_i = tv.tv_sec; -} - -static int MonthHash[32] = {0,0,7,0,0,0,0,0,0,0,0,3,0,0,0,2,6,0,5,0,9,8,4,0,0,11,1,10,0,0,0,0}; - -#define is_digit(c) ((c) >= '0' && (c) <= '9') - -__inline static int skip_atoi(char **s) -{ - int i=0; - - while (is_digit(**s)) - i = i*10 + *((*s)++) - '0'; - return i; -} - -time_t mimeTime_to_UnixTime(char *Q) -{ - int Y,M,D,H,Min,S; - unsigned int Hash; - time_t Temp; - char *s,**s2; - - s=Q; - s2=&s; - - if (strlen(s)<30) return 0; - if (s[3]!=',') return 0; - if (s[19]!=':') return 0; - - s+=5; /* Skip day of week */ - D = skip_atoi(s2); /* Day of month */ - s++; - Hash = (unsigned char)s[0]+(unsigned char)s[2]; - Hash = (Hash<<1) + (unsigned char)s[1]; - Hash = (Hash&63)>>1; - M = MonthHash[Hash]; - s+=4; - Y = skip_atoi(s2); /* Year */ - s++; - H = skip_atoi(s2); /* Hour */ - s++; - Min = skip_atoi(s2); /* Minutes */ - s++; - S = skip_atoi(s2); /* Seconds */ - s++; - if ((s[0]!='G')||(s[1]!='M')||(s[2]!='T')) - { - return 0; /* No GMT */ - } - - if (YKHTTPD_YEAROFFSET+9) Y = KHTTPD_YEAROFFSET+9; - - Temp = TimeDays[Y-KHTTPD_YEAROFFSET][M]; - Temp += D*86400+H*3600+Min*60+S; - - return Temp; -} diff -Nru a/net/khttpd/security.c b/net/khttpd/security.c --- a/net/khttpd/security.c Thu Aug 1 14:17:36 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,267 +0,0 @@ -/* - -kHTTPd -- the next generation - -Permissions/Security functions - -*/ - -/**************************************************************** - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ****************************************************************/ - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "sysctl.h" -#include "security.h" -#include "prototypes.h" - -/* - -The basic security function answers "Userspace" when any one of the following -conditions is met: - -1) The filename contains a "?" (this is before % decoding, all others are - after % decoding) -2) The filename doesn't start with a "/" -3) The file does not exist -4) The file does not have enough permissions - (sysctl-configurable, default = worldreadble) -5) The file has any of the "forbidden" permissions - (sysctl-configurable, default = execute, directory and sticky) -6) The filename contains a string as defined in the "Dynamic" list. - -*/ - - -/* Prototypes */ - -static void DecodeHexChars(char *URL); -static struct DynamicString *DynamicList=NULL; - - - -/* - -The function "OpenFileForSecurity" returns either the "struct file" pointer -of the file, or NULL. NULL means "let userspace handle it". - -*/ -struct file *OpenFileForSecurity(char *Filename) -{ - struct file *filp; - struct DynamicString *List; - umode_t permission; - - - - EnterFunction("OpenFileForSecurity"); - if (Filename==NULL) - return NULL; - - if (strlen(Filename)>=256 ) return NULL; /* Sanity check */ - - /* Rule no. 1 -- No "?" characters */ -#ifndef BENCHMARK - if (strchr(Filename,'?')!=NULL) - return NULL; - - /* Intermediate step: decode all %hex sequences */ - - DecodeHexChars(Filename); - - /* Rule no. 2 -- Must start with a "/" */ - - - if (Filename[0]!='/') - return NULL; - -#endif - /* Rule no. 3 -- Does the file exist ? */ - - filp = filp_open(Filename, O_RDONLY, 0); - - if (IS_ERR(filp)) - return NULL; - -#ifndef BENCHMARK - permission = filp->f_dentry->d_inode->i_mode; - - /* Rule no. 4 : must have enough permissions */ - - - if ((permission & sysctl_khttpd_permreq)==0) - { - if (filp!=NULL) - fput(filp); - filp=NULL; - return NULL; - } - - /* Rule no. 5 : cannot have "forbidden" permission */ - - - if ((permission & sysctl_khttpd_permforbid)!=0) - { - if (filp!=NULL) - fput(filp); - filp=NULL; - return NULL; - } - - /* Rule no. 6 : No string in DynamicList can be a - substring of the filename */ - - - List = DynamicList; - - while (List!=NULL) - { - if (strstr(Filename,List->value)!=NULL) - { - if (filp!=NULL) - fput(filp); - filp=NULL; - return NULL; - } - List = List->Next; - } - -#endif - LeaveFunction("OpenFileForSecurity - success"); - - return filp; -} - -/* - -DecodeHexChars does the actual %HEX decoding, in place. -In place is possible because strings only get shorter by this. - -*/ -static void DecodeHexChars(char *URL) -{ - char *Source,*Dest; - int val,val2; - - EnterFunction("DecodeHexChars"); - - Source = strchr(URL,'%'); - - if (Source==NULL) - return; - - Dest = Source; - - while (*Source!=0) - { - if (*Source=='%') - { - Source++; - val = *Source; - - if (val>'Z') val-=0x20; - val = val - '0'; - if (val<0) val=0; - if (val>9) val-=7; - if (val>15) val=15; - - Source++; - - val2 = *Source; - - if (val2>'Z') val2-=0x20; - val2 = val2 - '0'; - if (val2<0) val2=0; - if (val2>9) val2-=7; - if (val2>15) val2=15; - - *Dest=val*16+val2; - } else *Dest = *Source; - Dest++; - Source++; - } - *Dest=0; - - LeaveFunction("DecodeHexChars"); -} - - -void AddDynamicString(const char *String) -{ - struct DynamicString *Temp; - - EnterFunction("AddDynamicString"); - - Temp = (struct DynamicString*)kmalloc(sizeof(struct DynamicString),(int)GFP_KERNEL); - - if (Temp==NULL) - return; - - memset(Temp->value,0,sizeof(Temp->value)); - strncpy(Temp->value,String,sizeof(Temp->value)-1); - - Temp->Next = DynamicList; - DynamicList = Temp; - - LeaveFunction("AddDynamicString"); -} - -void GetSecureString(char *String) -{ - struct DynamicString *Temp; - int max; - - EnterFunction("GetSecureString"); - - *String = 0; - - memset(String,0,255); - - strncpy(String,"Dynamic strings are : -",255); - Temp = DynamicList; - while (Temp!=NULL) - { - max=253 - strlen(String) - strlen(Temp->value); - strncat(String,Temp->value,max); - max=253 - strlen(String) - 3; - strncat(String,"- -",max); - Temp = Temp->Next; - } - - LeaveFunction("GetSecureString"); -} diff -Nru a/net/khttpd/security.h b/net/khttpd/security.h --- a/net/khttpd/security.h Thu Aug 1 14:17:36 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,12 +0,0 @@ -#ifndef _INCLUDE_GUARD_SECURITY_H -#define _INCLUDE_GUARD_SECURITY_H - -struct DynamicString; - -struct DynamicString -{ - struct DynamicString* Next; - char value[32-sizeof(void*)]; /* fill 1 cache-line */ -}; - -#endif diff -Nru a/net/khttpd/sockets.c b/net/khttpd/sockets.c --- a/net/khttpd/sockets.c Thu Aug 1 14:17:36 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,101 +0,0 @@ -/* - -kHTTPd -- the next generation - -Basic socket functions - -*/ -/**************************************************************** - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ****************************************************************/ - -#include "prototypes.h" -#include -#include -#include -#include -#include - - -/* - -MainSocket is shared by all threads, therefore it has to be -a global variable. - -*/ -struct socket *MainSocket=NULL; - - -int StartListening(const int Port) -{ - struct socket *sock; - struct sockaddr_in sin; - int error; - - EnterFunction("StartListening"); - - /* First create a socket */ - - error = sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&sock); - if (error<0) - (void)printk(KERN_ERR "Error during creation of socket; terminating\n"); - - - - /* Now bind the socket */ - - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - sin.sin_port = htons((unsigned short)Port); - - error = sock->ops->bind(sock,(struct sockaddr*)&sin,sizeof(sin)); - if (error<0) - { - (void)printk(KERN_ERR "kHTTPd: Error binding socket. This means that some other \n"); - (void)printk(KERN_ERR " daemon is (or was a short time ago) using port %i.\n",Port); - return 0; - } - - /* Grrr... setsockopt() does this. */ - sock->sk->reuse = 1; - - /* Now, start listening on the socket */ - - /* I have no idea what a sane backlog-value is. 48 works so far. */ - - error=sock->ops->listen(sock,48); - if (error!=0) - (void)printk(KERN_ERR "kHTTPd: Error listening on socket \n"); - - MainSocket = sock; - - LeaveFunction("StartListening"); - return 1; -} - -void StopListening(void) -{ - struct socket *sock; - - EnterFunction("StopListening"); - if (MainSocket==NULL) return; - - sock=MainSocket; - MainSocket = NULL; - sock_release(sock); - - LeaveFunction("StopListening"); -} diff -Nru a/net/khttpd/structure.h b/net/khttpd/structure.h --- a/net/khttpd/structure.h Thu Aug 1 14:17:36 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,68 +0,0 @@ -#ifndef _INCLUDE_GUARD_STRUCTURE_H_ -#define _INCLUDE_GUARD_STRUCTURE_H_ - -#include -#include - - -struct http_request; - -struct http_request -{ - /* Linked list */ - struct http_request *Next; - - /* Network and File data */ - struct socket *sock; - struct file *filp; - - /* Raw data about the file */ - - int FileLength; /* File length in bytes */ - int Time; /* mtime of the file, unix format */ - int BytesSent; /* The number of bytes already sent */ - int IsForUserspace; /* 1 means let Userspace handle this one */ - - /* Wait queue */ - - wait_queue_t sleep; /* For putting in the socket's waitqueue */ - - /* HTTP request information */ - char FileName[256]; /* The requested filename */ - int FileNameLength; /* The length of the string representing the filename */ - char Agent[128]; /* The agent-string of the remote browser */ - char IMS[128]; /* If-modified-since time, rfc string format */ - char Host[128]; /* Value given by the Host: header */ - int HTTPVER; /* HTTP-version; 9 for 0.9, 10 for 1.0 and above */ - - - /* Derived date from the above fields */ - int IMS_Time; /* if-modified-since time, unix format */ - char TimeS[64]; /* File mtime, rfc string representation */ - char LengthS[14]; /* File length, string representation */ - char *MimeType; /* Pointer to a string with the mime-type - based on the filename */ - __kernel_size_t MimeLength; /* The length of this string */ - -}; - - - -/* - -struct khttpd_threadinfo represents the four queues that 1 thread has to deal with. -It is padded to occupy 1 (Intel) cache-line, to avoid "cacheline-pingpong". - -*/ -struct khttpd_threadinfo -{ - struct http_request* WaitForHeaderQueue; - struct http_request* DataSendingQueue; - struct http_request* LoggingQueue; - struct http_request* UserspaceQueue; - char dummy[16]; /* Padding for cache-lines */ -}; - - - -#endif diff -Nru a/net/khttpd/sysctl.c b/net/khttpd/sysctl.c --- a/net/khttpd/sysctl.c Thu Aug 1 14:17:41 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,320 +0,0 @@ -/* - -kHTTPd -- the next generation - -Sysctl interface - -*/ -/**************************************************************** - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ****************************************************************/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include "prototypes.h" - - - -char sysctl_khttpd_docroot[200] = "/var/www"; -int sysctl_khttpd_stop = 0; -int sysctl_khttpd_start = 0; -int sysctl_khttpd_unload = 0; -int sysctl_khttpd_clientport = 80; -int sysctl_khttpd_permreq = S_IROTH; /* "other" read-access is required by default*/ -int sysctl_khttpd_permforbid = S_IFDIR | S_ISVTX | S_IXOTH | S_IXGRP | S_IXUSR; - /* forbidden is execute, directory and sticky*/ -int sysctl_khttpd_logging = 0; -int sysctl_khttpd_serverport= 8080; - -char sysctl_khttpd_dynamicstring[200]; -int sysctl_khttpd_sloppymime= 0; -int sysctl_khttpd_threads = 2; -int sysctl_khttpd_maxconnect = 1000; - - -static struct ctl_table_header *khttpd_table_header; - -static int sysctl_SecureString(ctl_table *table, int *name, int nlen, - void *oldval, size_t *oldlenp, - void *newval, size_t newlen, void **context); -static int proc_dosecurestring(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp); - - -static ctl_table khttpd_table[] = { - { NET_KHTTPD_DOCROOT, - "documentroot", - &sysctl_khttpd_docroot, - sizeof(sysctl_khttpd_docroot), - 0644, - NULL, - proc_dostring, - &sysctl_string, - NULL, - NULL, - NULL - }, - { NET_KHTTPD_STOP, - "stop", - &sysctl_khttpd_stop, - sizeof(int), - 0644, - NULL, - proc_dointvec, - &sysctl_intvec, - NULL, - NULL, - NULL - }, - { NET_KHTTPD_START, - "start", - &sysctl_khttpd_start, - sizeof(int), - 0644, - NULL, - proc_dointvec, - &sysctl_intvec, - NULL, - NULL, - NULL - }, - { NET_KHTTPD_UNLOAD, - "unload", - &sysctl_khttpd_unload, - sizeof(int), - 0644, - NULL, - proc_dointvec, - &sysctl_intvec, - NULL, - NULL, - NULL - }, - { NET_KHTTPD_THREADS, - "threads", - &sysctl_khttpd_threads, - sizeof(int), - 0644, - NULL, - proc_dointvec, - &sysctl_intvec, - NULL, - NULL, - NULL - }, - { NET_KHTTPD_MAXCONNECT, - "maxconnect", - &sysctl_khttpd_maxconnect, - sizeof(int), - 0644, - NULL, - proc_dointvec, - &sysctl_intvec, - NULL, - NULL, - NULL - }, - { NET_KHTTPD_SLOPPYMIME, - "sloppymime", - &sysctl_khttpd_sloppymime, - sizeof(int), - 0644, - NULL, - proc_dointvec, - &sysctl_intvec, - NULL, - NULL, - NULL - }, - { NET_KHTTPD_CLIENTPORT, - "clientport", - &sysctl_khttpd_clientport, - sizeof(int), - 0644, - NULL, - proc_dointvec, - &sysctl_intvec, - NULL, - NULL, - NULL - }, - { NET_KHTTPD_PERMREQ, - "perm_required", - &sysctl_khttpd_permreq, - sizeof(int), - 0644, - NULL, - proc_dointvec, - &sysctl_intvec, - NULL, - NULL, - NULL - }, - { NET_KHTTPD_PERMFORBID, - "perm_forbid", - &sysctl_khttpd_permforbid, - sizeof(int), - 0644, - NULL, - proc_dointvec, - &sysctl_intvec, - NULL, - NULL, - NULL - }, - { NET_KHTTPD_LOGGING, - "logging", - &sysctl_khttpd_logging, - sizeof(int), - 0644, - NULL, - proc_dointvec, - &sysctl_intvec, - NULL, - NULL, - NULL - }, - { NET_KHTTPD_SERVERPORT, - "serverport", - &sysctl_khttpd_serverport, - sizeof(int), - 0644, - NULL, - proc_dointvec, - &sysctl_intvec, - NULL, - NULL, - NULL - }, - { NET_KHTTPD_DYNAMICSTRING, - "dynamic", - &sysctl_khttpd_dynamicstring, - sizeof(sysctl_khttpd_dynamicstring), - 0644, - NULL, - proc_dosecurestring, - &sysctl_SecureString, - NULL, - NULL, - NULL - }, - {0,0,0,0,0,0,0,0,0,0,0} }; - - -static ctl_table khttpd_dir_table[] = { - {NET_KHTTPD, "khttpd", NULL, 0, 0555, khttpd_table,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0} -}; - -static ctl_table khttpd_root_table[] = { - {CTL_NET, "net", NULL, 0, 0555, khttpd_dir_table,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0} -}; - - -void StartSysctl(void) -{ - khttpd_table_header = register_sysctl_table(khttpd_root_table,1); -} - - -void EndSysctl(void) -{ - unregister_sysctl_table(khttpd_table_header); -} - -static int proc_dosecurestring(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp) -{ - size_t len; - char *p, c=0; - char String[256]; - - if ((table->data==0) || (table->maxlen==0) || (*lenp==0) || - ((filp->f_pos!=0) && (write==0))) { - *lenp = 0; - return 0; - } - - if (write!=0) { - len = 0; - p = buffer; - while (len < *lenp) { - if(get_user(c, p++)) - return -EFAULT; - if (c == 0 || c == '\n') - break; - len++; - } - if (len >= table->maxlen) - len = table->maxlen-1; - if(copy_from_user(String, buffer,(unsigned long)len)) - return -EFAULT; - ((char *) String)[len] = 0; - filp->f_pos += *lenp; - AddDynamicString(String); - } else { - GetSecureString(String); - len = strlen(String); - if (len > table->maxlen) - len = table->maxlen; - if (len > *lenp) - len = *lenp; - if (len!=0) - if(copy_to_user(buffer, String,(unsigned long)len)) - return -EFAULT; - if (len < *lenp) { - if(put_user('\n', ((char *) buffer) + len)) - return -EFAULT; - len++; - } - *lenp = len; - filp->f_pos += len; - } - return 0; -} - -static int sysctl_SecureString (/*@unused@*/ctl_table *table, - /*@unused@*/int *name, - /*@unused@*/int nlen, - /*@unused@*/void *oldval, - /*@unused@*/size_t *oldlenp, - /*@unused@*/void *newval, - /*@unused@*/size_t newlen, - /*@unused@*/void **context) -{ - return -ENOSYS; -} diff -Nru a/net/khttpd/sysctl.h b/net/khttpd/sysctl.h --- a/net/khttpd/sysctl.h Thu Aug 1 14:17:39 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,17 +0,0 @@ -#ifndef _KHTTPD_INCLUDE_GUARD_SYSCTL_H -#define _KHTTPD_INCLUDE_GUARD_SYSCTL_H - -extern char sysctl_khttpd_docroot[200]; -extern int sysctl_khttpd_stop; -extern int sysctl_khttpd_start; -extern int sysctl_khttpd_unload; -extern int sysctl_khttpd_clientport; -extern int sysctl_khttpd_permreq; -extern int sysctl_khttpd_permforbid; -extern int sysctl_khttpd_logging; -extern int sysctl_khttpd_serverport; -extern int sysctl_khttpd_sloppymime; -extern int sysctl_khttpd_threads; -extern int sysctl_khttpd_maxconnect; - -#endif diff -Nru a/net/khttpd/userspace.c b/net/khttpd/userspace.c --- a/net/khttpd/userspace.c Thu Aug 1 14:17:36 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,243 +0,0 @@ -/* - -kHTTPd -- the next generation - -Pass connections to userspace-daemons - -*/ -/**************************************************************** - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ****************************************************************/ - -/* - -Purpose: - -Userspace() hands all requests in the queue to the userspace-daemon, if -such beast exists. - -Return value: - The number of requests that changed status -*/ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include - - -#include "structure.h" -#include "prototypes.h" -#include "sysctl.h" - -/* prototypes of local, static functions */ -static int AddSocketToAcceptQueue(struct socket *sock,const int Port); - - -int Userspace(const int CPUNR) -{ - struct http_request *CurrentRequest,**Prev,*Next; - - EnterFunction("Userspace"); - - - - - CurrentRequest = threadinfo[CPUNR].UserspaceQueue; - Prev = &(threadinfo[CPUNR].UserspaceQueue); - - while (CurrentRequest!=NULL) - { - - /* Clean-up the waitqueue of the socket.. Bad things happen if - this is forgotten. */ - if (CurrentRequest->sock!=NULL) - { - if ((CurrentRequest->sock!=NULL)&&(CurrentRequest->sock->sk!=NULL)) - { - remove_wait_queue(CurrentRequest->sock->sk->sleep,&(CurrentRequest->sleep)); - } - } - - - if (AddSocketToAcceptQueue(CurrentRequest->sock,sysctl_khttpd_clientport)>=0) - { - - (*Prev) = CurrentRequest->Next; - Next = CurrentRequest->Next; - - - sock_release(CurrentRequest->sock); - CurrentRequest->sock = NULL; /* We no longer own it */ - - CleanUpRequest(CurrentRequest); - - CurrentRequest = Next; - continue; - - } - else /* No userspace-daemon present, or other problems with it */ - { - (*Prev) = CurrentRequest->Next; - Next = CurrentRequest->Next; - - Send403(CurrentRequest->sock); /* Sorry, no go... */ - - CleanUpRequest(CurrentRequest); - - CurrentRequest = Next; - continue; - - } - - - Prev = &(CurrentRequest->Next); - CurrentRequest = CurrentRequest->Next; - } - - LeaveFunction("Userspace"); - return 0; -} - -void StopUserspace(const int CPUNR) -{ - struct http_request *CurrentRequest,*Next; - - EnterFunction("StopUserspace"); - CurrentRequest = threadinfo[CPUNR].UserspaceQueue; - - while (CurrentRequest!=NULL) - { - Next= CurrentRequest->Next; - CleanUpRequest(CurrentRequest); - CurrentRequest=Next; - } - threadinfo[CPUNR].UserspaceQueue = NULL; - - LeaveFunction("StopUserspace"); -} - - -/* - "FindUserspace" returns the struct sock of the userspace-daemon, so that we can - "drop" our request in the accept-queue -*/ - -static struct sock *FindUserspace(const unsigned short Port) -{ - struct sock *sk; - - EnterFunction("FindUserspace"); - - local_bh_disable(); - sk = tcp_v4_lookup_listener(INADDR_ANY,Port,0); - local_bh_enable(); - return sk; -} - -static void dummy_destructor(struct open_request *req) -{ -} - -static struct or_calltable Dummy = -{ - 0, - NULL, - NULL, - &dummy_destructor, - NULL -}; - -static int AddSocketToAcceptQueue(struct socket *sock,const int Port) -{ - struct open_request *req; - struct sock *sk, *nsk; - - EnterFunction("AddSocketToAcceptQueue"); - - - sk = FindUserspace((unsigned short)Port); - - if (sk==NULL) /* No userspace-daemon found */ - { - return -1; - } - - lock_sock(sk); - - if (sk->state != TCP_LISTEN || tcp_acceptq_is_full(sk)) - { - release_sock(sk); - sock_put(sk); - return -1; - } - - req = tcp_openreq_alloc(); - - if (req==NULL) - { - release_sock(sk); - sock_put(sk); - return -1; - } - - nsk = sock->sk; - sock->sk = NULL; - sock->state = SS_UNCONNECTED; - - req->class = &Dummy; - write_lock_bh(&nsk->callback_lock); - nsk->socket = NULL; - nsk->sleep = NULL; - write_unlock_bh(&nsk->callback_lock); - - tcp_acceptq_queue(sk, req, nsk); - - sk->data_ready(sk, 0); - - release_sock(sk); - sock_put(sk); - - LeaveFunction("AddSocketToAcceptQueue"); - - return +1; - - - -} - -void InitUserspace(const int CPUNR) -{ -} - - diff -Nru a/net/khttpd/waitheaders.c b/net/khttpd/waitheaders.c --- a/net/khttpd/waitheaders.c Thu Aug 1 14:17:39 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,298 +0,0 @@ -/* - -kHTTPd -- the next generation - -Wait for headers on the accepted connections - -*/ -/**************************************************************** - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ****************************************************************/ - -/* - -Purpose: - -WaitForHeaders polls all connections in "WaitForHeaderQueue" to see if -headers have arived. If so, the headers are decoded and the request is -moved to either the "SendingDataQueue" or the "UserspaceQueue". - -Return value: - The number of requests that changed status -*/ - -#include -#include -#include -#include -#include - -#include - -#include "structure.h" -#include "prototypes.h" - -static char *Buffer[CONFIG_KHTTPD_NUMCPU]; - - -static int DecodeHeader(const int CPUNR, struct http_request *Request); - - -int WaitForHeaders(const int CPUNR) -{ - struct http_request *CurrentRequest,**Prev; - struct sock *sk; - int count = 0; - - EnterFunction("WaitForHeaders"); - - CurrentRequest = threadinfo[CPUNR].WaitForHeaderQueue; - - Prev = &(threadinfo[CPUNR].WaitForHeaderQueue); - - while (CurrentRequest!=NULL) - { - - /* If the connection is lost, remove from queue */ - - if (CurrentRequest->sock->sk->state != TCP_ESTABLISHED - && CurrentRequest->sock->sk->state != TCP_CLOSE_WAIT) - { - struct http_request *Next; - - Next = CurrentRequest->Next; - - *Prev = CurrentRequest->Next; - CurrentRequest->Next = NULL; - - - CleanUpRequest(CurrentRequest); - CurrentRequest = Next; - continue; - } - - - - /* If data pending, take action */ - - sk = CurrentRequest->sock->sk; - - if (!skb_queue_empty(&(sk->receive_queue))) /* Do we have data ? */ - { - struct http_request *Next; - - - - /* Decode header */ - - if (DecodeHeader(CPUNR,CurrentRequest)<0) - { - CurrentRequest = CurrentRequest->Next; - continue; - } - - - /* Remove from WaitForHeaderQueue */ - - Next= CurrentRequest->Next; - - *Prev = Next; - count++; - - /* Add to either the UserspaceQueue or the DataSendingQueue */ - - if (CurrentRequest->IsForUserspace!=0) - { - CurrentRequest->Next = threadinfo[CPUNR].UserspaceQueue; - threadinfo[CPUNR].UserspaceQueue = CurrentRequest; - } else - { - CurrentRequest->Next = threadinfo[CPUNR].DataSendingQueue; - threadinfo[CPUNR].DataSendingQueue = CurrentRequest; - } - - CurrentRequest = Next; - continue; - - } - - - Prev = &(CurrentRequest->Next); - CurrentRequest = CurrentRequest->Next; - } - - LeaveFunction("WaitHeaders"); - return count; -} - -void StopWaitingForHeaders(const int CPUNR) -{ - struct http_request *CurrentRequest,*Next; - - EnterFunction("StopWaitingForHeaders"); - CurrentRequest = threadinfo[CPUNR].WaitForHeaderQueue; - - while (CurrentRequest!=NULL) - { - Next = CurrentRequest->Next; - CleanUpRequest(CurrentRequest); - CurrentRequest=Next; - } - - threadinfo[CPUNR].WaitForHeaderQueue = NULL; /* The queue is empty now */ - - free_page((unsigned long)Buffer[CPUNR]); - Buffer[CPUNR]=NULL; - - EnterFunction("StopWaitingForHeaders"); -} - - -/* - -DecodeHeader peeks at the TCP/IP data, determines what the request is, -fills the request-structure and sends the HTTP-header when apropriate. - -*/ - -static int DecodeHeader(const int CPUNR, struct http_request *Request) -{ - struct msghdr msg; - struct iovec iov; - int len; - - mm_segment_t oldfs; - - EnterFunction("DecodeHeader"); - - /* First, read the data */ - - msg.msg_name = 0; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - - msg.msg_iov->iov_base = &Buffer[CPUNR][0]; - msg.msg_iov->iov_len = (size_t)4095; - - len = 0; - oldfs = get_fs(); set_fs(KERNEL_DS); - /* 4095 leaves a "0" to terminate the string */ - - len = sock_recvmsg(Request->sock,&msg,4095,MSG_PEEK); - set_fs(oldfs); - - if (len<0) { - /* WONDERFUL. NO COMMENTS. --ANK */ - Request->IsForUserspace = 1; - return 0; - } - - if (len>=4094) /* BIG header, we cannot decode it so leave it to userspace */ - { - Request->IsForUserspace = 1; - return 0; - } - - /* Then, decode the header */ - - - ParseHeader(Buffer[CPUNR],len,Request); - - Request->filp = OpenFileForSecurity(Request->FileName); - - - Request->MimeType = ResolveMimeType(Request->FileName,&Request->MimeLength); - - - if (Request->MimeType==NULL) /* Unknown mime-type */ - { - if (Request->filp!=NULL) - { - fput(Request->filp); - Request->filp = NULL; - } - Request->IsForUserspace = 1; - - return 0; - } - - if (Request->filp==NULL) - { - Request->IsForUserspace = 1; - return 0; - } - else - { - Request->FileLength = (int)Request->filp->f_dentry->d_inode->i_size; - Request->Time = Request->filp->f_dentry->d_inode->i_mtime; - Request->IMS_Time = mimeTime_to_UnixTime(Request->IMS); - sprintf(Request->LengthS,"%i",Request->FileLength); - time_Unix2RFC(min_t(unsigned int, Request->Time,CurrentTime_i),Request->TimeS); - /* The min() is required by rfc1945, section 10.10: - It is not allowed to send a filetime in the future */ - - if (Request->IMS_Time>Request->Time) - { /* Not modified since last time */ - Send304(Request->sock); - Request->FileLength=0; - } - else /* Normal Case */ - { - struct tcp_opt *tp = tcp_sk(Request->sock->sk); - - tp->nonagle = 2; /* this is TCP_CORK */ - if (Request->HTTPVER!=9) /* HTTP/0.9 doesn't allow a header */ - SendHTTPHeader(Request); - } - - - } - - LeaveFunction("DecodeHeader"); - return 0; -} - - -int InitWaitHeaders(int ThreadCount) -{ - int I,I2; - - EnterFunction("InitWaitHeaders"); - I=0; - while (I #include #include @@ -286,7 +286,7 @@ #endif -#if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_KHTTPD) || defined (CONFIG_KHTTPD_MODULE) +#if defined (CONFIG_IPV6_MODULE) /* inet functions common to v4 and v6 */ EXPORT_SYMBOL(inet_release); EXPORT_SYMBOL(inet_stream_connect); diff -Nru a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c --- a/net/sched/sch_ingress.c Thu Aug 1 14:17:41 2002 +++ b/net/sched/sch_ingress.c Thu Aug 1 14:17:41 2002 @@ -106,7 +106,7 @@ #endif DPRINTK("ingress_change(sch %p,[qdisc %p],classid %x,parent %x)," "arg 0x%lx\n", sch, p, classid, parent, *arg); - DPRINTK("No effect. sch_ingress doesnt maintain classes at the moment"); + DPRINTK("No effect. sch_ingress doesn't maintain classes at the moment"); return 0; } @@ -118,7 +118,7 @@ struct ingress_qdisc_data *p = PRIV(sch); #endif DPRINTK("ingress_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker); - DPRINTK("No effect. sch_ingress doesnt maintain classes at the moment"); + DPRINTK("No effect. sch_ingress doesn't maintain classes at the moment"); } diff -Nru a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c --- a/net/sunrpc/clnt.c Thu Aug 1 14:17:40 2002 +++ b/net/sunrpc/clnt.c Thu Aug 1 14:17:40 2002 @@ -605,17 +605,17 @@ { struct rpc_clnt *clnt = task->tk_client; struct rpc_xprt *xprt = clnt->cl_xprt; - struct rpc_rqst *req; - int status = task->tk_status; + struct rpc_rqst *req = task->tk_rqstp; + int status; + + if (req->rq_received != 0) + task->tk_status = req->rq_received; dprintk("RPC: %4d call_status (status %d)\n", task->tk_pid, task->tk_status); - req = task->tk_rqstp; - if (req->rq_received != 0) - status = req->rq_received; + status = task->tk_status; if (status >= 0) { - req->rq_received = 0; task->tk_action = call_decode; return; } diff -Nru a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c --- a/net/sunrpc/xprt.c Thu Aug 1 14:17:36 2002 +++ b/net/sunrpc/xprt.c Thu Aug 1 14:17:36 2002 @@ -137,17 +137,14 @@ * Also prevents TCP socket reconnections from colliding with writes. */ static int -xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) +__xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) { - int retval; - spin_lock_bh(&xprt->sock_lock); if (!xprt->snd_task) { if (xprt->nocong || __xprt_get_cong(xprt, task)) xprt->snd_task = task; } if (xprt->snd_task != task) { - dprintk("RPC: %4d TCP write queue full (task %d)\n", - task->tk_pid, xprt->snd_task->tk_pid); + dprintk("RPC: %4d TCP write queue full\n", task->tk_pid); task->tk_timeout = 0; task->tk_status = -EAGAIN; if (task->tk_rqstp->rq_nresend) @@ -155,11 +152,21 @@ else rpc_sleep_on(&xprt->sending, task, NULL, NULL); } - retval = xprt->snd_task == task; + return xprt->snd_task == task; +} + +static inline int +xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) +{ + int retval; + + spin_lock_bh(&xprt->sock_lock); + retval = __xprt_lock_write(xprt, task); spin_unlock_bh(&xprt->sock_lock); return retval; } + static void __xprt_lock_write_next(struct rpc_xprt *xprt) { @@ -564,8 +571,8 @@ #endif dprintk("RPC: %4d has input (%d bytes)\n", task->tk_pid, copied); - task->tk_status = copied; req->rq_received = copied; + list_del_init(&req->rq_list); /* ... and wake up the process. */ rpc_wake_up_task(task); @@ -1057,8 +1064,16 @@ *marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker))); } - if (!xprt_lock_write(xprt, task)) + spin_lock_bh(&xprt->sock_lock); + if (!__xprt_lock_write(xprt, task)) { + spin_unlock_bh(&xprt->sock_lock); return; + } + if (list_empty(&req->rq_list)) { + list_add_tail(&req->rq_list, &xprt->recv); + req->rq_received = 0; + } + spin_unlock_bh(&xprt->sock_lock); do_xprt_transmit(task); } @@ -1242,9 +1257,6 @@ if (!xid) xid++; INIT_LIST_HEAD(&req->rq_list); - spin_lock_bh(&xprt->sock_lock); - list_add_tail(&req->rq_list, &xprt->recv); - spin_unlock_bh(&xprt->sock_lock); } /* diff -Nru a/scripts/fixdep.c b/scripts/fixdep.c --- a/scripts/fixdep.c Thu Aug 1 14:17:40 2002 +++ b/scripts/fixdep.c Thu Aug 1 14:17:40 2002 @@ -213,7 +213,7 @@ void parse_config_file(char *map, size_t len) { int *end = (int *) (map + len); - // start at +1, so that p can never be < map + /* start at +1, so that p can never be < map */ int *m = (int *) map + 1; char *p, *q; @@ -283,7 +283,7 @@ void parse_dep_file(void *map, size_t len) { char *m = map; - char *end = map + len; + char *end = m + len; char *p; char s[PATH_MAX]; diff -Nru a/scripts/mkcompile_h b/scripts/mkcompile_h --- a/scripts/mkcompile_h Thu Aug 1 14:17:41 2002 +++ b/scripts/mkcompile_h Thu Aug 1 14:17:41 2002 @@ -3,6 +3,20 @@ SMP=$3 CC=$4 +# If compile.h exists already and we don't own autoconf.h +# (i.e. we're not the same user who did make *config), don't +# modify compile.h +# So "sudo make install" won't change the "compiled by " +# do "compiled by root" + +if [ -r $TARGET -a ! -O ../include/linux/autoconf.h ]; then + echo ' (not modified)' + exit 0 +fi + +# Do not expand names +set -f + if [ -r ../.version ]; then VERSION=`cat ../.version` else diff -Nru a/security/capability.c b/security/capability.c --- a/security/capability.c Thu Aug 1 14:17:40 2002 +++ b/security/capability.c Thu Aug 1 14:17:40 2002 @@ -464,7 +464,7 @@ return 0; } -static int cap_file_lock (struct file *file, unsigned int cmd, int blocking) +static int cap_file_lock (struct file *file, unsigned int cmd) { return 0; } diff -Nru a/security/dummy.c b/security/dummy.c --- a/security/dummy.c Thu Aug 1 14:17:37 2002 +++ b/security/dummy.c Thu Aug 1 14:17:37 2002 @@ -366,7 +366,7 @@ return 0; } -static int dummy_file_lock (struct file *file, unsigned int cmd, int blocking) +static int dummy_file_lock (struct file *file, unsigned int cmd) { return 0; } diff -Nru a/sound/core/Makefile b/sound/core/Makefile --- a/sound/core/Makefile Thu Aug 1 14:17:36 2002 +++ b/sound/core/Makefile Thu Aug 1 14:17:36 2002 @@ -3,7 +3,7 @@ # Copyright (c) 1999,2001 by Jaroslav Kysela # -export-objs := sound.o pcm.o pcm_lib.o rawmidi.o timer.o rtctimer.o hwdep.o +export-objs := sound.o pcm.o pcm_lib.o rawmidi.o timer.o hwdep.o snd-objs := sound.o init.o isadma.o memory.o info.o control.o misc.o \ device.o wrappers.o diff -Nru a/sound/core/info.c b/sound/core/info.c --- a/sound/core/info.c Thu Aug 1 14:17:40 2002 +++ b/sound/core/info.c Thu Aug 1 14:17:40 2002 @@ -973,10 +973,10 @@ sprintf(dname, "snd/%s", entry->name); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) master = devfs_find_handle(NULL, dname, strlen(dname), 0, 0, DEVFS_SPECIAL_CHR, 0); + devfs_unregister(master); #else - master = devfs_find_handle(NULL, dname, 0, 0, DEVFS_SPECIAL_CHR, 0); + devfs_find_and_unregister(NULL, dname, 0, 0, DEVFS_SPECIAL_CHR, 0); #endif - devfs_unregister(master); } #endif snd_info_free_entry(entry); diff -Nru a/sound/core/seq/Makefile b/sound/core/seq/Makefile --- a/sound/core/seq/Makefile Thu Aug 1 14:17:41 2002 +++ b/sound/core/seq/Makefile Thu Aug 1 14:17:41 2002 @@ -8,7 +8,7 @@ obj-$(CONFIG_SND_SEQUENCER) += oss/ endif -export-objs := seq_device.o seq.o seq_ports.o seq_instr.o seq_midi_emul.o \ +export-objs := seq_device.o seq.o seq_instr.o seq_midi_emul.o \ seq_midi_event.o seq_virmidi.o snd-seq-device-objs := seq_device.o diff -Nru a/sound/core/sound.c b/sound/core/sound.c --- a/sound/core/sound.c Thu Aug 1 14:17:36 2002 +++ b/sound/core/sound.c Thu Aug 1 14:17:36 2002 @@ -315,10 +315,8 @@ #else devfs_handle = devfs_mk_dir(NULL, "snd", NULL); #endif - if (devfs_register_chrdev(snd_major, "alsa", &snd_fops)) { -#else - if (register_chrdev(snd_major, "alsa", &snd_fops)) { #endif + if (register_chrdev(snd_major, "alsa", &snd_fops)) { snd_printk(KERN_ERR "unable to register native major device number %d\n", snd_major); #ifdef CONFIG_SND_OSSEMUL snd_oss_cleanup_module(); @@ -368,10 +366,10 @@ sprintf(controlname, "snd/controlC%d", controlnum); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) master = devfs_find_handle(NULL, controlname, strlen(controlname), 0, 0, DEVFS_SPECIAL_CHR, 0); + devfs_unregister(master); #else - master = devfs_find_handle(NULL, controlname, 0, 0, DEVFS_SPECIAL_CHR, 0); + devfs_find_and_unregister(NULL, controlname, 0, 0, DEVFS_SPECIAL_CHR, 0); #endif - devfs_unregister(master); } #endif @@ -386,11 +384,7 @@ #ifdef CONFIG_SND_DEBUG_MEMORY snd_memory_done(); #endif -#ifdef CONFIG_DEVFS_FS - if (devfs_unregister_chrdev(snd_major, "alsa") != 0) -#else if (unregister_chrdev(snd_major, "alsa") != 0) -#endif snd_printk(KERN_ERR "unable to unregister major device number %d\n", snd_major); #ifdef CONFIG_DEVFS_FS devfs_unregister(devfs_handle); diff -Nru a/sound/isa/sb/Makefile b/sound/isa/sb/Makefile --- a/sound/isa/sb/Makefile Thu Aug 1 14:17:40 2002 +++ b/sound/isa/sb/Makefile Thu Aug 1 14:17:40 2002 @@ -3,7 +3,7 @@ # Copyright (c) 2001 by Jaroslav Kysela # -export-objs := emu8000.o emu8000_synth.o sb_common.o sb8_main.o sb16_main.o sb16_csp.o +export-objs := emu8000.o sb_common.o sb8_main.o sb16_main.o sb16_csp.o snd-sb-common-objs := sb_common.o sb_mixer.o snd-sb8-dsp-objs := sb8_main.o sb8_midi.o diff -Nru a/sound/oss/Makefile b/sound/oss/Makefile --- a/sound/oss/Makefile Thu Aug 1 14:17:39 2002 +++ b/sound/oss/Makefile Thu Aug 1 14:17:39 2002 @@ -6,10 +6,9 @@ # All of the (potential) objects that export symbols. # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. -export-objs := ad1848.o audio_syms.o midi_syms.o mpu401.o \ - msnd.o opl3.o sb_common.o sequencer_syms.o \ - sound_syms.o uart401.o \ - nm256_audio.o ac97.o ac97_codec.o aci.o +export-objs := ad1848.o audio_syms.o midi_syms.o mpu401.o ac97_codec.o \ + msnd.o opl3.o sb_common.o sequencer_syms.o ac97.o aci.o \ + sound_syms.o uart401.o # Each configuration option enables a list of files. diff -Nru a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c --- a/sound/oss/cs46xx.c Thu Aug 1 14:17:36 2002 +++ b/sound/oss/cs46xx.c Thu Aug 1 14:17:36 2002 @@ -2521,7 +2521,7 @@ { dmabuf = &state->dmabuf; stop_dac(state); - synchronize_irq(); + synchronize_irq(card->irq); dmabuf->ready = 0; resync_dma_ptrs(state); dmabuf->swptr = dmabuf->hwptr = 0; @@ -2536,7 +2536,7 @@ { dmabuf = &state->dmabuf; stop_adc(state); - synchronize_irq(); + synchronize_irq(card->irq); resync_dma_ptrs(state); dmabuf->ready = 0; dmabuf->swptr = dmabuf->hwptr = 0; diff -Nru a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c --- a/sound/oss/i810_audio.c Thu Aug 1 14:17:41 2002 +++ b/sound/oss/i810_audio.c Thu Aug 1 14:17:41 2002 @@ -1733,7 +1733,6 @@ } spin_unlock_irqrestore(&state->card->lock, flags); - synchronize_irq(state->card->irq); dmabuf->ready = 0; dmabuf->swptr = dmabuf->hwptr = 0; dmabuf->count = dmabuf->total_bytes = 0; diff -Nru a/sound/oss/soundcard.c b/sound/oss/soundcard.c --- a/sound/oss/soundcard.c Thu Aug 1 14:17:40 2002 +++ b/sound/oss/soundcard.c Thu Aug 1 14:17:40 2002 @@ -566,13 +566,9 @@ SOUND_MAJOR, dev_list[i].minor+ (j* 0x10), S_IFCHR | dev_list[i].mode, &oss_sound_fops, NULL); - else { - devfs_handle_t de; - - de = devfs_find_handle (NULL, name_buf, 0, 0, - DEVFS_SPECIAL_CHR, 0); - devfs_unregister (de); - } + else + devfs_find_and_unregister(NULL, name_buf, 0, 0, + DEVFS_SPECIAL_CHR,0); } } } diff -Nru a/sound/oss/trident.c b/sound/oss/trident.c --- a/sound/oss/trident.c Thu Aug 1 14:17:41 2002 +++ b/sound/oss/trident.c Thu Aug 1 14:17:41 2002 @@ -36,6 +36,35 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * History + * v0.14.10f + * July 24 2002 Muli Ben-Yehuda + * patch from Eric Lemar (via Ian Soboroff): in suspend and resume, + * fix wrong cast from pci_dev* to struct trident_card*. + * v0.14.10e + * July 19 2002 Muli Ben-Yehuda + * rewrite the DMA buffer allocation/deallcoation functions, to make it + * modular and fix a bug where we would call free_pages on memory + * obtained with pci_alloc_consistent. Also remove unnecessary #ifdef + * CONFIG_PROC_FS and various other cleanups. + * v0.14.10d + * July 19 2002 Muli Ben-Yehuda + * made several printk(KERN_NOTICE...) into TRDBG(...), to avoid spamming + * my syslog with hundreds of messages. + * v0.14.10c + * July 16 2002 Muli Ben-Yehuda + * Cleaned up Lei Hu's 0.4.10 driver to conform to Documentation/CodingStyle + * and the coding style used in the rest of the file. + * v0.14.10b + * June 23 2002 Muli Ben-Yehuda + * add a missing unlock_set_fmt, remove a superflous lock/unlock pair + * with nothing in between. + * v0.14.10a + * June 21 2002 Muli Ben-Yehuda + * use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns + * per line, use 'do {} while (0)' in statement macros. + * v0.14.10 + * June 6 2002 Lei Hu + * rewrite the part to read/write registers of audio codec for Ali5451 * v0.14.9e * January 2 2002 Vojtech Pavlik added gameport * support to avoid resource conflict with pcigame.c @@ -161,20 +190,21 @@ #include #include #include -#include -#include #include #include #include #include #include #include -#include -#include #include #include #include +#include #include +#include +#include +#include +#include #if defined CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC #include @@ -182,9 +212,7 @@ #include "trident.h" -#include - -#define DRIVER_VERSION "0.14.9e" +#define DRIVER_VERSION "0.14.10f" /* magic numbers to protect our data structures */ #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ @@ -202,7 +230,13 @@ /* minor number of /dev/swmodem (temporary, experimental) */ #define SND_DEV_SWMODEM 7 -static const unsigned ali_multi_channels_5_1[] = { /*ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL,*/ ALI_CENTER_CHANNEL, ALI_LEF_CHANNEL, ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL}; +static const unsigned ali_multi_channels_5_1[] = { + /*ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL,*/ + ALI_CENTER_CHANNEL, + ALI_LEF_CHANNEL, + ALI_SURR_LEFT_CHANNEL, + ALI_SURR_RIGHT_CHANNEL +}; static const unsigned sample_size[] = { 1, 2, 2, 4 }; static const unsigned sample_shift[] = { 0, 1, 1, 2 }; @@ -292,7 +326,7 @@ } dmabuf; - /* 5.1channels */ + /* 5.1 channels */ struct trident_state *other_states[4]; int multi_channels_adjust_count; unsigned chans_num; @@ -319,6 +353,7 @@ u32 aint; u32 aint_en; }; + static struct trident_pcm_bank_address bank_a_addrs = { T4D_START_A, @@ -326,6 +361,7 @@ T4D_AINT_A, T4D_AINTEN_A }; + static struct trident_pcm_bank_address bank_b_addrs = { T4D_START_B, @@ -333,6 +369,7 @@ T4D_AINT_B, T4D_AINTEN_B }; + struct trident_pcm_bank { /* register addresses to control bank operations */ struct trident_pcm_bank_address *addresses; @@ -398,6 +435,7 @@ HSET, MIC, MODEM_LINE1, MODEM_LINE2, I2S_LR, SPDIF_LR }; + /* table to map from channel attribute to CHANNELMASK for SiS 7018 */ static int attr2mask [] = { DSP_BIND_MODEM1, DSP_BIND_MODEM2, DSP_BIND_FRONT, DSP_BIND_HANDSET, @@ -406,7 +444,7 @@ /* Added by Matt Wu 01-05-2001 for spdif in */ static int ali_close_multi_channels(void); -static void ali_delay(struct trident_card *card,int interval); +static void ali_delay(struct trident_card *card, int interval); static void ali_detect_spdif_rate(struct trident_card *card); static void ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val); @@ -438,8 +476,11 @@ static void ali_disable_spdif_in(struct trident_card *card); static void ali_disable_special_channel(struct trident_card *card, int ch); static void ali_setup_spdif_out(struct trident_card *card, int flag); -static int ali_write_5_1(struct trident_state *state, const char *buffer,int cnt_for_multi_channel, unsigned int *copy_count, unsigned int *state_cnt); -static int ali_allocate_other_states_resources(struct trident_state *state, int chan_nums); +static int ali_write_5_1(struct trident_state *state, const char *buffer, + int cnt_for_multi_channel, unsigned int *copy_count, + unsigned int *state_cnt); +static int ali_allocate_other_states_resources(struct trident_state *state, + int chan_nums); static void ali_free_other_states_resources(struct trident_state *state); @@ -450,22 +491,29 @@ unsigned mixer_regs[ALI_MIXER_REGS]; } ali_registers; -#define seek_offset(dma_ptr, buffer, cnt, offset, copy_count) (dma_ptr) += (offset); \ - (buffer) += (offset); \ - (cnt) -= (offset); \ - (copy_count) += (offset); - -#define lock_set_fmt(state) {spin_lock_irqsave(&state->card->lock, flags); \ - if (state->fmt_flag) { \ - spin_unlock_irqrestore(&state->card->lock, flags); \ - return -EFAULT; \ - } \ - state->fmt_flag = 1; \ - spin_unlock_irqrestore(&state->card->lock, flags);} +#define seek_offset(dma_ptr, buffer, cnt, offset, copy_count) do { \ + (dma_ptr) += (offset); \ + (buffer) += (offset); \ + (cnt) -= (offset); \ + (copy_count) += (offset); \ +} while (0) + + +#define lock_set_fmt(state) do { \ + spin_lock_irqsave(&state->card->lock, flags); \ + if (state->fmt_flag) { \ + spin_unlock_irqrestore(&state->card->lock, flags); \ + return -EFAULT; \ + } \ + state->fmt_flag = 1; \ + spin_unlock_irqrestore(&state->card->lock, flags); \ +} while (0) -#define unlock_set_fmt(state) {spin_lock_irqsave(&state->card->lock, flags); \ - state->fmt_flag = 0; \ - spin_unlock_irqrestore(&state->card->lock, flags);} +#define unlock_set_fmt(state) do { \ + spin_lock_irqsave(&state->card->lock, flags); \ + state->fmt_flag = 0; \ + spin_unlock_irqrestore(&state->card->lock, flags); \ +} while (0) static int trident_enable_loop_interrupts(struct trident_card * card) { @@ -490,10 +538,9 @@ outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR)); -#ifdef DEBUG - printk("trident: Enable Loop Interrupts, globctl = 0x%08X\n", - inl(TRID_REG(card, T4D_LFO_GC_CIR))); -#endif + TRDBG("trident: Enable Loop Interrupts, globctl = 0x%08X\n", + inl(TRID_REG(card, T4D_LFO_GC_CIR))); + return (TRUE); } @@ -505,10 +552,9 @@ global_control &= ~(ENDLP_IE | MIDLP_IE); outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR)); -#ifdef DEBUG - printk("trident: Disabled Loop Interrupts, globctl = 0x%08X\n", - global_control); -#endif + TRDBG("trident: Disabled Loop Interrupts, globctl = 0x%08X\n", + global_control); + return (TRUE); } @@ -524,9 +570,9 @@ #ifdef DEBUG reg = inl(TRID_REG(card, addr)); - printk("trident: enabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", - channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr); -#endif + TRDBG("trident: enabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", + channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr); +#endif /* DEBUG */ } static void trident_disable_voice_irq(struct trident_card * card, unsigned int channel) @@ -544,9 +590,9 @@ #ifdef DEBUG reg = inl(TRID_REG(card, addr)); - printk("trident: disabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", - channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr); -#endif + TRDBG("trident: disabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", + channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr); +#endif /* DEBUG */ } static void trident_start_voice(struct trident_card * card, unsigned int channel) @@ -557,15 +603,15 @@ #ifdef DEBUG u32 reg; -#endif +#endif /* DEBUG */ outl(mask, TRID_REG(card, addr)); -#ifdef DEBUG +#ifdef DEBUG reg = inl(TRID_REG(card, addr)); - printk("trident: start voice on channel %d, %s = 0x%08x(addr:%X)\n", - channel, addr==T4D_START_B? "START_B":"START_A",reg,addr); -#endif + TRDBG("trident: start voice on channel %d, %s = 0x%08x(addr:%X)\n", + channel, addr==T4D_START_B? "START_B":"START_A",reg,addr); +#endif /* DEBUG */ } static void trident_stop_voice(struct trident_card * card, unsigned int channel) @@ -576,15 +622,15 @@ #ifdef DEBUG u32 reg; -#endif +#endif /* DEBUG */ outl(mask, TRID_REG(card, addr)); #ifdef DEBUG reg = inl(TRID_REG(card, addr)); - printk("trident: stop voice on channel %d, %s = 0x%08x(addr:%X)\n", - channel, addr==T4D_STOP_B? "STOP_B":"STOP_A",reg,addr); -#endif + TRDBG("trident: stop voice on channel %d, %s = 0x%08x(addr:%X)\n", + channel, addr==T4D_STOP_B? "STOP_B":"STOP_A",reg,addr); +#endif /* DEBUG */ } static u32 trident_get_interrupt_mask (struct trident_card * card, unsigned int channel) @@ -601,9 +647,9 @@ #ifdef DEBUG if (reg & mask) - printk("trident: channel %d has interrupt, %s = 0x%08x\n", - channel,reg==T4D_AINT_B? "AINT_B":"AINT_A", reg); -#endif + TRDBG("trident: channel %d has interrupt, %s = 0x%08x\n", + channel,reg==T4D_AINT_B? "AINT_B":"AINT_A", reg); +#endif /* DEBUG */ return (reg & mask) ? TRUE : FALSE; } @@ -619,9 +665,9 @@ #ifdef DEBUG reg = inl(TRID_REG(card, T4D_AINT_B)); - printk("trident: Ack channel %d interrupt, AINT_B = 0x%08x\n", - channel, reg); -#endif + TRDBG("trident: Ack channel %d interrupt, AINT_B = 0x%08x\n", + channel, reg); +#endif /* DEBUG */ } static struct trident_channel * trident_alloc_pcm_channel(struct trident_card *card) @@ -722,9 +768,8 @@ * Keep interrupts off for the configure - we don't want to * clash with another cyberpro config event */ - - save_flags(flags); - cli(); + + spin_lock_irqsave(&card->lock, flags); portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE); /* enable, if it was disabled */ if( (portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE ) { @@ -749,7 +794,7 @@ cyber_outidx( CYBER_PORT_AUDIO, 0xb3, 0x06 ); cyber_outidx( CYBER_PORT_AUDIO, 0xbf, 0x00 ); } - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); return ret; } @@ -869,9 +914,7 @@ trident_write_voice_regs(state); -#ifdef DEBUG - printk("trident: called trident_set_dac_rate : rate = %d\n", rate); -#endif + TRDBG("trident: called trident_set_dac_rate : rate = %d\n", rate); return rate; } @@ -891,9 +934,8 @@ trident_write_voice_regs(state); -#ifdef DEBUG - printk("trident: called trident_set_adc_rate : rate = %d\n", rate); -#endif + TRDBG("trident: called trident_set_adc_rate : rate = %d\n", rate); + return rate; } @@ -935,11 +977,11 @@ if (dmabuf->fmt & TRIDENT_FMT_STEREO) /* stereo */ channel->control |= CHANNEL_STEREO; -#ifdef DEBUG - printk("trident: trident_play_setup, LBA = 0x%08x, " - "Delta = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n", - channel->lba, channel->delta, channel->eso, channel->control); -#endif + + TRDBG("trident: trident_play_setup, LBA = 0x%08x, " + "Delta = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n", + channel->lba, channel->delta, channel->eso, channel->control); + trident_write_voice_regs(state); } @@ -1021,11 +1063,11 @@ if (dmabuf->fmt & TRIDENT_FMT_STEREO) /* stereo */ channel->control |= CHANNEL_STEREO; -#ifdef DEBUG - printk("trident: trident_rec_setup, LBA = 0x%08x, " - "Delat = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n", - channel->lba, channel->delta, channel->eso, channel->control); -#endif + + TRDBG("trident: trident_rec_setup, LBA = 0x%08x, " + "Delat = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n", + channel->lba, channel->delta, channel->eso, channel->control); + trident_write_voice_regs(state); } @@ -1058,11 +1100,10 @@ return 0; } -#ifdef DEBUG - printk("trident: trident_get_dma_addr: chip reported channel: %d, " - "cso = 0x%04x\n", - dmabuf->channel->num, cso); -#endif + + TRDBG("trident: trident_get_dma_addr: chip reported channel: %d, " + "cso = 0x%04x\n", dmabuf->channel->num, cso); + /* ESO and CSO are in units of Samples, convert to byte offset */ cso <<= sample_shift[dmabuf->fmt]; @@ -1160,27 +1201,18 @@ #define DMABUF_DEFAULTORDER (15-PAGE_SHIFT) #define DMABUF_MINORDER 1 -/* allocate DMA buffer, playback and recording buffer should be allocated seperately */ -static int alloc_dmabuf(struct trident_state *state) +/* alloc a DMA buffer of with a buffer of this order */ +static int alloc_dmabuf(struct dmabuf* dmabuf, struct pci_dev* pci_dev, int order) { - struct dmabuf *dmabuf = &state->dmabuf; void *rawbuf = NULL; - int order; struct page *page, *pend; - /* alloc as big a chunk as we can, FIXME: is this necessary ?? */ - for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) - if ((rawbuf = pci_alloc_consistent(state->card->pci_dev, - PAGE_SIZE << order, - &dmabuf->dma_handle))) - break; - if (!rawbuf) + if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order, + &dmabuf->dma_handle))) return -ENOMEM; -#ifdef DEBUG - printk("trident: allocated %ld (order = %d) bytes at %p\n", - PAGE_SIZE << order, order, rawbuf); -#endif + TRDBG("trident: allocated %ld (order = %d) bytes at %p\n", + PAGE_SIZE << order, order, rawbuf); dmabuf->ready = dmabuf->mapped = 0; dmabuf->rawbuf = rawbuf; @@ -1194,21 +1226,37 @@ return 0; } -/* free DMA buffer */ -static void dealloc_dmabuf(struct trident_state *state) +/* allocate the main DMA buffer, playback and recording buffer should be */ +/* allocated seperately */ +static int alloc_main_dmabuf(struct trident_state *state) { struct dmabuf *dmabuf = &state->dmabuf; - struct page *page, *pend; + int order; + int ret = -ENOMEM; + /* alloc as big a chunk as we can, FIXME: is this necessary ?? */ + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) { + if (!(ret = alloc_dmabuf(dmabuf, state->card->pci_dev, order))) + return 0; + /* else try again */ + } + return ret; +} + +/* deallocate a DMA buffer */ +static void dealloc_dmabuf(struct dmabuf* dmabuf, struct pci_dev* pci_dev) +{ + struct page *page, *pend; + if (dmabuf->rawbuf) { /* undo marking the pages as reserved */ pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++) mem_map_unreserve(page); - pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder, + pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder, dmabuf->rawbuf, dmabuf->dma_handle); + dmabuf->rawbuf = NULL; } - dmabuf->rawbuf = NULL; dmabuf->mapped = dmabuf->ready = 0; } @@ -1220,16 +1268,16 @@ unsigned bufsize, dma_nums; unsigned long flags; int ret, i, order; - struct page *page, *pend; lock_set_fmt(state); if (state->chans_num == 6) dma_nums = 5; - else dma_nums = 1; + else + dma_nums = 1; for (i = 0; i < dma_nums; i++) { if (i > 0) { - s = state->other_states[i - 1]; + s = state->other_states[i - 1]; dmabuf = &s->dmabuf; dmabuf->fmt = state->dmabuf.fmt; dmabuf->rate = state->dmabuf.rate; @@ -1243,35 +1291,25 @@ /* allocate DMA buffer if not allocated yet */ if (!dmabuf->rawbuf) { if (i == 0) { - if ((ret = alloc_dmabuf(state))) { + if ((ret = alloc_main_dmabuf(state))) { unlock_set_fmt(state); return ret; } - } - else { + } else { + ret = -ENOMEM; if ((order = state->dmabuf.buforder - 1) >= DMABUF_MINORDER) { - dmabuf->rawbuf = pci_alloc_consistent(state->card->pci_dev, - PAGE_SIZE << order, - &dmabuf->dma_handle); + ret = alloc_dmabuf(dmabuf, state->card->pci_dev, order); } - if (!dmabuf->rawbuf) { - free_pages((unsigned long)state->dmabuf.rawbuf, state->dmabuf.buforder); - state->dmabuf.rawbuf = NULL; - i-=2; - for (; i >= 0; i--) { - pci_free_consistent(state->card->pci_dev, - PAGE_SIZE << state->other_states[i]->dmabuf.buforder, - state->other_states[i]->dmabuf.rawbuf, - state->other_states[i]->dmabuf.dma_handle); - } + if (ret) { + /* release the main DMA buffer */ + dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); + /* release the auxiliary DMA buffers */ + for (i-=2; i >= 0; i--) + dealloc_dmabuf(&state->other_states[i]->dmabuf, + state->card->pci_dev); unlock_set_fmt(state); - return -ENOMEM; + return ret; } - dmabuf->ready = dmabuf->mapped = 0; - dmabuf->buforder = order; - pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << order) - 1); - for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++) - mem_map_reserve(page); } } /* FIXME: figure out all this OSS fragment stuff */ @@ -1301,22 +1339,20 @@ dmabuf->dmasize); spin_lock_irqsave(&s->card->lock, flags); - if (rec) { + if (rec) trident_rec_setup(s); - } else { + else trident_play_setup(s); - } + spin_unlock_irqrestore(&s->card->lock, flags); /* set the ready flag for the dma buffer */ dmabuf->ready = 1; -#ifdef DEBUG - printk("trident: prog_dmabuf(%d), sample rate = %d, format = %d, numfrag = %d, " - "fragsize = %d dmasize = %d\n", - dmabuf->channel->num, dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, - dmabuf->fragsize, dmabuf->dmasize); -#endif + TRDBG("trident: prog_dmabuf(%d), sample rate = %d, format = %d, numfrag = %d, " + "fragsize = %d dmasize = %d\n", + dmabuf->channel->num, dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, + dmabuf->fragsize, dmabuf->dmasize); } unlock_set_fmt(state); return 0; @@ -1540,19 +1576,21 @@ { int i; struct trident_state *state; + unsigned int channel; /* Update the pointers for all channels we are running. */ /* FIXME: should read interrupt status only once */ for (i = 0; i < NR_HW_CH; i++) { - if (trident_check_channel_interrupt(card, 63 - i)) { - trident_ack_channel_interrupt(card, 63 - i); + channel = 63 - i; + if (trident_check_channel_interrupt(card, channel)) { + trident_ack_channel_interrupt(card, channel); if ((state = card->states[i]) != NULL) { trident_update_ptr(state); } else { - printk("trident: spurious channel irq %d.\n", - 63 - i); - trident_stop_voice(card, 63 - i); - trident_disable_voice_irq(card, 63 - i); + printk(KERN_WARNING "trident: spurious channel " + "irq %d.\n", channel); + trident_stop_voice(card, channel); + trident_disable_voice_irq(card, channel); } } } @@ -1660,29 +1698,29 @@ { int i,irq_status; struct trident_state *state; + unsigned int channel; /* Update the pointers for all channels we are running. */ /* FIXED: read interrupt status only once */ irq_status=inl(TRID_REG(card, T4D_AINT_A) ); -#ifdef DEBUG - printk("cyber_address_interrupt: irq_status 0x%X\n",irq_status); -#endif - for (i = 0; i < NR_HW_CH; i++) { - if (irq_status & ( 1 << (31 - i)) ) { + TRDBG("cyber_address_interrupt: irq_status 0x%X\n",irq_status); + + for (i = 0; i < NR_HW_CH; i++) { + channel = 31 - i; + if (irq_status & ( 1 << channel) ) { /* clear bit by writing a 1, zeroes are ignored */ - outl( (1 <<(31-i)), TRID_REG(card, T4D_AINT_A)); + outl( (1 << channel), TRID_REG(card, T4D_AINT_A)); -#ifdef DEBUG - printk("cyber_interrupt: channel %d\n", 31-i); -#endif + TRDBG("cyber_interrupt: channel %d\n", channel); + if ((state = card->states[i]) != NULL) { trident_update_ptr(state); } else { - printk("cyber5050: spurious channel irq %d.\n", - 31 - i); - trident_stop_voice(card, 31 - i); - trident_disable_voice_irq(card, 31 - i); + printk(KERN_WARNING "cyber5050: spurious " + "channel irq %d.\n", channel); + trident_stop_voice(card, channel); + trident_disable_voice_irq(card, channel); } } } @@ -1697,9 +1735,7 @@ spin_lock(&card->lock); event = inl(TRID_REG(card, T4D_MISCINT)); -#ifdef DEBUG - printk("trident: trident_interrupt called, MISCINT = 0x%08x\n", event); -#endif + TRDBG("trident: trident_interrupt called, MISCINT = 0x%08x\n", event); if (event & ADDRESS_IRQ) { card->address_interrupt(card); @@ -1737,9 +1773,7 @@ unsigned swptr; int cnt; -#ifdef DEBUG - printk("trident: trident_read called, count = %d\n", count); -#endif + TRDBG("trident: trident_read called, count = %d\n", count); VALIDATE_STATE(state); if (ppos != &file->f_pos) @@ -1793,12 +1827,11 @@ which results in a (potential) buffer overrun. And worse, there is NOTHING we can do to prevent it. */ if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { -#ifdef DEBUG - printk(KERN_ERR "trident: recording schedule timeout, " - "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", - dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, - dmabuf->hwptr, dmabuf->swptr); -#endif + TRDBG(KERN_ERR "trident: recording schedule timeout, " + "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", + dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, + dmabuf->hwptr, dmabuf->swptr); + /* a buffer overrun, we delay the recovery until next time the while loop begin and we REALLY have space to record */ } @@ -1852,9 +1885,8 @@ unsigned int state_cnt; unsigned int copy_count; -#ifdef DEBUG - printk("trident: trident_write called, count = %d\n", count); -#endif + TRDBG("trident: trident_write called, count = %d\n", count); + VALIDATE_STATE(state); if (ppos != &file->f_pos) return -ESPIPE; @@ -1922,12 +1954,11 @@ which results in a (potential) buffer underrun. And worse, there is NOTHING we can do to prevent it. */ if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { -#ifdef DEBUG - printk(KERN_ERR "trident: playback schedule timeout, " - "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", - dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, - dmabuf->hwptr, dmabuf->swptr); -#endif + TRDBG(KERN_ERR "trident: playback schedule timeout, " + "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", + dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, + dmabuf->hwptr, dmabuf->swptr); + /* a buffer underrun, we delay the recovery until next time the while loop begin and we REALLY have data to play */ } @@ -2106,10 +2137,8 @@ VALIDATE_STATE(state); mapped = ((file->f_mode & FMODE_WRITE) && dmabuf->mapped) || ((file->f_mode & FMODE_READ) && dmabuf->mapped); -#ifdef DEBUG - printk("trident: trident_ioctl, command = %2d, arg = 0x%08x\n", - _IOC_NR(cmd), arg ? *(int *)arg : 0); -#endif + TRDBG("trident: trident_ioctl, command = %2d, arg = 0x%08x\n", + _IOC_NR(cmd), arg ? *(int *)arg : 0); switch (cmd) { @@ -2269,6 +2298,7 @@ { printk(KERN_ERR "trident: Record is working on the card!\n"); ret = -EBUSY; + unlock_set_fmt(state); break; } @@ -2454,8 +2484,7 @@ if (dmabuf->mapped) dmabuf->count &= dmabuf->fragsize-1; spin_unlock_irqrestore(&state->card->lock, flags); - ret = copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? - -EFAULT : 0; + ret = copy_to_user((void *)arg, &cinfo, sizeof(cinfo))?-EFAULT:0; break; case SNDCTL_DSP_GETOPTR: @@ -2673,10 +2702,8 @@ state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); up(&card->open_sem); -#ifdef DEBUG - printk(KERN_ERR "trident: open virtual channel %d, hard channel %d\n", + TRDBG("trident: open virtual channel %d, hard channel %d\n", state->virt, dmabuf->channel->num); -#endif return 0; } @@ -2686,7 +2713,6 @@ struct trident_state *state = (struct trident_state *)file->private_data; struct trident_card *card; struct dmabuf *dmabuf; - unsigned long flags; lock_kernel(); card = state->card; @@ -2698,20 +2724,15 @@ drain_dac(state, file->f_flags & O_NONBLOCK); } -#ifdef DEBUG - printk(KERN_ERR "trident: closing virtual channel %d, hard channel %d\n", - state->virt, dmabuf->channel->num); -#endif + TRDBG("trident: closing virtual channel %d, hard channel %d\n", + state->virt, dmabuf->channel->num); /* stop DMA state machine and free DMA buffers/channels */ down(&card->open_sem); if (file->f_mode & FMODE_WRITE) { stop_dac(state); - lock_set_fmt(state); - - unlock_set_fmt(state); - dealloc_dmabuf(state); + dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); state->card->free_pcm_channel(state->card, dmabuf->channel->num); /* Added by Matt Wu */ @@ -2727,7 +2748,7 @@ } if (file->f_mode & FMODE_READ) { stop_adc(state); - dealloc_dmabuf(state); + dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); state->card->free_pcm_channel(state->card, dmabuf->channel->num); /* Added by Matt Wu */ @@ -2876,62 +2897,74 @@ return ((u16) (data >> 16)); } -/* Write AC97 codec registers for ALi*/ -static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val) +/* rewrite ac97 read and write mixer register by hulei for ALI*/ +static int acquirecodecaccess(struct trident_card *card) { - unsigned int address, mask; - unsigned int wCount1 = 0xffff; - unsigned int wCount2= 0xffff; - unsigned long chk1, chk2; - unsigned long flags; - u32 data; - - data = ((u32) val) << 16; - - if(!card) - BUG(); - - address = ALI_AC97_WRITE; - mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY; - if (secondary) - mask |= ALI_AC97_SECONDARY; - if (card->revision == ALI_5451_V02) - mask |= ALI_AC97_WRITE_MIXER_REGISTER; + u16 wsemamask=0x6000; /* bit 14..13 */ + u16 wsemabits; + u16 wcontrol ; + int block = 0; + int ncount = 25; + while (1) { + wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); + wsemabits = wcontrol & wsemamask; - spin_lock_irqsave(&card->lock, flags); - while (wCount1--) { - if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_WRITE) == 0) { - data |= (mask | (reg & AC97_REG_ADDR)); - - chk1 = inl(TRID_REG(card, ALI_STIMER)); - chk2 = inl(TRID_REG(card, ALI_STIMER)); - while (wCount2-- && (chk1 == chk2)) - chk2 = inl(TRID_REG(card, ALI_STIMER)); - if (wCount2 == 0) { - spin_unlock_irqrestore(&card->lock, flags); - return; - } - outl(data, TRID_REG(card, address)); //write! - spin_unlock_irqrestore(&card->lock, flags); - return; //success + if (wsemabits==0x4000) + return 1; /* 0x4000 is audio ,then success */ + if (ncount-- < 0) + break; + if (wsemabits == 0) + { + unlock: + outl(((u32)(wcontrol & 0x1eff)|0x00004000), TRID_REG(card, ALI_AC97_WRITE)); + continue; } - inw(TRID_REG(card, address)); //wait for a read cycle + udelay(20); + } + if(!block) + { + TRDBG("accesscodecsemaphore: try unlock\n"); + block = 1; + goto unlock; } + printk(KERN_ERR "accesscodecsemaphore: fail\n"); + return 0; +} - printk(KERN_ERR "ali: AC97 CODEC write timed out.\n"); - spin_unlock_irqrestore(&card->lock, flags); - return; +static void releasecodecaccess(struct trident_card *card) +{ + unsigned long wcontrol; + wcontrol = inl(TRID_REG(card, ALI_AC97_WRITE)); + outl((wcontrol & 0xffff1eff), TRID_REG(card, ALI_AC97_WRITE)); +} + +static int waitforstimertick(struct trident_card *card) +{ + unsigned long chk1, chk2; + unsigned int wcount = 0xffff; + chk1 = inl(TRID_REG(card, ALI_STIMER)); + + while(1) { + chk2 = inl(TRID_REG(card, ALI_STIMER)); + if( (wcount > 0) && chk1 != chk2) + return 1; + if(wcount <= 0) + break; + udelay(50); + } + + printk(KERN_NOTICE "waitforstimertick :BIT_CLK is dead\n"); + return 0; } /* Read AC97 codec registers for ALi*/ static u16 ali_ac97_get(struct trident_card *card, int secondary, u8 reg) { unsigned int address, mask; - unsigned int wCount1 = 0xffff; - unsigned int wCount2= 0xffff; - unsigned long chk1, chk2; - unsigned long flags; + unsigned int ncount; + unsigned long aud_reg; u32 data; + u16 wcontrol; if(!card) BUG(); @@ -2943,37 +2976,102 @@ mask = ALI_AC97_READ_ACTION | ALI_AC97_AUDIO_BUSY; if (secondary) mask |= ALI_AC97_SECONDARY; + + if (!acquirecodecaccess(card)) + printk(KERN_ERR "access codec fail\n"); + + wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); + wcontrol &= 0xfe00; + wcontrol |= (0x8000|reg); + outw(wcontrol,TRID_REG(card, ALI_AC97_WRITE)); - spin_lock_irqsave(&card->lock, flags); data = (mask | (reg & AC97_REG_ADDR)); - while (wCount1--) { - if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_READ) == 0) { - chk1 = inl(TRID_REG(card, ALI_STIMER)); - chk2 = inl(TRID_REG(card, ALI_STIMER)); - while (wCount2-- && (chk1 == chk2)) - chk2 = inl(TRID_REG(card, ALI_STIMER)); - if (wCount2 == 0) { - printk(KERN_ERR "ali: AC97 CODEC read timed out.\n"); - spin_unlock_irqrestore(&card->lock, flags); - return 0; - } - outl(data, TRID_REG(card, address)); //read! - wCount2 = 0xffff; - while (wCount2--) { - if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_READ) == 0) { - data = inl(TRID_REG(card, address)); - spin_unlock_irqrestore(&card->lock, flags); - return ((u16) (data >> 16)); - } - } + + if(!waitforstimertick(card)) { + printk(KERN_ERR "BIT_CLOCK is dead\n"); + goto releasecodec; + } + + udelay(20); + + ncount=10; + + while(1) { + if ((inw(TRID_REG(card,ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ) != 0) + break; + if(ncount <=0) + break; + if(ncount--==1) { + TRDBG("ali_ac97_read :try clear busy flag\n"); + aud_reg = inl(TRID_REG(card, ALI_AC97_WRITE)); + outl((aud_reg & 0xffff7fff), TRID_REG(card, ALI_AC97_WRITE)); } - inw(TRID_REG(card, address)); //wait a read cycle + udelay(10); } - spin_unlock_irqrestore(&card->lock, flags); + + data = inl(TRID_REG(card, address)); + + return ((u16) (data >> 16)); + + releasecodec: + releasecodecaccess(card); printk(KERN_ERR "ali: AC97 CODEC read timed out.\n"); return 0; } + +/* Write AC97 codec registers for hulei*/ +static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val) +{ + unsigned int address, mask; + unsigned int ncount; + u32 data; + u16 wcontrol; + + data = ((u32) val) << 16; + + if(!card) + BUG(); + + address = ALI_AC97_WRITE; + mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY; + if (secondary) + mask |= ALI_AC97_SECONDARY; + if (card->revision == ALI_5451_V02) + mask |= ALI_AC97_WRITE_MIXER_REGISTER; + + if (!acquirecodecaccess(card)) + printk(KERN_ERR "access codec fail\n"); + + wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); + wcontrol &= 0xff00; + wcontrol |= (0x8100|reg);/* bit 8=1: (ali1535 )reserved /ali1535+ write */ + outl(( data |wcontrol), TRID_REG(card,ALI_AC97_WRITE )); + + if(!waitforstimertick(card)) { + printk(KERN_ERR "BIT_CLOCK is dead\n"); + goto releasecodec; + } + + ncount = 10; + while(1) { + wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); + if(!wcontrol & 0x8000) + break; + if(ncount <= 0) + break; + if(ncount-- == 1) { + TRDBG("ali_ac97_set :try clear busy flag!!\n"); + outw(wcontrol & 0x7fff, TRID_REG(card, ALI_AC97_WRITE)); + } + udelay(10); + } + + releasecodec: + releasecodecaccess(card); + return; +} + static void ali_enable_special_channel(struct trident_state *stat) { struct trident_card *card = stat->card; @@ -3305,11 +3403,18 @@ ali_ac97_write(card->ac97_codec[0], 0x02, 8080); ali_ac97_write(card->ac97_codec[0], 0x36, 0); ali_ac97_write(card->ac97_codec[0], 0x38, 0); - ali_ac97_write(card->ac97_codec[1], 0x36, 0); - ali_ac97_write(card->ac97_codec[1], 0x38, 0); - ali_ac97_write(card->ac97_codec[1], 0x02, 0x0606); - ali_ac97_write(card->ac97_codec[1], 0x18, 0x0303); - ali_ac97_write(card->ac97_codec[1], 0x74, 0x3); + /* + * On a board with a single codec you won't get the + * surround. On other boards configure it. + */ + if(card->ac97_codec[1]!=NULL) + { + ali_ac97_write(card->ac97_codec[1], 0x36, 0); + ali_ac97_write(card->ac97_codec[1], 0x38, 0); + ali_ac97_write(card->ac97_codec[1], 0x02, 0x0606); + ali_ac97_write(card->ac97_codec[1], 0x18, 0x0303); + ali_ac97_write(card->ac97_codec[1], 0x74, 0x3); + } return 1; } } @@ -3396,9 +3501,8 @@ unsigned long flags; int i, j; - save_flags(flags); - cli(); - + spin_lock_irqsave(&card->lock, flags); + ali_registers.global_regs[0x2c] = inl(TRID_REG(card,T4D_MISCINT)); //ali_registers.global_regs[0x20] = inl(TRID_REG(card,T4D_START_A)); ali_registers.global_regs[0x21] = inl(TRID_REG(card,T4D_STOP_A)); @@ -3426,7 +3530,7 @@ //Stop all HW channel outl(ALI_STOP_ALL_CHANNELS, TRID_REG(card, T4D_STOP_A)); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } static void ali_restore_regs(struct trident_card *card) @@ -3434,8 +3538,7 @@ unsigned long flags; int i, j; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); for (i = 1; i < ALI_MIXER_REGS; i++) ali_ac97_write(card->ac97_codec[0], i*2, ali_registers.mixer_regs[i]); @@ -3458,13 +3561,13 @@ outl(ali_registers.global_regs[0x20], TRID_REG(card,T4D_START_A)); //restore IRQ enable bits outl(ali_registers.global_regs[0x2c], TRID_REG(card,T4D_MISCINT)); - - restore_flags(flags); + + spin_unlock_irqrestore(&card->lock, flags); } static int trident_suspend(struct pci_dev *dev, u32 unused) { - struct trident_card *card = (struct trident_card *) dev; + struct trident_card *card = pci_get_drvdata(dev); if(card->pci_id == PCI_DEVICE_ID_ALI_5451) { ali_save_regs(card); @@ -3474,7 +3577,7 @@ static int trident_resume(struct pci_dev *dev) { - struct trident_card *card = (struct trident_card *) dev; + struct trident_card *card = pci_get_drvdata(dev); if(card->pci_id == PCI_DEVICE_ID_ALI_5451) { ali_restore_regs(card); @@ -3601,7 +3704,10 @@ depend on a master state's DMA, and changing the counters of the master state DMA is protected by a spinlock. */ -static int ali_write_5_1(struct trident_state *state, const char *buf, int cnt_for_multi_channel, unsigned int *copy_count, unsigned int *state_cnt) +static int ali_write_5_1(struct trident_state *state, + const char *buf, int cnt_for_multi_channel, + unsigned int *copy_count, + unsigned int *state_cnt) { struct dmabuf *dmabuf = &state->dmabuf; @@ -3707,7 +3813,7 @@ other_states_count = state->chans_num - 2; /* except PCM L/R channels*/ for ( i = 0; i < other_states_count; i++) { s = state->other_states[i]; - dealloc_dmabuf(s); + dealloc_dmabuf(&s->dmabuf, card->pci_dev); ali_disable_special_channel(s->card, s->dmabuf.channel->num); state->card->free_pcm_channel(s->card, s->dmabuf.channel->num); card->states[s->virt] = NULL; @@ -3715,7 +3821,6 @@ } } -#ifdef CONFIG_PROC_FS struct proc_dir_entry *res; static int ali_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) { @@ -3753,7 +3858,6 @@ return count; } -#endif /* OSS /dev/mixer file operation methods */ static int trident_open_mixdev(struct inode *inode, struct file *file) @@ -3821,7 +3925,7 @@ pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff); udelay(5000); - wCount = 200; + wCount = 2000; while(wCount--) { wReg = ali_ac97_get(card, 0, AC97_POWER_CONTROL); if((wReg & 0x000f) == 0x000f) @@ -4087,13 +4191,11 @@ /* ALi SPDIF OUT function */ if(card->revision == ALI_5451_V02) { ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT); -#ifdef CONFIG_PROC_FS res = create_proc_entry("ALi5451", 0, NULL); if (res) { res->write_proc = ali_write_proc; res->data = card; } -#endif } /* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */ @@ -4186,7 +4288,7 @@ ali_ac97_set(card, 0, AC97_POWER_CONTROL, ac97_data | ALI_EAPD_POWER_DOWN); } } -#endif +#endif /* CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC */ /* edited by HMSEO for GT sound*/ } rc = 0; @@ -4204,12 +4306,10 @@ out_free_irq: free_irq(card->irq, card); out_proc_fs: -#ifdef CONFIG_PROC_FS if (res) { remove_proc_entry("ALi5451", NULL); res = NULL; } -#endif kfree(card); devs = NULL; out_release_region: @@ -4234,9 +4334,7 @@ ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT); ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL); ali_disable_spdif_in(card); -#ifdef CONFIG_PROC_FS remove_proc_entry("ALi5451", NULL); -#endif } /* Unregister gameport */ @@ -4283,8 +4381,9 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro 5050 PCI Audio, version " - DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro " + "5050 PCI Audio, version " DRIVER_VERSION ", " + __TIME__ " " __DATE__ "\n"); if (!pci_register_driver(&trident_pci_driver)) { pci_unregister_driver(&trident_pci_driver); diff -Nru a/sound/oss/trident.h b/sound/oss/trident.h --- a/sound/oss/trident.h Thu Aug 1 14:17:36 2002 +++ b/sound/oss/trident.h Thu Aug 1 14:17:36 2002 @@ -360,5 +360,16 @@ return r; } -#endif /* __TRID4DWAVE_H */ +#ifdef DEBUG + +#define TRDBG(msg, args...) do { \ + printk(KERN_DEBUG msg , ##args ); \ +} while (0) + +#else /* !defined(DEBUG) */ +#define TRDBG(msg, args...) do { } while (0) + +#endif /* DEBUG */ + +#endif /* __TRID4DWAVE_H */ diff -Nru a/sound/sound_core.c b/sound/sound_core.c --- a/sound/sound_core.c Thu Aug 1 14:17:40 2002 +++ b/sound/sound_core.c Thu Aug 1 14:17:40 2002 @@ -554,14 +554,13 @@ { /* We have nothing to really do here - we know the lists must be empty */ - devfs_unregister_chrdev(SOUND_MAJOR, "sound"); + unregister_chrdev(SOUND_MAJOR, "sound"); devfs_unregister (devfs_handle); } static int __init init_soundcore(void) { - if(devfs_register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1) - { + if (register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1) { printk(KERN_ERR "soundcore: sound device already in use.\n"); return -EBUSY; }