From e29413a9d12cb9021888672c33212f041e1506c3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:38:35 -0500 Subject: [PATCH] - pre5: - truncate. Guess what? We threw away the key to the clue-box. - simplify signal notification. And remember the spinlock. - VIA ide driver update (well, rewrite - the old one was buggy and broken) - network driver fixes (not checking for oom etc) - USB serial driver SMP locking fixes - fix memory leak on failed USB configuration queries - USB initialization using proper "init()" calls. - dvd capacity bug fix and other cdrom driver cleanups - sis5513 IDE chipset update - do_fork() - add "stack-top" for ia64 (and potentially other architectures that may care) - devfs support for LVM - quota transfer miscount fix - x86 checksum/copy prefetch - NFS sillydelete fix - mark_buffer_dirty() doesn't actually use the second argument. Delete it. - SCSI communications device - no need to complain about it - SCSI WP test fix (all pages, not just the first one) - epic driver update - fix pcmcia "driver asserts interrupts when booting up" issues --- CREDITS | 10 +- Documentation/Changes | 21 +- Documentation/Configure.help | 19 + Documentation/kernel-parameters.txt | 2 + MAINTAINERS | 6 +- arch/alpha/kernel/process.c | 5 +- arch/alpha/kernel/smp.c | 2 +- arch/arm/kernel/process.c | 1 + arch/arm/kernel/sys_arm.c | 6 +- arch/arm/mach-footbridge/ebsa285-leds.c | 1 + arch/arm/mach-footbridge/netwinder-hw.c | 1 + arch/arm/mach-footbridge/netwinder-leds.c | 1 + arch/i386/kernel/process.c | 7 +- arch/i386/kernel/smpboot.c | 2 +- arch/i386/lib/checksum.S | 12 +- arch/ia64/ia32/ia32_entry.S | 4 +- arch/ia64/kernel/entry.S | 8 +- arch/m68k/kernel/process.c | 7 +- arch/mips/kernel/process.c | 1 + arch/mips/kernel/syscall.c | 4 +- arch/mips64/kernel/process.c | 1 + arch/mips64/kernel/syscall.c | 4 +- arch/ppc/kernel/process.c | 7 +- arch/ppc/kernel/smp.c | 2 +- arch/s390/kernel/process.c | 7 +- arch/s390/kernel/smp.c | 2 +- arch/sh/kernel/process.c | 7 +- arch/sparc/kernel/entry.S | 3 + arch/sparc/kernel/process.c | 1 + arch/sparc64/kernel/entry.S | 2 +- arch/sparc64/kernel/process.c | 1 + drivers/block/loop.c | 2 +- drivers/block/lvm.c | 41 +- drivers/block/md.c | 2 +- drivers/cdrom/cdrom.c | 147 +-- drivers/cdrom/sbpcd.c | 117 ++- drivers/cdrom/sbpcd.h | 1 + drivers/char/drm/i810_drv.c | 2 +- drivers/ide/Config.in | 1 - drivers/ide/ide-cd.c | 247 +++-- drivers/ide/ide.c | 74 -- drivers/ide/sis5513.c | 151 +-- drivers/ide/via82cxxx.c | 1606 +++++++++++------------------ drivers/media/video/cpia_usb.c | 18 +- drivers/net/3c503.c | 3 + drivers/net/ac3200.c | 3 + drivers/net/defxx.c | 16 +- drivers/net/defxx.h | 137 +-- drivers/net/natsemi.c | 97 +- drivers/net/ncr885e.c | 8 +- drivers/pcmcia/cardbus.c | 1 - drivers/scsi/scsi_dma.c | 1 + drivers/scsi/scsi_scan.c | 1 + drivers/scsi/sd.c | 16 +- drivers/scsi/sr.c | 85 +- drivers/scsi/sr_ioctl.c | 21 +- drivers/scsi/tmscsim.h | 1 - drivers/usb/audio.c | 14 +- drivers/usb/dabusb.c | 14 +- drivers/usb/dsbr100.c | 12 +- drivers/usb/hub.c | 1 + drivers/usb/ibmcam.c | 18 +- drivers/usb/plusb.c | 18 +- drivers/usb/serial/digi_acceleport.c | 4 +- drivers/usb/serial/ftdi_sio.c | 4 +- drivers/usb/serial/keyspan.c | 4 +- drivers/usb/serial/keyspan_pda.c | 141 ++- drivers/usb/serial/omninet.c | 163 ++- drivers/usb/serial/usb-serial.h | 20 + drivers/usb/serial/usbserial.c | 105 +- drivers/usb/serial/visor.c | 65 +- drivers/usb/serial/whiteheat.c | 4 +- drivers/usb/storage/freecom.c | 1 - drivers/usb/storage/usb.c | 2 +- drivers/usb/usb-core.c | 28 - drivers/usb/usb.c | 1 + fs/adfs/dir_f.c | 2 +- fs/affs/amigaffs.c | 8 +- fs/affs/bitmap.c | 4 +- fs/affs/file.c | 16 +- fs/affs/inode.c | 8 +- fs/affs/namei.c | 4 +- fs/affs/super.c | 8 +- fs/bfs/dir.c | 6 +- fs/bfs/file.c | 6 +- fs/bfs/inode.c | 10 +- fs/block_dev.c | 2 +- fs/buffer.c | 20 +- fs/dquot.c | 26 +- fs/ext2/balloc.c | 12 +- fs/ext2/ialloc.c | 14 +- fs/ext2/inode.c | 68 +- fs/ext2/namei.c | 10 +- fs/ext2/super.c | 12 +- fs/fat/buffer.c | 15 +- fs/fat/cache.c | 6 +- fs/fat/cvf.c | 4 +- fs/fat/dir.c | 2 +- fs/fat/inode.c | 2 +- fs/fat/misc.c | 4 +- fs/fat/msbuffer.h | 3 +- fs/hfs/file.c | 2 +- fs/hpfs/anode.c | 34 +- fs/hpfs/buffer.c | 8 +- fs/hpfs/dnode.c | 4 +- fs/hpfs/ea.c | 6 +- fs/hpfs/inode.c | 2 +- fs/hpfs/namei.c | 12 +- fs/hpfs/super.c | 6 +- fs/minix/bitmap.c | 12 +- fs/minix/inode.c | 28 +- fs/minix/namei.c | 24 +- fs/minix/truncate.c | 10 +- fs/msdos/namei.c | 12 +- fs/nfs/Makefile | 2 +- fs/nfs/dir.c | 12 +- fs/nfs/nfs3proc.c | 30 + fs/nfs/proc.c | 25 + fs/nfs/unlink.c | 212 ++++ fs/ntfs/support.c | 2 +- fs/qnx4/bitmap.c | 2 +- fs/qnx4/inode.c | 4 +- fs/qnx4/namei.c | 4 +- fs/sysv/balloc.c | 16 +- fs/sysv/ialloc.c | 14 +- fs/sysv/inode.c | 10 +- fs/sysv/namei.c | 24 +- fs/sysv/truncate.c | 6 +- fs/udf/balloc.c | 12 +- fs/udf/file.c | 4 +- fs/udf/ialloc.c | 4 +- fs/udf/inode.c | 22 +- fs/udf/namei.c | 10 +- fs/udf/super.c | 4 +- fs/udf/truncate.c | 4 +- fs/ufs/balloc.c | 20 +- fs/ufs/cylinder.c | 2 +- fs/ufs/ialloc.c | 8 +- fs/ufs/inode.c | 6 +- fs/ufs/namei.c | 24 +- fs/ufs/super.c | 10 +- fs/ufs/truncate.c | 8 +- fs/ufs/util.c | 4 +- fs/ufs/util.h | 2 +- fs/umsdos/dir.c | 3 +- fs/umsdos/emd.c | 8 +- fs/umsdos/ioctl.c | 3 +- fs/vfat/namei.c | 10 +- include/linux/fat_cvf.h | 3 +- include/linux/fs.h | 4 +- include/linux/hfs_sysdep.h | 2 +- include/linux/nfs_fs.h | 6 + include/linux/nfs_xdr.h | 3 + include/linux/nfsd/interface.h | 2 + include/linux/sched.h | 9 +- include/scsi/scsi.h | 1 + kernel/fork.c | 17 +- kernel/info.c | 36 + kernel/signal.c | 18 +- 159 files changed, 2436 insertions(+), 2203 deletions(-) rewrite drivers/ide/via82cxxx.c (91%) create mode 100644 fs/nfs/unlink.c diff --git a/CREDITS b/CREDITS index 0663d2a19..3a2378a96 100644 --- a/CREDITS +++ b/CREDITS @@ -514,6 +514,14 @@ D: USB Bluetooth Driver S: University of Michigan S: Ann Arbor, MI +N: Kees Cook +E: cook@cpoint.net +W: http://outflux.net/ +P: 1024D/17063E6D 9FA3 C49C 23C9 D1BC 2E30 1975 1FFF 4BA9 1706 3E6D +D: Minor updates to SCSI code for the Communications type +S: (ask for current address) +S: USA + N: Alan Cox W: http://roadrunner.swansea.linux.org.uk/alan.shtml E: alan@lxorguk.ukuu.org.uk @@ -2084,7 +2092,7 @@ E: ken@halcyon.com D: CDROM driver "sonycd535" (Sony CDU-535/531) N: Frederic Potter -E: Frederic.Potter@masi.ibp.fr +E: fpotter@cirpack.com D: Some PCI kernel support N: Rui Prior diff --git a/Documentation/Changes b/Documentation/Changes index 9b0e67bf1..c12ed2e6d 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -25,7 +25,10 @@ document. Smotrite file , yavlyaushisya russkim perevodom dannogo documenta. -Last updated: August 15, 2000 +Visite para obtener la traducción +al español de este documento en varios formatos. + +Last updated: August 28, 2000 Chris Ricker (kaboom@gatech.edu or chris.ricker@genetics.utah.edu). @@ -44,10 +47,10 @@ with pcmcia-cs. o Gnu C 2.7.2.3 # gcc --version o Gnu make 3.77 # make --version -o binutils 2.9.1.0.22 # ld -v +o binutils 2.9.1.0.25 # ld -v o util-linux 2.10o # kbdrate -v -o modutils 2.3.13 # insmod -V -o e2fsprogs 1.18 # /sbin/tune2fs --version +o modutils 2.3.15 # insmod -V +o e2fsprogs 1.18 # tune2fs --version o pcmcia-cs 3.1.19 # cardmgr -V o PPP 2.4.0 # pppd --version o isdn4k-utils 3.1beta7 # isdnctrl 2>&1|grep version @@ -257,16 +260,16 @@ Binutils ------------ o -2.9.5 series +2.10 series ------------ -o +o System utilities **************** Util-linux ---------- -o +o Ksymoops -------- @@ -274,7 +277,7 @@ o Modutils -------- -o +o Mkinitrd -------- @@ -291,7 +294,7 @@ o Pcmcia-cs --------- -o +o Jade ---- diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 2c157e55b..89b4c516d 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -7903,6 +7903,25 @@ CONFIG_COMX_HW_MIXCOM Documentation/modules.txt. The module will be called comx-hw-mixcom.o. +i810 TCO support +CONFIG_I810_TCO + Hardware driver for the TCO timer built into the Intel i810 and i815 + chipset family. The TCO (Total Cost of Ownership) timer is a watchdog + timer that will reboot the machine after it's second expiration. The + expiration time can be configured by commandline argument + "i810_margin=" where is the counter initial value. It is + decremented every 0.6 secs, the default is 50 which gives a timeout + of 30 seconds and one minute until reset. + + On some motherboards the driver may fail to reset the chipset's + NO_REBOOT flag which prevents the watchdog from rebooting the machine. + If this is the case you will get a kernel message like + "i810tco init: failed to reset NO_REBOOT flag". + + If you want to compile this as a module, say M and read + Documentation/modules.txt. The module will be called + i810-tco.o. + MultiGate Cisco-HDLC and synchronous PPP protocol support CONFIG_COMX_PROTO_PPP Cisco-HDLC and synchronous PPP protocol driver for all MultiGate diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index d3c8bbdaa..495c9a0be 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -516,6 +516,8 @@ running once the system is up. stram_swap= [HW] + swiotlb= [IA-64] Number of I/O TLB slabs. + switches= [HW, M68K] sym53c416= [HW,SCSI] diff --git a/MAINTAINERS b/MAINTAINERS index 1a4cc0d4a..2fc898a4a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -540,7 +540,7 @@ S: Supported IDE/ATAPI CDROM DRIVER P: Jens Axboe -M: axboe@image.dk +M: axboe@suse.de L: linux-kernel@vger.kernel.org W: http://www.kernel.dk S: Maintained @@ -988,7 +988,7 @@ S: Maintained SCSI CDROM DRIVER P: Jens Axboe -M: axboe@image.dk +M: axboe@suse.de L: linux-scsi@vger.kernel.org W: http://www.kernel.dk S: Maintained @@ -1176,7 +1176,7 @@ S: Maintained UNIFORM CDROM DRIVER P: Jens Axboe -M: axboe@image.dk +M: axboe@suse.de L: linux-kernel@vger.kernel.org W: http://www.kernel.dk S: Maintained diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 81d85386d..508e278b0 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -276,14 +276,14 @@ alpha_clone(unsigned long clone_flags, unsigned long usp, { if (!usp) usp = rdusp(); - return do_fork(clone_flags, usp, (struct pt_regs *) (swstack+1)); + return do_fork(clone_flags, usp, (struct pt_regs *) (swstack+1), 0); } int alpha_vfork(struct switch_stack * swstack) { return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), - (struct pt_regs *) (swstack+1)); + (struct pt_regs *) (swstack+1), 0); } /* @@ -299,6 +299,7 @@ alpha_vfork(struct switch_stack * swstack) int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, + unsigned long unused, struct task_struct * p, struct pt_regs * regs) { extern void ret_from_sys_call(void); diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 4f7a04b3f..9e8483a1a 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -420,7 +420,7 @@ static int __init fork_by_hand(void) * don't care about the regs settings since * we'll never reschedule the forked task. */ - return do_fork(CLONE_VM|CLONE_PID, 0, ®s); + return do_fork(CLONE_VM|CLONE_PID, 0, ®s, 0); } /* diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 3456df4fd..72ce0daa7 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -291,6 +291,7 @@ void release_thread(struct task_struct *dead_task) } int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, + unsigned long unused, struct task_struct * p, struct pt_regs * regs) { struct pt_regs * childregs; diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 6d49e1427..fb15b3d97 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -203,7 +203,7 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, */ asmlinkage int sys_fork(struct pt_regs *regs) { - return do_fork(SIGCHLD, regs->ARM_sp, regs); + return do_fork(SIGCHLD, regs->ARM_sp, regs, 0); } /* Clone a task - this clones the calling program thread. @@ -213,12 +213,12 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct { if (!newsp) newsp = regs->ARM_sp; - return do_fork(clone_flags, newsp, regs); + return do_fork(clone_flags, newsp, regs, 0); } asmlinkage int sys_vfork(struct pt_regs *regs) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0); } /* sys_execve() executes a new program. diff --git a/arch/arm/mach-footbridge/ebsa285-leds.c b/arch/arm/mach-footbridge/ebsa285-leds.c index 0855da985..4038ff377 100644 --- a/arch/arm/mach-footbridge/ebsa285-leds.c +++ b/arch/arm/mach-footbridge/ebsa285-leds.c @@ -13,6 +13,7 @@ * Changelog: * 02-05-1999 RMK Various cleanups */ +#include #include #include #include diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c index c1b9c9b10..4b47b6e47 100644 --- a/arch/arm/mach-footbridge/netwinder-hw.c +++ b/arch/arm/mach-footbridge/netwinder-hw.c @@ -5,6 +5,7 @@ * * Copyright (C) 1998, 1999 Russell King, Phil Blundell */ +#include #include #include #include diff --git a/arch/arm/mach-footbridge/netwinder-leds.c b/arch/arm/mach-footbridge/netwinder-leds.c index 9d39073ab..095bbe6ec 100644 --- a/arch/arm/mach-footbridge/netwinder-leds.c +++ b/arch/arm/mach-footbridge/netwinder-leds.c @@ -12,6 +12,7 @@ * Changelog: * 02-05-1999 RMK Various cleanups */ +#include #include #include #include diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 83ec9d192..c23ec7844 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -525,6 +525,7 @@ void copy_segments(struct task_struct *p, struct mm_struct *new_mm) asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value))) int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, + unsigned long unused, struct task_struct * p, struct pt_regs * regs) { struct pt_regs * childregs; @@ -686,7 +687,7 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p) asmlinkage int sys_fork(struct pt_regs regs) { - return do_fork(SIGCHLD, regs.esp, ®s); + return do_fork(SIGCHLD, regs.esp, ®s, 0); } asmlinkage int sys_clone(struct pt_regs regs) @@ -698,7 +699,7 @@ asmlinkage int sys_clone(struct pt_regs regs) newsp = regs.ecx; if (!newsp) newsp = regs.esp; - return do_fork(clone_flags, newsp, ®s); + return do_fork(clone_flags, newsp, ®s, 0); } /* @@ -713,7 +714,7 @@ asmlinkage int sys_clone(struct pt_regs regs) */ asmlinkage int sys_vfork(struct pt_regs regs) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0); } /* diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 7629bb3d2..4f847369e 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -497,7 +497,7 @@ static int __init fork_by_hand(void) * don't care about the eip and regs settings since * we'll never reschedule the forked task. */ - return do_fork(CLONE_VM|CLONE_PID, 0, ®s); + return do_fork(CLONE_VM|CLONE_PID, 0, ®s, 0); } #if APIC_DEBUG diff --git a/arch/i386/lib/checksum.S b/arch/i386/lib/checksum.S index 0d66abee0..bfc638953 100644 --- a/arch/i386/lib/checksum.S +++ b/arch/i386/lib/checksum.S @@ -394,26 +394,32 @@ csum_partial_copy_generic: movl ARGBASE+8(%esp),%edi #dst movl ARGBASE+12(%esp),%ecx #len movl ARGBASE+16(%esp),%eax #sum - movl %ecx, %edx +# movl %ecx, %edx movl %ecx, %ebx + movl %esi, %edx shrl $6, %ecx andl $0x3c, %ebx negl %ebx subl %ebx, %esi subl %ebx, %edi + lea -1(%esi),%edx + andl $-32,%edx lea 3f(%ebx,%ebx), %ebx testl %esi, %esi - jmp *%ebx + jmp *%ebx 1: addl $64,%esi addl $64,%edi + SRC(movb -32(%edx),%bl) ; SRC(movb (%edx),%bl) ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52) ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36) ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20) ROUND (-16) ROUND(-12) ROUND(-8) ROUND(-4) 3: adcl $0,%eax + addl $64, %edx dec %ecx jge 1b -4: andl $3, %edx +4: movl ARGBASE+12(%esp),%edx #len + andl $3, %edx jz 7f cmpl $2, %edx jb 5f diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S index ad963b92f..5fb064a3b 100644 --- a/arch/ia64/ia32/ia32_entry.S +++ b/arch/ia64/ia32/ia32_entry.S @@ -91,8 +91,8 @@ GLOBAL_ENTRY(sys32_fork) UNW(.body) mov out1=0 - mov out2=0 - adds out3=IA64_SWITCH_STACK_SIZE+16,sp + mov out3=0 + adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s br.call.sptk.few rp=do_fork .ret3: mov ar.pfs=loc1 UNW(.restore sp) diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index e37bd0df8..eba75378e 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -68,8 +68,8 @@ GLOBAL_ENTRY(sys_clone2) mov loc1=r16 // save ar.pfs across do_fork UNW(.body) mov out1=in1 - mov out2=in2 - adds out3=IA64_SWITCH_STACK_SIZE+16,sp // out3 = ®s + mov out3=in2 + adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s mov out0=in0 // out0 = clone_flags br.call.sptk.few rp=do_fork .ret1: UNW(.restore sp) @@ -87,8 +87,8 @@ GLOBAL_ENTRY(sys_clone) mov loc1=r16 // save ar.pfs across do_fork UNW(.body) mov out1=in1 - mov out2=0 - adds out3=IA64_SWITCH_STACK_SIZE+16,sp // out3 = ®s + mov out3=0 + adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s mov out0=in0 // out0 = clone_flags br.call.sptk.few rp=do_fork .ret2: UNW(.restore sp) diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index ef4a49339..6934e4168 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -181,12 +181,12 @@ void flush_thread(void) asmlinkage int m68k_fork(struct pt_regs *regs) { - return do_fork(SIGCHLD, rdusp(), regs); + return do_fork(SIGCHLD, rdusp(), regs, 0); } asmlinkage int m68k_vfork(struct pt_regs *regs) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0); } asmlinkage int m68k_clone(struct pt_regs *regs) @@ -199,10 +199,11 @@ asmlinkage int m68k_clone(struct pt_regs *regs) newsp = regs->d2; if (!newsp) newsp = rdusp(); - return do_fork(clone_flags, newsp, regs); + return do_fork(clone_flags, newsp, regs, 0); } int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, + unsigned long unused, struct task_struct * p, struct pt_regs * regs) { struct pt_regs * childregs; diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index a5a630769..6a1a6c326 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -72,6 +72,7 @@ void flush_thread(void) } int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, + unsigned long unused, struct task_struct * p, struct pt_regs * regs) { struct pt_regs * childregs; diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 2afb00e0a..a7887b6d0 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -97,7 +97,7 @@ asmlinkage int sys_fork(struct pt_regs regs) int res; save_static(®s); - res = do_fork(SIGCHLD, regs.regs[29], ®s); + res = do_fork(SIGCHLD, regs.regs[29], ®s, 0); return res; } @@ -112,7 +112,7 @@ asmlinkage int sys_clone(struct pt_regs regs) newsp = regs.regs[5]; if (!newsp) newsp = regs.regs[29]; - res = do_fork(clone_flags, newsp, ®s); + res = do_fork(clone_flags, newsp, ®s, 0); return res; } diff --git a/arch/mips64/kernel/process.c b/arch/mips64/kernel/process.c index 924140719..df03ef081 100644 --- a/arch/mips64/kernel/process.c +++ b/arch/mips64/kernel/process.c @@ -69,6 +69,7 @@ void flush_thread(void) } int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, + unsigned long unused, struct task_struct * p, struct pt_regs * regs) { struct pt_regs * childregs; diff --git a/arch/mips64/kernel/syscall.c b/arch/mips64/kernel/syscall.c index 1588b95a7..ca7fd4c4d 100644 --- a/arch/mips64/kernel/syscall.c +++ b/arch/mips64/kernel/syscall.c @@ -77,7 +77,7 @@ asmlinkage int sys_fork(abi64_no_regargs, struct pt_regs regs) int res; save_static(®s); - res = do_fork(SIGCHLD, regs.regs[29], ®s); + res = do_fork(SIGCHLD, regs.regs[29], ®s, 0); return res; } @@ -92,7 +92,7 @@ asmlinkage int sys_clone(abi64_no_regargs, struct pt_regs regs) newsp = regs.regs[5]; if (!newsp) newsp = regs.regs[29]; - res = do_fork(clone_flags, newsp, ®s); + res = do_fork(clone_flags, newsp, ®s, 0); return res; } diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index 7bc5cb82f..7d228788c 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -315,6 +315,7 @@ release_thread(struct task_struct *t) */ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, + unsigned long unused, struct task_struct * p, struct pt_regs * regs) { unsigned long msr; @@ -446,7 +447,7 @@ asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, unsigned long clone_flags = p1; int res; lock_kernel(); - res = do_fork(clone_flags, regs->gpr[1], regs); + res = do_fork(clone_flags, regs->gpr[1], regs, 0); #ifdef CONFIG_SMP /* When we clone the idle task we keep the same pid but * the return value of 0 for both causes problems. @@ -465,7 +466,7 @@ asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, int res; - res = do_fork(SIGCHLD, regs->gpr[1], regs); + res = do_fork(SIGCHLD, regs->gpr[1], regs, 0); #ifdef CONFIG_SMP /* When we clone the idle task we keep the same pid but * the return value of 0 for both causes problems. @@ -480,7 +481,7 @@ asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, asmlinkage int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0); } asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index 8cb68c6b2..4c46d380c 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -347,7 +347,7 @@ void __init smp_boot_cpus(void) /* create a process for the processor */ /* we don't care about the values in regs since we'll never reschedule the forked task. */ - if (do_fork(CLONE_VM|CLONE_PID, 0, ®s) < 0) + if (do_fork(CLONE_VM|CLONE_PID, 0, ®s, 0) < 0) panic("failed fork for CPU %d", i); p = init_task.prev_task; if (!p) diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 6f6a5287b..2fc6d08fa 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -264,6 +264,7 @@ void release_thread(struct task_struct *dead_task) } int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, + unsigned long unused, struct task_struct * p, struct pt_regs * regs) { struct stack_frame @@ -313,7 +314,7 @@ asmlinkage int sys_fork(struct pt_regs regs) int ret; lock_kernel(); - ret = do_fork(SIGCHLD, regs.gprs[15], ®s); + ret = do_fork(SIGCHLD, regs.gprs[15], ®s, 0); unlock_kernel(); return ret; } @@ -329,7 +330,7 @@ asmlinkage int sys_clone(struct pt_regs regs) newsp = regs.gprs[2]; if (!newsp) newsp = regs.gprs[15]; - ret = do_fork(clone_flags, newsp, ®s); + ret = do_fork(clone_flags, newsp, ®s, 0); unlock_kernel(); return ret; } @@ -347,7 +348,7 @@ asmlinkage int sys_clone(struct pt_regs regs) asmlinkage int sys_vfork(struct pt_regs regs) { return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, - regs.gprs[15], ®s); + regs.gprs[15], ®s, 0); } /* diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 8f72782d2..6cf2e6918 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -528,7 +528,7 @@ static int __init fork_by_hand(void) /* don't care about the psw and regs settings since we'll never reschedule the forked task. */ memset(®s,sizeof(pt_regs),0); - return do_fork(CLONE_VM|CLONE_PID, 0, ®s); + return do_fork(CLONE_VM|CLONE_PID, 0, ®s, 0); } static void __init do_boot_cpu(int cpu) diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 60205379c..4a6a63983 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -211,6 +211,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) asmlinkage void ret_from_fork(void); int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, + unsigned long unused, struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs; @@ -292,7 +293,7 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs) { - return do_fork(SIGCHLD, regs.regs[15], ®s); + return do_fork(SIGCHLD, regs.regs[15], ®s, 0); } asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, @@ -301,7 +302,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, { if (!newsp) newsp = regs.regs[15]; - return do_fork(clone_flags, newsp, ®s); + return do_fork(clone_flags, newsp, ®s, 0); } /* @@ -318,7 +319,7 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], ®s); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], ®s, 0); } /* diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index f701027e0..cd2f3731a 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -1391,6 +1391,7 @@ flush_patch_two: mov %fp, %o1 ! arg1: usp std %g4, [%curptr + AOFF_task_thread + AOFF_thread_fork_kpsr] add %sp, REGWIN_SZ, %o2 ! arg2: pt_regs ptr + mov 0, %o3 call C_LABEL(do_fork) mov %l5, %o7 @@ -1413,6 +1414,7 @@ flush_patch_three: 1: std %g4, [%curptr + AOFF_task_thread + AOFF_thread_fork_kpsr] add %sp, REGWIN_SZ, %o2 ! arg2: pt_regs ptr + mov 0, %o3 call C_LABEL(do_fork) mov %l5, %o7 @@ -1430,6 +1432,7 @@ flush_patch_four: mov %fp, %o1 or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0 sethi %hi(C_LABEL(do_fork)), %l1 + mov 0, %o3 jmpl %l1 + %lo(C_LABEL(do_fork)), %g0 add %sp, REGWIN_SZ, %o2 diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index f119c59ac..f730f850b 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -462,6 +462,7 @@ extern void ret_from_syscall(void); #endif int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, + unsigned long unused, struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs; diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index e95e0392e..9d946df0a 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -911,7 +911,7 @@ sys_fork: clr %o1 mov SIGCHLD, %o0 sys_clone: flushw movrz %o1, %fp, %o1 - nop + mov 0, %o3 ba,pt %xcc, do_fork add %sp, STACK_BIAS + REGWIN_SZ, %o2 ret_from_syscall: diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 21d43bb1e..82679eef0 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -573,6 +573,7 @@ barf: * do_fork(). */ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, + unsigned long unused, struct task_struct *p, struct pt_regs *regs) { struct thread_struct *t = &p->thread; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 47651b852..5037f517b 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -357,7 +357,7 @@ repeat: if (current_request->cmd == WRITE) { mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); } brelse(bh); dest_addr += size; diff --git a/drivers/block/lvm.c b/drivers/block/lvm.c index d8cf20d79..fc762c54f 100644 --- a/drivers/block/lvm.c +++ b/drivers/block/lvm.c @@ -299,6 +299,11 @@ static DECLARE_WAIT_QUEUE_HEAD(lvm_map_wait); static spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED; +static devfs_handle_t lvm_devfs_handle; +static devfs_handle_t vg_devfs_handle[MAX_VG]; +static devfs_handle_t ch_devfs_handle[MAX_VG]; +static devfs_handle_t lv_devfs_handle[MAX_LV]; + static struct file_operations lvm_chr_fops = { owner: THIS_MODULE, @@ -358,13 +363,18 @@ int __init lvm_init(void) printk(KERN_ERR "%s -- register_chrdev failed\n", lvm_name); return -EIO; } - if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 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 -- unregister_chrdev failed\n", lvm_name); return -EIO; } + + lvm_devfs_handle = devfs_register( + 0 , "lvm", 0, 0, LVM_CHAR_MAJOR, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, + &lvm_chr_fops, NULL); + #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS create_proc_info_entry(LVM_NAME, S_IFREG | S_IRUGO, &proc_root, lvm_proc_get_info_ptr); @@ -422,6 +432,8 @@ void cleanup_module(void) { struct gendisk *gendisk_ptr = NULL, *gendisk_ptr_prev = NULL; + devfs_unregister (lvm_devfs_handle); + if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) { printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name); } @@ -1625,6 +1637,14 @@ int lvm_do_vg_create(int minor, void *arg) kfree(vg_ptr); return -EFAULT; } + + vg_devfs_handle[vg_ptr->vg_number] = devfs_mk_dir(0, vg_ptr->vg_name, NULL); + ch_devfs_handle[vg_ptr->vg_number] = devfs_register( + vg_devfs_handle[vg_ptr->vg_number] , "group", + DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, + &lvm_chr_fops, NULL); + /* we are not that active so far... */ vg_ptr->vg_status &= ~VG_ACTIVE; vg[VG_CHR(minor)] = vg_ptr; @@ -1852,6 +1872,9 @@ static int lvm_do_vg_remove(int minor) /* let's go inactive */ vg_ptr->vg_status &= ~VG_ACTIVE; + devfs_unregister (ch_devfs_handle[vg_ptr->vg_number]); + devfs_unregister (vg_devfs_handle[vg_ptr->vg_number]); + /* free LVs */ /* first free snapshot logical volumes */ for (i = 0; i < vg_ptr->lv_max; i++) { @@ -1907,6 +1930,7 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) { int l, le, l_new, p, size; ulong lv_status_save; + char *lv_tmp, *lv_buf; lv_block_exception_t *lvbe = lv->lv_block_exception; vg_t *vg_ptr = vg[VG_CHR(minor)]; lv_t *lv_ptr = NULL; @@ -2062,6 +2086,17 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) vg_ptr->lv_cur++; lv_ptr->lv_status = lv_status_save; + strtok(lv->lv_name, "/"); /* /dev */ + + while((lv_tmp = strtok(NULL, "/")) != NULL) + lv_buf = lv_tmp; + + lv_devfs_handle[lv->lv_number] = devfs_register( + vg_devfs_handle[vg_ptr->vg_number], lv_buf, + DEVFS_FL_DEFAULT, LVM_BLK_MAJOR, lv->lv_number, + S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, + &lvm_blk_dops, NULL); + /* optionally add our new snapshot LV */ if (lv_ptr->lv_access & LV_SNAPSHOT) { /* sync the original logical volume */ @@ -2154,6 +2189,8 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l) lvm_snapshot_release(lv_ptr); } + devfs_unregister(lv_devfs_handle[lv_ptr->lv_number]); + #ifdef DEBUG_KFREE printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__); #endif diff --git a/drivers/block/md.c b/drivers/block/md.c index 19b97d161..587bfcbf6 100644 --- a/drivers/block/md.c +++ b/drivers/block/md.c @@ -952,7 +952,7 @@ static int write_disk_sb(mdk_rdev_t * rdev) memcpy(sb, rdev->sb, MD_SB_BYTES); mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); ll_rw_block(WRITE, 1, &bh); wait_on_buffer(bh); brelse(bh); diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index f032a310a..9fb94b21a 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -291,11 +291,13 @@ MODULE_PARM(check_media_type, "i"); #endif /* These are used to simplify getting data in from and back to user land */ -#define IOCTL_IN(arg, type, in) \ - copy_from_user(&in, (type *) arg, sizeof in) +#define IOCTL_IN(arg, type, in) \ + if (copy_from_user(&in, (type *) arg, sizeof in)) \ + return -EFAULT; #define IOCTL_OUT(arg, type, out) \ - copy_to_user((type *) arg, &out, sizeof out) + if (copy_to_user((type *) arg, &out, sizeof out)) \ + return -EFAULT; /* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in a lot of places. This macro makes the code more clear. */ @@ -784,6 +786,8 @@ int cdrom_select_disc(struct cdrom_device_info *cdi, int slot) if (!CDROM_CAN(CDC_SELECT_DISC)) return -EDRIVE_CANT_DO_THIS; + (void) cdi->ops->media_changed(cdi, slot); + if (slot == CDSL_NONE) { /* set media changed bits, on both queues */ cdi->mc_flags = 0x3; @@ -851,8 +855,8 @@ static int cdrom_media_changed(kdev_t dev) if (cdi == NULL || cdi->ops->media_changed == NULL) return 0; if (!CDROM_CAN(CDC_MEDIA_CHANGED)) - return 0; - return (media_changed(cdi, 0)); + return 0; + return media_changed(cdi, 0); } /* badly broken, I know. Is due for a fixup anytime. */ @@ -872,8 +876,7 @@ void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks) return; } /* Grab the TOC header so we can see how many tracks there are */ - ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header); - if (ret) { + if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header))) { if (ret == -ENOMEDIUM) tracks->error = CDS_NO_DISC; else @@ -1463,8 +1466,7 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n"); if (!(cdo->capability & CDC_MULTI_SESSION)) return -ENOSYS; - if (IOCTL_IN(arg, struct cdrom_multisession, ms_info)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_multisession, ms_info); requested_format = ms_info.addr_format; if (!((requested_format == CDROM_MSF) || (requested_format == CDROM_LBA))) @@ -1474,8 +1476,7 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return ret; sanitize_format(&ms_info.addr, &ms_info.addr_format, requested_format); - if (IOCTL_OUT(arg, struct cdrom_multisession, ms_info)) - return -EFAULT; + IOCTL_OUT(arg, struct cdrom_multisession, ms_info); cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n"); return 0; } @@ -1518,12 +1519,13 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n"); if (!CDROM_CAN(CDC_MEDIA_CHANGED)) return -ENOSYS; + + /* cannot select disc or select current disc */ if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT) - /* cannot select disc or select current disc */ return media_changed(cdi, 1); - if ((unsigned int)arg >= cdi->capacity) { + + if ((unsigned int)arg >= cdi->capacity) return -EINVAL; - } if ((ret = cdrom_read_mech_status(cdi, &info))) return ret; @@ -1572,10 +1574,10 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_SELECT_DISC)) return -ENOSYS; - if ((arg != CDSL_CURRENT) && (arg != CDSL_NONE)) { - if ((int)arg >= cdi->capacity) - return -EINVAL; - } + if ((arg != CDSL_CURRENT) && (arg != CDSL_NONE)) + if ((int)arg >= cdi->capacity) + return -EINVAL; + /* cdo->select_disc is a hook to allow a driver-specific * way of seleting disc. However, since there is no * equiv hook for cdrom_slot_status this may not @@ -1603,8 +1605,9 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_LOCK)) return -EDRIVE_CANT_DO_THIS; keeplocked = arg ? 1 : 0; - /* don't unlock the door on multiple opens */ - if ((cdi->use_count != 1) && !arg) + /* don't unlock the door on multiple opens,but allow root + * to do so */ + if ((cdi->use_count != 1) && !arg && !capable(CAP_SYS_ADMIN)) return -EBUSY; return cdo->lock_door(cdi, arg); } @@ -1634,8 +1637,7 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return -ENOSYS; if ((ret=cdo->get_mcn(cdi, &mcn))) return ret; - if (IOCTL_OUT(arg, struct cdrom_mcn, mcn)) - return -EFAULT; + IOCTL_OUT(arg, struct cdrom_mcn, mcn); cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n"); return 0; } @@ -1720,8 +1722,7 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO)) return -ENOSYS; /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/ - if (IOCTL_IN(arg, struct cdrom_subchnl, q)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_subchnl, q); requested = q.cdsc_format; if (!((requested == CDROM_MSF) || (requested == CDROM_LBA))) @@ -1732,8 +1733,7 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, back = q.cdsc_format; /* local copy */ sanitize_format(&q.cdsc_absaddr, &back, requested); sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); - if (IOCTL_OUT(arg, struct cdrom_subchnl, q)) - return -EFAULT; + IOCTL_OUT(arg, struct cdrom_subchnl, q); /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ return 0; } @@ -1742,12 +1742,10 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO)) return -ENOSYS; /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */ - if (IOCTL_IN(arg, struct cdrom_tochdr, header)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_tochdr, header); if ((ret=cdo->audio_ioctl(cdi, cmd, &header))) return ret; - if (IOCTL_OUT(arg, struct cdrom_tochdr, header)) - return -EFAULT; + IOCTL_OUT(arg, struct cdrom_tochdr, header); /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */ return 0; } @@ -1757,8 +1755,7 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO)) return -ENOSYS; /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */ - if (IOCTL_IN(arg, struct cdrom_tocentry, entry)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_tocentry, entry); requested_format = entry.cdte_format; if (!((requested_format == CDROM_MSF) || (requested_format == CDROM_LBA))) @@ -1769,8 +1766,7 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return ret; sanitize_format(&entry.cdte_addr, &entry.cdte_format, requested_format); - if (IOCTL_OUT(arg, struct cdrom_tocentry, entry)) - return -EFAULT; + IOCTL_OUT(arg, struct cdrom_tocentry, entry); /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */ return 0; } @@ -1779,8 +1775,7 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO)) return -ENOSYS; cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); - if (IOCTL_IN(arg, struct cdrom_msf, msf)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_msf, msf); return cdo->audio_ioctl(cdi, cmd, &msf); } case CDROMPLAYTRKIND: { @@ -1788,8 +1783,7 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO)) return -ENOSYS; cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); - if (IOCTL_IN(arg, struct cdrom_ti, ti)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_ti, ti); CHECKAUDIO; return cdo->audio_ioctl(cdi, cmd, &ti); } @@ -1798,8 +1792,7 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO)) return -ENOSYS; cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n"); - if (IOCTL_IN(arg, struct cdrom_volctrl, volume)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_volctrl, volume); return cdo->audio_ioctl(cdi, cmd, &volume); } case CDROMVOLREAD: { @@ -1809,8 +1802,7 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n"); if ((ret=cdo->audio_ioctl(cdi, cmd, &volume))) return ret; - if (IOCTL_OUT(arg, struct cdrom_volctrl, volume)) - return -EFAULT; + IOCTL_OUT(arg, struct cdrom_volctrl, volume); return 0; } case CDROMSTART: @@ -1847,7 +1839,6 @@ static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size) struct cdrom_device_ops *cdo = cdi->ops; struct cdrom_generic_command cgc; struct modesel_head mh; - int ret; memset(&mh, 0, sizeof(mh)); mh.block_desc_length = 0x08; @@ -1865,14 +1856,7 @@ static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size) mh.block_length_med = (size >> 8) & 0xff; mh.block_length_lo = size & 0xff; - ret = cdo->generic_packet(cdi, &cgc); - if (ret) { - printk("switch_blocksize failed, ret %x ", ret); - if (cgc.sense) - printk("sense %02x.%02x.%02x", cgc.sense->sense_key, cgc.sense->asc, cgc.sense->ascq); - printk("\n"); - } - return ret; + return cdo->generic_packet(cdi, &cgc); } static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, @@ -1907,8 +1891,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, blocksize = CD_FRAMESIZE_RAW0; break; } - if (IOCTL_IN(arg, struct cdrom_msf, msf)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_msf, msf); lba = msf_to_lba(msf.cdmsf_min0,msf.cdmsf_sec0,msf.cdmsf_frame0); /* FIXME: we need upper bound checking, too!! */ if (lba < 0) @@ -1930,16 +1913,10 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, } cgc.sense = NULL; ret = cdrom_read_cd(cdi, &cgc, lba, blocksize, 1); - if (ret) { - printk("read_cd failed, ret %x ", ret); - if (cgc.sense) - printk("sense %02x.%02x.%02x", cgc.sense->sense_key, cgc.sense->asc, cgc.sense->ascq); - printk("\n"); - } ret |= cdrom_switch_blocksize(cdi, blocksize); } if (!ret && copy_to_user((char *)arg, cgc.buffer, blocksize)) - ret = -EFAULT; + ret = -EFAULT; kfree(cgc.buffer); return ret; } @@ -1947,8 +1924,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, struct cdrom_read_audio ra; int lba, frames; - if (IOCTL_IN(arg, struct cdrom_read_audio, ra)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_read_audio, ra); if (ra.addr_format == CDROM_MSF) lba = msf_to_lba(ra.addr.msf.minute, @@ -1990,8 +1966,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, case CDROMSUBCHNL: { struct cdrom_subchnl q; u_char requested, back; - if (IOCTL_IN(arg, struct cdrom_subchnl, q)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_subchnl, q); requested = q.cdsc_format; if (!((requested == CDROM_MSF) || (requested == CDROM_LBA))) @@ -2002,30 +1977,14 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, back = q.cdsc_format; /* local copy */ sanitize_format(&q.cdsc_absaddr, &back, requested); sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); - if (IOCTL_OUT(arg, struct cdrom_subchnl, q)) - return -EFAULT; + IOCTL_OUT(arg, struct cdrom_subchnl, q); /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ return 0; } - case CDROMPLAYTRKIND: { - struct cdrom_ti ti; - - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); - if (IOCTL_IN(arg, struct cdrom_ti, ti)) - return -EFAULT; - - cgc.cmd[0] = GPCMD_PLAY_AUDIO_TI; - cgc.cmd[4] = ti.cdti_trk0; - cgc.cmd[5] = ti.cdti_ind0; - cgc.cmd[7] = ti.cdti_trk1; - cgc.cmd[8] = ti.cdti_ind1; - return cdo->generic_packet(cdi, &cgc); - } case CDROMPLAYMSF: { struct cdrom_msf msf; cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); - if (IOCTL_IN(arg, struct cdrom_msf, msf)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_msf, msf); cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF; cgc.cmd[3] = msf.cdmsf_min0; cgc.cmd[4] = msf.cdmsf_sec0; @@ -2039,8 +1998,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, case CDROMPLAYBLK: { struct cdrom_blk blk; cdinfo(CD_DO_IOCTL, "entering CDROMPLAYBLK\n"); - if (IOCTL_IN(arg, struct cdrom_blk, blk)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_blk, blk); cgc.cmd[0] = GPCMD_PLAY_AUDIO_10; cgc.cmd[2] = (blk.from >> 24) & 0xff; cgc.cmd[3] = (blk.from >> 16) & 0xff; @@ -2058,8 +2016,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, unsigned short offset; cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n"); - if (IOCTL_IN(arg, struct cdrom_volctrl, volctrl)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_volctrl, volctrl); cgc.buffer = buffer; cgc.buflen = 24; @@ -2085,8 +2042,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, volctrl.channel1 = buffer[offset+11]; volctrl.channel2 = buffer[offset+13]; volctrl.channel3 = buffer[offset+15]; - if (IOCTL_OUT(arg, struct cdrom_volctrl, volctrl)) - return -EFAULT; + IOCTL_OUT(arg, struct cdrom_volctrl, volctrl); return 0; } @@ -2152,12 +2108,10 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, if (!CDROM_CAN(CDC_DVD)) return -ENOSYS; cdinfo(CD_DO_IOCTL, "entering DVD_AUTH\n"); - if (IOCTL_IN(arg, dvd_authinfo, ai)) - return -EFAULT; + IOCTL_IN(arg, dvd_authinfo, ai); if ((ret = dvd_do_auth (cdi, &ai))) return ret; - if (IOCTL_OUT(arg, dvd_authinfo, ai)) - return -EFAULT; + IOCTL_OUT(arg, dvd_authinfo, ai); return 0; } @@ -2167,8 +2121,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, if (!CDROM_CAN(CDC_GENERIC_PACKET)) return -ENOSYS; cdinfo(CD_DO_IOCTL, "entering CDROM_SEND_PACKET\n"); - if (IOCTL_IN(arg, struct cdrom_generic_command, cgc)) - return -EFAULT; + IOCTL_IN(arg, struct cdrom_generic_command, cgc); copy = !!cgc.buflen; userbuf = cgc.buffer; cgc.buffer = NULL; @@ -2215,8 +2168,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n"); if ((ret = cdrom_get_next_writable(dev, &next))) return ret; - if (IOCTL_OUT(arg, long, next)) - return -EFAULT; + IOCTL_OUT(arg, long, next); return 0; } case CDROM_LAST_WRITTEN: { @@ -2224,8 +2176,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n"); if ((ret = cdrom_get_last_written(dev, &last))) return ret; - if (IOCTL_OUT(arg, long, last)) - return -EFAULT; + IOCTL_OUT(arg, long, last); return 0; } } /* switch */ diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index df2174a8c..07e97a1d7 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -1,3 +1,5 @@ + + /* * sbpcd.c CD-ROM device driver for the whole family of traditional, * non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives. @@ -13,7 +15,7 @@ * labelled E2550UA or MK4015 or 2800F). */ -#define VERSION "v4.61 Eberhard Moenkeberg " +#define VERSION "v4.63 Andrew J. Kroll Wed Jul 26 04:24:10 EDT 2000" /* Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg * @@ -46,7 +48,7 @@ * * 0.1 initial release, April/May 93, after mcd.c (Martin Harriss) * - * 0.2 the "repeat:"-loop in do_sbpcd_request did not check for + * 0.2 thek "repeat:"-loop in do_sbpcd_request did not check for * end-of-request_queue (resulting in kernel panic). * Flow control seems stable, but throughput is not better. * @@ -312,9 +314,20 @@ * module_init & module_exit. * Torben Mathiasen * + * 4.63 Bug fixes for audio annoyances, new legacy CDROM maintainer. + * Annoying things fixed: + * TOC reread on automated disk changes + * TOC reread on manual cd changes + * Play IOCTL tries to play CD before it's actually ready... sometimes. + * CD_AUDIO_COMPLETED state so workman (and other playes) can repeat play. + * Andrew J. Kroll Wed Jul 26 04:24:10 EDT 2000 + * * * TODO * implement "read all subchannel data" (96 bytes per frame) + * remove alot of the virtual status bits and deal with hardware status + * move the change of cd for audio to a better place + * add debug levels to insmod parameters (trivial) * * special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine * elaborated speed-up experiments (and the fabulous results!), for @@ -637,9 +650,9 @@ static u_int maxtim_data= 9000; static u_int maxtim_data= 3000; #endif LONG_TIMING #if DISTRIBUTION -static int n_retries=3; +static int n_retries=6; #else -static int n_retries=1; +static int n_retries=6; #endif /*==========================================================================*/ @@ -2046,7 +2059,9 @@ static int DriveReset(void) do { i=GetStatus(); - if ((i<0)&&(i!=-ERR_DISKCHANGE)) return (-2); /* from sta2err */ + if ((i<0)&&(i!=-ERR_DISKCHANGE)) { + return (-2); /* from sta2err */ + } if (!st_caddy_in) break; sbp_sleep(1); } @@ -2343,16 +2358,21 @@ static int cc_CloseTray(void) static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position) { - int i; - i = MINOR(cdi->dev); - - switch_drive(i); - if (position == 1) { - cc_SpinDown(); - } else { - return cc_CloseTray(); - } - return 0; + int i; + int retval=0; + i = MINOR(cdi->dev); + switch_drive(i); + /* DUH! --AJK */ + if(D_S[d].CD_changed != 0xFF) { + D_S[d].CD_changed=0xFF; + D_S[d].diskstate_flags &= ~cd_size_bit; + } + if (position == 1) { + cc_SpinDown(); + } else { + retval=cc_CloseTray(); + } + return retval; } /*==========================================================================*/ @@ -4023,6 +4043,7 @@ static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok); msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning); msg(DBG_000,"Drive Status: busy =%d.\n", st_busy); + #if 0 if (!(D_S[MINOR(cdi->dev)].status_bits & p_door_closed)) return CDS_TRAY_OPEN; if (D_S[MINOR(cdi->dev)].status_bits & p_disk_ok) return CDS_DISC_OK; @@ -4031,8 +4052,11 @@ static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) return CDS_NO_DISC; #else if (D_S[MINOR(cdi->dev)].status_bits & p_spinning) return CDS_DISC_OK; - return CDS_TRAY_OPEN; +/* return CDS_TRAY_OPEN; */ + return CDS_NO_DISC; + #endif + } @@ -4500,7 +4524,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, void * arg) { - int i, st; + int i, st, j; msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08p)\n", MINOR(cdi->dev), cmd, arg); @@ -4696,19 +4720,68 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, case CDROMSUBCHNL: /* Get subchannel info */ msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n"); + /* Bogus, I can do better than this! --AJK if ((st_spinning)||(!subq_valid)) { i=cc_ReadSubQ(); if (i<0) RETURN_UP(-EIO); } + */ + i=cc_ReadSubQ(); + if (i<0) { + j=cc_ReadError(); /* clear out error status from drive */ + D_S[d].audio_state=CDROM_AUDIO_NO_STATUS; + /* get and set the disk state here, + probably not the right place, but who cares! + It makes it work properly! --AJK */ + if (D_S[d].CD_changed==0xFF) { + msg(DBG_000,"Disk changed detect\n"); + D_S[d].diskstate_flags &= ~cd_size_bit; + } + RETURN_UP(-EIO); + } + if (D_S[d].CD_changed==0xFF) { + /* reread the TOC because the disk has changed! --AJK */ + msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n"); + i=DiskInfo(); + if(i==0) { + D_S[d].CD_changed=0x00; /* cd has changed, procede, */ + RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */ + } else { + RETURN_UP(-EIO); /* we weren't ready yet! --AJK */ + } + } memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); + /* + This virtual crap is very bogus! + It doesn't detect when the cd is done playing audio! + Lets do this right with proper hardware register reading! + */ + cc_ReadStatus(); + i=ResponseStatus(); + msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked); + msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed); + msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in); + msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok); + msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning); + msg(DBG_000,"Drive Status: busy =%d.\n", st_busy); + /* st_busy indicates if it's _ACTUALLY_ playing audio */ switch (D_S[d].audio_state) { case audio_playing: - SC.cdsc_audiostatus=CDROM_AUDIO_PLAY; + if(st_busy==0) { + /* CD has stopped playing audio --AJK */ + D_S[d].audio_state=audio_completed; + SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED; + } else { + SC.cdsc_audiostatus=CDROM_AUDIO_PLAY; + } break; case audio_pausing: SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED; break; + case audio_completed: + SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED; + break; default: SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS; break; @@ -5883,6 +5956,14 @@ static int sbpcd_chk_disk_change(kdev_t full_dev) { D_S[i].CD_changed=0; msg(DBG_CHK,"medium changed (drive %d)\n", i); + /* BUG! Should invalidate buffers! --AJK */ + invalidate_buffers(full_dev); + D_S[d].diskstate_flags &= ~toc_bit; + D_S[d].diskstate_flags &= ~cd_size_bit; +#if SAFE_MIXED + D_S[d].has_data=0; +#endif SAFE_MIXED + return (1); } else diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h index 805e98a82..6632fa48c 100644 --- a/drivers/cdrom/sbpcd.h +++ b/drivers/cdrom/sbpcd.h @@ -412,6 +412,7 @@ /* * audio states: */ +#define audio_completed 3 /* Forgot this one! --AJK */ #define audio_playing 2 #define audio_pausing 1 diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c index 6bef56a23..fc8e73992 100644 --- a/drivers/char/drm/i810_drv.c +++ b/drivers/char/drm/i810_drv.c @@ -438,7 +438,7 @@ int i810_version(struct inode *inode, struct file *filp, unsigned int cmd, if (len > name##_len) len = name##_len; \ name##_len = strlen(value); \ if (len && name) { \ - if (copy_to_user(name, value, len, -EFAULT)) \ + if (copy_to_user(name, value, len)) \ return -EFAULT; \ } diff --git a/drivers/ide/Config.in b/drivers/ide/Config.in index 2719f6f80..d4687f703 100644 --- a/drivers/ide/Config.in +++ b/drivers/ide/Config.in @@ -71,7 +71,6 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then dep_bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 dep_bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' VIA82CXXX chipset support' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' VIA82CXXX Tuning support (WIP)' CONFIG_VIA82CXXX_TUNING $CONFIG_BLK_DEV_VIA82CXXX $CONFIG_IDEDMA_PCI_WIP fi if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105 diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index b03bc2fac..d2a5ae37e 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -542,11 +542,11 @@ static void cdrom_end_request (int uptodate, ide_drive_t *drive) /* Returns 0 if the request should be continued. Returns 1 if the request was ended. */ -static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive, int good_stat, - int *stat_ret) +static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive, + int good_stat, int *stat_ret) { struct request *rq = HWGROUP(drive)->rq; - int stat, cmd, err, sense_key; + int stat, err, sense_key; struct packet_command *pc; /* Check for errors. */ @@ -560,103 +560,99 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive, err = GET_ERR(); sense_key = err >> 4; - if (rq == NULL) - printk ("%s: missing request in cdrom_decode_status\n", - drive->name); - else { - cmd = rq->cmd; - - if (cmd == REQUEST_SENSE_COMMAND) { - /* We got an error trying to get sense info - from the drive (probably while trying - to recover from a former error). Just give up. */ - - pc = (struct packet_command *) rq->buffer; - pc->stat = 1; - cdrom_end_request (1, drive); - *startstop = ide_error (drive, "request sense failure", stat); - return 1; - - } else if (cmd == PACKET_COMMAND) { - /* All other functions, except for READ. */ - - struct semaphore *sem = NULL; - pc = (struct packet_command *) rq->buffer; + if (rq == NULL) { + printk("%s: missing rq in cdrom_decode_status\n", drive->name); + *startstop = ide_stopped; + return 1; + } - /* Check for tray open. */ - if (sense_key == NOT_READY) { - cdrom_saw_media_change (drive); - } else if (sense_key == UNIT_ATTENTION) { - /* Check for media change. */ - cdrom_saw_media_change (drive); - /*printk("%s: media changed\n",drive->name);*/ - return 0; - } else { - /* Otherwise, print an error. */ - ide_dump_status (drive, "packet command error", - stat); - } - - /* Set the error flag and complete the request. - Then, if we have a CHECK CONDITION status, - queue a request sense command. We must be careful, - though: we don't want the thread in - cdrom_queue_packet_command to wake up until - the request sense has completed. We do this - by transferring the semaphore from the packet - command request to the request sense request. */ - - if ((stat & ERR_STAT) != 0) { - sem = rq->sem; - rq->sem = NULL; - } + if (rq->cmd == REQUEST_SENSE_COMMAND) { + /* We got an error trying to get sense info + from the drive (probably while trying + to recover from a former error). Just give up. */ - pc->stat = 1; - cdrom_end_request (1, drive); + pc = (struct packet_command *) rq->buffer; + pc->stat = 1; + cdrom_end_request (1, drive); + *startstop = ide_error (drive, "request sense failure", stat); + return 1; - if ((stat & ERR_STAT) != 0) - cdrom_queue_request_sense(drive, sem, pc->sense, - pc); + } else if (rq->cmd == PACKET_COMMAND) { + /* All other functions, except for READ. */ + struct semaphore *sem = NULL; + pc = (struct packet_command *) rq->buffer; + + /* Check for tray open. */ + if (sense_key == NOT_READY) { + cdrom_saw_media_change (drive); + } else if (sense_key == UNIT_ATTENTION) { + /* Check for media change. */ + cdrom_saw_media_change (drive); + /*printk("%s: media changed\n",drive->name);*/ + return 0; } else { - /* Handle errors from READ requests. */ + /* Otherwise, print an error. */ + ide_dump_status(drive, "packet command error", stat); + } + + /* Set the error flag and complete the request. + Then, if we have a CHECK CONDITION status, + queue a request sense command. We must be careful, + though: we don't want the thread in + cdrom_queue_packet_command to wake up until + the request sense has completed. We do this + by transferring the semaphore from the packet + command request to the request sense request. */ + + if ((stat & ERR_STAT) != 0) { + sem = rq->sem; + rq->sem = NULL; + } - if (sense_key == NOT_READY) { - /* Tray open. */ - cdrom_saw_media_change (drive); + pc->stat = 1; + cdrom_end_request (1, drive); - /* Fail the request. */ - printk ("%s: tray open\n", drive->name); - cdrom_end_request (0, drive); - } else if (sense_key == UNIT_ATTENTION) { - /* Media change. */ - cdrom_saw_media_change (drive); + if ((stat & ERR_STAT) != 0) + cdrom_queue_request_sense(drive, sem, pc->sense, pc); + } else { + /* Handle errors from READ requests. */ - /* Arrange to retry the request. - But be sure to give up if we've retried - too many times. */ - if (++rq->errors > ERROR_MAX) - cdrom_end_request (0, drive); - } else if (sense_key == ILLEGAL_REQUEST || - sense_key == DATA_PROTECT) { - /* No point in retrying after an illegal - request or data protect error.*/ - ide_dump_status (drive, "command error", stat); - cdrom_end_request (0, drive); - } else if ((err & ~ABRT_ERR) != 0) { - /* Go to the default handler - for other errors. */ - *startstop = ide_error (drive, "cdrom_decode_status", stat); - return 1; - } else if ((++rq->errors > ERROR_MAX)) { - /* We've racked up too many retries. Abort. */ - cdrom_end_request (0, drive); - } + if (sense_key == NOT_READY) { + /* Tray open. */ + cdrom_saw_media_change (drive); - /* If we got a CHECK_CONDITION status, - queue a request sense command. */ - if ((stat & ERR_STAT) != 0) - cdrom_queue_request_sense(drive, NULL, NULL, NULL); + /* Fail the request. */ + printk ("%s: tray open\n", drive->name); + cdrom_end_request (0, drive); + } else if (sense_key == UNIT_ATTENTION) { + /* Media change. */ + cdrom_saw_media_change (drive); + + /* Arrange to retry the request. + But be sure to give up if we've retried + too many times. */ + if (++rq->errors > ERROR_MAX) + cdrom_end_request (0, drive); + } else if (sense_key == ILLEGAL_REQUEST || + sense_key == DATA_PROTECT) { + /* No point in retrying after an illegal + request or data protect error.*/ + ide_dump_status (drive, "command error", stat); + cdrom_end_request (0, drive); + } else if ((err & ~ABRT_ERR) != 0) { + /* Go to the default handler + for other errors. */ + *startstop = ide_error (drive, "cdrom_decode_status", stat); + return 1; + } else if ((++rq->errors > ERROR_MAX)) { + /* We've racked up too many retries. Abort. */ + cdrom_end_request (0, drive); } + + /* If we got a CHECK_CONDITION status, + queue a request sense command. */ + if ((stat & ERR_STAT) != 0) + cdrom_queue_request_sense(drive, NULL, NULL, NULL); } /* Retry, or handle the next request. */ @@ -686,8 +682,9 @@ static int cdrom_timer_expiry(ide_drive_t *drive) called when the interrupt from the drive arrives. Otherwise, HANDLER will be called immediately after the drive is prepared for the transfer. */ -static ide_startstop_t cdrom_start_packet_command (ide_drive_t *drive, int xferlen, - ide_handler_t *handler) +static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, + int xferlen, + ide_handler_t *handler) { ide_startstop_t startstop; struct cdrom_info *info = drive->driver_data; @@ -783,7 +780,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, /* If we couldn't get a buffer, don't try to buffer anything... */ if (info->buffer == NULL) - sectors_to_buffer = 0; + sectors_to_buffer = 0; /* If this is the first sector in the buffer, remember its number. */ if (info->nsectors_buffered == 0) @@ -1657,10 +1654,10 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) /* Check to see if the existing data is still valid. If it is, just return. */ - if (CDROM_STATE_FLAGS (drive)->toc_valid) - (void) cdrom_check_status(drive, sense); + (void) cdrom_check_status(drive, sense); - if (CDROM_STATE_FLAGS (drive)->toc_valid) return 0; + if (CDROM_STATE_FLAGS(drive)->toc_valid) + return 0; /* First read just the header, so we know how long the TOC is. */ stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr, @@ -1717,10 +1714,10 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) toc->hdr.first_track = CDROM_LEADOUT; toc->hdr.last_track = CDROM_LEADOUT; } - } else if (stat) { - return stat; } - if (stat) return stat; + + if (stat) + return stat; toc->hdr.toc_length = ntohs (toc->hdr.toc_length); @@ -1836,6 +1833,20 @@ static int cdrom_select_speed(ide_drive_t *drive, int speed, return cdrom_queue_packet_command(drive, &pc); } +static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end) +{ + struct request_sense sense; + struct packet_command pc; + + memset(&pc, 0, sizeof (pc)); + pc.sense = &sense; + + pc.c[0] = GPCMD_PLAY_AUDIO_10; + put_unaligned(cpu_to_be32(lba_start), (unsigned int *) &pc.c[2]); + put_unaligned(cpu_to_be16(lba_end - lba_start), (unsigned int *) &pc.c[7]); + + return cdrom_queue_packet_command(drive, &pc); +} static int cdrom_get_toc_entry(ide_drive_t *drive, int track, struct atapi_toc_entry **ent) @@ -1844,6 +1855,12 @@ static int cdrom_get_toc_entry(ide_drive_t *drive, int track, struct atapi_toc *toc = info->toc; int ntracks; + /* + * don't serve cached data, if the toc isn't valid + */ + if (!CDROM_STATE_FLAGS(drive)->toc_valid) + return -EINVAL; + /* Check validity of requested track number. */ ntracks = toc->hdr.last_track - toc->hdr.first_track + 1; if (toc->hdr.first_track == CDROM_LEADOUT) ntracks = 0; @@ -1941,6 +1958,34 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, struct cdrom_info *info = drive->driver_data; switch (cmd) { + /* + * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since + * atapi doesn't support it + */ + case CDROMPLAYTRKIND: { + int stat, lba_start, lba_end; + struct cdrom_ti *ti = (struct cdrom_ti *)arg; + struct atapi_toc_entry *first_toc, *last_toc; + + stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc); + if (stat) + return stat; + + stat = cdrom_get_toc_entry(drive, ti->cdti_trk1, &last_toc); + if (stat) + return stat; + + if (ti->cdti_trk1 != CDROM_LEADOUT) + ++last_toc; + lba_start = first_toc->addr.lba; + lba_end = last_toc->addr.lba; + + if (lba_end <= lba_start) + return -EINVAL; + + return cdrom_play_audio(drive, lba_start, lba_end); + } + case CDROMREADTOCHDR: { int stat; struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg; @@ -2287,7 +2332,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) CDROM_CONFIG_FLAGS (drive)->dvd_r = 1; if (cap.audio_play) CDROM_CONFIG_FLAGS (drive)->audio_play = 1; - if (cap.mechtype == 0) + if (cap.mechtype == mechtype_caddy || cap.mechtype == mechtype_popup) CDROM_CONFIG_FLAGS (drive)->close_tray = 0; #if ! STANDARD_ATAPI diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index d9ef9510f..1c5530ba5 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -161,10 +161,6 @@ #include #endif /* CONFIG_KMOD */ -#ifdef CONFIG_BLK_DEV_VIA82CXXX -extern byte fifoconfig; /* defined in via82cxxx.c used by ide_setup() */ -#endif /* CONFIG_BLK_DEV_VIA82CXXX */ - static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR }; static int idebus_parameter = 0; /* holds the "idebus=" parameter */ @@ -2851,21 +2847,6 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m * currently unknown. * "ide=reverse" : Formerly called to pci sub-system, but now local. * - * "splitfifo=betweenChan" - * : FIFO Configuration of VIA 82c586(,"A"or"B"). - * --see what follows... - * "splitfifo=betweenChan,thresholdprim,thresholdsec" - * : FIFO Configuration of VIA 82c586(,"A" or "B"). - * betweenChan = 1(all FIFO's to primary channel) - * , 2(all FIFO's to secondary channel) - * , 3 or 4(evenly shared between them). - * note: without FIFO, a channel is (u)dma disabled! - * thresholdprim = 4, 3, 2 or 1 - * (standing for 1, 3/4, 1/2, 1/4). - * Sets the threshold of FIFO to begin dma - * transfer on the primary channel. - * thresholdsec = cf upper, but for secondary channel. - * * The following are valid ONLY on ide0, (except dc4030) * and the defaults for the base,ctl ports must not be altered. * @@ -2894,9 +2875,6 @@ int __init ide_setup (char *s) if (strncmp(s,"ide",3) && strncmp(s,"idebus",6) && -#ifdef CONFIG_BLK_DEV_VIA82CXXX - strncmp(s,"splitfifo",9) && -#endif /* CONFIG_BLK_DEV_VIA82CXXX */ strncmp(s,"hd",2)) /* hdx= & hdxlun= */ return 0; @@ -3013,58 +2991,6 @@ int __init ide_setup (char *s) } } -#if defined(CONFIG_BLK_DEV_VIA82CXXX) - /* - * Look for drive option "splitfifo=..." - */ - - if (s[0] == 's' && s[1] == 'p' && s[2] == 'l' && - s[3] == 'i' && s[4] == 't' && s[5] == 'f' && - s[6] == 'i' && s[7] == 'f' && s[8] == 'o') { - byte tmp = 0x3a; /* default config byte */ - - i = match_parm(&s[9], NULL, vals, 3); - switch(i) { - case 3: - tmp &= 0xf0; - if ((vals[1] > 0) && (vals[1] < 5)) { - /* sets threshold for primary Channel: */ - byte x = 4 - vals[1]; - tmp |= (x << 2); - } - else - goto bad_option; - if ((vals[2] > 0) && (vals[2] < 5)) { - /* sets threshold for secondary Channel: */ - byte x = 4 - vals[2]; - tmp |= x; - } - else - goto bad_option; - case 1: - /* set the FIFO config between channels to 0: */ - tmp &= 0x9f; - /* set the needed FIFO config between channels: */ - if (vals[0] == 1) /* primary fifo only */ - tmp |= 0x10; - else if (vals[0] == 2) /* secondary fifo only */ - tmp |= 0x70; - else if (vals[0] == 4) /* other shared fifo config */ - tmp |= 0x50; - else if (vals[0] == 3) /* default config */ - tmp |= 0x30; - else - goto bad_option; - break; - default: - goto bad_option; - } - /* set the found option in fifoconfig */ - fifoconfig = tmp; - goto done; - } -#endif /* defined(CONFIG_BLK_DEV_VIA82CXXX) */ - if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e') goto bad_option; /* diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c index 4f0a33086..c00f3305a 100644 --- a/drivers/ide/sis5513.c +++ b/drivers/ide/sis5513.c @@ -320,36 +320,18 @@ static int config_chipset_for_pio (ide_drive_t *drive, byte pio) } config_art_rwp_pio(drive, pio); + drive->current_speed = speed; err = ide_config_drive_speed(drive, speed); return err; } -#define SIS5513_TUNEPROC - -#ifdef SIS5513_TUNEPROC -static void sis5513_tune_drive (ide_drive_t *drive, byte pio) -{ - (void) config_chipset_for_pio(drive, pio); -} -#endif /* SIS5513_TUNEPROC */ - -#ifdef CONFIG_BLK_DEV_IDEDMA -/* - * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four)) - */ -static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) +static int sis5513_tune_chipset (ide_drive_t *drive, byte speed) { - struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - byte drive_pci, test1, test2, mask; - int err; - - unsigned long dma_base = hwif->dma_base; - byte unit = (drive->select.b.unit & 0x01); - byte speed = 0x00, unmask = 0xE0, four_two = 0x00; - byte udma_66 = eighty_ninty_three(drive); + byte drive_pci, test1, test2; + byte unmask, four_two, mask = 0; if (host_dev) { switch(host_dev->device) { @@ -359,9 +341,15 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) case PCI_DEVICE_ID_SI_630: unmask = 0xF0; four_two = 0x01; + break; default: + unmask = 0xE0; + four_two = 0x00; break; } + } else { + unmask = 0xE0; + four_two = 0x00; } switch(drive->dn) { @@ -375,61 +363,103 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) pci_read_config_byte(dev, drive_pci, &test1); pci_read_config_byte(dev, drive_pci|0x01, &test2); - if ((!ultra) && (test2 & 0x80)) { + if ((speed <= XFER_MW_DMA_2) && (test2 & 0x80)) { pci_write_config_byte(dev, drive_pci|0x01, test2 & ~0x80); pci_read_config_byte(dev, drive_pci|0x01, &test2); + } else { + pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); + } + + switch(speed) { +#ifdef CONFIG_BLK_DEV_IDEDMA + case XFER_UDMA_5: /* can not do ultra mode 5 yet */ + case XFER_UDMA_4: mask = 0x90; break; + case XFER_UDMA_3: mask = 0xA0; break; + case XFER_UDMA_2: mask = (four_two) ? 0xB0 : 0xA0; break; + case XFER_UDMA_1: mask = (four_two) ? 0xD0 : 0xC0; break; + case XFER_UDMA_0: mask = unmask; break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_MW_DMA_0: + case XFER_SW_DMA_2: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: break; +#endif /* CONFIG_BLK_DEV_IDEDMA */ + case XFER_PIO_4: return((int) config_chipset_for_pio(drive, 4)); + case XFER_PIO_3: return((int) config_chipset_for_pio(drive, 3)); + case XFER_PIO_2: return((int) config_chipset_for_pio(drive, 2)); + case XFER_PIO_1: return((int) config_chipset_for_pio(drive, 1)); + case XFER_PIO_0: + default: return((int) config_chipset_for_pio(drive, 0)); } - if ((id->dma_ultra & 0x0010) && (ultra) && (udma_66) && (four_two)) { - if (!(test2 & 0x90)) { - pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); - pci_write_config_byte(dev, drive_pci|0x01, test2|0x90); + if (speed > XFER_MW_DMA_2) + pci_write_config_byte(dev, drive_pci|0x01, test2|mask); + + drive->current_speed = speed; + return ((int) ide_config_drive_speed(drive, speed)); +} + +static void sis5513_tune_drive (ide_drive_t *drive, byte pio) +{ + (void) config_chipset_for_pio(drive, pio); +} + +#ifdef CONFIG_BLK_DEV_IDEDMA +/* + * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four)) + */ +static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + + byte four_two = 0, speed = 0; + int err; + + byte unit = (drive->select.b.unit & 0x01); + byte udma_66 = eighty_ninty_three(drive); + + if (host_dev) { + switch(host_dev->device) { + case PCI_DEVICE_ID_SI_530: + case PCI_DEVICE_ID_SI_540: + case PCI_DEVICE_ID_SI_620: + case PCI_DEVICE_ID_SI_630: + four_two = 0x01; break; + default: + four_two = 0x00; break; } + } + + if ((id->dma_ultra & 0x0010) && (ultra) && (udma_66) && (four_two)) speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (ultra) && (udma_66) && (four_two)) { - if (!(test2 & 0xA0)) { - pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); - pci_write_config_byte(dev, drive_pci|0x01, test2|0xA0); - } + else if ((id->dma_ultra & 0x0008) && (ultra) && (udma_66) && (four_two)) speed = XFER_UDMA_3; - } else if ((id->dma_ultra & 0x0004) && (ultra)) { - mask = (four_two) ? 0xB0 : 0xA0; - if (!(test2 & mask)) { - pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); - pci_write_config_byte(dev, drive_pci|0x01, test2|mask); - } + else if ((id->dma_ultra & 0x0004) && (ultra)) speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra)) { - mask = (four_two) ? 0xD0 : 0xC0; - if (!(test2 & mask)) { - pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); - pci_write_config_byte(dev, drive_pci|0x01, test2|mask); - } + else if ((id->dma_ultra & 0x0002) && (ultra)) speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra)) { - if (!(test2 & unmask)) { - pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); - pci_write_config_byte(dev, drive_pci|0x01, test2|unmask); - } + else if ((id->dma_ultra & 0x0001) && (ultra)) speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { + else if (id->dma_mword & 0x0004) speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { + else if (id->dma_mword & 0x0002) speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { + else if (id->dma_mword & 0x0001) speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { + else if (id->dma_1word & 0x0004) speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { + else if (id->dma_1word & 0x0002) speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { + else if (id->dma_1word & 0x0001) speed = XFER_SW_DMA_0; - } else { + else return ((int) ide_dma_off_quietly); - } - outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); - err = ide_config_drive_speed(drive, speed); + outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2); + + err = sis5513_tune_chipset(drive, speed); #if SIS5513_DEBUG_DRIVE_INFO printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn); @@ -575,9 +605,8 @@ void __init ide_init_sis5513 (ide_hwif_t *hwif) hwif->irq = hwif->channel ? 15 : 14; -#ifdef SIS5513_TUNEPROC hwif->tuneproc = &sis5513_tune_drive; -#endif /* SIS5513_TUNEPROC */ + hwif->speedproc = &sis5513_tune_chipset; if (!(hwif->dma_base)) return; diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c dissimilarity index 91% index 3ab298596..ef21c2cb7 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -1,982 +1,624 @@ -/* - * linux/drivers/ide/via82cxxx.c Version 0.10 June 9, 2000 - * - * Copyright (C) 1998-99 Michel Aubry, Maintainer - * Copyright (C) 1999 Jeff Garzik, MVP4 Support - * (jgarzik@mandrakesoft.com) - * Copyright (C) 1998-2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License - * - * The VIA MVP-4 is reported OK with UDMA. - * The VIA MVP-3 is reported OK with UDMA. - * The TX Pro III is also reported OK with UDMA. - * - * VIA chips also have a single FIFO, with the same 64 bytes deep - * buffer (16 levels of 4 bytes each). - * - * However, VIA chips can have the buffer split either 8:8 levels, - * 16:0 levels or 0:16 levels between both channels. One could think - * of using this feature, as even if no level of FIFO is given to a - * given channel, one can for instance always reach ATAPI drives through - * it, or, if one channel is unused, configuration defaults to - * an even split FIFO levels. - * - * This feature is available only through a kernel command line : - * "splitfifo=Chan,Thr0,Thr1" or "splitfifo=Chan". - * where: Chan =1,2,3 or 4 and Thrx = 1,2,3,or 4. - * - * If Chan == 1: - * gives all the fifo to channel 0, - * sets its threshold to Thr0/4, - * and disables any dma access to channel 1. - * - * If chan == 2: - * gives all the fifo to channel 1, - * sets its threshold to Thr1/4, - * and disables any dma access to channel 0. - * - * If chan == 3 or 4: - * shares evenly fifo between channels, - * gives channel 0 a threshold of Thr0/4, - * and channel 1 a threshold of Thr1/4. - * - * Note that by default (if no command line is provided) and if a channel - * has been disabled in Bios, all the fifo is given to the active channel, - * and its threshold is set to 3/4. - * - * VT82c586B - * - * Offset 4B-48 - Drive Timing Control - * | pio0 | pio1 | pio2 | pio3 | pio4 - * 25.0 MHz | 0xA8 | 0x65 | 0x65 | 0x31 | 0x20 - * 33.0 MHz | 0xA8 | 0x65 | 0x65 | 0x31 | 0x20 - * 37.5 MHz | 0xA9 | 0x76 | 0x76 | 0x32 | 0x21 - * - * Offset 53-50 - UltraDMA Extended Timing Control - * UDMA | NO | 0 | 1 | 2 - * | 0x03 | 0x62 | 0x61 | 0x60 - * - * VT82c596B & VT82c686A - * - * Offset 4B-48 - Drive Timing Control - * | pio0 | pio1 | pio2 | pio3 | pio4 - * 25.0 MHz | 0xA8 | 0x65 | 0x65 | 0x31 | 0x20 - * 33.0 MHz | 0xA8 | 0x65 | 0x65 | 0x31 | 0x20 - * 37.5 MHz | 0xDB | 0x87 | 0x87 | 0x42 | 0x31 - * 41.5 MHz | 0xFE | 0xA8 | 0xA8 | 0x53 | 0x32 - * - * Offset 53-50 - UltraDMA Extended Timing Control - * UDMA | NO | 0 | 1 | 2 - * 33.0 MHz | 0x03 | 0xE2 | 0xE1 | 0xE0 - * 37.5 MHz | 0x03 | 0xE2 | 0xE2 | 0xE1 (1) - * - * Offset 53-50 - UltraDMA Extended Timing Control - * UDMA | NO | 0 | 1 | 2 | 3 | 4 - * 33.0 MHz | (2) | 0xE6 | 0xE4 | 0xE2 | 0xE1 | 0xE0 - * 37.5 MHz | (2) | 0xE6 | 0xE6 | 0xE4 | 0xE2 | 0xE1 (1) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -static struct pci_dev *host_dev = NULL; -static struct pci_dev *isa_dev = NULL; - -struct chipset_bus_clock_list_entry { - byte xfer_speed; - - byte ultra_settings_25; - byte chipset_settings_25; - byte ultra_settings_33; - byte chipset_settings_33; - byte ultra_settings_37; - byte chipset_settings_37; - byte ultra_settings_41; - byte chipset_settings_41; -}; - -static struct chipset_bus_clock_list_entry * via82cxxx_table = NULL; - -static struct chipset_bus_clock_list_entry via82cxxx_type_one [] = { - /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */ -#ifdef CONFIG_BLK_DEV_IDEDMA - { XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { XFER_UDMA_3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { XFER_UDMA_2, 0x60, 0x20, 0x60, 0x20, 0x60, 0x21, 0x00, 0x00 }, - { XFER_UDMA_1, 0x61, 0x20, 0x61, 0x20, 0x61, 0x21, 0x00, 0x00 }, - { XFER_UDMA_0, 0x62, 0x20, 0x62, 0x20, 0x62, 0x21, 0x00, 0x00 }, - - { XFER_MW_DMA_2, 0x03, 0x20, 0x03, 0x20, 0x03, 0x21, 0x00, 0x00 }, - { XFER_MW_DMA_1, 0x03, 0x31, 0x03, 0x31, 0x03, 0x32, 0x00, 0x00 }, - { XFER_MW_DMA_0, 0x03, 0x31, 0x03, 0x31, 0x03, 0x32, 0x00, 0x00 }, -#endif /* CONFIG_BLK_DEV_IDEDMA */ - { XFER_PIO_4, 0x03, 0x20, 0x03, 0x20, 0x03, 0x21, 0x00, 0x00 }, - { XFER_PIO_3, 0x03, 0x31, 0x03, 0x31, 0x03, 0x32, 0x00, 0x00 }, - { XFER_PIO_2, 0x03, 0x65, 0x03, 0x65, 0x03, 0x76, 0x00, 0x00 }, - { XFER_PIO_1, 0x03, 0x65, 0x03, 0x65, 0x03, 0x76, 0x00, 0x00 }, - { XFER_PIO_0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xA9, 0x00, 0x00 }, - { 0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xA9, 0x00, 0x00 } -}; - -static struct chipset_bus_clock_list_entry via82cxxx_type_two [] = { - /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */ -#ifdef CONFIG_BLK_DEV_IDEDMA - { XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { XFER_UDMA_3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { XFER_UDMA_2, 0xE0, 0x20, 0xE0, 0x20, 0xE1, 0x31, 0xE1, 0x32 }, - { XFER_UDMA_1, 0xE1, 0x20, 0xE1, 0x20, 0xE2, 0x31, 0xE2, 0x32 }, - { XFER_UDMA_0, 0xE2, 0x20, 0xE2, 0x20, 0xE2, 0x31, 0xE2, 0x32 }, - - { XFER_MW_DMA_2, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 }, - { XFER_MW_DMA_1, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 }, - { XFER_MW_DMA_0, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 }, -#endif /* CONFIG_BLK_DEV_IDEDMA */ - { XFER_PIO_4, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 }, - { XFER_PIO_3, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 }, - { XFER_PIO_2, 0x03, 0x65, 0x03, 0x65, 0x03, 0x87, 0x03, 0xA8 }, - { XFER_PIO_1, 0x03, 0x65, 0x03, 0x65, 0x03, 0x87, 0x03, 0xA8 }, - { XFER_PIO_0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xDB, 0x03, 0xFE }, - { 0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xDB, 0x03, 0xFE } -}; - -static struct chipset_bus_clock_list_entry via82cxxx_type_three [] = { - /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */ -#ifdef CONFIG_BLK_DEV_IDEDMA - { XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { XFER_UDMA_3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { XFER_UDMA_2, 0xE0, 0x20, 0xE0, 0x20, 0xE1, 0x31, 0xE1, 0x32 }, - { XFER_UDMA_1, 0xE1, 0x20, 0xE1, 0x20, 0xE2, 0x31, 0xE2, 0x32 }, - { XFER_UDMA_0, 0xE2, 0x20, 0xE2, 0x20, 0xE2, 0x31, 0xE2, 0x32 }, - - { XFER_MW_DMA_2, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 }, - { XFER_MW_DMA_1, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 }, - { XFER_MW_DMA_0, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 }, -#endif /* CONFIG_BLK_DEV_IDEDMA */ - { XFER_PIO_4, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 }, - { XFER_PIO_3, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 }, - { XFER_PIO_2, 0x03, 0x65, 0x03, 0x65, 0x03, 0x87, 0x03, 0xA8 }, - { XFER_PIO_1, 0x03, 0x65, 0x03, 0x65, 0x03, 0x87, 0x03, 0xA8 }, - { XFER_PIO_0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xDB, 0x03, 0xFE }, - { 0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xDB, 0x03, 0xFE } -}; - -static struct chipset_bus_clock_list_entry via82cxxx_type_four [] = { - /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */ -#ifdef CONFIG_BLK_DEV_IDEDMA - { XFER_UDMA_4, 0x00, 0x00, 0xE0, 0x20, 0xE1, 0x31, 0x00, 0x00 }, - { XFER_UDMA_3, 0x00, 0x00, 0xE1, 0x20, 0xE2, 0x31, 0x00, 0x00 }, - { XFER_UDMA_2, 0x00, 0x00, 0xE2, 0x20, 0xE4, 0x31, 0x00, 0x00 }, - { XFER_UDMA_1, 0x00, 0x00, 0xE4, 0x20, 0xE6, 0x31, 0x00, 0x00 }, - { XFER_UDMA_0, 0x00, 0x00, 0xE6, 0x20, 0xE6, 0x31, 0x00, 0x00 }, - - { XFER_MW_DMA_2, 0x00, 0x00, 0x03, 0x20, 0x03, 0x31, 0x00, 0x00 }, - { XFER_MW_DMA_1, 0x00, 0x00, 0x03, 0x31, 0x03, 0x42, 0x00, 0x00 }, - { XFER_MW_DMA_0, 0x00, 0x00, 0x03, 0x31, 0x03, 0x42, 0x00, 0x00 }, -#endif /* CONFIG_BLK_DEV_IDEDMA */ - { XFER_PIO_4, 0x00, 0x00, 0x03, 0x20, 0x03, 0x31, 0x00, 0x00 }, - { XFER_PIO_3, 0x00, 0x00, 0x03, 0x31, 0x03, 0x42, 0x00, 0x00 }, - { XFER_PIO_2, 0x00, 0x00, 0x03, 0x65, 0x03, 0x87, 0x00, 0x00 }, - { XFER_PIO_1, 0x00, 0x00, 0x03, 0x65, 0x03, 0x87, 0x00, 0x00 }, - { XFER_PIO_0, 0x00, 0x00, 0x03, 0xA8, 0x03, 0xDB, 0x00, 0x00 }, - { 0, 0x00, 0x00, 0x03, 0xA8, 0x03, 0xDB, 0x00, 0x00 } -}; - -static const struct { - const char *name; - unsigned short vendor_id; - unsigned short host_id; -} ApolloHostChipInfo[] = { - { "VT 82C585 Apollo VP1/VPX", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C585, }, - { "VT 82C595 Apollo VP2", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C595, }, - { "VT 82C597 Apollo VP3", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, }, - { "VT 82C598 Apollo MVP3", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C598_0, }, - { "VT 82C598 Apollo MVP3", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C598_0, }, - { "VT 82C680 Apollo P6", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C680, }, - { "VT 82C691 Apollo Pro", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C691, }, - { "VT 82C693 Apollo Pro Plus", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C693, }, - { "Apollo MVP4", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8501_0, }, - { "VT 8371", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_0, }, - { "VT 8601", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, }, - { "AMD IronGate", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_7006, }, -}; - -#define NUM_APOLLO_ISA_CHIP_DEVICES 2 -#define VIA_FLAG_NULL 0x00000000 -#define VIA_FLAG_CHECK_REV 0x00000001 -#define VIA_FLAG_ATA_66 0x00000002 - -static const struct { - unsigned short host_id; - unsigned short isa_id; - unsigned int flags; - struct chipset_bus_clock_list_entry * chipset_table; -} ApolloISAChipInfo[] = { - { PCI_DEVICE_ID_VIA_82C585, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV, via82cxxx_type_one }, - { PCI_DEVICE_ID_VIA_82C595, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV, via82cxxx_type_one }, - { PCI_DEVICE_ID_VIA_82C597_0, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV, via82cxxx_type_one }, - { PCI_DEVICE_ID_VIA_82C598_0, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV, via82cxxx_type_one }, - { PCI_DEVICE_ID_VIA_82C598_0, PCI_DEVICE_ID_VIA_82C596, VIA_FLAG_NULL, via82cxxx_type_one }, - { PCI_DEVICE_ID_VIA_82C680, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV, via82cxxx_type_one }, - { PCI_DEVICE_ID_VIA_82C691, PCI_DEVICE_ID_VIA_82C596, VIA_FLAG_ATA_66, via82cxxx_type_two }, - { PCI_DEVICE_ID_VIA_82C693, PCI_DEVICE_ID_VIA_82C596, VIA_FLAG_NULL, via82cxxx_type_one }, - { PCI_DEVICE_ID_VIA_8501_0, PCI_DEVICE_ID_VIA_82C686, VIA_FLAG_ATA_66, via82cxxx_type_two }, - { PCI_DEVICE_ID_VIA_8371_0, PCI_DEVICE_ID_VIA_82C686, VIA_FLAG_ATA_66, via82cxxx_type_two }, - { PCI_DEVICE_ID_VIA_8601_0, PCI_DEVICE_ID_VIA_8231, VIA_FLAG_ATA_66, via82cxxx_type_two }, - { PCI_DEVICE_ID_AMD_FE_GATE_7006, PCI_DEVICE_ID_VIA_82C686, VIA_FLAG_ATA_66, via82cxxx_type_two }, -}; - -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - -#define DISPLAY_VIA_TIMINGS - -#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static char *FIFO_str[] = { - " 1 ", - "3/4", - "1/2", - "1/4" -}; - -static char *control3_str[] = { - "No limitation", - "64", - "128", - "192" -}; - -static int via_get_info(char *, char **, off_t, int); -extern int (*via_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -static char * print_apollo_drive_config (char *buf, struct pci_dev *dev) -{ - int rc; - unsigned int time; - byte tm; - char *p = buf; - - /* Drive Timing Control */ - rc = pci_read_config_dword(dev, 0x48, &time); - p += sprintf(p, "Act Pls Width: %02d %02d %02d %02d\n", - ((time & 0xf0000000)>>28) + 1, - ((time & 0xf00000)>>20) + 1, - ((time & 0xf000)>>12) + 1, - ((time & 0xf0)>>4) + 1 ); - p += sprintf(p, "Recovery Time: %02d %02d %02d %02d\n", - ((time & 0x0f000000)>>24) + 1, - ((time & 0x0f0000)>>16) + 1, - ((time & 0x0f00)>>8) + 1, - (time & 0x0f) + 1 ); - - /* Address Setup Time */ - rc = pci_read_config_byte(dev, 0x4C, &tm); - p += sprintf(p, "Add. Setup T.: %01dT %01dT %01dT %01dT\n", - ((tm & 0xc0)>>6) + 1, - ((tm & 0x30)>>4) + 1, - ((tm & 0x0c)>>2) + 1, - (tm & 0x03) + 1 ); - - /* UltraDMA33 Extended Timing Control */ - rc = pci_read_config_dword(dev, 0x50, &time); - p += sprintf(p, "------------------UDMA-Timing-Control------------------------\n"); - p += sprintf(p, "Enable Meth.: %01d %01d %01d %01d\n", - (time & 0x80000000) ? 1 : 0, - (time & 0x800000) ? 1 : 0, - (time & 0x8000) ? 1 : 0, - (time & 0x80) ? 1 : 0 ); - p += sprintf(p, "Enable: %s %s %s %s\n", - (time & 0x40000000) ? "yes" : "no ", - (time & 0x400000) ? "yes" : "no ", - (time & 0x4000) ? "yes" : "no ", - (time & 0x40) ? "yes" : "no " ); - p += sprintf(p, "Transfer Mode: %s %s %s %s\n", - (time & 0x20000000) ? "PIO" : "DMA", - (time & 0x200000) ? "PIO" : "DMA", - (time & 0x2000) ? "PIO" : "DMA", - (time & 0x20) ? "PIO" : "DMA" ); - p += sprintf(p, "Cycle Time: %01dT %01dT %01dT %01dT\n", - ((time & 0x03000000)>>24) + 2, - ((time & 0x030000)>>16) + 2, - ((time & 0x0300)>>8) + 2, - (time & 0x03) + 2 ); - - return (char *)p; -} - -static char * print_apollo_ide_config (char *buf, struct pci_dev *dev) -{ - byte time, tmp; - unsigned short size0, size1; - int rc; - char *p = buf; - - rc = pci_read_config_byte(dev, 0x41, &time); - p += sprintf(p, "Prefetch Buffer : %s %s\n", - (time & 128) ? "on " : "off", - (time & 32) ? "on " : "off" ); - p += sprintf(p, "Post Write Buffer: %s %s\n", - (time & 64) ? "on " : "off", - (time & 16) ? "on " : "off" ); - - /* FIFO configuration */ - rc = pci_read_config_byte(dev, 0x43, &time); - tmp = ((time & 0x20)>>2) + ((time & 0x40)>>3); - p += sprintf(p, "FIFO Conf/Chan. : %02d %02d\n", - 16 - tmp, tmp); - tmp = (time & 0x0F)>>2; - p += sprintf(p, "Threshold Prim. : %s %s\n", - FIFO_str[tmp], - FIFO_str[time & 0x03] ); - - /* chipset Control3 */ - rc = pci_read_config_byte(dev, 0x46, &time); - p += sprintf(p, "Read DMA FIFO flush: %s %s\n", - (time & 0x80) ? "on " : "off", - (time & 0x40) ? "on " : "off" ); - p += sprintf(p, "End Sect. FIFO flush: %s %s\n", - (time & 0x20) ? "on " : "off", - (time & 0x10) ? "on " : "off" ); - p += sprintf(p, "Max DRDY Pulse Width: %s %s\n", - control3_str[(time & 0x03)], - (time & 0x03) ? "PCI clocks" : "" ); - - /* Primary and Secondary sector sizes */ - rc = pci_read_config_word(dev, 0x60, &size0); - rc = pci_read_config_word(dev, 0x68, &size1); - p += sprintf(p, "Bytes Per Sector: %03d %03d\n", - size0 & 0xfff, - size1 & 0xfff ); - - return (char *)p; -} - -static char * print_apollo_chipset_control1 (char *buf, struct pci_dev *dev) -{ - byte t; - int rc; - char *p = buf; - unsigned short c; - byte l, l_max; - - rc = pci_read_config_word(dev, 0x04, &c); - rc = pci_read_config_byte(dev, 0x44, &t); - rc = pci_read_config_byte(dev, 0x0d, &l); - rc = pci_read_config_byte(dev, 0x3f, &l_max); - - p += sprintf(p, "Command register = 0x%x\n", c); - p += sprintf(p, "Master Read Cycle IRDY %d Wait State\n", - (t & 64) >>6 ); - p += sprintf(p, "Master Write Cycle IRDY %d Wait State\n", - (t & 32) >> 5 ); - p += sprintf(p, "FIFO Output Data 1/2 Clock Advance: %s\n", - (t & 16) ? "on " : "off" ); - p += sprintf(p, "Bus Master IDE Status Register Read Retry: %s\n", - (t & 8) ? "on " : "off" ); - p += sprintf(p, "Latency timer = %d (max. = %d)\n", - l, l_max); - - return (char *)p; -} - -static char * print_apollo_chipset_control2 (char *buf, struct pci_dev *dev) -{ - byte t; - int rc; - char *p = buf; - rc = pci_read_config_byte(dev, 0x45, &t); - p += sprintf(p, "Interrupt Steering Swap: %s\n", - (t & 64) ? "on ":"off" ); - - return (char *)p; -} - -static char * print_apollo_chipset_control3 (char *buf, struct pci_dev *dev, - unsigned short n) -{ - /* - * at that point we can be sure that register 0x20 of the - * chipset contains the right address... - */ - unsigned int bibma; - int rc; - byte c0, c1; - char *p = buf; - - rc = pci_read_config_dword(dev, 0x20, &bibma); - bibma = (bibma & 0xfff0) ; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb((unsigned short)bibma + 0x02); - c1 = inb((unsigned short)bibma + 0x0a); - - if (n == 0) { - /*p = sprintf(p,"--------------------Primary IDE------------Secondary IDE-----");*/ - p += sprintf(p, "both channels togth: %s %s\n", - (c0&0x80) ? "no" : "yes", - (c1&0x80) ? "no" : "yes" ); - } else { - /*p = sprintf(p,"--------------drive0------drive1-------drive0------drive1----");*/ - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - } - - return (char *)p; -} - -static int via_get_info (char *buffer, char **addr, off_t offset, int count) -{ - /* - * print what /proc/via displays, - * if required from DISPLAY_APOLLO_TIMINGS - */ - char *p = buffer; - /* Parameter of chipset : */ - - /* Miscellaneous control 1 */ - p = print_apollo_chipset_control1(buffer, bmide_dev); - - /* Miscellaneous control 2 */ - p = print_apollo_chipset_control2(p, bmide_dev); - /* Parameters of drives: */ - - /* Header */ - p += sprintf(p, "------------------Primary IDE------------Secondary IDE-----\n"); - p = print_apollo_chipset_control3(p, bmide_dev, 0); - p = print_apollo_ide_config(p, bmide_dev); - p += sprintf(p, "--------------drive0------drive1-------drive0------drive1----\n"); - p = print_apollo_chipset_control3(p, bmide_dev, 1); - p = print_apollo_drive_config(p, bmide_dev); - - return p-buffer; /* hoping it is less than 4K... */ -} - -#endif /* defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) */ - -/* - * Used to set Fifo configuration via kernel command line: - */ - -byte via_proc = 0; -byte fifoconfig = 0; -static byte newfifo = 0; - -/* Used to just intialize once Fifo configuration */ -static short int done = 0; - -/* - * Set VIA Chipset Timings for (U)DMA modes enabled. - * - * VIA Apollo chipset has complete support for - * setting up the timing parameters. - */ -static void set_via_timings (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - byte post = hwif->channel ? 0x30 : 0xc0; - byte flush = hwif->channel ? 0x50 : 0xa0; - int mask = hwif->channel ? ((newfifo & 0x60) ? 0 : 1) : - (((newfifo & 0x60) == 0x60) ? 1 : 0); - byte via_config = 0; - int rc = 0, errors = 0; - - printk("%s: VIA Bus-Master ", hwif->name); - - /* - * setting IDE read prefetch buffer and IDE post write buffer. - * (This feature allows prefetched reads and post writes). - */ - if ((rc = pci_read_config_byte(dev, 0x41, &via_config))) - errors++; - - if (mask) { - if ((rc = pci_write_config_byte(dev, 0x41, via_config & ~post))) - errors++; - } else { - if ((rc = pci_write_config_byte(dev, 0x41, via_config | post))) - errors++; - } - - /* - * setting Channel read and End-of-sector FIFO flush. - * (This feature ensures that FIFO flush is enabled: - * - for read DMA when interrupt asserts the given channel. - * - at the end of each sector for the given channel.) - */ - if ((rc = pci_read_config_byte(dev, 0x46, &via_config))) - errors++; - - if (mask) { - if ((rc = pci_write_config_byte(dev, 0x46, via_config & ~flush))) - errors++; - } else { - if ((rc = pci_write_config_byte(dev, 0x46, via_config | flush))) - errors++; - } - - if (!hwif->dma_base) - printk("Config %s. No DMA Enabled\n", - errors ? "ERROR":"Success"); - else - printk("(U)DMA Timing Config %s\n", - errors ? "ERROR" : "Success"); -} - -/* - * Sets VIA 82cxxx FIFO configuration: - * This chipsets gets a splitable fifo. This can be driven either by command - * line option (eg "splitfifo=2,2,3" which asks this driver to switch all the - * 16 fifo levels to the second drive, and give it a threshold of 3 for (u)dma - * triggering. - */ - -static int via_set_fifoconfig(ide_hwif_t *hwif) -{ - byte fifo; - unsigned int timings; - struct pci_dev *dev = hwif->pci_dev; - - /* read port configuration */ - if (pci_read_config_dword(dev, 0x40, &timings)) - return 1; - - /* first read actual fifo config: */ - if (pci_read_config_byte(dev, 0x43, &fifo)) - return 1; - - /* keep 4 and 7 bit as they seem to differ between chipsets flavors... */ - newfifo = fifo & 0x90; - - if (fifoconfig) { - /* we received a config request from kernel command line: */ - newfifo |= fifoconfig & 0x6f; - } else { - /* If ever just one channel is unused, allocate all fifo levels to it - * and give it a 3/4 threshold for (u)dma transfers. - * Otherwise, share it evenly between channels: - */ - if ((timings & 3) == 2) { - /* only primary channel is enabled - * 16 buf. to prim. chan. thresh=3/4 - */ - newfifo |= 0x06; - } else if ((timings & 3) == 1) { - /* only secondary channel is enabled! - * 16 buffers to sec. ch. thresh=3/4 - */ - newfifo |= 0x69; - } else { - /* fifo evenly distributed: */ - newfifo |= 0x2a; - } - } - - /* write resulting configuration to chipset: */ - if (pci_write_config_byte(dev, 0x43, newfifo)) - return 1; - - /* and then reread it to get the actual one */ - if (pci_read_config_byte(dev, 0x43, &newfifo)) - return 1; - - /* print a kernel report: */ - printk("Split FIFO Configuration: %s Primary buffers, threshold = %s\n", - ((newfifo & 0x60) == 0x60) ? " 0" : - ((newfifo & 0x60) ? " 8" : "16"), - !(newfifo & 0x0c) ? "1" : - (!(newfifo & 0x08) ? "3/4" : - (newfifo & 0x04) ? "1/4" : "1/2")); - - printk(" %s Second. buffers, threshold = %s\n", - ((newfifo & 0x60) == 0x60) ? "16" : - ((newfifo & 0x60) ? " 8" : " 0"), - !(newfifo & 0x03) ? "1" : - (!(newfifo & 0x02) ? "3/4" : - (newfifo & 0x01) ? "1/4" : "1/2")); - return 0; -} - -#ifdef CONFIG_VIA82CXXX_TUNING -static byte pci_bus_clock_list (byte speed, int ide_clock, struct chipset_bus_clock_list_entry * chipset_table) -{ - for ( ; chipset_table->xfer_speed ; chipset_table++) - if (chipset_table->xfer_speed == speed) { - switch(ide_clock) { - case 25: return chipset_table->chipset_settings_25; - case 33: return chipset_table->chipset_settings_33; - case 37: return chipset_table->chipset_settings_37; - case 41: return chipset_table->chipset_settings_41; - default: break; - } - } - return 0x00; -} - -static byte pci_bus_clock_list_ultra (byte speed, int ide_clock, struct chipset_bus_clock_list_entry * chipset_table) -{ - for ( ; chipset_table->xfer_speed ; chipset_table++) - if (chipset_table->xfer_speed == speed) { - switch(ide_clock) { - case 25: return chipset_table->ultra_settings_25; - case 33: return chipset_table->ultra_settings_33; - case 37: return chipset_table->ultra_settings_37; - case 41: return chipset_table->ultra_settings_41; - default: break; - } - } - return 0x00; -} - -static int via82cxxx_tune_chipset (ide_drive_t *drive, byte speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - struct chipset_bus_clock_list_entry * temp_table = NULL; - - byte unit = (drive->select.b.unit & 0x01) ? 1 : 0; - byte ata2_pci = 0x00; - byte ata3_pci = 0x00; - byte timing = 0x00; - byte ultra = 0x00; - int err; - - int bus_speed = system_bus_clock(); - - if (via82cxxx_table == NULL) - return -1; - - switch(drive->dn) { - case 0: ata2_pci = 0x4b; ata3_pci = 0x53; break; - case 1: ata2_pci = 0x4a; ata3_pci = 0x52; break; - case 2: ata2_pci = 0x49; ata3_pci = 0x51; break; - case 3: ata2_pci = 0x48; ata3_pci = 0x50; break; - default: - return -1; - } - - if ((via82cxxx_table == via82cxxx_type_four) && - (!(hwif->udma_four)) && - (speed <= XFER_UDMA_2)) { - temp_table = via82cxxx_type_three; - } else { - temp_table = via82cxxx_table; - } - - pci_read_config_byte(dev, ata2_pci, &timing); - timing = pci_bus_clock_list(speed, bus_speed, temp_table); - pci_write_config_byte(dev, ata2_pci, timing); - - pci_read_config_byte(dev, ata3_pci, &ultra); - ultra = pci_bus_clock_list_ultra(speed, bus_speed, temp_table); - if ((unit) && (hwif->udma_four)) - ultra |= 0x04; - pci_write_config_byte(dev, ata3_pci, ultra); - - if (!drive->init_speed) - drive->init_speed = speed; - - err = ide_config_drive_speed(drive, speed); - - drive->current_speed = speed; - return(err); -} - -static void config_chipset_for_pio (ide_drive_t *drive) -{ - unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; - unsigned short xfer_pio = drive->id->eide_pio_modes; - byte timing, speed, pio; - - pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - - if (xfer_pio> 4) - xfer_pio = 0; - - if (drive->id->eide_pio_iordy > 0) { - for (xfer_pio = 5; - xfer_pio>0 && - drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; - xfer_pio--); - } else { - xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : - (drive->id->eide_pio_modes & 2) ? 0x04 : - (drive->id->eide_pio_modes & 1) ? 0x03 : - (drive->id->tPIO & 2) ? 0x02 : - (drive->id->tPIO & 1) ? 0x01 : xfer_pio; - } - - timing = (xfer_pio >= pio) ? xfer_pio : pio; - switch(timing) { - case 4: speed = XFER_PIO_4; break; - case 3: speed = XFER_PIO_3; break; - case 2: speed = XFER_PIO_2; break; - case 1: speed = XFER_PIO_1; break; - default: - speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; - break; - } - (void) via82cxxx_tune_chipset(drive, speed); -} - -static void via82cxxx_tune_drive (ide_drive_t *drive, byte pio) -{ - byte speed; - switch(pio) { - case 4: speed = XFER_PIO_4; break; - case 3: speed = XFER_PIO_3; break; - case 2: speed = XFER_PIO_2; break; - case 1: speed = XFER_PIO_1; break; - default: speed = XFER_PIO_0; break; - } - (void) via82cxxx_tune_chipset(drive, speed); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte speed = 0x00; - byte ultra66 = eighty_ninty_three(drive); - byte ultra100 = 0; - int rval; - - if ((id->dma_ultra & 0x0020) && (ultra66) && (ultra100)) { - speed = XFER_UDMA_5; - } else if ((id->dma_ultra & 0x0010) && (ultra66)) { - speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (ultra66)) { - speed = XFER_UDMA_3; - } else if (id->dma_ultra & 0x0004) { - speed = XFER_UDMA_2; - } else if (id->dma_ultra & 0x0002) { - speed = XFER_UDMA_1; - } else if (id->dma_ultra & 0x0001) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); - } - - (void) via82cxxx_tune_chipset(drive, speed); - - rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); - return rval; -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x002F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if (id->dma_mword & 0x0007) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - config_chipset_for_pio(drive); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -int via82cxxx_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ -#endif /* CONFIG_VIA82CXXX_TUNING */ - -unsigned int __init pci_init_via82cxxx (struct pci_dev *dev, const char *name) -{ - struct pci_dev *host; - struct pci_dev *isa; - int i, j, ata33, ata66; - - int bus_speed = system_bus_clock(); - byte revision = 0; - - for (i = 0; i < arraysize (ApolloHostChipInfo) && !host_dev; i++) { - host = pci_find_device (ApolloHostChipInfo[i].vendor_id, - ApolloHostChipInfo[i].host_id, - NULL); - if (!host) - continue; - - host_dev = host; - printk(ApolloHostChipInfo[i].name); - printk("\n"); - for (j = 0; j < arraysize (ApolloISAChipInfo) && !isa_dev; j++) { - if (ApolloISAChipInfo[j].host_id != - ApolloHostChipInfo[i].host_id) - continue; - - isa = pci_find_device (PCI_VENDOR_ID_VIA, - ApolloISAChipInfo[j].isa_id, - NULL); - if (!isa) - continue; - - isa_dev = isa; - - ata33 = 1; - ata66 = 0; - - via82cxxx_table = ApolloISAChipInfo[j].chipset_table; - - if (ApolloISAChipInfo[j].flags & VIA_FLAG_CHECK_REV) { - pci_read_config_byte(isa_dev, 0x0d, &revision); - ata33 = (revision >= 0x20) ? 1 : 0; - } else if (ApolloISAChipInfo[j].flags & VIA_FLAG_ATA_66) { - byte ata66_0 = 0, ata66_1 = 0; - ata33 = 0; - ata66 = 1; - pci_read_config_byte(dev, 0x50, &ata66_1); - pci_read_config_byte(dev, 0x52, &ata66_0); - if ((ata66_0 & 0x04) || (ata66_1 & 0x04)) { - via82cxxx_table = (bus_speed == 33 || bus_speed == 37) ? - via82cxxx_type_four : - via82cxxx_type_three; - } - } - - if (ata33 | ata66) - printk(" Chipset Core ATA-%s", ata66 ? "66" : "33"); - } - printk("\n"); - } - -#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) - if (!via_proc) { - via_proc = 1; - bmide_dev = dev; - via_display_info = &via_get_info; - } -#endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS*/ - - return 0; -} - -unsigned int __init ata66_via82cxxx (ide_hwif_t *hwif) -{ - byte ata66 = 0; - byte ata66reg = hwif->channel ? 0x50 : 0x52; - pci_read_config_byte(hwif->pci_dev, ata66reg, &ata66); - - return ((ata66 & 0x04) ? 1 : 0); -} - -void __init ide_init_via82cxxx (ide_hwif_t *hwif) -{ - set_via_timings(hwif); - -#ifdef CONFIG_VIA82CXXX_TUNING - hwif->tuneproc = &via82cxxx_tune_drive; - hwif->speedproc = &via82cxxx_tune_chipset; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->autodma = 0; -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - hwif->dmaproc = &via82cxxx_dmaproc; - hwif->autodma = 1; - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ -#endif /* CONFIG_VIA82CXXX_TUNING */ -} - -/* - * ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long) - * checks if channel "channel" of if hwif is dma - * capable or not, according to kernel command line, - * and the new fifo settings. - * It calls "ide_setup_dma" on capable mainboards, and - * bypasses the setup if not capable. - */ - -void ide_dmacapable_via82cxxx (ide_hwif_t *hwif, unsigned long dmabase) -{ - if (!done) { - via_set_fifoconfig(hwif); - done = 1; - } - - /* - * check if any fifo is available for requested port: - */ - if (((hwif->channel == 0) && ((newfifo & 0x60) == 0x60)) || - ((hwif->channel == 1) && ((newfifo & 0x60) == 0x00))) { - printk(" %s: VP_IDE Bus-Master DMA disabled (FIFO setting)\n", hwif->name); - } else { - ide_setup_dma(hwif, dmabase, 8); - } -} +/* + * $Id: via82cxxx.c,v 2.1 2000/08/29 01:34:60 vojtech Exp $ + * + * Copyright (c) 2000 Vojtech Pavlik + * + * Based on the work of: + * Michel Aubry + * Jeff Garzik + * Andre Hedrick + * + * Sponsored by SuSE + */ + +/* + * VIA vt82c586 IDE driver for Linux. Supports + * + * vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, vt82c686a, vt8231 + * + * southbridges, which can be found in + * + * VIA Apollo VP, VPX, VPX/97, VP2, VP2/97, VP3, MVP3, MVP4 + * VIA Apollo Pro, Pro Plus, Pro 133, Pro 133A, ProMedia 601, ProSavage 605 + * VIA Apollo KX133, KT133 + * AMD-640, AMD-750 IronGate + * + * chipsets. Supports PIO 0-5, MWDMA 0-2, SWDMA 0-2 and + * UDMA 0-5 (includes UDMA33, 66 and 100) modes. UDMA100 isn't possible + * on any of the supported chipsets yet. + * + * UDMA66 and higher modes are autodetected only in case the BIOS has enabled them. + * To force UDMA66, use 'ide0=ata66' or 'ide1=ata66' on the kernel command line. + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ide_modes.h" + +#define VIA_BM_BASE 0x20 +#define VIA_IDE_ENABLE 0x40 +#define VIA_IDE_CONFIG 0x41 +#define VIA_FIFO_CONFIG 0x43 +#define VIA_MISC_1 0x44 +#define VIA_MISC_2 0x45 +#define VIA_MISC_3 0x46 +#define VIA_DRIVE_TIMING 0x48 +#define VIA_ADDRESS_SETUP 0x4c +#define VIA_UDMA_TIMING 0x50 +#define VIA_PRI_SECTOR_SIZE 0x60 +#define VIA_SEC_SECTOR_SIZE 0x68 + +/* + * VIA SouthBridge chips. + */ + +static const struct { + char *name; + unsigned short id; + unsigned char speed; +} via_isa_bridges[] = { + { "vt8231", PCI_DEVICE_ID_VIA_8231, XFER_UDMA_4 }, + { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, XFER_UDMA_4 }, + { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, XFER_UDMA_4 }, + { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, XFER_UDMA_2 }, + { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, XFER_UDMA_2 }, + { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, XFER_UDMA_2 }, + { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, XFER_MW_DMA_2 }, + { "Unknown SouthBridge", 0, XFER_UDMA_4 }, + { "Unknown SouthBridge", 0, XFER_UDMA_2 }, +}; + +static unsigned char via_config; +static unsigned char via_enabled; +static unsigned int via_ata66; + +/* + * PIO 0-5, MWDMA 0-2 and UDMA 0-5 timings (in nanoseconds). + * These were taken from ATA/ATAPI-6 standard, rev 0a, except + * for PIO 5, which is a nonstandard extension. + * + * Dilemma: 8-bit (register) PIO accesses need more relaxed timing. + * Hopefully the chipset is taking care of that. If it doesn't + * do so, define VIA_USE_8_BIT_TIMING to see if it helps. + */ + +#ifndef XFER_PIO_5 +#define XFER_PIO_5 0x0d +#endif + +static const struct { + int mode; + char *name; + short setup; /* t1 */ + short active; /* t2 or tD */ + short recover; /* t2i or tK */ + short cycle; /* t0 */ + short udma; /* t2CYCTYP/2 */ +} via_timing[] = { + { XFER_UDMA_5, "UDMA5", 25, 70, 25, 120, 20 }, + { XFER_UDMA_4, "UDMA4", 25, 70, 25, 120, 30 }, + { XFER_UDMA_3, "UDMA3", 25, 70, 25, 120, 45 }, + + { XFER_UDMA_2, "UDMA2", 25, 70, 25, 120, 60 }, + { XFER_UDMA_1, "UDMA1", 25, 70, 25, 120, 80 }, + { XFER_UDMA_0, "UDMA0", 25, 70, 25, 120, 120 }, + + { XFER_MW_DMA_2, "MDMA2", 25, 70, 25, 120, 0 }, + { XFER_MW_DMA_1, "MDMA1", 45, 80, 50, 150, 0 }, + { XFER_MW_DMA_0, "MDMA0", 60, 215, 215, 480, 0 }, + + { XFER_SW_DMA_0, "SDMA0", 60, 120, 120, 240, 0 }, + { XFER_SW_DMA_0, "SDMA0", 90, 240, 240, 480, 0 }, + { XFER_SW_DMA_0, "SDMA0",120, 480, 480, 960, 0 }, + + { XFER_PIO_5, "PIO5", 20, 50, 30, 100, 0 }, + { XFER_PIO_4, "PIO4", 25, 70, 25, 120, 0 }, + { XFER_PIO_3, "PIO3", 30, 80, 70, 180, 0 }, + +#ifdef VIA_USE_8_BIT_TIMING + { XFER_PIO_2, "PIO2", 30, 290, 60, 330, 0 }, + { XFER_PIO_1, "PIO1", 50, 290, 100, 383, 0 }, + { XFER_PIO_0, "PIO0", 70, 290, 300, 600, 0 }, +#else + { XFER_PIO_2, "PIO2", 30, 100, 90, 240, 0 }, + { XFER_PIO_1, "PIO1", 50, 125, 100, 383, 0 }, + { XFER_PIO_0, "PIO0", 70, 165, 150, 600, 0 }, +#endif + + { XFER_PIO_SLOW, "SLOW", 120, 290, 240, 960, 0 }, + { 0 } +}; + +/* + * VIA /proc entry. + */ + +#ifdef CONFIG_PROC_FS + +#include +#include + +int via_proc = 0; +static struct pci_dev *bmide_dev, *isa_dev; +extern int (*via_display_info)(char *, char **, off_t, int); /* ide-proc.c */ + +static char *via_fifo[] = { " 1 ", "3/4", "1/2", "1/4" }; +static char *via_control3[] = { "No limit", "64", "128", "192" }; + +#define via_print(format, arg...) p += sprintf(p, format "\n" , ## arg) +#define via_print_drive(name, format, arg...)\ + p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n"); + +static int via_get_info(char *buffer, char **addr, off_t offset, int count) +{ + short pci_clock, speed[4], cycle[4], setup[4], active[4], recover[4], umul[4], uen[4], udma[4]; + struct pci_dev *dev = bmide_dev; + unsigned int v, u, i, base; + unsigned short c, size0, size1; + unsigned char t, c0, c1; + char *p = buffer; + + via_print("----------VIA BusMastering IDE Configuration----------------"); + + via_print("Driver Version: 2.1"); + + pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t); + via_print("South Bridge: VIA %s rev %#x", via_isa_bridges[via_config].name, t); + + pci_read_config_word(dev, PCI_COMMAND, &c); + via_print("Command register: %#x", c); + + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &t); + via_print("Latency timer: %d", t); + + pci_clock = system_bus_clock(); + via_print("PCI clock: %dMHz", pci_clock); + + pci_read_config_byte(dev, VIA_MISC_1, &t); + via_print("Master Read Cycle IRDY: %dws", (t & 64) >>6 ); + via_print("Master Write Cycle IRDY: %dws", (t & 32) >> 5 ); + via_print("FIFO Output Data 1/2 Clock Advance: %s", (t & 16) ? "on" : "off" ); + via_print("BM IDE Status Register Read Retry: %s", (t & 8) ? "on" : "off" ); + + pci_read_config_byte(dev, VIA_MISC_2, &t); + sprintf(p, "Interrupt Steering Swap: %s", (t & 64) ? "on" : "off"); + + pci_read_config_byte(dev, VIA_MISC_3, &t); + via_print("Max DRDY Pulse Width: %s%s", via_control3[(t & 0x03)], (t & 0x03) ? "PCI clocks" : ""); + + via_print("-----------------------Primary IDE-------Secondary IDE------"); + via_print("Read DMA FIFO flush: %10s%20s", (t & 0x80) ? "on" : "off", (t & 0x40) ? "on" : "off" ); + via_print("End Sect. FIFO flush: %10s%20s", (t & 0x20) ? "on" : "off", (t & 0x10) ? "on" : "off" ); + + pci_read_config_byte(dev, VIA_IDE_CONFIG, &t); + via_print("Prefetch Buffer: %10s%20s", (t & 0x80) ? "on" : "off", (t & 0x20) ? "on" : "off" ); + via_print("Post Write Buffer: %10s%20s", (t & 0x40) ? "on" : "off", (t & 0x10) ? "on" : "off" ); + + pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t); + via_print("FIFO size: %10d%20d", 16 - (((t >> 5) & 1) + ((t >> 6) & 1)) * 8, + (((t >> 5) & 1) + ((t >> 6) & 1)) * 8); + via_print("Threshold Prim.: %10s%20s", via_fifo[(t >> 2) & 3], via_fifo[t & 3]); + + pci_read_config_word(dev, VIA_PRI_SECTOR_SIZE, &size0); + pci_read_config_word(dev, VIA_SEC_SECTOR_SIZE, &size1); + via_print("Bytes Per Sector: %10d%20d", size0 & 0xfff, size1 & 0xfff); + + pci_read_config_dword(dev, VIA_BM_BASE, &base); + base = (base & 0xfff0) ; + + c0 = inb((unsigned short)base + 0x02); + c1 = inb((unsigned short)base + 0x0a); + + via_print("Both channels togth: %10s%20s", (c0 & 0x80) ? "no" : "yes", (c1 & 0x80) ? "no" : "yes" ); + + via_print("-------------------drive0----drive1----drive2----drive3-----"); + + via_print("BMDMA enabled: %10s%10s%10s%10s", (c0 & 0x20) ? "yes" : "no", (c0 & 0x40) ? "yes" : "no", + (c1 & 0x20) ? "yes" : "no", (c1 & 0x40) ? "yes" : "no" ); + + pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); + pci_read_config_dword(dev, VIA_DRIVE_TIMING, &v); + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); + + for (i = 0; i < 4; i++) { + setup[i] = ((t >> ((3 - i) << 1) ) & 0x3) + 1; + active[i] = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1; + recover[i] = ((v >> ((3 - i) << 3) ) & 0xf) + 1; + udma[i] = ((u >> ((3 - i) << 3) ) & 0x7) + 2; + umul[i] = ((u >> (((3 - i) & 2) << 3)) & 0x8) ? 2 : 1; + uen[i] = ((u >> ((3 - i) << 3)) & 0x20) ? 1 : 0; + speed[i] = uen[i] ? 20 * pci_clock * umul[i] / udma[i] : + 20 * pci_clock / (active[i] + recover[i]); + cycle[i] = uen[i] ? 1000 / (pci_clock * umul[i]) * udma[i] : + 1000 / pci_clock * (active[i] + recover[i]); + } + + via_print_drive("Transfer Mode: ", "%10s", uen[i] ? "UDMA" : "DMA/PIO"); + via_print_drive("Address Setup: ", "%8dns", (1000 / pci_clock) * setup[i]); + via_print_drive("Active Pulse: ", "%8dns", (1000 / pci_clock) * active[i]); + via_print_drive("Recovery Time: ", "%8dns", (1000 / pci_clock) * recover[i]); + via_print_drive("Cycle Time: ", "%8dns", cycle[i]); + via_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 10, speed[i] % 10); + + return p - buffer; /* hoping it is less than 4K... */ +} + +#endif + +#define FIT(v,min,max) (((v)>(max)?(max):(v))<(min)?(min):(v)) +#define ENOUGH(v,un) (((v)-1)/(un)+1) + +#ifdef DEBUG +#define via_write_config_byte(dev,number,value) do {\ + printk(KERN_DEBUG "VP_IDE: Setting register %#x to %#x\n", number, value);\ + pci_write_config_byte(dev,number,value); } while (0) +#else +#define via_write_config_byte pci_write_config_byte +#endif + +static int via_set_speed(ide_drive_t *drive, byte speed) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + int i, T, err = 0; + unsigned char t, setup, active, recover, cycle; + + if (drive->dn > 3) return -1; + + T = 1000 / system_bus_clock(); + + if (speed > via_isa_bridges[via_config].speed) + speed = via_isa_bridges[via_config].speed; + + for (i = 0; via_timing[i].mode && via_timing[i].mode != speed; i++); + +#ifdef DEBUG + printk(KERN_DEBUG "VP_IDE: Setting drive %d to %s\n", drive->dn, via_timing[i].name); +#endif + + setup = ENOUGH(via_timing[i].setup, T); + active = ENOUGH(via_timing[i].active, T); + recover = ENOUGH(via_timing[i].recover, T); + cycle = ENOUGH(via_timing[i].cycle, T); + + if (active + recover < cycle) { + active += (cycle - (active + recover)) / 2; + recover = cycle - active; + } + +/* + * PIO address setup + */ + + pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); + t = (t & ~(3 << ((3 - drive->dn) << 1))) | (FIT(setup - 1, 0, 3) << ((3 - drive->dn) << 1)); + via_write_config_byte(dev, VIA_ADDRESS_SETUP, t); + +/* + * PIO active & recover + */ + + via_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - drive->dn), + (FIT(active - 1, 0, 0xf) << 4) | FIT(recover - 1, 0, 0xf)); + +/* + * UDMA cycle + */ + + if (via_timing[i].udma) { + t = 0xe8; + if (via_isa_bridges[via_config].speed >= XFER_UDMA_4) + t |= FIT(ENOUGH(via_timing[i].udma, T >> 1) - 2, 0, 7); + else + t |= FIT(ENOUGH(via_timing[i].udma, T ) - 2, 0, 3); + } else t = 0x0b; + + via_write_config_byte(dev, VIA_UDMA_TIMING + (3 - drive->dn), t); + +/* + * Drive init + */ + + if (!drive->init_speed) drive->init_speed = speed; + if ((err = ide_config_drive_speed(drive, speed))) + return err; + drive->current_speed = speed; + + return 0; +} + +static void config_chipset_for_pio(ide_drive_t *drive) +{ + short eide_pio_timing[] = {600, 383, 240, 180, 120, 100}; + signed char pio, ide_pio; + + if (drive->id->eide_pio_iordy > 0) { /* Has timing table */ + for (pio = 5; pio >= 0; pio--) + if (drive->id->eide_pio_iordy <= eide_pio_timing[pio]) + break; + } else { /* No timing table -> use mode capabilities */ + pio = (drive->id->eide_pio_modes & 4) ? 5 : + (drive->id->eide_pio_modes & 2) ? 4 : + (drive->id->eide_pio_modes & 1) ? 3 : + (drive->id->tPIO == 2) ? 2 : + (drive->id->tPIO == 1) ? 1 : 0; + } + + ide_pio = ide_get_best_pio_mode(drive, 255, 5, NULL); + pio = (pio >= ide_pio) ? pio : ide_pio; /* Phew. What about the blacklist? */ + + if (!pio) pio = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; + else pio += XFER_PIO_0; + + /* Fixup because of broken ide-probe.c */ + drive->dn = HWIF(drive)->channel * 2 + (drive->select.b.unit & 1); + + via_set_speed(drive, pio); +} + +static void via82cxxx_tune_drive(ide_drive_t *drive, byte pio) +{ + if (pio == 255) { + config_chipset_for_pio(drive); + return; + } + + if (pio > 5) pio = 5; + + via_set_speed(drive, XFER_PIO_0 + pio); +} + +#ifdef CONFIG_BLK_DEV_IDEDMA + +static int config_chipset_for_dma(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + unsigned char ultra66 = eighty_ninty_three(drive); + unsigned char speed = + + ((id->dma_ultra & 0x0010) && ultra66) ? XFER_UDMA_4 : + ((id->dma_ultra & 0x0008) && ultra66) ? XFER_UDMA_3 : + (id->dma_ultra & 0x0004) ? XFER_UDMA_2 : + (id->dma_ultra & 0x0002) ? XFER_UDMA_1 : + (id->dma_ultra & 0x0001) ? XFER_UDMA_0 : + (id->dma_mword & 0x0004) ? XFER_MW_DMA_2 : + (id->dma_mword & 0x0002) ? XFER_MW_DMA_1 : + (id->dma_mword & 0x0001) ? XFER_MW_DMA_0 : + (id->dma_1word & 0x0004) ? XFER_SW_DMA_2 : + (id->dma_1word & 0x0002) ? XFER_SW_DMA_1 : + (id->dma_1word & 0x0001) ? XFER_SW_DMA_0 : 0; + + if (!speed) return (int) ide_dma_off_quietly; + + via_set_speed(drive, speed); + + return (int) ide_dma_on; +} + +/* + * Almost a library function. + */ + +static int config_drive_xfer_rate(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_dma_action_t dma_func = ide_dma_on; + + if (id && (id->capability & 1) && HWIF(drive)->autodma) { + /* Consult the list of known "bad" drives */ + if (ide_dmaproc(ide_dma_bad_drive, drive)) { + dma_func = ide_dma_off; + goto fast_ata_pio; + } + dma_func = ide_dma_off_quietly; + if (id->field_valid & 4) { + if (id->dma_ultra & 0x002F) { + /* Force if Capable UltraDMA */ + dma_func = config_chipset_for_dma(drive); + if ((id->field_valid & 2) && + (dma_func != ide_dma_on)) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if (id->dma_mword & 0x0007) { + /* Force if Capable regular DMA modes */ + dma_func = config_chipset_for_dma(drive); + if (dma_func != ide_dma_on) + goto no_dma_set; + } + } else if (ide_dmaproc(ide_dma_good_drive, drive)) { + if (id->eide_dma_time > 150) { + goto no_dma_set; + } + /* Consult the list of known "good" drives */ + dma_func = config_chipset_for_dma(drive); + if (dma_func != ide_dma_on) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: + dma_func = ide_dma_off_quietly; +no_dma_set: + config_chipset_for_pio(drive); + } + return HWIF(drive)->dmaproc(dma_func, drive); +} + + +int via82cxxx_dmaproc(ide_dma_action_t func, ide_drive_t *drive) +{ + if (func == ide_dma_check) + return config_drive_xfer_rate(drive); + return ide_dmaproc(func, drive); +} +#endif /* CONFIG_BLK_DEV_IDEDMA */ + +unsigned int __init pci_init_via82cxxx(struct pci_dev *dev, const char *name) +{ + struct pci_dev *isa = NULL; + unsigned char f, t, m; + unsigned int u, i; + +/* + * Find ISA bridge to see how good the IDE is. + */ + + for (via_config = 0; via_isa_bridges[via_config].id; via_config++) + if ((isa = pci_find_device(PCI_VENDOR_ID_VIA, via_isa_bridges[via_config].id, NULL))) + break; +/* + * Read revision. + */ + + if (via_isa_bridges[via_config].id == PCI_DEVICE_ID_VIA_82C586_0) { + pci_read_config_byte(isa, PCI_REVISION_ID, &t); + if (t < 0x30) via_config++; /* vt82c586a */ + if (t < 0x20) via_config++; /* vt82c586 */ + } + +/* + * Check UDMA66 mode set by BIOS. + */ + + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); + + for (i = 0; i < 4; i++) { + pci_read_config_byte(dev, VIA_UDMA_TIMING + (3 - i), &t); + if ((u & (0x80000 >> ((i >> 1) << 4))) && ((t & 7) < 2)) via_ata66 |= (1 << (i >> 1)); + } + +#ifdef DEBUG + printk(KERN_DEBUG "VP_IDE: BIOS enabled ATA66: primary: %s, secondary: %s\n", + via_ata66 & 1 ? "yes" : "no", via_ata66 & 2 ? "yes" : "no"); +#endif + +/* + * Set UDMA66 double clock bits. + */ + + pci_write_config_dword(dev, VIA_UDMA_TIMING, u | 0x80008); + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); + + if ((via_isa_bridges[via_config].id == PCI_DEVICE_ID_VIA_82C596 || !isa) + && (u & 0x80008) != 0x80008) + via_config++; /* vt82c596a / Unknown UDMA33 */ + +/* + * Set up FIFO, flush, prefetch and post-writes. + */ + + pci_read_config_dword(dev, VIA_IDE_ENABLE, &u); + pci_read_config_byte(dev, VIA_FIFO_CONFIG, &f); + pci_read_config_byte(dev, VIA_IDE_CONFIG, &t); + pci_read_config_byte(dev, VIA_MISC_3, &m); + + f &= 0x90; t &= 0x0f; m &= 0x0f; + + switch (u & 3) { + case 2: via_enabled = 1; f |= 0x06; t |= 0xc0; m |= 0xa0; break; /* primary only, 3/4 */ + case 1: via_enabled = 2; f |= 0x69; t |= 0x30; m |= 0x50; break; /* secondary only, 3/4 */ + case 3: via_enabled = 3; + default: f |= 0x2a; t |= 0xf0; m |= 0xf0; break; /* fifo evenly distributed */ + } + + via_write_config_byte(dev, VIA_FIFO_CONFIG, f); + via_write_config_byte(dev, VIA_IDE_CONFIG, t); + via_write_config_byte(dev, VIA_MISC_3, m); + +/* + * Print the boot message. + */ + + printk(KERN_INFO "VP_IDE: VIA %s IDE %s controller on pci%d:%d.%d\n", + via_isa_bridges[via_config].name, + via_isa_bridges[via_config].speed >= XFER_UDMA_4 ? "UDMA66" : + via_isa_bridges[via_config].speed >= XFER_UDMA_2 ? "UDMA33" : "MWDMA16", + dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); +/* + * Register /proc/ide/via entry + */ + +#if defined(CONFIG_PROC_FS) + if (!via_proc) { + via_proc = 1; + bmide_dev = dev; + isa_dev = isa; + via_display_info = &via_get_info; + } +#endif + + return 0; +} + +/* + * Since we don't have a way to detect the 80-wire ribbon cable + * we rely on the BIOS detection. We also check the IDENTIFY byte + * 93 to check the drive's point of view. I think we could return + * '1' here + */ + +unsigned int __init ata66_via82cxxx(ide_hwif_t *hwif) +{ + return ((via_enabled && via_ata66) >> hwif->channel) & 1; +} + +void __init ide_init_via82cxxx(ide_hwif_t *hwif) +{ + hwif->tuneproc = &via82cxxx_tune_drive; + hwif->speedproc = &via_set_speed; + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + hwif->autodma = 0; + +#ifdef CONFIG_BLK_DEV_IDEDMA + if (hwif->dma_base) { + hwif->dmaproc = &via82cxxx_dmaproc; + hwif->autodma = 1; + } +#endif /* CONFIG_BLK_DEV_IDEDMA */ +} + +/* + * We allow the BM-DMA driver only work on enabled interfaces. + */ + +void ide_dmacapable_via82cxxx(ide_hwif_t *hwif, unsigned long dmabase) +{ + if ((via_enabled >> hwif->channel) & 1) + ide_setup_dma(hwif, dmabase, 8); +} diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c index 6b67fbc81..fd216af2d 100644 --- a/drivers/media/video/cpia_usb.c +++ b/drivers/media/video/cpia_usb.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -594,14 +595,14 @@ static void cpia_disconnect(struct usb_device *udev, void *ptr) kfree(ucpia); } -int usb_cpia_init(void) +static int __init usb_cpia_init(void) { cam_list = NULL; return usb_register(&cpia_driver); } -void usb_cpia_cleanup(void) +static void __exit usb_cpia_cleanup(void) { /* struct cam_data *cam; @@ -613,14 +614,7 @@ void usb_cpia_cleanup(void) usb_deregister(&cpia_driver); } -#ifdef MODULE -int init_module(void) -{ - return usb_cpia_init(); -} -void cleanup_module(void) -{ - usb_cpia_cleanup(); -} -#endif /* !MODULE */ +module_init (usb_cpia_init); +module_exit (usb_cpia_cleanup); + diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index 3dc9b42f0..3aa8cc8f8 100644 --- a/drivers/net/3c503.c +++ b/drivers/net/3c503.c @@ -190,6 +190,9 @@ el2_probe1(struct net_device *dev, int ioaddr) if (dev == NULL) { printk("3c503.c: Passed a NULL device.\n"); dev = init_etherdev(0, 0); + + if (!dev) + return -ENOMEM; } if (ei_debug && version_printed++ == 0) diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c index 5551311f3..8399af8c9 100644 --- a/drivers/net/ac3200.c +++ b/drivers/net/ac3200.c @@ -139,6 +139,9 @@ static int __init ac_probe1(int ioaddr, struct net_device *dev) if (dev == NULL) { printk("ac3200.c: Passed a NULL device.\n"); dev = init_etherdev(0, 0); + + if (!dev) + return -ENOMEM; } printk("AC3200 in EISA slot %d, node", ioaddr/0x1000); diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index 14646b686..37e4ba907 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -194,6 +194,7 @@ * Mar 2000 AC Did various cleanups for 2.3.x * Jun 2000 jgarzik PCI and resource alloc cleanups * Jul 2000 tjeerd Much cleanup and some bug fixes + * Sep 2000 tjeerd Fix leak on unload, cosmetic code cleanup */ /* Include files */ @@ -224,7 +225,7 @@ /* Version information string - should be updated prior to each new release!!! */ static char version[] __devinitdata = - "defxx.c:v1.05c 2000/07/14 Lawrence V. Stefani and others\n"; + "defxx.c:v1.05d 2000/09/05 Lawrence V. Stefani and others\n"; #define DYNAMIC_BUFFERS 1 @@ -891,7 +892,7 @@ static int __devinit dfx_driver_init(struct net_device *dev) #endif sizeof(PI_CONSUMER_BLOCK) + (PI_ALIGN_K_DESC_BLK - 1); - top_v = (char *) kmalloc(alloc_size, GFP_KERNEL); + bp->kmalloced = top_v = (char *) kmalloc(alloc_size, GFP_KERNEL); if (top_v == NULL) { printk("%s: Could not allocate memory for host buffers and structures!\n", dev->name); @@ -957,7 +958,7 @@ static int __devinit dfx_driver_init(struct net_device *dev) DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n", dev->name, (long)bp->cmd_req_virt, bp->cmd_req_phys); DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n", dev->name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys); DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n", dev->name, (long)bp->rcv_block_virt, bp->rcv_block_phys); - DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n", dev->name, (long)bp->cons_block_virt, bp->cons_block_phys); + DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n", dev->name, (long)bp->cons_block_virt, bp->cons_block_phys); return(DFX_K_SUCCESS); } @@ -3259,10 +3260,13 @@ static void dfx_xmt_flush( DFX_board_t *bp ) return; } -static void __devexit dfx_remove_device(struct pci_dev *pdev, struct net_device *dev) +static void __devexit dfx_remove_one_pci_or_eisa(struct pci_dev *pdev, struct net_device *dev) { + DFX_board_t *bp = (DFX_board_t*)dev->priv; + unregister_netdev(dev); release_region(dev->base_addr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN ); + if (bp->kmalloced) kfree(bp->kmalloced); kfree(dev); } @@ -3270,7 +3274,7 @@ static void __devexit dfx_remove_one (struct pci_dev *pdev) { struct net_device *dev = pdev->driver_data; - dfx_remove_device(pdev, dev); + dfx_remove_one_pci_or_eisa(pdev, dev); } static struct pci_device_id dfx_pci_tbl[] __devinitdata = { @@ -3301,7 +3305,7 @@ static void __exit dfx_eisa_cleanup(void) bp = (DFX_board_t*)dev->priv; tmp = bp->next; - dfx_remove_device(NULL, dev); + dfx_remove_one_pci_or_eisa(NULL, dev); dev = tmp; } } diff --git a/drivers/net/defxx.h b/drivers/net/defxx.h index 223ad7d5d..10e159c92 100644 --- a/drivers/net/defxx.h +++ b/drivers/net/defxx.h @@ -1469,9 +1469,9 @@ typedef union /* Define EISA controller register offsets */ -#define PI_ESIC_K_BURST_HOLDOFF 0x040 +#define PI_ESIC_K_BURST_HOLDOFF 0x040 #define PI_ESIC_K_SLOT_ID 0xC80 -#define PI_ESIC_K_SLOT_CNTRL 0xC84 +#define PI_ESIC_K_SLOT_CNTRL 0xC84 #define PI_ESIC_K_MEM_ADD_CMP_0 0xC85 #define PI_ESIC_K_MEM_ADD_CMP_1 0xC86 #define PI_ESIC_K_MEM_ADD_CMP_2 0xC87 @@ -1484,14 +1484,14 @@ typedef union #define PI_ESIC_K_MEM_ADD_LO_CMP_0 0xC8E #define PI_ESIC_K_MEM_ADD_LO_CMP_1 0xC8F #define PI_ESIC_K_MEM_ADD_LO_CMP_2 0xC90 -#define PI_ESIC_K_IO_CMP_0_0 0xC91 -#define PI_ESIC_K_IO_CMP_0_1 0xC92 -#define PI_ESIC_K_IO_CMP_1_0 0xC93 -#define PI_ESIC_K_IO_CMP_1_1 0xC94 -#define PI_ESIC_K_IO_CMP_2_0 0xC95 -#define PI_ESIC_K_IO_CMP_2_1 0xC96 -#define PI_ESIC_K_IO_CMP_3_0 0xC97 -#define PI_ESIC_K_IO_CMP_3_1 0xC98 +#define PI_ESIC_K_IO_CMP_0_0 0xC91 +#define PI_ESIC_K_IO_CMP_0_1 0xC92 +#define PI_ESIC_K_IO_CMP_1_0 0xC93 +#define PI_ESIC_K_IO_CMP_1_1 0xC94 +#define PI_ESIC_K_IO_CMP_2_0 0xC95 +#define PI_ESIC_K_IO_CMP_2_1 0xC96 +#define PI_ESIC_K_IO_CMP_3_0 0xC97 +#define PI_ESIC_K_IO_CMP_3_1 0xC98 #define PI_ESIC_K_IO_ADD_MASK_0_0 0xC99 #define PI_ESIC_K_IO_ADD_MASK_0_1 0xC9A #define PI_ESIC_K_IO_ADD_MASK_1_0 0xC9B @@ -1500,21 +1500,21 @@ typedef union #define PI_ESIC_K_IO_ADD_MASK_2_1 0xC9E #define PI_ESIC_K_IO_ADD_MASK_3_0 0xC9F #define PI_ESIC_K_IO_ADD_MASK_3_1 0xCA0 -#define PI_ESIC_K_MOD_CONFIG_1 0xCA1 -#define PI_ESIC_K_MOD_CONFIG_2 0xCA2 -#define PI_ESIC_K_MOD_CONFIG_3 0xCA3 -#define PI_ESIC_K_MOD_CONFIG_4 0xCA4 -#define PI_ESIC_K_MOD_CONFIG_5 0xCA5 -#define PI_ESIC_K_MOD_CONFIG_6 0xCA6 -#define PI_ESIC_K_MOD_CONFIG_7 0xCA7 +#define PI_ESIC_K_MOD_CONFIG_1 0xCA1 +#define PI_ESIC_K_MOD_CONFIG_2 0xCA2 +#define PI_ESIC_K_MOD_CONFIG_3 0xCA3 +#define PI_ESIC_K_MOD_CONFIG_4 0xCA4 +#define PI_ESIC_K_MOD_CONFIG_5 0xCA5 +#define PI_ESIC_K_MOD_CONFIG_6 0xCA6 +#define PI_ESIC_K_MOD_CONFIG_7 0xCA7 #define PI_ESIC_K_DIP_SWITCH 0xCA8 #define PI_ESIC_K_IO_CONFIG_STAT_0 0xCA9 #define PI_ESIC_K_IO_CONFIG_STAT_1 0xCAA #define PI_ESIC_K_DMA_CONFIG 0xCAB #define PI_ESIC_K_INPUT_PORT 0xCAC #define PI_ESIC_K_OUTPUT_PORT 0xCAD -#define PI_ESIC_K_FUNCTION_CNTRL 0xCAE -#define PI_ESIC_K_CSR_IO_LEN PI_ESIC_K_FUNCTION_CNTRL+1 /* always last reg + 1 */ +#define PI_ESIC_K_FUNCTION_CNTRL 0xCAE +#define PI_ESIC_K_CSR_IO_LEN PI_ESIC_K_FUNCTION_CNTRL+1 /* always last reg + 1 */ /* Define the value all drivers must write to the function control register. */ @@ -1524,7 +1524,7 @@ typedef union #define PI_SLOT_CNTRL_M_RESET 0x04 /* Don't use. */ #define PI_SLOT_CNTRL_M_ERROR 0x02 /* Not implemented. */ -#define PI_SLOT_CNTRL_M_ENB 0x01 /* Must be set. */ +#define PI_SLOT_CNTRL_M_ENB 0x01 /* Must be set. */ /* Define the bits in the burst holdoff register. */ @@ -1590,24 +1590,24 @@ typedef union #define PFI_K_REG_RESERVED_0 0X00000038 #define PFI_K_REG_RESERVED_1 0X0000003C -#define PFI_K_REG_MODE_CTRL 0X00000040 -#define PFI_K_REG_STATUS 0X00000044 +#define PFI_K_REG_MODE_CTRL 0X00000040 +#define PFI_K_REG_STATUS 0X00000044 #define PFI_K_REG_FIFO_WRITE 0X00000048 -#define PFI_K_REG_FIFO_READ 0X0000004C +#define PFI_K_REG_FIFO_READ 0X0000004C /* PFI Mode Control Register Constants */ -#define PFI_MODE_M_RESERVED 0XFFFFFFF0 +#define PFI_MODE_M_RESERVED 0XFFFFFFF0 #define PFI_MODE_M_TGT_ABORT_ENB 0X00000008 #define PFI_MODE_M_PDQ_INT_ENB 0X00000004 #define PFI_MODE_M_PFI_INT_ENB 0X00000002 -#define PFI_MODE_M_DMA_ENB 0X00000001 +#define PFI_MODE_M_DMA_ENB 0X00000001 -#define PFI_MODE_V_RESERVED 4 +#define PFI_MODE_V_RESERVED 4 #define PFI_MODE_V_TGT_ABORT_ENB 3 #define PFI_MODE_V_PDQ_INT_ENB 2 #define PFI_MODE_V_PFI_INT_ENB 1 -#define PFI_MODE_V_DMA_ENB 0 +#define PFI_MODE_V_DMA_ENB 0 #define PFI_MODE_K_ALL_DISABLE 0X00000000 @@ -1619,10 +1619,10 @@ typedef union #define PFI_STATUS_M_PDQ_DMA_ABORT 0X00000008 #define PFI_STATUS_M_FIFO_FULL 0X00000004 #define PFI_STATUS_M_FIFO_EMPTY 0X00000002 -#define PFI_STATUS_M_DMA_IN_PROGRESS 0X00000001 +#define PFI_STATUS_M_DMA_IN_PROGRESS 0X00000001 #define PFI_STATUS_V_RESERVED 6 -#define PFI_STATUS_V_PFI_ERROR 5 /* only valid in rev 1 or later PFI */ +#define PFI_STATUS_V_PFI_ERROR 5 /* only valid in rev 1 or later PFI */ #define PFI_STATUS_V_PDQ_INT 4 #define PFI_STATUS_V_PDQ_DMA_ABORT 3 #define PFI_STATUS_V_FIFO_FULL 2 @@ -1635,7 +1635,7 @@ typedef union #define DFX_BUS_TYPE_PCI 0 /* type code for DEC FDDIcontroller/PCI */ #define DFX_BUS_TYPE_EISA 1 /* type code for DEC FDDIcontroller/EISA */ -#define DFX_FC_PRH2_PRH1_PRH0 0x54003820 /* Packet Request Header bytes + FC */ +#define DFX_FC_PRH2_PRH1_PRH0 0x54003820 /* Packet Request Header bytes + FC */ #define DFX_PRH0_BYTE 0x20 /* Packet Request Header byte 0 */ #define DFX_PRH1_BYTE 0x38 /* Packet Request Header byte 1 */ #define DFX_PRH2_BYTE 0x00 /* Packet Request Header byte 2 */ @@ -1691,7 +1691,7 @@ typedef union /* Define constants for masking/unmasking interrupts */ #define DFX_MASK_INTERRUPTS 1 -#define DFX_UNMASK_INTERRUPTS 0 +#define DFX_UNMASK_INTERRUPTS 0 /* Define structure for driver transmit descriptor block */ @@ -1704,16 +1704,17 @@ typedef struct DFX_board_tag { /* Keep virtual and physical pointers to locked, physically contiguous memory */ + char *kmalloced; /* kfree this on unload */ PI_DESCR_BLOCK *descr_block_virt; /* PDQ descriptor block virt address */ - u32 descr_block_phys; /* PDQ descriptor block phys address */ + u32 descr_block_phys; /* PDQ descriptor block phys address */ PI_DMA_CMD_REQ *cmd_req_virt; /* Command request buffer virt address */ - u32 cmd_req_phys; /* Command request buffer phys address */ + u32 cmd_req_phys; /* Command request buffer phys address */ PI_DMA_CMD_RSP *cmd_rsp_virt; /* Command response buffer virt address */ - u32 cmd_rsp_phys; /* Command response buffer phys address */ - char *rcv_block_virt; /* LLC host receive queue buf blk virt */ - u32 rcv_block_phys; /* LLC host receive queue buf blk phys */ + u32 cmd_rsp_phys; /* Command response buffer phys address */ + char *rcv_block_virt; /* LLC host receive queue buf blk virt */ + u32 rcv_block_phys; /* LLC host receive queue buf blk phys */ PI_CONSUMER_BLOCK *cons_block_virt; /* PDQ consumer block virt address */ - u32 cons_block_phys; /* PDQ consumer block phys address */ + u32 cons_block_phys; /* PDQ consumer block phys address */ /* Keep local copies of Type 1 and Type 2 register data */ @@ -1723,27 +1724,27 @@ typedef struct DFX_board_tag /* Storage for unicast and multicast address entries in adapter CAM */ - u8 uc_table[1*FDDI_K_ALEN]; - u32 uc_count; /* number of unicast addresses */ - u8 mc_table[PI_CMD_ADDR_FILTER_K_SIZE*FDDI_K_ALEN]; - u32 mc_count; /* number of multicast addresses */ + u8 uc_table[1*FDDI_K_ALEN]; + u32 uc_count; /* number of unicast addresses */ + u8 mc_table[PI_CMD_ADDR_FILTER_K_SIZE*FDDI_K_ALEN]; + u32 mc_count; /* number of multicast addresses */ /* Current packet filter settings */ - u32 ind_group_prom; /* LLC individual & group frame prom mode */ - u32 group_prom; /* LLC group (multicast) frame prom mode */ + u32 ind_group_prom; /* LLC individual & group frame prom mode */ + u32 group_prom; /* LLC group (multicast) frame prom mode */ /* Link available flag needed to determine whether to drop outgoing packet requests */ - u32 link_available; /* is link available? */ + u32 link_available; /* is link available? */ /* Resources to indicate reset type when resetting adapter */ - u32 reset_type; /* skip or rerun diagnostics */ + u32 reset_type; /* skip or rerun diagnostics */ /* Store pointers to receive buffers for queue processing code */ - char *p_rcv_buff_va[PI_RCV_DATA_K_NUM_ENTRIES]; + char *p_rcv_buff_va[PI_RCV_DATA_K_NUM_ENTRIES]; /* Store pointers to transmit buffers for transmit completion code */ @@ -1755,33 +1756,33 @@ typedef struct DFX_board_tag /* Store device, bus-specific, and parameter information for this adapter */ - struct net_device *dev; /* pointer to device structure */ - struct net_device *next; - u32 bus_type; /* bus type (0 == PCI, 1 == EISA) */ - u16 base_addr; /* base I/O address (same as dev->base_addr) */ - struct pci_dev * pci_dev; - u32 full_duplex_enb; /* FDDI Full Duplex enable (1 == on, 2 == off) */ - u32 req_ttrt; /* requested TTRT value (in 80ns units) */ - u32 burst_size; /* adapter burst size (enumerated) */ - u32 rcv_bufs_to_post; /* receive buffers to post for LLC host queue */ - u8 factory_mac_addr[FDDI_K_ALEN]; /* factory (on-board) MAC address */ + struct net_device *dev; /* pointer to device structure */ + struct net_device *next; + u32 bus_type; /* bus type (0 == PCI, 1 == EISA) */ + u16 base_addr; /* base I/O address (same as dev->base_addr) */ + struct pci_dev * pci_dev; + u32 full_duplex_enb; /* FDDI Full Duplex enable (1 == on, 2 == off) */ + u32 req_ttrt; /* requested TTRT value (in 80ns units) */ + u32 burst_size; /* adapter burst size (enumerated) */ + u32 rcv_bufs_to_post; /* receive buffers to post for LLC host queue */ + u8 factory_mac_addr[FDDI_K_ALEN]; /* factory (on-board) MAC address */ /* Common FDDI statistics structure and private counters */ struct fddi_statistics stats; - u32 rcv_discards; - u32 rcv_crc_errors; - u32 rcv_frame_status_errors; - u32 rcv_length_errors; - u32 rcv_total_frames; - u32 rcv_multicast_frames; - u32 rcv_total_bytes; - - u32 xmt_discards; - u32 xmt_length_errors; - u32 xmt_total_frames; - u32 xmt_total_bytes; + u32 rcv_discards; + u32 rcv_crc_errors; + u32 rcv_frame_status_errors; + u32 rcv_length_errors; + u32 rcv_total_frames; + u32 rcv_multicast_frames; + u32 rcv_total_bytes; + + u32 xmt_discards; + u32 xmt_length_errors; + u32 xmt_total_frames; + u32 xmt_total_bytes; } DFX_board_t; #endif /* #ifndef _DEFXX_H_ */ diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 565ddc52b..e02298ded 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -17,6 +17,14 @@ Support information and updates available at http://www.scyld.com/network/netsemi.html + + + Linux kernel modifications: + + Version 1.0.1: + - Spinlock fixes + - Bug fixes and better intr performance (Tjeerd) + */ /* These identify the driver base version and may not be removed. */ @@ -25,7 +33,7 @@ static const char version1[] = static const char version2[] = " http://www.scyld.com/network/natsemi.html\n"; static const char version3[] = -" (unofficial 2.4.x kernel port, version 1.0.0, August 10, 2000)\n"; +" (unofficial 2.4.x kernel port, version 1.0.1, September 5, 2000 Jeff Garzik, Tjeerd Mulder)\n"; /* Updated to recommendations in pci-skeleton v2.03. */ /* Automatically extracted configuration info: @@ -193,7 +201,8 @@ IVb. References http://www.scyld.com/expert/100mbps.html http://www.scyld.com/expert/NWay.html -No NatSemi datasheet was publically available at the initial release date. +Datasheet is available from: +http://www.national.com/pf/DP/DP83815.html IVc. Errata @@ -237,7 +246,7 @@ enum register_offsets { ChipCmd=0x00, ChipConfig=0x04, EECtrl=0x08, PCIBusCfg=0x0C, IntrStatus=0x10, IntrMask=0x14, IntrEnable=0x18, TxRingPtr=0x20, TxConfig=0x24, - RxRingPtr=0x30, RxConfig=0x34, + RxRingPtr=0x30, RxConfig=0x34, ClkRun=0x3C, WOLCmd=0x40, PauseCmd=0x44, RxFilterAddr=0x48, RxFilterData=0x4C, BootRomAddr=0x50, BootRomData=0x54, StatsCtrl=0x5C, StatsData=0x60, RxPktErrs=0x60, RxMissed=0x68, RxCRCErrs=0x64, @@ -259,15 +268,19 @@ enum intr_status_bits { WOLPkt=0x2000, RxResetDone=0x1000000, TxResetDone=0x2000000, IntrPCIErr=0x00f00000, - IntrNormalSummary=0x0251, IntrAbnormalSummary=0xCD20, + IntrAbnormalSummary=0xCD20, }; /* Bits in the RxMode register. */ enum rx_mode_bits { - AcceptErr=0x20, AcceptRunt=0x10, - AcceptBroadcast=0xC0000000, - AcceptMulticast=0x00200000, AcceptAllMulticast=0x20000000, - AcceptAllPhys=0x10000000, AcceptMyPhys=0x08000000, + EnableFilter = 0x80000000, + AcceptBroadcast = 0x40000000, + AcceptAllMulticast = 0x20000000, + AcceptAllPhys = 0x10000000, + AcceptMyPhys = 0x08000000, + AcceptMulticast = 0x00200000, + AcceptErr=0x20, /* these 2 are in another register */ + AcceptRunt=0x10,/* and are not used in this driver */ }; /* The Rx and Tx buffer descriptors. */ @@ -315,6 +328,8 @@ struct netdev_private { u32 rx_filter[16]; /* FIFO and PCI burst thresholds. */ int tx_config, rx_config; + /* original contents of ClkRun register */ + int SavedClkRun; /* MII transceiver section. */ u16 advertising; /* NWay media advertisement */ @@ -349,7 +364,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, int i, option, irq = pdev->irq, chip_idx = ent->driver_data; static int find_cnt = -1; static int printed_version; - unsigned long ioaddr; + unsigned long ioaddr, iosize; const int pcibar = 1; /* PCI base address register */ if ((debug <= 1) && !printed_version++) @@ -359,6 +374,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, find_cnt++; option = find_cnt < MAX_UNITS ? options[find_cnt] : 0; ioaddr = pci_resource_start(pdev, pcibar); + iosize = pci_resource_len(pdev, pcibar); if (pci_enable_device(pdev)) return -EIO; @@ -371,15 +387,14 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, { void *mmio; - if (request_mem_region(ioaddr, pci_resource_len (pdev, pcibar), - dev->name) == NULL) { + if (request_mem_region(ioaddr, iosize, dev->name) == NULL) { unregister_netdev(dev); kfree(dev); return -EBUSY; } - mmio = ioremap (ioaddr, pci_resource_len (pdev, pcibar)); + mmio = ioremap (ioaddr, iosize); if (!mmio) { - release_mem_region(ioaddr, pci_resource_len (pdev, pcibar)); + release_mem_region(ioaddr, iosize); unregister_netdev(dev); kfree(dev); return -ENOMEM; @@ -390,9 +405,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, printk(KERN_INFO "%s: %s at 0x%lx, ", dev->name, natsemi_pci_info[chip_idx].name, ioaddr); - for (i = 0; i < 3; i++) + for (i = 0; i < ETH_ALEN/2; i++) ((u16 *)dev->dev_addr)[i] = be16_to_cpu(eeprom_read(ioaddr, i + 7)); - for (i = 0; i < 5; i++) + for (i = 0; i < ETH_ALEN-1; i++) printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq); @@ -413,7 +428,8 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, np->pci_dev = pdev; pdev->driver_data = dev; - np->iosize = pci_resource_len(pdev, pcibar); + np->iosize = iosize; + spin_lock_init(&np->lock); if (dev->mem_start) option = dev->mem_start; @@ -551,7 +567,7 @@ static int netdev_open(struct net_device *dev) writel(virt_to_bus(np->rx_ring), ioaddr + RxRingPtr); writel(virt_to_bus(np->tx_ring), ioaddr + TxRingPtr); - for (i = 0; i < 6; i += 2) { + for (i = 0; i < ETH_ALEN; i += 2) { writel(i, ioaddr + RxFilterAddr); writew(dev->dev_addr[i] + (dev->dev_addr[i+1] << 8), ioaddr + RxFilterData); @@ -560,21 +576,32 @@ static int netdev_open(struct net_device *dev) /* Initialize other registers. */ /* Configure the PCI bus bursts and FIFO thresholds. */ /* Configure for standard, in-spec Ethernet. */ - np->tx_config = 0x10800802; + np->tx_config = (1<<28) + /* Automatic transmit padding */ + (1<<23) + /* Excessive collision retry */ + (0x0<<20) + /* Max DMA burst = 512 byte */ + (8<<8) + /* fill threshold = 256 byte */ + 2; /* drain threshold = 64 byte */ writel(np->tx_config, ioaddr + TxConfig); - np->rx_config = 0x0020; + np->rx_config = (0x0<<20) /* Max DMA burst = 512 byte */ + + (0x8<<1); /* Drain Threshold = 64 byte */ writel(np->rx_config, ioaddr + RxConfig); if (dev->if_port == 0) dev->if_port = np->default_port; + /* Disable PME */ + np->SavedClkRun = readl(ioaddr + ClkRun); + writel(np->SavedClkRun & ~0x100, ioaddr + ClkRun); + netif_start_queue(dev); check_duplex(dev); set_rx_mode(dev); - /* Enable interrupts by setting the interrupt mask. */ - writel(IntrNormalSummary | IntrAbnormalSummary | 0x1f, ioaddr + IntrMask); + /* Enable interrupts by setting the interrupt mask. + * We don't listen for TxDone interrupts and rely on TxIdle. */ + writel(IntrAbnormalSummary | IntrTxIdle | IntrRxIdle | IntrRxDone, + ioaddr + IntrMask); writel(1, ioaddr + IntrEnable); writel(RxOn | TxOn, ioaddr + ChipCmd); @@ -616,8 +643,8 @@ static void check_duplex(struct net_device *dev) np->rx_config &= ~0x10000000; np->tx_config &= ~0xC0000000; } - writew(np->tx_config, ioaddr + TxConfig); - writew(np->rx_config, ioaddr + RxConfig); + writel(np->tx_config, ioaddr + TxConfig); + writel(np->rx_config, ioaddr + RxConfig); } } @@ -700,7 +727,7 @@ static void init_ring(struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ np->rx_ring[i].addr = virt_to_le32desc(skb->tail); np->rx_ring[i].cmd_status = - cpu_to_le32(DescIntr | np->rx_buf_sz); + cpu_to_le32(np->rx_buf_sz); } np->dirty_rx = (unsigned int)(i - RX_RING_SIZE); @@ -727,7 +754,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) np->tx_skbuff[entry] = skb; np->tx_ring[entry].addr = virt_to_le32desc(skb->data); - np->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn|DescIntr | skb->len); + np->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn | skb->len); np->cur_tx++; /* StrongARM: Explicitly cache flush np->tx_ring and skb->data,skb->len. */ @@ -768,8 +795,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) ioaddr = dev->base_addr; np = (struct netdev_private *)dev->priv; - if (!spin_trylock(&np->lock)) - return; + spin_lock(&np->lock); do { u32 intr_status = readl(ioaddr + IntrStatus); @@ -784,7 +810,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) if (intr_status == 0) break; - if (intr_status & (IntrRxDone | IntrRxIntr)) + if (intr_status & (IntrRxDone | IntrRxErr | IntrRxIdle | IntrRxOverrun)) netdev_rx(dev); for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) { @@ -805,7 +831,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) np->stats.tx_errors++; } /* Free the original skb. */ - dev_kfree_skb(np->tx_skbuff[entry]); + dev_kfree_skb_irq(np->tx_skbuff[entry]); np->tx_skbuff[entry] = 0; } if (np->tx_full @@ -862,6 +888,7 @@ static int netdev_rx(struct net_device *dev) entry, desc_status); if (--boguscnt < 0) break; + if ((desc_status & (DescMore|DescPktOK|RxTooLong)) != DescPktOK) { if (desc_status & DescMore) { printk(KERN_WARNING "%s: Oversized(?) Ethernet frame spanned " @@ -947,7 +974,7 @@ static int netdev_rx(struct net_device *dev) np->rx_ring[entry].addr = virt_to_le32desc(skb->tail); } np->rx_ring[entry].cmd_status = - cpu_to_le32(DescIntr | np->rx_buf_sz); + cpu_to_le32(np->rx_buf_sz); } /* Restart Rx engine if stopped. */ @@ -1045,13 +1072,13 @@ static void set_rx_mode(struct net_device *dev) set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff, mc_filter); } - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; for (i = 0; i < 32; i++) { writew(0x200 + (i<<1), ioaddr + RxFilterAddr); writew(cpu_to_be16(mc_filter[i]), ioaddr + RxFilterData); } + rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; } - writel(rx_mode, ioaddr + RxFilterAddr); + writel(rx_mode | EnableFilter, ioaddr + RxFilterAddr); np->cur_rx_mode = rx_mode; } @@ -1138,7 +1165,8 @@ static int netdev_close(struct net_device *dev) dev_kfree_skb(np->tx_skbuff[i]); np->tx_skbuff[i] = 0; } - + /* Restore PME enable bit */ + writel(np->SavedClkRun, ioaddr + ClkRun); #if 0 writel(0x0200, ioaddr + ChipConfig); /* Power down Xcvr. */ #endif @@ -1153,9 +1181,10 @@ static void __devexit natsemi_remove1 (struct pci_dev *pdev) { struct net_device *dev = pdev->driver_data; struct netdev_private *np = (struct netdev_private *)dev->priv; + const int pcibar = 1; /* PCI base address register */ unregister_netdev (dev); - release_mem_region(dev->base_addr, np->iosize); + release_mem_region(pci_resource_start(pdev, pcibar), np->iosize); iounmap ((char *) dev->base_addr); kfree (dev); } diff --git a/drivers/net/ncr885e.c b/drivers/net/ncr885e.c index 2500cb282..e9f724288 100644 --- a/drivers/net/ncr885e.c +++ b/drivers/net/ncr885e.c @@ -1367,13 +1367,7 @@ write_mii( unsigned long ioaddr, int reg, int data ) #endif /* NCR885E_DEBUG_MII */ -int -init_module(void) -{ - return ncr885e_probe(); -} - -static void __exit cleanup_module(void) +static void __exit ncr885e_cleanup(void) { if ( root_dev ) { unregister_netdev( root_dev ); diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 0216ed2b3..7def8a493 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -50,7 +50,6 @@ #include #include -#include #include #include #include diff --git a/drivers/scsi/scsi_dma.c b/drivers/scsi/scsi_dma.c index ccb366593..3de835130 100644 --- a/drivers/scsi/scsi_dma.c +++ b/drivers/scsi/scsi_dma.c @@ -260,6 +260,7 @@ void scsi_resize_dma_pool(void) new_dma_sectors += (2048 >> 9) * SDpnt->queue_depth; } else if (SDpnt->type == TYPE_SCANNER || SDpnt->type == TYPE_PROCESSOR || + SDpnt->type == TYPE_COMM || SDpnt->type == TYPE_MEDIUM_CHANGER || SDpnt->type == TYPE_ENCLOSURE) { new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth; diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 4bbfd56bf..620902bfc 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -578,6 +578,7 @@ static int scan_scsis_single(int channel, int dev, int lun, int *max_dev_lun, case TYPE_SCANNER: case TYPE_MEDIUM_CHANGER: case TYPE_ENCLOSURE: + case TYPE_COMM: SDpnt->writeable = 1; break; case TYPE_WORM: diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 263fcd09e..295066797 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -957,17 +957,23 @@ static int sd_init_onedisk(int i) /* FLOPTICAL */ /* - * for removable scsi disk ( FLOPTICAL ) we have to recognise - * the Write Protect Flag. This flag is kept in the Scsi_Disk struct - * and tested at open ! + * For removable scsi disk ( FLOPTICAL ) we have to recognise + * the Write Protect Flag. This flag is kept in the Scsi_Disk + * struct and tested at open ! * Daniel Roche ( dan@lectra.fr ) + * + * Changed to get all pages (0x3f) rather than page 1 to + * get around devices which do not have a page 1. Since + * we're only interested in the header anyway, this should + * be fine. + * -- Matthew Dharm (mdharm-scsi@one-eyed-alien.net) */ memset((void *) &cmd[0], 0, 8); cmd[0] = MODE_SENSE; cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0; - cmd[2] = 1; /* page code 1 ?? */ - cmd[4] = 12; + cmd[2] = 0x3f; /* Get all pages */ + cmd[4] = 8; /* But we only want the 8 byte header */ SRpnt->sr_cmd_len = 0; SRpnt->sr_sense_buffer[0] = 0; SRpnt->sr_sense_buffer[2] = 0; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index c5680bca3..b18a96bf4 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -28,6 +28,9 @@ * Modified by Jens Axboe - support DVD-RAM * transparently and loose the GHOST hack * + * Modified by Arnaldo Carvalho de Melo + * check resource allocation in sr_init and some cleanups + * */ #include @@ -82,11 +85,11 @@ struct Scsi_Device_Template sr_template = init_command:sr_init_command }; -Scsi_CD *scsi_CDs = NULL; -static int *sr_sizes = NULL; +Scsi_CD *scsi_CDs; +static int *sr_sizes; -static int *sr_blocksizes = NULL; -static int *sr_hardsizes = NULL; +static int *sr_blocksizes; +static int *sr_hardsizes; static int sr_open(struct cdrom_device_info *, int); void get_sectorsize(int); @@ -710,30 +713,45 @@ static int sr_init() } if (scsi_CDs) return 0; - sr_template.dev_max = - sr_template.dev_noticed + SR_EXTRA_DEVS; - scsi_CDs = (Scsi_CD *) kmalloc(sr_template.dev_max * sizeof(Scsi_CD), GFP_ATOMIC); + + 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; memset(scsi_CDs, 0, sr_template.dev_max * sizeof(Scsi_CD)); - sr_sizes = (int *) kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC); + sr_sizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC); + if (!sr_sizes) + goto cleanup_cds; memset(sr_sizes, 0, sr_template.dev_max * sizeof(int)); - sr_blocksizes = (int *) kmalloc(sr_template.dev_max * - sizeof(int), GFP_ATOMIC); + sr_blocksizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC); + if (!sr_blocksizes) + goto cleanup_sizes; - sr_hardsizes = (int *) kmalloc(sr_template.dev_max * - sizeof(int), GFP_ATOMIC); + sr_hardsizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC); + if (!sr_hardsizes) + goto cleanup_blocksizes; /* * These are good guesses for the time being. */ - for (i = 0; i < sr_template.dev_max; i++) - { + for (i = 0; i < sr_template.dev_max; i++) { sr_blocksizes[i] = 2048; sr_hardsizes[i] = 2048; } blksize_size[MAJOR_NR] = sr_blocksizes; hardsect_size[MAJOR_NR] = sr_hardsizes; return 0; +cleanup_blocksizes: + kfree(sr_blocksizes); +cleanup_sizes: + kfree(sr_sizes); +cleanup_cds: + kfree(scsi_CDs); +cleanup_devfs: + devfs_unregister_blkdev(MAJOR_NR, "sr"); + sr_registered--; + return 1; } void sr_finish() @@ -830,29 +848,26 @@ static void sr_detach(Scsi_Device * SDp) return; } - -#ifdef MODULE - -int init_module(void) +int init_sr(void) { - sr_template.module = &__this_module; + sr_template.module = THIS_MODULE; return scsi_register_module(MODULE_SCSI_DEV, &sr_template); } -void cleanup_module(void) +void exit_sr(void) { scsi_unregister_module(MODULE_SCSI_DEV, &sr_template); devfs_unregister_blkdev(MAJOR_NR, "sr"); sr_registered--; if (scsi_CDs != NULL) { - kfree((char *) scsi_CDs); + kfree(scsi_CDs); - kfree((char *) sr_sizes); + kfree(sr_sizes); sr_sizes = NULL; - kfree((char *) sr_blocksizes); + kfree(sr_blocksizes); sr_blocksizes = NULL; - kfree((char *) sr_hardsizes); + kfree(sr_hardsizes); sr_hardsizes = NULL; } blksize_size[MAJOR_NR] = NULL; @@ -863,23 +878,5 @@ void cleanup_module(void) sr_template.dev_max = 0; } -#endif /* MODULE */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ +module_init(init_sr); +module_exit(exit_sr); diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index bbb24f4eb..82869fb81 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -284,6 +284,8 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) int result, target = MINOR(cdi->dev); unsigned char buffer[32]; + memset(sr_cmd, 0, sizeof(sr_cmd)); + switch (cmd) { case CDROMREADTOCHDR: { @@ -292,10 +294,7 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) sr_cmd[0] = GPCMD_READ_TOC_PMA_ATIP; sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5); sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; - sr_cmd[6] = 0; - sr_cmd[7] = 0; /* MSB of length (12) */ sr_cmd[8] = 12; /* LSB of length */ - sr_cmd[9] = 0; result = sr_do_ioctl(target, sr_cmd, buffer, 12, 1, SCSI_DATA_READ); @@ -314,9 +313,7 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0); sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; sr_cmd[6] = tocentry->cdte_track; - sr_cmd[7] = 0; /* MSB of length (12) */ sr_cmd[8] = 12; /* LSB of length */ - sr_cmd[9] = 0; result = sr_do_ioctl(target, sr_cmd, buffer, 12, 0, SCSI_DATA_READ); @@ -334,6 +331,20 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) break; } + case CDROMPLAYTRKIND: { + struct cdrom_ti* ti = (struct cdrom_ti*)arg; + + sr_cmd[0] = GPCMD_PLAYAUDIO_TI; + sr_cmd[1] = scsi_CDs[target].device->lun << 5; + sr_cmd[4] = ti->cdti_trk0; + sr_cmd[5] = ti->cdti_ind0; + sr_cmd[7] = ti->cdti_trk1; + sr_cmd[8] = ti->cdti_ind1; + + result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0, SCSI_DATA_NONE); + break; + } + default: return -EINVAL; } diff --git a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h index 1b6e2ff08..c824bf0d0 100644 --- a/drivers/scsi/tmscsim.h +++ b/drivers/scsi/tmscsim.h @@ -442,7 +442,6 @@ typedef struct _SCSIInqData { /* INQUIRY */ /* see include/scsi/scsi.h for the rest */ #define TYPE_PRINTER 0x02 /* Printer device */ -#define TYPE_COMM 0x09 /* Communications device */ /* ** Inquiry flag definitions (Inq data byte 7) diff --git a/drivers/usb/audio.c b/drivers/usb/audio.c index 12c308bce..3b2a91949 100644 --- a/drivers/usb/audio.c +++ b/drivers/usb/audio.c @@ -3725,23 +3725,21 @@ static void usb_audio_disconnect(struct usb_device *dev, void *ptr) wake_up(&open_wait); } -int usb_audio_init(void) +static int __init usb_audio_init(void) { usb_register(&usb_audio_driver); return 0; } -#ifdef MODULE -int init_module(void) -{ - return usb_audio_init(); -} -void cleanup_module(void) +static void __exit usb_audio_cleanup(void) { usb_deregister(&usb_audio_driver); } +module_init(usb_audio_init); +module_exit(usb_audio_cleanup); + MODULE_AUTHOR("Alan Cox , Thomas Sailer (sailer@ife.ee.ethz.ch)"); MODULE_DESCRIPTION("USB Audio Class driver"); -#endif + diff --git a/drivers/usb/dabusb.c b/drivers/usb/dabusb.c index d04d3eaaa..a9982288b 100644 --- a/drivers/usb/dabusb.c +++ b/drivers/usb/dabusb.c @@ -802,7 +802,7 @@ static struct usb_driver dabusb_driver = /* --------------------------------------------------------------------- */ -int __init dabusb_init (void) +static int __init dabusb_init (void) { unsigned u; @@ -828,7 +828,7 @@ int __init dabusb_init (void) return 0; } -void __exit dabusb_cleanup (void) +static void __exit dabusb_cleanup (void) { dbg("dabusb_cleanup"); @@ -843,15 +843,9 @@ MODULE_DESCRIPTION ("DAB-USB Interface Driver for Linux (c)1999"); MODULE_PARM (buffers, "i"); MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); -int __init init_module (void) -{ - return dabusb_init (); -} +module_init (dabusb_init); +module_exit (dabusb_cleanup); -void __exit cleanup_module (void) -{ - dabusb_cleanup (); -} #endif diff --git a/drivers/usb/dsbr100.c b/drivers/usb/dsbr100.c index 6ffffdc6f..ca1d8abba 100644 --- a/drivers/usb/dsbr100.c +++ b/drivers/usb/dsbr100.c @@ -321,7 +321,7 @@ static void usb_dsbr100_close(struct video_device *dev) MOD_DEC_USE_COUNT; } -int __init dsbr100_init(void) +static int __init dsbr100_init(void) { usb_dsbr100_radio.priv = NULL; usb_register(&usb_dsbr100_driver); @@ -332,12 +332,7 @@ int __init dsbr100_init(void) return 0; } -int __init init_module(void) -{ - return dsbr100_init(); -} - -void cleanup_module(void) +static void __exit dsbr100_exit(void) { usb_dsbr100 *radio=usb_dsbr100_radio.priv; @@ -347,6 +342,9 @@ void cleanup_module(void) usb_deregister(&usb_dsbr100_driver); } +module_init (dsbr100_init); +module_exit (dsbr100_exit); + MODULE_AUTHOR("Markus Demleitner "); MODULE_DESCRIPTION("D-Link DSB-R100 USB radio driver"); diff --git a/drivers/usb/hub.c b/drivers/usb/hub.c index 71d6aabb9..08e84dde4 100644 --- a/drivers/usb/hub.c +++ b/drivers/usb/hub.c @@ -758,6 +758,7 @@ int usb_reset_device(struct usb_device *dev) ret = usb_get_configuration(dev); if (ret < 0) { err("unable to get configuration (error=%d)", ret); + usb_destroy_configuration(dev); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; diff --git a/drivers/usb/ibmcam.c b/drivers/usb/ibmcam.c index 806c9834d..590bcd4bd 100644 --- a/drivers/usb/ibmcam.c +++ b/drivers/usb/ibmcam.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -3138,7 +3139,7 @@ static struct usb_driver ibmcam_driver = { * History: * 1/27/00 Reworked to use statically allocated usb_ibmcam structures. */ -int usb_ibmcam_init(void) +static int __init usb_ibmcam_init(void) { unsigned u; @@ -3150,19 +3151,12 @@ int usb_ibmcam_init(void) return usb_register(&ibmcam_driver); } -void usb_ibmcam_cleanup(void) +static void __exit usb_ibmcam_cleanup(void) { usb_deregister(&ibmcam_driver); } -#ifdef MODULE -int init_module(void) -{ - return usb_ibmcam_init(); -} +module_init(usb_ibmcam_init); +module_exit(usb_ibmcam_cleanup); + -void cleanup_module(void) -{ - usb_ibmcam_cleanup(); -} -#endif diff --git a/drivers/usb/plusb.c b/drivers/usb/plusb.c index 9165779cb..a8ffa3aba 100644 --- a/drivers/usb/plusb.c +++ b/drivers/usb/plusb.c @@ -557,7 +557,7 @@ static struct usb_driver plusb_driver = /* --------------------------------------------------------------------- */ -int __init plusb_init (void) +static int __init plusb_init (void) { unsigned u; dbg("plusb_init"); @@ -583,7 +583,7 @@ int __init plusb_init (void) /* --------------------------------------------------------------------- */ -void __exit plusb_cleanup (void) +static void __exit plusb_cleanup (void) { unsigned u; @@ -601,21 +601,11 @@ void __exit plusb_cleanup (void) /* --------------------------------------------------------------------- */ -#ifdef MODULE MODULE_AUTHOR ("Deti Fliegl, deti@fliegl.de"); MODULE_DESCRIPTION ("PL-2302 USB Interface Driver for Linux (c)2000"); -/* --------------------------------------------------------------------- */ -int __init init_module (void) -{ - return plusb_init (); -} -/* --------------------------------------------------------------------- */ -void __exit cleanup_module (void) -{ - plusb_cleanup (); -} -#endif +module_init (plusb_init); +module_exit (plusb_cleanup); /* --------------------------------------------------------------------- */ diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index f168b1bfc..8fabc8364 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -2014,7 +2014,7 @@ opcode, line, status, val ); } -int digi_init (void) +static int __init digi_init (void) { usb_serial_register (&digi_acceleport_2_device); usb_serial_register (&digi_acceleport_4_device); @@ -2022,7 +2022,7 @@ int digi_init (void) } -void digi_exit (void) +static void __exit digi_exit (void) { usb_serial_deregister (&digi_acceleport_2_device); usb_serial_deregister (&digi_acceleport_4_device); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index aa156ba8d..0e5b67b1e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -725,14 +725,14 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns } /* ftdi_sio_ioctl */ -int ftdi_sio_init (void) +static int __init ftdi_sio_init (void) { usb_serial_register (&ftdi_sio_device); return 0; } -void ftdi_sio_exit (void) +static void __exit ftdi_sio_exit (void) { usb_serial_deregister (&ftdi_sio_device); } diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 64a1f709e..7a1d02609 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -687,7 +687,7 @@ static void keyspan_shutdown (struct usb_serial *serial) } -int keyspan_init (void) +static int __init keyspan_init (void) { usb_serial_register (&keyspan_usa18x_pre_device); usb_serial_register (&keyspan_usa19_pre_device); @@ -703,7 +703,7 @@ int keyspan_init (void) } -void keyspan_exit (void) +static void __exit keyspan_exit (void) { usb_serial_deregister (&keyspan_usa18x_pre_device); usb_serial_deregister (&keyspan_usa19_pre_device); diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index e118e29b8..537ad80c9 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -12,6 +12,11 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (08/28/2000) gkh + * Added locks for SMP safeness. + * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more + * than once. + * * (07/20/2000) borchers * - keyspan_pda_write no longer sleeps if it is called on interrupt time; * PPP and the line discipline with stty echo on can call write on @@ -416,6 +421,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user, int request_unthrottle = 0; int rc = 0; struct keyspan_pda_private *priv; + unsigned long flags; priv = (struct keyspan_pda_private *)(port->private); /* guess how much room is left in the device's ring buffer, and if we @@ -445,6 +451,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user, finished). Also, the tx process is not throttled. So we are ready to write. */ + spin_lock_irqsave (&port->port_lock, flags); count = (count > port->bulk_out_size) ? port->bulk_out_size : count; /* Check if we might overrun the Tx buffer. If so, ask the @@ -464,10 +471,12 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user, 2*HZ); if (rc < 0) { dbg(" roomquery failed"); + spin_unlock_irqrestore (&port->port_lock, flags); return rc; /* failed */ } if (rc == 0) { dbg(" roomquery returned 0 bytes"); + spin_unlock_irqrestore (&port->port_lock, flags); return -EIO; /* device didn't return any data */ } dbg(" roomquery says %d", room); @@ -484,8 +493,10 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user, /* now transfer data */ if (from_user) { if( copy_from_user(port->write_urb->transfer_buffer, - buf, count) ) + buf, count) ) { + spin_unlock_irqrestore (&port->port_lock, flags); return( -EFAULT ); + } } else { memcpy (port->write_urb->transfer_buffer, buf, count); @@ -495,8 +506,11 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user, priv->tx_room -= count; - if (usb_submit_urb(port->write_urb)) + if (usb_submit_urb(port->write_urb)) { dbg(" usb_submit_urb(write bulk) failed"); + spin_unlock_irqrestore (&port->port_lock, flags); + return (0); + } } else { /* There wasn't any room left, so we are throttled until @@ -509,6 +523,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user, queue_task( &priv->unthrottle_task, &tq_scheduler ); } + spin_unlock_irqrestore (&port->port_lock, flags); return (count); } @@ -568,61 +583,92 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp) unsigned char room; int rc; struct keyspan_pda_private *priv; - priv = (struct keyspan_pda_private *)(port->private); + unsigned long flags; - if (port->active) { - return -EINVAL; - } - port->active = 1; + spin_lock_irqsave (&port->port_lock, flags); + + MOD_INC_USE_COUNT; + ++port->open_count; + + if (!port->active) { + port->active = 1; - /* find out how much room is in the Tx ring */ - rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - 6, /* write_room */ - USB_TYPE_VENDOR | USB_RECIP_INTERFACE - | USB_DIR_IN, - 0, /* value */ - 0, /* index */ - &room, - 1, - 2*HZ); - if (rc < 0) { - dbg(" roomquery failed"); - return rc; /* failed */ - } - if (rc == 0) { - dbg(" roomquery returned 0 bytes"); - return -EIO; /* device didn't return any data */ - } - priv->tx_room = room; - priv->tx_throttled = room ? 0 : 1; + /* find out how much room is in the Tx ring */ + spin_unlock_irqrestore (&port->port_lock, flags); + rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + 6, /* write_room */ + USB_TYPE_VENDOR | USB_RECIP_INTERFACE + | USB_DIR_IN, + 0, /* value */ + 0, /* index */ + &room, + 1, + 2*HZ); + spin_lock_irqsave (&port->port_lock, flags); + if (rc < 0) { + dbg(__FUNCTION__" - roomquery failed"); + goto error; + } + if (rc == 0) { + dbg(__FUNCTION__" - roomquery returned 0 bytes"); + rc = -EIO; + goto error; + } + priv = (struct keyspan_pda_private *)(port->private); + priv->tx_room = room; + priv->tx_throttled = room ? 0 : 1; - /* the normal serial device seems to always turn on DTR and RTS here, - so do the same */ - if (port->tty->termios->c_cflag & CBAUD) - keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) ); - else - keyspan_pda_set_modem_info(serial, 0); + /* the normal serial device seems to always turn on DTR and RTS here, + so do the same */ + spin_unlock_irqrestore (&port->port_lock, flags); + if (port->tty->termios->c_cflag & CBAUD) + keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) ); + else + keyspan_pda_set_modem_info(serial, 0); + + /*Start reading from the device*/ + if (usb_submit_urb(port->interrupt_in_urb)) + dbg(__FUNCTION__" - usb_submit_urb(read int) failed"); + } else { + spin_unlock_irqrestore (&port->port_lock, flags); + } - /*Start reading from the device*/ - if (usb_submit_urb(port->interrupt_in_urb)) - dbg(" usb_submit_urb(read int) failed"); return (0); +error: + --port->open_count; + port->active = 0; + MOD_DEC_USE_COUNT; + spin_unlock_irqrestore (&port->port_lock, flags); + return rc; } static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; + unsigned long flags; - /* the normal serial device seems to always shut off DTR and RTS now */ - if (port->tty->termios->c_cflag & HUPCL) - keyspan_pda_set_modem_info(serial, 0); + spin_lock_irqsave (&port->port_lock, flags); - /* shutdown our bulk reads and writes */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->interrupt_in_urb); - port->active = 0; + --port->open_count; + MOD_DEC_USE_COUNT; + + if (port->open_count <= 0) { + /* the normal serial device seems to always shut off DTR and RTS now */ + spin_unlock_irqrestore (&port->port_lock, flags); + if (port->tty->termios->c_cflag & HUPCL) + keyspan_pda_set_modem_info(serial, 0); + spin_lock_irqsave (&port->port_lock, flags); + + /* shutdown our bulk reads and writes */ + usb_unlink_urb (port->write_urb); + usb_unlink_urb (port->interrupt_in_urb); + port->active = 0; + port->open_count = 0; + } + + spin_unlock_irqrestore (&port->port_lock, flags); } @@ -683,6 +729,11 @@ static int keyspan_pda_startup (struct usb_serial *serial) static void keyspan_pda_shutdown (struct usb_serial *serial) { + dbg (__FUNCTION__); + + while (serial->port[0].open_count > 0) { + keyspan_pda_close (&serial->port[0], NULL); + } kfree(serial->port[0].private); } @@ -728,7 +779,7 @@ struct usb_serial_device_type keyspan_pda_device = { }; -int keyspan_pda_init (void) +static int __init keyspan_pda_init (void) { usb_serial_register (&keyspan_pda_fake_device); usb_serial_register (&keyspan_pda_device); @@ -736,7 +787,7 @@ int keyspan_pda_init (void) } -void keyspan_pda_exit (void) +static void __exit keyspan_pda_exit (void) { usb_serial_deregister (&keyspan_pda_fake_device); usb_serial_deregister (&keyspan_pda_device); diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 7a68a0072..1d1bd088c 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -10,6 +10,12 @@ * * Please report both successes and troubles to the author at omninet@kroah.com * + * (08/28/2000) gkh + * Added locks for SMP safeness. + * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more + * than once. + * Fixed potential race in omninet_write_bulk_callback + * * (07/19/2000) gkh * Added module_init and module_exit functions to handle the fact that this * driver is a loadable module now. @@ -54,6 +60,7 @@ static void omninet_read_bulk_callback (struct urb *urb); static void omninet_write_bulk_callback (struct urb *urb); static int omninet_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); static int omninet_write_room (struct usb_serial_port *port); +static void omninet_shutdown (struct usb_serial *serial); /* All of the device info needed for the omni.net */ static __u16 zyxel_vendor_id = ZYXEL_VENDOR_ID; @@ -76,6 +83,7 @@ struct usb_serial_device_type zyxel_omninet_device = { write_room: omninet_write_room, read_bulk_callback: omninet_read_bulk_callback, write_bulk_callback: omninet_write_bulk_callback, + shutdown: omninet_shutdown, }; @@ -117,52 +125,87 @@ struct omninet_data static int omninet_open (struct usb_serial_port *port, struct file *filp) { - struct usb_serial *serial = port->serial; - struct usb_serial_port *wport = &serial->port[1]; - struct omninet_data *od; + struct usb_serial *serial; + struct usb_serial_port *wport; + struct omninet_data *od; + unsigned long flags; - dbg("omninet_open port %d", port->number); + if (port_paranoia_check (port, __FUNCTION__)) + return -ENODEV; - if (port->active) { - dbg ("device already open"); - return -EINVAL; - } - port->active = 1; + dbg(__FUNCTION__ " - port %d", port->number); - od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL ); + serial = get_usb_serial (port, __FUNCTION__); + if (!serial) + return -ENODEV; - if( !od ) - { - err("omninet_open: kmalloc(%d) failed.", sizeof(struct omninet_data)); - return -ENOMEM; - } + spin_lock_irqsave (&port->port_lock, flags); + + MOD_INC_USE_COUNT; + ++port->open_count; + + if (!port->active) { + port->active = 1; + + od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL ); + if( !od ) { + err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct omninet_data)); + --port->open_count; + port->active = 0; + spin_unlock_irqrestore (&port->port_lock, flags); + MOD_DEC_USE_COUNT; + return -ENOMEM; + } - port->private = od; + port->private = od; + wport = &serial->port[1]; + wport->tty = port->tty; - /* Start reading from the device */ - if (usb_submit_urb(port->read_urb)) - dbg("usb_submit_urb(read bulk, %p) failed", port->read_urb); + /* Start reading from the device */ + if (usb_submit_urb(port->read_urb)) + dbg(__FUNCTION__" - read bulk (%p) failed", port->read_urb); + } - wport->tty = port->tty; + spin_unlock_irqrestore (&port->port_lock, flags); return (0); } static void omninet_close (struct usb_serial_port *port, struct file * filp) { - struct usb_serial *serial = port->serial; - struct usb_serial_port *wport = &serial->port[1]; - struct omninet_data *od = (struct omninet_data *) port->private; + struct usb_serial *serial; + struct usb_serial_port *wport; + struct omninet_data *od; + unsigned long flags; + + if (port_paranoia_check (port, __FUNCTION__)) + return; + + dbg(__FUNCTION__ " - port %d", port->number); - port->active = 0; + serial = get_usb_serial (port, __FUNCTION__); + if (!serial) + return; + + spin_lock_irqsave (&port->port_lock, flags); + --port->open_count; + MOD_DEC_USE_COUNT; - dbg("zyxel_close port %d", port->number); + if (port->open_count <= 0) { + od = (struct omninet_data *)port->private; + wport = &serial->port[1]; - usb_unlink_urb (wport->write_urb); - usb_unlink_urb (port->read_urb); + usb_unlink_urb (wport->write_urb); + usb_unlink_urb (port->read_urb); - if(od) kfree(od); + port->active = 0; + port->open_count = 0; + if (od) + kfree(od); + } + + spin_unlock_irqrestore (&port->port_lock, flags); } @@ -173,7 +216,7 @@ static void omninet_close (struct usb_serial_port *port, struct file * filp) static void omninet_read_bulk_callback (struct urb *urb) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; - struct usb_serial *serial = port->serial; + struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); unsigned char *data = urb->transfer_buffer; struct omninet_header *header = (struct omninet_header *) &data[0]; @@ -182,22 +225,18 @@ static void omninet_read_bulk_callback (struct urb *urb) // dbg("omninet_read_bulk_callback"); - if (port_paranoia_check (port, "omninet_read_bulk_callback")) { - return; - } - - if (serial_paranoia_check (serial, "omninet_read_bulk_callback")) { + if (!serial) { + dbg(__FUNCTION__ " - bad serial pointer, exiting"); return; } if (urb->status) { - dbg("nonzero read bulk status received: %d", urb->status); + dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status); return; } #ifdef DEBUG - if(header->oh_xxx != 0x30) - { + if(header->oh_xxx != 0x30) { if (urb->actual_length) { printk (KERN_DEBUG __FILE__ ": omninet_read %d: ", header->oh_len); for (i = 0; i < (header->oh_len + OMNINET_HEADERLEN); i++) { @@ -208,8 +247,7 @@ static void omninet_read_bulk_callback (struct urb *urb) } #endif - if (urb->actual_length && header->oh_len) - { + if (urb->actual_length && header->oh_len) { for (i = 0; i < header->oh_len; i++) { tty_insert_flip_char(port->tty, data[OMNINET_DATAOFFSET + i], 0); } @@ -218,7 +256,7 @@ static void omninet_read_bulk_callback (struct urb *urb) /* Continue trying to always read */ if (usb_submit_urb(urb)) - dbg("failed resubmitting read urb"); + dbg(__FUNCTION__" - failed resubmitting read urb"); return; } @@ -230,6 +268,8 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns struct omninet_data *od = (struct omninet_data *) port->private; struct omninet_header *header = (struct omninet_header *) wport->write_urb->transfer_buffer; + + unsigned long flags; /* #ifdef DEBUG int i; @@ -239,7 +279,7 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns // dbg("omninet_write port %d", port->number); if (count == 0) { - dbg("write request of 0 bytes"); + dbg(__FUNCTION__" - write request of 0 bytes"); return (0); } /* @@ -255,10 +295,12 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns #endif */ if (wport->write_urb->status == -EINPROGRESS) { - dbg ("already writing"); + dbg (__FUNCTION__" - already writing"); return (0); } + spin_lock_irqsave (&port->port_lock, flags); + count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; if (from_user) { @@ -277,11 +319,15 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns /* send the data out the bulk port, always 64 bytes */ wport->write_urb->transfer_buffer_length = 64; - if (usb_submit_urb(wport->write_urb)) - dbg("usb_submit_urb(write bulk) failed"); + if (usb_submit_urb(wport->write_urb)) { + dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed"); + spin_unlock_irqrestore (&port->port_lock, flags); + return 0; + } // dbg("omninet_write returns %d", count); + spin_unlock_irqrestore (&port->port_lock, flags); return (count); } @@ -306,31 +352,26 @@ static void omninet_write_bulk_callback (struct urb *urb) /* struct omninet_header *header = (struct omninet_header *) urb->transfer_buffer; */ struct usb_serial_port *port = (struct usb_serial_port *) urb->context; struct usb_serial *serial; - struct tty_struct *tty; // dbg("omninet_write_bulk_callback, port %0x\n", port); - if (port_paranoia_check (port, "omninet_write_bulk_callback")) { + if (port_paranoia_check (port, __FUNCTION__)) { return; } serial = port->serial; - if (serial_paranoia_check (serial, "omninet_write_bulk_callback")) { + if (serial_paranoia_check (serial, __FUNCTION__)) { return; } if (urb->status) { - dbg("nonzero write bulk status received: %d", urb->status); + dbg(__FUNCTION__" - nonzero write bulk status received: %d", urb->status); return; } - tty = port->tty; - - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - - wake_up_interruptible(&tty->write_wait); + queue_task(&port->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); // dbg("omninet_write_bulk_callback, tty %0x\n", tty); @@ -338,14 +379,24 @@ static void omninet_write_bulk_callback (struct urb *urb) } -int omninet_init (void) +static void omninet_shutdown (struct usb_serial *serial) +{ + dbg (__FUNCTION__); + + while (serial->port[0].open_count > 0) { + omninet_close (&serial->port[0], NULL); + } +} + + +static int __init omninet_init (void) { usb_serial_register (&zyxel_omninet_device); return 0; } -void omninet_exit (void) +static void __exit omninet_exit (void) { usb_serial_deregister (&zyxel_omninet_device); } diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index 10d57076c..7c830bf7f 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h @@ -11,6 +11,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (08/28/2000) gkh + * Added port_lock to port structure. + * * (08/08/2000) gkh * Added open_count to port structure. * @@ -63,6 +66,7 @@ struct usb_serial_port { struct tq_struct tqueue; /* task queue for line discipline waking up */ int open_count; /* number of times this port has been opened */ + spinlock_t port_lock; void * private; /* data private to the specific port */ }; @@ -185,5 +189,21 @@ static inline int port_paranoia_check (struct usb_serial_port *port, const char return 0; } + +static inline struct usb_serial* get_usb_serial (struct usb_serial_port *port, const char *function) +{ + /* if no port was specified, or it fails a paranoia check */ + if (!port || + port_paranoia_check (port, function) || + serial_paranoia_check (port->serial, function)) { + /* then say that we dont have a valid usb_serial thing, which will + * end up genrating -ENODEV return values */ + return NULL; + } + + return port->serial; +} + + #endif /* ifdef __LINUX_USB_SERIAL_H */ diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c index 735aecaed..276a7e5db 100644 --- a/drivers/usb/serial/usbserial.c +++ b/drivers/usb/serial/usbserial.c @@ -15,6 +15,11 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (08/28/2000) gkh + * Added port_lock to port structure. + * Added locks for SMP safeness to generic driver + * Fixed the ability to open a generic device's port more than once. + * * (07/23/2000) gkh * Added bulk_out_endpointAddress to port structure. * @@ -264,6 +269,7 @@ static int generic_write_room (struct usb_serial_port *port); static int generic_chars_in_buffer (struct usb_serial_port *port); static void generic_read_bulk_callback (struct urb *urb); static void generic_write_bulk_callback (struct urb *urb); +static void generic_shutdown (struct usb_serial *serial); #ifdef CONFIG_USB_SERIAL_GENERIC @@ -287,6 +293,7 @@ static struct usb_serial_device_type generic_device = { num_bulk_in: NUM_DONT_CARE, num_bulk_out: NUM_DONT_CARE, num_ports: 1, + shutdown: generic_shutdown, }; #endif @@ -321,21 +328,6 @@ static struct usb_serial *serial_table[SERIAL_TTY_MINORS] = {NULL, }; LIST_HEAD(usb_serial_driver_list); -static inline struct usb_serial* get_usb_serial (struct usb_serial_port *port, const char *function) -{ - /* if no port was specified, or it fails a paranoia check */ - if (!port || - port_paranoia_check (port, function) || - serial_paranoia_check (port->serial, function)) { - /* then say that we dont have a valid usb_serial thing, which will - * end up genrating -ENODEV return values */ - return NULL; - } - - return port->serial; -} - - static struct usb_serial *get_serial_by_minor (int minor) { return serial_table[minor]; @@ -697,47 +689,65 @@ static void serial_break (struct tty_struct *tty, int break_state) static int generic_open (struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; + unsigned long flags; + + if (port_paranoia_check (port, __FUNCTION__)) + return -ENODEV; dbg(__FUNCTION__ " - port %d", port->number); - if (port->active) { - dbg (__FUNCTION__ " - device already open"); - return -EINVAL; - } - port->active = 1; - - /* if we have a bulk interrupt, start reading from it */ - if (serial->num_bulk_in) { - /*Start reading from the device*/ - if (usb_submit_urb(port->read_urb)) - dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed"); - } + spin_lock_irqsave (&port->port_lock, flags); + + ++port->open_count; + MOD_INC_USE_COUNT; + + if (!port->active) { + port->active = 1; - return (0); + /* if we have a bulk interrupt, start reading from it */ + if (serial->num_bulk_in) { + /*Start reading from the device*/ + if (usb_submit_urb(port->read_urb)) + dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed"); + } + } + + spin_unlock_irqrestore (&port->port_lock, flags); + + return 0; } static void generic_close (struct usb_serial_port *port, struct file * filp) { struct usb_serial *serial = port->serial; + unsigned long flags; dbg(__FUNCTION__ " - port %d", port->number); - - /* shutdown any bulk reads that might be going on */ - if (serial->num_bulk_out) { - usb_unlink_urb (port->write_urb); - } - if (serial->num_bulk_in) { - usb_unlink_urb (port->read_urb); + + spin_lock_irqsave (&port->port_lock, flags); + + --port->open_count; + + if (port->open_count <= 0) { + /* shutdown any bulk reads that might be going on */ + if (serial->num_bulk_out) + usb_unlink_urb (port->write_urb); + if (serial->num_bulk_in) + usb_unlink_urb (port->read_urb); + + port->active = 0; + port->open_count = 0; } - port->active = 0; + spin_unlock_irqrestore (&port->port_lock, flags); } static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; + unsigned long flags; dbg(__FUNCTION__ " - port %d", port->number); @@ -753,6 +763,7 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns return (0); } + spin_lock_irqsave (&port->port_lock, flags); count = (count > port->bulk_out_size) ? port->bulk_out_size : count; #ifdef DEBUG @@ -776,9 +787,13 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns /* send the data out the bulk port */ port->write_urb->transfer_buffer_length = count; - if (usb_submit_urb(port->write_urb)) + if (usb_submit_urb(port->write_urb)) { dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed"); + spin_unlock_irqrestore (&port->port_lock, flags); + return 0; + } + spin_unlock_irqrestore (&port->port_lock, flags); return (count); } @@ -889,6 +904,21 @@ static void generic_write_bulk_callback (struct urb *urb) } +static void generic_shutdown (struct usb_serial *serial) +{ + int i; + + dbg (__FUNCTION__); + + /* stop reads and writes on all ports */ + for (i=0; i < serial->num_ports; ++i) { + while (serial->port[i].open_count > 0) { + generic_close (&serial->port[i], NULL); + } + } +} + + static void port_softint(void *private) { struct usb_serial_port *port = (struct usb_serial_port *)private; @@ -1127,6 +1157,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) port->magic = USB_SERIAL_PORT_MAGIC; port->tqueue.routine = port_softint; port->tqueue.data = port; + spin_lock_init (&port->port_lock); } /* initialize the devfs nodes for this device and let the user know what ports we are bound to */ diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index bc0ea807a..6ebc3a961 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -11,6 +11,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (08/28/2000) gkh + * Added locks for SMP safeness. + * * (08/08/2000) gkh * Fixed endian problem in visor_startup. * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more @@ -109,21 +112,23 @@ struct usb_serial_device_type handspring_device = { #define NUM_URBS 24 -static struct urb *write_urb_pool[NUM_URBS]; - +static struct urb *write_urb_pool[NUM_URBS]; +static spinlock_t write_urb_pool_lock; /****************************************************************************** * Handspring Visor specific driver functions ******************************************************************************/ static int visor_open (struct usb_serial_port *port, struct file *filp) { - dbg(__FUNCTION__ " - port %d", port->number); + unsigned long flags; - if (port->active) { - dbg (__FUNCTION__ " - device already open"); - return -EINVAL; - } + if (port_paranoia_check (port, __FUNCTION__)) + return -ENODEV; + + dbg(__FUNCTION__ " - port %d", port->number); + spin_lock_irqsave (&port->port_lock, flags); + ++port->open_count; MOD_INC_USE_COUNT; @@ -135,21 +140,34 @@ static int visor_open (struct usb_serial_port *port, struct file *filp) dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed"); } + spin_unlock_irqrestore (&port->port_lock, flags); + return 0; } static void visor_close (struct usb_serial_port *port, struct file * filp) { - struct usb_serial *serial = port->serial; - unsigned char *transfer_buffer = kmalloc (0x12, GFP_KERNEL); + struct usb_serial *serial; + unsigned char *transfer_buffer; + unsigned long flags; + + if (port_paranoia_check (port, __FUNCTION__)) + return; dbg(__FUNCTION__ " - port %d", port->number); + serial = get_usb_serial (port, __FUNCTION__); + if (!serial) + return; + + spin_lock_irqsave (&port->port_lock, flags); + --port->open_count; MOD_DEC_USE_COUNT; if (port->open_count <= 0) { + transfer_buffer = kmalloc (0x12, GFP_KERNEL); if (!transfer_buffer) { err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12); } else { @@ -164,6 +182,8 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) port->active = 0; port->open_count = 0; } + + spin_unlock_irqrestore (&port->port_lock, flags); } @@ -174,6 +194,7 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig unsigned char *buffer = NULL; int status; int i; + unsigned long flags; dbg(__FUNCTION__ " - port %d", port->number); @@ -183,12 +204,14 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig } /* try to find a free urb in our list of them */ + spin_lock_irqsave (&write_urb_pool_lock, flags); for (i = 0; i < NUM_URBS; ++i) { if (write_urb_pool[i]->status != -EINPROGRESS) { urb = write_urb_pool[i]; break; } } + spin_unlock_irqrestore (&write_urb_pool_lock, flags); if (urb == NULL) { dbg (__FUNCTION__ " - no free urbs"); return 0; @@ -256,21 +279,33 @@ static void visor_write_bulk_callback (struct urb *urb) static void visor_throttle (struct usb_serial_port *port) { + unsigned long flags; + dbg(__FUNCTION__ " - port %d", port->number); + spin_lock_irqsave (&port->port_lock, flags); + usb_unlink_urb (port->read_urb); + spin_unlock_irqrestore (&port->port_lock, flags); + return; } static void visor_unthrottle (struct usb_serial_port *port) { + unsigned long flags; + dbg(__FUNCTION__ " - port %d", port->number); + spin_lock_irqsave (&port->port_lock, flags); + if (usb_submit_urb (port->read_urb)) dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed"); + spin_unlock_irqrestore (&port->port_lock, flags); + return; } @@ -429,13 +464,14 @@ static void visor_set_termios (struct usb_serial_port *port, struct termios *old } -int visor_init (void) +static int __init visor_init (void) { int i; usb_serial_register (&handspring_device); /* create our write urb pool */ + spin_lock_init (&write_urb_pool_lock); for (i = 0; i < NUM_URBS; ++i) { struct urb *urb = usb_alloc_urb(0); if (urb == NULL) { @@ -450,18 +486,23 @@ int visor_init (void) } -void visor_exit (void) +static void __exit visor_exit (void) { int i; + unsigned long flags; usb_serial_deregister (&handspring_device); - + + spin_lock_irqsave (&write_urb_pool_lock, flags); + for (i = 0; i < NUM_URBS; ++i) { usb_unlink_urb(write_urb_pool[i]); if (write_urb_pool[i]->transfer_buffer) kfree(write_urb_pool[i]->transfer_buffer); usb_free_urb (write_urb_pool[i]); } + + spin_unlock_irqrestore (&write_urb_pool_lock, flags); } diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 7ec405501..b8b599358 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -531,7 +531,7 @@ static inline void set_break (struct usb_serial_port *port, unsigned char brk) } -int whiteheat_init (void) +static int __init whiteheat_init (void) { usb_serial_register (&whiteheat_fake_device); usb_serial_register (&whiteheat_device); @@ -539,7 +539,7 @@ int whiteheat_init (void) } -void whiteheat_exit (void) +static void __exit whiteheat_exit (void) { usb_serial_deregister (&whiteheat_fake_device); usb_serial_deregister (&whiteheat_device); diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 6b0914cf6..a9501a06a 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -28,7 +28,6 @@ * (http://www.freecom.de/) */ -#include #include "transport.h" #include "protocol.h" #include "usb.h" diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 07f0598e5..abf0bf1c8 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -43,6 +43,7 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include "usb.h" #include "scsiglue.h" #include "transport.h" @@ -66,7 +67,6 @@ #include #include #include -#include /* Some informational data */ MODULE_AUTHOR("Matthew Dharm "); diff --git a/drivers/usb/usb-core.c b/drivers/usb/usb-core.c index 017a99dce..7f124b897 100644 --- a/drivers/usb/usb-core.c +++ b/drivers/usb/usb-core.c @@ -25,16 +25,6 @@ void usb_hub_cleanup(void); int usb_major_init(void); void usb_major_cleanup(void); -/* - * USB device drivers - */ - -int usb_cpia_init(void); -int usb_audio_init(void); -int usb_ibmcam_init(void); -int dabusb_init(void); -int plusb_init(void); -int dsbr100_init(void); /* * HCI drivers @@ -65,24 +55,6 @@ static int __init usb_init(void) usb_hub_init(); #ifndef CONFIG_USB_MODULE -#ifdef CONFIG_VIDEO_CPIA_USB - usb_cpia_init(); -#endif -#ifdef CONFIG_USB_AUDIO - usb_audio_init(); -#endif -#ifdef CONFIG_USB_IBMCAM - usb_ibmcam_init(); -#endif -#ifdef CONFIG_USB_DABUSB - dabusb_init(); -#endif -#ifdef CONFIG_USB_DSBR - dsbr100_init(); -#endif -#ifdef CONFIG_USB_PLUSB - plusb_init(); -#endif #ifdef CONFIG_USB_UHCI uhci_init(); #endif diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c index 93fe7826c..17cd8d8ef 100644 --- a/drivers/usb/usb.c +++ b/drivers/usb/usb.c @@ -1945,6 +1945,7 @@ int usb_new_device(struct usb_device *dev) err = usb_get_configuration(dev); if (err < 0) { err("unable to get configuration (error=%d)", err); + usb_destroy_configuration(dev); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; diff --git a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c index bdcce1c51..35564c3b1 100644 --- a/fs/adfs/dir_f.c +++ b/fs/adfs/dir_f.c @@ -437,7 +437,7 @@ adfs_f_update(struct adfs_dir *dir, struct object_info *obj) } #endif for (i = dir->nr_buffers - 1; i >= 0; i--) - mark_buffer_dirty(dir->bh[i], 1); + mark_buffer_dirty(dir->bh[i]); ret = 0; out: diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index d01f618c8..5c4ec8e6b 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c @@ -79,7 +79,7 @@ affs_insert_hash(unsigned long next, struct buffer_head *file, struct inode *ino DIR_END(file->b_data,inode)->hash_chain = cpu_to_be32(next); ((s32 *)bh->b_data)[offset] = cpu_to_be32(ino); affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); - mark_buffer_dirty(bh,1); + mark_buffer_dirty(bh); affs_brelse(bh); return 0; @@ -130,7 +130,7 @@ affs_remove_hash(struct buffer_head *dbh, struct inode *inode) if (ownkey == key) { ((s32 *)bh->b_data)[offset] = FILE_END(dbh->b_data,inode)->hash_chain; affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); - mark_buffer_dirty(bh,1); + mark_buffer_dirty(bh); affs_brelse(bh); retval = 0; break; @@ -178,7 +178,7 @@ affs_remove_link(struct buffer_head *dbh, struct inode *inode) FILE_END(bh->b_data,inode)->link_chain = FILE_END(dbh->b_data,inode)->link_chain; affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); - mark_buffer_dirty(bh,1); + mark_buffer_dirty(bh); affs_brelse(bh); retval = 0; break; @@ -261,7 +261,7 @@ affs_remove_header(struct buffer_head *bh, struct inode *inode) return error; } affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); - mark_buffer_dirty(bh,1); + mark_buffer_dirty(bh); affs_brelse(link_bh); affs_free_block(inode->i_sb,link_ino); /* Mark the link's parent dir as changed, too. */ diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c index 3382a82f9..de477b331 100644 --- a/fs/affs/bitmap.c +++ b/fs/affs/bitmap.c @@ -93,7 +93,7 @@ affs_free_block(struct super_block *sb, s32 block) else { sb->u.affs_sb.s_alloc[zone_no].az_free++; ((u32 *)bm->bm_bh->b_data)[0] = cpu_to_be32(be32_to_cpu(((u32 *)bm->bm_bh->b_data)[0]) - blk); - mark_buffer_dirty(bm->bm_bh,1); + mark_buffer_dirty(bm->bm_bh); sb->s_dirt = 1; } if (--bm->bm_count == 0) { @@ -176,7 +176,7 @@ found: w = ~w - be32_to_cpu(bm[i]); bm[0] = cpu_to_be32(be32_to_cpu(bm[0]) + w); unlock_super(sb); - mark_buffer_dirty(zone->z_bm->bm_bh,1); + mark_buffer_dirty(zone->z_bm->bm_bh); sb->s_dirt = 1; zone->z_lru_time = jiffies; diff --git a/fs/affs/file.c b/fs/affs/file.c index cd31491b0..de0808b9e 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -447,12 +447,12 @@ static struct buffer_head * affs_getblock(struct inode *inode, s32 block) DATA_FRONT(ebh)->header_key = cpu_to_be32(inode->i_ino); DATA_FRONT(ebh)->sequence_number = cpu_to_be32(inode->u.affs_i.i_lastblock + 1); affs_fix_checksum(AFFS_I2BSIZE(inode), ebh->b_data, 5); - mark_buffer_dirty(ebh, 0); + mark_buffer_dirty(ebh); if (pbh) { DATA_FRONT(pbh)->data_size = cpu_to_be32(AFFS_I2BSIZE(inode) - 24); DATA_FRONT(pbh)->next_data = cpu_to_be32(nkey); affs_fix_checksum(AFFS_I2BSIZE(inode),pbh->b_data,5); - mark_buffer_dirty(pbh,0); + mark_buffer_dirty(pbh); affs_brelse(pbh); } pbh = ebh; @@ -466,7 +466,7 @@ static struct buffer_head * affs_getblock(struct inode *inode, s32 block) fdp->first_data = AFFS_BLOCK(bh->b_data,inode,0); fdp->block_count = cpu_to_be32(j); affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); - mark_buffer_dirty(bh,1); + mark_buffer_dirty(bh); } if (block < j) { @@ -495,10 +495,10 @@ static struct buffer_head * affs_getblock(struct inode *inode, s32 block) FILE_END(ebh->b_data,inode)->secondary_type = cpu_to_be32(ST_FILE); FILE_END(ebh->b_data,inode)->parent = cpu_to_be32(inode->i_ino); affs_fix_checksum(AFFS_I2BSIZE(inode),ebh->b_data,5); - mark_buffer_dirty(ebh, 1); + mark_buffer_dirty(ebh); FILE_END(bh->b_data,inode)->extension = cpu_to_be32(key); affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); - mark_buffer_dirty(bh,1); + mark_buffer_dirty(bh); affs_brelse(bh); bh = ebh; } @@ -678,7 +678,7 @@ affs_truncate(struct inode *inode) rem = do_div(tmp, net_blocksize); DATA_FRONT(bh)->data_size = cpu_to_be32(rem ? rem : net_blocksize); affs_fix_checksum(blocksize,bh->b_data,5); - mark_buffer_dirty(bh,0); + mark_buffer_dirty(bh); } goto out_truncate; } @@ -733,7 +733,7 @@ affs_truncate(struct inode *inode) first = 0; *keyp = 0; affs_fix_checksum(blocksize,bh->b_data,5); - mark_buffer_dirty(bh,1); + mark_buffer_dirty(bh); } else first -= AFFS_I2HSIZE(inode); affs_brelse(bh); @@ -766,7 +766,7 @@ affs_truncate(struct inode *inode) ((struct data_front *)bh->b_data)->next_data = 0; affs_fix_checksum(blocksize,bh->b_data,5); } - mark_buffer_dirty(bh,1); + mark_buffer_dirty(bh); } else affs_error(inode->i_sb,"truncate","Cannot read block %d",block); } diff --git a/fs/affs/inode.c b/fs/affs/inode.c index f98a2cd0b..2f8c36aa5 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -232,7 +232,7 @@ affs_write_inode(struct inode *inode, int unused) } } affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); - mark_buffer_dirty(bh,1); + mark_buffer_dirty(bh); brelse(bh); unlock_kernel(); } @@ -392,7 +392,7 @@ affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode, affs_fix_checksum(AFFS_I2BSIZE(link),link_bh->b_data,5); link->i_version = ++event; mark_inode_dirty(link); - mark_buffer_dirty(link_bh,1); + mark_buffer_dirty(link_bh); } affs_fix_checksum(AFFS_I2BSIZE(inode),inode_bh->b_data,5); affs_fix_checksum(AFFS_I2BSIZE(dir),dir_bh->b_data,5); @@ -402,8 +402,8 @@ affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode, mark_inode_dirty(dir); mark_inode_dirty(inode); - mark_buffer_dirty(dir_bh,1); - mark_buffer_dirty(inode_bh,1); + mark_buffer_dirty(dir_bh); + mark_buffer_dirty(inode_bh); addentry_done: affs_brelse(dir_bh); diff --git a/fs/affs/namei.c b/fs/affs/namei.c index 8ad7b07a2..a73e60618 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -440,7 +440,7 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) symname++; } *p = 0; - mark_buffer_dirty(bh,1); + mark_buffer_dirty(bh); affs_brelse(bh); mark_inode_dirty(inode); @@ -592,7 +592,7 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry, retval = 0; mark_inode_dirty(new_dir); mark_inode_dirty(old_dir); - mark_buffer_dirty(old_bh,1); + mark_buffer_dirty(old_bh); end_rename: affs_brelse(old_bh); diff --git a/fs/affs/super.c b/fs/affs/super.c index 46c11a8e2..32ad74eb9 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -52,7 +52,7 @@ affs_put_super(struct super_block *sb) secs_to_datestamp(CURRENT_TIME, &ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered); affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5); - mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1); + mark_buffer_dirty(sb->u.affs_sb.s_root_bh); } if (sb->u.affs_sb.s_prefix) @@ -88,7 +88,7 @@ affs_write_super(struct super_block *sb) secs_to_datestamp(CURRENT_TIME, &ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered); affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5); - mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1); + mark_buffer_dirty(sb->u.affs_sb.s_root_bh); sb->s_dirt = !clean; /* redo until bitmap synced */ } else sb->s_dirt = 0; @@ -491,7 +491,7 @@ got_root: chksum = cpu_to_be32(0x7FFFFFFF >> (31 - key)); ((u32 *)bb->b_data)[ptype] &= chksum; affs_fix_checksum(s->s_blocksize,bb->b_data,0); - mark_buffer_dirty(bb,1); + mark_buffer_dirty(bb); bmalt = 1; } ptype = (size + 31) & ~0x1F; @@ -553,7 +553,7 @@ nobitmap: secs_to_datestamp(CURRENT_TIME,&ROOT_END( s->u.affs_sb.s_root_bh->b_data,root_inode)->disk_altered); affs_fix_checksum(s->s_blocksize,s->u.affs_sb.s_root_bh->b_data,5); - mark_buffer_dirty(s->u.affs_sb.s_root_bh,1); + mark_buffer_dirty(s->u.affs_sb.s_root_bh); } affs_make_zones(s); } diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 721739e31..9ebea1ca7 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -177,7 +177,7 @@ static int bfs_unlink(struct inode * dir, struct dentry * dentry) } de->ino = 0; dir->i_version = ++event; - mark_buffer_dirty(bh, 0); + mark_buffer_dirty(bh); dir->i_ctime = dir->i_mtime = CURRENT_TIME; mark_inode_dirty(dir); inode->i_nlink--; @@ -236,7 +236,7 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry, new_inode->i_ctime = CURRENT_TIME; mark_inode_dirty(new_inode); } - mark_buffer_dirty(old_bh, 0); + mark_buffer_dirty(old_bh); error = 0; end_rename: @@ -288,7 +288,7 @@ static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int de->ino = ino; for (i=0; iname[i] = (i < namelen) ? name[i] : 0; - mark_buffer_dirty(bh, 0); + mark_buffer_dirty(bh); brelse(bh); return 0; } diff --git a/fs/bfs/file.c b/fs/bfs/file.c index 1335d301b..1da12e6ae 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c @@ -33,7 +33,7 @@ static int bfs_move_block(unsigned long from, unsigned long to, kdev_t dev) return -EIO; new = getblk(dev, to, BFS_BSIZE); memcpy(new->b_data, bh->b_data, bh->b_size); - mark_buffer_dirty(new, 0); + mark_buffer_dirty(new); bforget(bh); brelse(new); return 0; @@ -98,7 +98,7 @@ static int bfs_get_block(struct inode * inode, long block, bh_result->b_state |= (1UL << BH_Mapped); s->su_lf_eblk = inode->iu_eblock = inode->iu_sblock + block; mark_inode_dirty(inode); - mark_buffer_dirty(s->su_sbh, 1); + mark_buffer_dirty(s->su_sbh); err = 0; goto out; } @@ -118,7 +118,7 @@ static int bfs_get_block(struct inode * inode, long block, inode->iu_sblock = next_free_block; s->su_lf_eblk = inode->iu_eblock = next_free_block + block; mark_inode_dirty(inode); - mark_buffer_dirty(s->su_sbh, 1); + mark_buffer_dirty(s->su_sbh); bh_result->b_dev = inode->i_dev; bh_result->b_blocknr = inode->iu_sblock + block; bh_result->b_state |= (1UL << BH_Mapped); diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 9f53cbcd3..f96acf581 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -127,7 +127,7 @@ static void bfs_write_inode(struct inode * inode, int unused) di->i_eblock = inode->iu_eblock; di->i_eoffset = di->i_sblock * BFS_BSIZE + inode->i_size - 1; - mark_buffer_dirty(bh, 0); + mark_buffer_dirty(bh); brelse(bh); unlock_kernel(); } @@ -169,7 +169,7 @@ static void bfs_delete_inode(struct inode * inode) } di->i_ino = 0; di->i_sblock = 0; - mark_buffer_dirty(bh, 0); + mark_buffer_dirty(bh); brelse(bh); /* if this was the last file, make the previous @@ -177,7 +177,7 @@ static void bfs_delete_inode(struct inode * inode) saves us 1 gap */ if (s->su_lf_eblk == inode->iu_eblock) { s->su_lf_eblk = inode->iu_sblock - 1; - mark_buffer_dirty(s->su_sbh, 1); + mark_buffer_dirty(s->su_sbh); } unlock_kernel(); clear_inode(inode); @@ -205,7 +205,7 @@ static int bfs_statfs(struct super_block *s, struct statfs *buf) static void bfs_write_super(struct super_block *s) { if (!(s->s_flags & MS_RDONLY)) - mark_buffer_dirty(s->su_sbh, 1); + mark_buffer_dirty(s->su_sbh); s->s_dirt = 0; } @@ -314,7 +314,7 @@ static struct super_block * bfs_read_super(struct super_block * s, iput(inode); } if (!(s->s_flags & MS_RDONLY)) { - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); s->s_dirt = 1; } dump_imap("read_super", s); diff --git a/fs/block_dev.c b/fs/block_dev.c index 21bc086e3..0ddf2fd3b 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -129,7 +129,7 @@ ssize_t block_write(struct file * filp, const char * buf, p += chars; buf += chars; mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 0); + mark_buffer_dirty(bh); if (filp->f_flags & O_SYNC) bufferlist[buffercount++] = bh; else diff --git a/fs/buffer.c b/fs/buffer.c index 5ee5d376f..58083e2b3 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -892,7 +892,7 @@ void balance_dirty(kdev_t dev) wakeup_bdflush(state); } -static __inline__ void __mark_dirty(struct buffer_head *bh, int flag) +static __inline__ void __mark_dirty(struct buffer_head *bh) { bh->b_flushtime = jiffies + bdf_prm.b_un.age_buffer; refile_buffer(bh); @@ -900,15 +900,15 @@ static __inline__ void __mark_dirty(struct buffer_head *bh, int flag) /* atomic version, the user must call balance_dirty() by hand as soon as it become possible to block */ -void __mark_buffer_dirty(struct buffer_head *bh, int flag) +void __mark_buffer_dirty(struct buffer_head *bh) { if (!atomic_set_buffer_dirty(bh)) - __mark_dirty(bh, flag); + __mark_dirty(bh); } -void mark_buffer_dirty(struct buffer_head *bh, int flag) +void mark_buffer_dirty(struct buffer_head *bh) { - __mark_buffer_dirty(bh, flag); + __mark_buffer_dirty(bh); balance_dirty(bh->b_dev); } @@ -1419,7 +1419,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, get_b } set_bit(BH_Uptodate, &bh->b_state); if (!atomic_set_buffer_dirty(bh)) { - __mark_dirty(bh, 0); + __mark_dirty(bh); need_balance_dirty = 1; } @@ -1514,16 +1514,16 @@ static int __block_commit_write(struct inode *inode, struct page *page, bh != head || !block_start; block_start=block_end, bh = bh->b_this_page) { block_end = block_start + blocksize; - /* This can happen for the truncate case */ - if (!buffer_mapped(bh)) - continue; if (block_end <= from || block_start >= to) { if (!buffer_uptodate(bh)) partial = 1; } else { + /* This can happen for the truncate case */ + if (!buffer_mapped(bh)) + continue; set_bit(BH_Uptodate, &bh->b_state); if (!atomic_set_buffer_dirty(bh)) { - __mark_dirty(bh, 0); + __mark_dirty(bh); need_balance_dirty = 1; } } diff --git a/fs/dquot.c b/fs/dquot.c index 2271f4746..3e49ed325 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -1214,14 +1214,6 @@ int dquot_transfer(struct dentry *dentry, struct iattr *iattr) lock_kernel(); /* - * Find out if this filesystem uses i_blocks. - */ - if (!inode->i_sb->s_blocksize) - blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE_BITS); - else - blocks = (inode->i_blocks >> 1); - - /* * Build the transfer_from and transfer_to lists and check quotas to see * if operation is permitted. */ @@ -1280,14 +1272,26 @@ int dquot_transfer(struct dentry *dentry, struct iattr *iattr) * dqget() could block and so the first structure might got * invalidated or locked... */ - if (!transfer_to[cnt]->dq_sb || !transfer_from[cnt]->dq_sb || - check_idq(transfer_to[cnt], 1) == NO_QUOTA || - check_bdq(transfer_to[cnt], blocks, 0) == NO_QUOTA) { + if (!transfer_to[cnt]->dq_sb || !transfer_from[cnt]->dq_sb) { cnt++; goto put_all; } } + /* + * Find out if this filesystem uses i_blocks. + */ + if (!inode->i_sb->s_blocksize) + blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE_BITS); + else + blocks = (inode->i_blocks >> 1); + for (cnt = 0; cnt < MAXQUOTAS; cnt++) + if (check_idq(transfer_to[cnt], 1) == NO_QUOTA || + check_bdq(transfer_to[cnt], blocks, 0) == NO_QUOTA) { + cnt = MAXQUOTAS; + goto put_all; + } + if ((error = notify_change(dentry, iattr))) goto put_all; /* diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index 831aa67e9..99c832845 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -325,10 +325,10 @@ do_more: } } - mark_buffer_dirty(bh2, 1); - mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); + mark_buffer_dirty(bh2); + mark_buffer_dirty(sb->u.ext2_sb.s_sbh); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (sb->s_flags & MS_SYNCHRONOUS) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -582,7 +582,7 @@ got_block: j = tmp; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (sb->s_flags & MS_SYNCHRONOUS) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -600,9 +600,9 @@ got_block: "Goal hits %d of %d.\n", j, goal_hits, goal_attempts); gdp->bg_free_blocks_count = cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - 1); - mark_buffer_dirty(bh2, 1); + mark_buffer_dirty(bh2); es->s_free_blocks_count = cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - 1); - mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); + mark_buffer_dirty(sb->u.ext2_sb.s_sbh); sb->s_dirt = 1; unlock_super (sb); *err = 0; diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 6f5ecebe8..4ec715bf3 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -230,12 +230,12 @@ void ext2_free_inode (struct inode * inode) gdp->bg_used_dirs_count = cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) - 1); } - mark_buffer_dirty(bh2, 1); + mark_buffer_dirty(bh2); es->s_free_inodes_count = cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1); - mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); + mark_buffer_dirty(sb->u.ext2_sb.s_sbh); } - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (sb->s_flags & MS_SYNCHRONOUS) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -388,7 +388,7 @@ repeat: "bit already set for inode %d", j); goto repeat; } - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (sb->s_flags & MS_SYNCHRONOUS) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -404,7 +404,7 @@ repeat: return NULL; } gdp->bg_free_inodes_count = 0; - mark_buffer_dirty(bh2, 1); + mark_buffer_dirty(bh2); } goto repeat; } @@ -423,10 +423,10 @@ repeat: if (S_ISDIR(mode)) gdp->bg_used_dirs_count = cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1); - mark_buffer_dirty(bh2, 1); + mark_buffer_dirty(bh2); es->s_free_inodes_count = cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1); - mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); + mark_buffer_dirty(sb->u.ext2_sb.s_sbh); sb->s_dirt = 1; inode->i_mode = mode; inode->i_sb = sb; diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 6c89f5090..720597b36 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -245,47 +245,17 @@ static inline Indirect *ext2_get_branch(struct inode *inode, add_chain (chain, NULL, inode->u.ext2_i.i_data + *offsets); if (!p->key) goto no_block; - /* - * switch below is merely an unrolled loop - body should be - * repeated depth-1 times. Maybe loop would be actually better, - * but that way we get straight execution path in normal cases. - * Easy to change, anyway - all cases in switch are literally - * identical. - */ - switch (depth) { - case 4: - bh = bread(dev, le32_to_cpu(p->key), size); - if (!bh) - goto failure; - /* Reader: pointers */ - if (!verify_chain(chain, p)) - goto changed; - add_chain(++p, bh, (u32*)bh->b_data + *++offsets); - /* Reader: end */ - if (!p->key) - goto no_block; - case 3: - bh = bread(dev, le32_to_cpu(p->key), size); - if (!bh) - goto failure; - /* Reader: pointers */ - if (!verify_chain(chain, p)) - goto changed; - add_chain(++p, bh, (u32*)bh->b_data + *++offsets); - /* Reader: end */ - if (!p->key) - goto no_block; - case 2: - bh = bread(dev, le32_to_cpu(p->key), size); - if (!bh) - goto failure; - /* Reader: pointers */ - if (!verify_chain(chain, p)) - goto changed; - add_chain(++p, bh, (u32*)bh->b_data + *++offsets); - /* Reader: end */ - if (!p->key) - goto no_block; + while (--depth) { + bh = bread(dev, le32_to_cpu(p->key), size); + if (!bh) + goto failure; + /* Reader: pointers */ + if (!verify_chain(chain, p)) + goto changed; + add_chain(++p, bh, (u32*)bh->b_data + *++offsets); + /* Reader: end */ + if (!p->key) + goto no_block; } return NULL; @@ -433,7 +403,7 @@ static int ext2_alloc_branch(struct inode *inode, branch[n].p = (u32*) bh->b_data + offsets[n]; *branch[n].p = branch[n].key; mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -498,7 +468,7 @@ static inline int ext2_splice_branch(struct inode *inode, /* had we spliced it onto indirect block? */ if (where->bh) { - mark_buffer_dirty(where->bh, 1); + mark_buffer_dirty(where->bh); if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) { ll_rw_block (WRITE, 1, &where->bh); wait_on_buffer(where->bh); @@ -620,7 +590,7 @@ struct buffer_head * ext2_getblk(struct inode * inode, long block, int create, i wait_on_buffer(bh); memset(bh->b_data, 0, inode->i_sb->s_blocksize); mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); } return bh; } @@ -713,8 +683,8 @@ static inline int all_zeroes(u32 *p, u32 *q) { while (p < q) if (*p++) - return 1; - return 0; + return 0; + return 1; } /** @@ -937,7 +907,7 @@ void ext2_truncate (struct inode * inode) if (partial == chain) mark_inode_dirty(inode); else - mark_buffer_dirty(partial->bh, 1); + mark_buffer_dirty(partial->bh); ext2_free_branches(inode, &nr, &nr+1, (chain+n-1) - partial); } /* Clear the ends of indirect blocks on the shared branch */ @@ -946,7 +916,7 @@ void ext2_truncate (struct inode * inode) partial->p + 1, (u32*)partial->bh->b_data + addr_per_block, (chain+n-1) - partial); - mark_buffer_dirty(partial->bh, 1); + mark_buffer_dirty(partial->bh); if (IS_SYNC(inode)) { ll_rw_block (WRITE, 1, &partial->bh); wait_on_buffer (partial->bh); @@ -1238,7 +1208,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync) raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev)); else for (block = 0; block < EXT2_N_BLOCKS; block++) raw_inode->i_block[block] = inode->u.ext2_i.i_data[block]; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (do_sync) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 44423a620..8028f00a7 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -298,7 +298,7 @@ int ext2_add_entry (struct inode * dir, const char * name, int namelen, dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; mark_inode_dirty(dir); dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -339,7 +339,7 @@ static int ext2_delete_entry (struct inode * dir, else de->inode = 0; dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -451,7 +451,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) strcpy (de->name, ".."); ext2_set_de_type(dir->i_sb, de, S_IFDIR); inode->i_nlink = 2; - mark_buffer_dirty(dir_block, 1); + mark_buffer_dirty(dir_block); brelse (dir_block); inode->i_mode = S_IFDIR | mode; if (dir->i_mode & S_ISGID) @@ -757,7 +757,7 @@ static int ext2_rename (struct inode * old_dir, struct dentry *old_dentry, EXT2_FEATURE_INCOMPAT_FILETYPE)) new_de->file_type = old_de->file_type; new_dir->i_version = ++event; - mark_buffer_dirty(new_bh, 1); + mark_buffer_dirty(new_bh); if (IS_SYNC(new_dir)) { ll_rw_block (WRITE, 1, &new_bh); wait_on_buffer (new_bh); @@ -788,7 +788,7 @@ static int ext2_rename (struct inode * old_dir, struct dentry *old_dentry, mark_inode_dirty(old_dir); if (dir_bh) { PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino); - mark_buffer_dirty(dir_bh, 1); + mark_buffer_dirty(dir_bh); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { diff --git a/fs/ext2/super.c b/fs/ext2/super.c index bca514ee5..f69af1fdd 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -38,7 +38,7 @@ void ext2_error (struct super_block * sb, const char * function, sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS; sb->u.ext2_sb.s_es->s_state = cpu_to_le16(le16_to_cpu(sb->u.ext2_sb.s_es->s_state) | EXT2_ERROR_FS); - mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); + mark_buffer_dirty(sb->u.ext2_sb.s_sbh); sb->s_dirt = 1; } va_start (args, fmt); @@ -68,7 +68,7 @@ NORET_TYPE void ext2_panic (struct super_block * sb, const char * function, sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS; sb->u.ext2_sb.s_es->s_state = cpu_to_le16(le16_to_cpu(sb->u.ext2_sb.s_es->s_state) | EXT2_ERROR_FS); - mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); + mark_buffer_dirty(sb->u.ext2_sb.s_sbh); sb->s_dirt = 1; } va_start (args, fmt); @@ -101,7 +101,7 @@ void ext2_put_super (struct super_block * sb) if (!(sb->s_flags & MS_RDONLY)) { sb->u.ext2_sb.s_es->s_state = le16_to_cpu(sb->u.ext2_sb.s_mount_state); - mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); + mark_buffer_dirty(sb->u.ext2_sb.s_sbh); } db_count = sb->u.ext2_sb.s_db_per_group; for (i = 0; i < db_count; i++) @@ -286,7 +286,7 @@ static int ext2_setup_super (struct super_block * sb, es->s_max_mnt_count = (__s16) cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT); es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1); es->s_mtime = cpu_to_le32(CURRENT_TIME); - mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); + mark_buffer_dirty(sb->u.ext2_sb.s_sbh); sb->s_dirt = 1; if (test_opt (sb, DEBUG)) printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, " @@ -612,7 +612,7 @@ static void ext2_commit_super (struct super_block * sb, struct ext2_super_block * es) { es->s_wtime = cpu_to_le32(CURRENT_TIME); - mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); + mark_buffer_dirty(sb->u.ext2_sb.s_sbh); sb->s_dirt = 0; } @@ -677,7 +677,7 @@ int ext2_remount (struct super_block * sb, int * flags, char * data) */ es->s_state = cpu_to_le16(sb->u.ext2_sb.s_mount_state); es->s_mtime = cpu_to_le32(CURRENT_TIME); - mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); + mark_buffer_dirty(sb->u.ext2_sb.s_sbh); sb->s_dirt = 1; ext2_commit_super (sb, es); } diff --git a/fs/fat/buffer.c b/fs/fat/buffer.c index 7ab13267d..6e8716b1e 100644 --- a/fs/fat/buffer.c +++ b/fs/fat/buffer.c @@ -32,10 +32,9 @@ void fat_brelse (struct super_block *sb, struct buffer_head *bh) } void fat_mark_buffer_dirty ( struct super_block *sb, - struct buffer_head *bh, - int dirty) + struct buffer_head *bh) { - MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty(sb,bh,dirty); + MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty(sb,bh); } void fat_set_uptodate ( struct super_block *sb, @@ -71,10 +70,9 @@ void default_fat_brelse(struct super_block *sb, struct buffer_head *bh) } void default_fat_mark_buffer_dirty ( struct super_block *sb, - struct buffer_head *bh, - int dirty) + struct buffer_head *bh) { - mark_buffer_dirty (bh,dirty); + mark_buffer_dirty (bh); } void default_fat_set_uptodate ( struct super_block *sb, @@ -170,10 +168,9 @@ void bigblock_fat_brelse ( void bigblock_fat_mark_buffer_dirty ( struct super_block *sb, - struct buffer_head *bh, - int dirty) + struct buffer_head *bh) { - mark_buffer_dirty (bh->b_next,dirty); + mark_buffer_dirty (bh->b_next); } void bigblock_fat_set_uptodate ( diff --git a/fs/fat/cache.c b/fs/fat/cache.c index cabb08f76..fd3746920 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -106,16 +106,16 @@ int default_fat_access(struct super_block *sb,int nr,int new_value) *p_first = new_value & 0xff; *p_last = (*p_last & 0xf0) | (new_value >> 8); } - fat_mark_buffer_dirty(sb, bh2, 1); + fat_mark_buffer_dirty(sb, bh2); } - fat_mark_buffer_dirty(sb, bh, 1); + fat_mark_buffer_dirty(sb, bh); for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) { b = MSDOS_SB(sb)->fat_start + (first >> SECTOR_BITS) + MSDOS_SB(sb)->fat_length * copy; if (!(c_bh = fat_bread(sb, b))) break; memcpy(c_bh->b_data,bh->b_data,SECTOR_SIZE); - fat_mark_buffer_dirty(sb, c_bh, 1); + fat_mark_buffer_dirty(sb, c_bh); if (bh != bh2) { if (!(c_bh2 = fat_bread(sb, b+1))) { fat_brelse(sb, c_bh); diff --git a/fs/fat/cvf.c b/fs/fat/cvf.c index 24cf1164f..5bfbaeb64 100644 --- a/fs/fat/cvf.c +++ b/fs/fat/cvf.c @@ -27,9 +27,9 @@ struct buffer_head *bigblock_fat_bread(struct super_block *, int); void default_fat_brelse(struct super_block *, struct buffer_head *); void bigblock_fat_brelse(struct super_block *, struct buffer_head *); void default_fat_mark_buffer_dirty (struct super_block *, - struct buffer_head *, int); + struct buffer_head *); void bigblock_fat_mark_buffer_dirty (struct super_block *, - struct buffer_head *, int); + struct buffer_head *); void default_fat_set_uptodate (struct super_block *, struct buffer_head *,int); void bigblock_fat_set_uptodate (struct super_block *, struct buffer_head *,int); int default_fat_is_uptodate(struct super_block *, struct buffer_head *); diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 5f7a643d7..272baa936 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -679,7 +679,7 @@ int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat) de[0].starthi = CT_LE_W(MSDOS_I(dir)->i_logstart>>16); de[1].start = CT_LE_W(MSDOS_I(parent)->i_logstart); de[1].starthi = CT_LE_W(MSDOS_I(parent)->i_logstart>>16); - fat_mark_buffer_dirty(sb, bh, 1); + fat_mark_buffer_dirty(sb, bh); fat_brelse(sb, bh); dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; mark_inode_dirty(dir); diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 11ac092cb..d1e8557f7 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -898,7 +898,7 @@ retry: raw_entry->cdate = CT_LE_W(raw_entry->cdate); } spin_unlock(&fat_inode_lock); - fat_mark_buffer_dirty(sb, bh, 1); + fat_mark_buffer_dirty(sb, bh); fat_brelse(sb, bh); unlock_kernel(); } diff --git a/fs/fat/misc.c b/fs/fat/misc.c index bca75467b..2213a41fe 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -129,7 +129,7 @@ void fat_clusters_flush(struct super_block *sb) return; } fsinfo->free_clusters = CF_LE_L(MSDOS_SB(sb)->free_clusters); - fat_mark_buffer_dirty(sb, bh, 1); + fat_mark_buffer_dirty(sb, bh); fat_brelse(sb, bh); } @@ -291,7 +291,7 @@ if (last) printk("next set to %d\n",fat_access(sb,last,-1)); else { memset(bh->b_data,0,SECTOR_SIZE); fat_set_uptodate(sb, bh, 1); - fat_mark_buffer_dirty(sb, bh, 1); + fat_mark_buffer_dirty(sb, bh); if (!res) res=bh; else diff --git a/fs/fat/msbuffer.h b/fs/fat/msbuffer.h index 5a052251d..563ee0df2 100644 --- a/fs/fat/msbuffer.h +++ b/fs/fat/msbuffer.h @@ -5,8 +5,7 @@ struct buffer_head *fat_bread (struct super_block *sb, int block); struct buffer_head *fat_getblk (struct super_block *sb, int block); void fat_brelse (struct super_block *sb, struct buffer_head *bh); void fat_mark_buffer_dirty (struct super_block *sb, - struct buffer_head *bh, - int dirty_val); + struct buffer_head *bh); void fat_set_uptodate (struct super_block *sb, struct buffer_head *bh, int val); diff --git a/fs/hfs/file.c b/fs/hfs/file.c index 4d4a3e9b8..35fbac9de 100644 --- a/fs/hfs/file.c +++ b/fs/hfs/file.c @@ -489,7 +489,7 @@ hfs_s32 hfs_do_write(struct inode *inode, struct hfs_fork * fork, hfs_u32 pos, written += c; buf += c; mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 0); + mark_buffer_dirty(bh); brelse(bh); } if (written > 0) { diff --git a/fs/hpfs/anode.c b/fs/hpfs/anode.c index 6fb9c1633..263cce238 100644 --- a/fs/hpfs/anode.c +++ b/fs/hpfs/anode.c @@ -84,7 +84,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi if (btree->internal) { a = btree->u.internal[n].down; btree->u.internal[n].file_secno = -1; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); if (s->s_hpfs_chk) if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_add_sector_to_btree #1")) return -1; @@ -102,7 +102,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi } if (hpfs_alloc_if_possible(s, se = btree->u.external[n].disk_secno + btree->u.external[n].length)) { btree->u.external[n].length++; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); return se; } @@ -139,7 +139,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi btree->first_free = (char *)&(btree->u.internal[1]) - (char *)btree; btree->u.internal[0].file_secno = -1; btree->u.internal[0].down = na; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); } else if (!(ranode = hpfs_alloc_anode(s, /*a*/0, &ra, &bh2))) { brelse(bh); brelse(bh1); @@ -156,7 +156,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi btree->u.external[n].disk_secno = se; btree->u.external[n].file_secno = fs; btree->u.external[n].length = 1; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); if ((a == node && fnod) || na == -1) return se; c2 = 0; @@ -176,14 +176,14 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi btree->u.internal[n].file_secno = -1; btree->u.internal[n].down = na; btree->u.internal[n-1].file_secno = fs; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); brelse(bh2); hpfs_free_sectors(s, ra, 1); if ((anode = hpfs_map_anode(s, na, &bh))) { anode->up = up; anode->btree.fnode_parent = up == node && fnod; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); } return se; @@ -191,7 +191,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi up = up != node ? anode->up : -1; btree->u.internal[btree->n_used_nodes - 1].file_secno = /*fs*/-1; if (up == -1) anode->up = ra; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); a = na; if ((anode = hpfs_alloc_anode(s, a, &na, &bh))) { @@ -202,11 +202,11 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi anode->btree.first_free = 16; anode->btree.u.internal[0].down = a; anode->btree.u.internal[0].file_secno = -1; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); if ((anode = hpfs_map_anode(s, a, &bh))) { anode->up = na; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); } } else na = a; @@ -214,7 +214,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi if ((anode = hpfs_map_anode(s, na, &bh))) { anode->up = node; if (fnod) anode->btree.fnode_parent = 1; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); } if (!fnod) { @@ -239,7 +239,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi if ((unode = hpfs_map_anode(s, ranode->u.internal[n].down, &bh1))) { unode->up = ra; unode->btree.fnode_parent = 0; - mark_buffer_dirty(bh1, 1); + mark_buffer_dirty(bh1); brelse(bh1); } } @@ -251,9 +251,9 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi btree->u.internal[0].down = ra; btree->u.internal[1].file_secno = -1; btree->u.internal[1].down = na; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); - mark_buffer_dirty(bh2, 1); + mark_buffer_dirty(bh2); brelse(bh2); return se; } @@ -367,7 +367,7 @@ int hpfs_ea_write(struct super_block *s, secno a, int ano, unsigned pos, return -1; l = 0x200 - (pos & 0x1ff); if (l > len) l = len; memcpy(data + (pos & 0x1ff), buf, l); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); buf += l; pos += l; len -= l; } @@ -411,7 +411,7 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs) btree->n_used_nodes = 0; btree->first_free = 8; btree->internal = 0; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); } else hpfs_free_sectors(s, f, 1); brelse(bh); return; @@ -429,7 +429,7 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs) btree->n_used_nodes = i + 1; btree->n_free_nodes = nodes - btree->n_used_nodes; btree->first_free = 8 + 8 * btree->n_used_nodes; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (btree->u.internal[i].file_secno == secs) { brelse(bh); return; @@ -463,7 +463,7 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs) btree->n_used_nodes = i + 1; btree->n_free_nodes = nodes - btree->n_used_nodes; btree->first_free = 8 + 12 * btree->n_used_nodes; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); } diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c index 7ea14e4c4..43eb2cb57 100644 --- a/fs/hpfs/buffer.c +++ b/fs/hpfs/buffer.c @@ -261,8 +261,8 @@ void hpfs_mark_4buffers_dirty(struct quad_buffer_head *qbh) memcpy(qbh->bh[1]->b_data, qbh->data + 512, 512); memcpy(qbh->bh[2]->b_data, qbh->data + 2 * 512, 512); memcpy(qbh->bh[3]->b_data, qbh->data + 3 * 512, 512); - mark_buffer_dirty(qbh->bh[0],1); - mark_buffer_dirty(qbh->bh[1],1); - mark_buffer_dirty(qbh->bh[2],1); - mark_buffer_dirty(qbh->bh[3],1); + mark_buffer_dirty(qbh->bh[0]); + mark_buffer_dirty(qbh->bh[1]); + mark_buffer_dirty(qbh->bh[2]); + mark_buffer_dirty(qbh->bh[3]); } diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c index d1ca8e3e6..78286ad36 100644 --- a/fs/hpfs/dnode.c +++ b/fs/hpfs/dnode.c @@ -337,7 +337,7 @@ int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, unsigned char *name, uns return 1; } fnode->u.external[0].disk_secno = rdno; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); d->up = ad->up = i->i_hpfs_dno = rdno; d->root_dnode = ad->root_dnode = 0; @@ -535,7 +535,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) } if ((fnode = hpfs_map_fnode(i->i_sb, up, &bh))) { fnode->u.external[0].disk_secno = down; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); } i->i_hpfs_dno = down; diff --git a/fs/hpfs/ea.c b/fs/hpfs/ea.c index 9632c054c..6c21acfb0 100644 --- a/fs/hpfs/ea.c +++ b/fs/hpfs/ea.c @@ -277,7 +277,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, char *key, char *data fnode->ea_size_s = 0; fnode->ea_secno = n; fnode->ea_anode = 0; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); } pos = fnode->ea_size_l + 5 + strlen(key) + size; @@ -307,7 +307,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, char *key, char *data anode->u.external[0].disk_secno = fnode->ea_secno; anode->u.external[0].file_secno = 0; anode->u.external[0].length = len; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); fnode->ea_anode = 1; fnode->ea_secno = a_s;*/ @@ -329,7 +329,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, char *key, char *data } memcpy(b2, b1, 512); brelse(bh1); - mark_buffer_dirty(bh2, 1); + mark_buffer_dirty(bh2); brelse(bh2); } hpfs_free_sectors(s, fnode->ea_secno, len); diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index a9f085863..06f5d0783 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c @@ -291,7 +291,7 @@ void hpfs_write_inode_nolock(struct inode *i) hpfs_brelse4(&qbh); } else hpfs_error(i->i_sb, "directory %08x doesn't have '.' entry", i->i_ino); } - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); } diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index c912126d7..3438cdb85 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c @@ -62,7 +62,7 @@ int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) de->first = de->directory = 1; /*de->hidden = de->system = 0;*/ de->fnode = fno; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); hpfs_mark_4buffers_dirty(&qbh0); hpfs_brelse4(&qbh0); @@ -128,7 +128,7 @@ int hpfs_create(struct inode *dir, struct dentry *dentry, int mode) fnode->len = len; memcpy(fnode->name, name, len > 15 ? 15 : len); fnode->up = dir->i_ino; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); hpfs_lock_iget(dir->i_sb, 2); if ((result = iget(dir->i_sb, fno))) { @@ -196,7 +196,7 @@ int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev) fnode->len = len; memcpy(fnode->name, name, len > 15 ? 15 : len); fnode->up = dir->i_ino; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); hpfs_lock_iget(dir->i_sb, 2); if ((result = iget(dir->i_sb, fno))) { result->i_hpfs_parent_dir = dir->i_ino; @@ -258,7 +258,7 @@ int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink) fnode->len = len; memcpy(fnode->name, name, len > 15 ? 15 : len); fnode->up = dir->i_ino; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); hpfs_lock_iget(dir->i_sb, 2); if ((result = iget(dir->i_sb, fno))) { @@ -276,7 +276,7 @@ int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink) result->i_data.a_ops = &hpfs_symlink_aops; if ((fnode = hpfs_map_fnode(dir->i_sb, fno, &bh))) { hpfs_set_ea(result, fnode, "SYMLINK", (char *)symlink, strlen(symlink)); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); } hpfs_write_inode_nolock(result); @@ -523,7 +523,7 @@ int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, fnode->len = new_len; memcpy(fnode->name, new_name, new_len>15?15:new_len); if (new_len < 15) memset(&fnode->name[new_len], 0, 15 - new_len); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); } i->i_hpfs_conv = i->i_sb->s_hpfs_conv; diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 04cd6428d..a5db0acd3 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -21,7 +21,7 @@ static void mark_dirty(struct super_block *s) if ((sb = hpfs_map_sector(s, 17, &bh, 0))) { sb->dirty = 1; sb->old_wrote = 0; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); } } @@ -38,7 +38,7 @@ static void unmark_dirty(struct super_block *s) if ((sb = hpfs_map_sector(s, 17, &bh, 0))) { sb->dirty = s->s_hpfs_chkdsk > 1 - s->s_hpfs_was_error; sb->old_wrote = s->s_hpfs_chkdsk >= 2 && !s->s_hpfs_was_error; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); } } @@ -466,7 +466,7 @@ struct super_block *hpfs_read_super(struct super_block *s, void *options, if (!(s->s_flags & MS_RDONLY)) { spareblock->dirty = 1; spareblock->old_wrote = 0; - mark_buffer_dirty(bh2, 1); + mark_buffer_dirty(bh2); } if (spareblock->hotfixes_used || spareblock->n_spares_used) { diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index fa2bd5f03..27e893ac7 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c @@ -85,7 +85,7 @@ void minix_free_block(struct inode * inode, int block) kdevname(sb->s_dev), block); else DQUOT_FREE_BLOCK(sb, inode, 1); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); return; } @@ -117,7 +117,7 @@ repeat: DQUOT_FREE_BLOCK(sb, inode, 1); goto repeat; } - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); j += i*8192 + sb->u.minix_sb.s_firstdatazone-1; if (j < sb->u.minix_sb.s_firstdatazone || j >= sb->u.minix_sb.s_nzones) @@ -156,7 +156,7 @@ static struct buffer_head *V1_minix_clear_inode(struct inode *inode) (ino - 1) % MINIX_INODES_PER_BLOCK); raw_inode->i_nlinks = 0; raw_inode->i_mode = 0; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); return bh; } @@ -184,7 +184,7 @@ static struct buffer_head *V2_minix_clear_inode(struct inode *inode) (ino - 1) % MINIX2_INODES_PER_BLOCK); raw_inode->i_nlinks = 0; raw_inode->i_mode = 0; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); return bh; } @@ -223,7 +223,7 @@ void minix_free_inode(struct inode * inode) clear_inode(inode); if (!minix_test_and_clear_bit(ino & 8191, bh->b_data)) printk("free_inode: bit %lu already cleared.\n",ino); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); } struct inode * minix_new_inode(const struct inode * dir, int * error) @@ -258,7 +258,7 @@ struct inode * minix_new_inode(const struct inode * dir, int * error) unlock_super(sb); return NULL; } - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); j += i*8192; if (!j || j > inode->i_sb->u.minix_sb.s_ninodes) { iput(inode); diff --git a/fs/minix/inode.c b/fs/minix/inode.c index b49626923..36d5be213 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -45,7 +45,7 @@ static void minix_delete_inode(struct inode *inode) static void minix_commit_super(struct super_block * sb) { - mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1); + mark_buffer_dirty(sb->u.minix_sb.s_sbh); sb->s_dirt = 0; } @@ -70,7 +70,7 @@ static void minix_put_super(struct super_block *sb) if (!(sb->s_flags & MS_RDONLY)) { sb->u.minix_sb.s_ms->s_state = sb->u.minix_sb.s_mount_state; - mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1); + mark_buffer_dirty(sb->u.minix_sb.s_sbh); } for (i = 0; i < sb->u.minix_sb.s_imap_blocks; i++) brelse(sb->u.minix_sb.s_imap[i]); @@ -105,7 +105,7 @@ static int minix_remount (struct super_block * sb, int * flags, char * data) return 0; /* Mounting a rw partition read-only. */ ms->s_state = sb->u.minix_sb.s_mount_state; - mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1); + mark_buffer_dirty(sb->u.minix_sb.s_sbh); sb->s_dirt = 1; minix_commit_super(sb); } @@ -113,7 +113,7 @@ static int minix_remount (struct super_block * sb, int * flags, char * data) /* Mount a partition which is read-only, read-write. */ sb->u.minix_sb.s_mount_state = ms->s_state; ms->s_state &= ~MINIX_VALID_FS; - mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1); + mark_buffer_dirty(sb->u.minix_sb.s_sbh); sb->s_dirt = 1; if (!(sb->u.minix_sb.s_mount_state & MINIX_VALID_FS)) @@ -279,7 +279,7 @@ static struct super_block *minix_read_super(struct super_block *s, void *data, if (!(s->s_flags & MS_RDONLY)) { ms->s_state &= ~MINIX_VALID_FS; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); s->s_dirt = 1; } if (!(s->u.minix_sb.s_mount_state & MINIX_VALID_FS)) @@ -520,7 +520,7 @@ repeat: } memset(result->b_data, 0, BLOCK_SIZE); mark_buffer_uptodate(result, 1); - mark_buffer_dirty(result, 1); + mark_buffer_dirty(result); } else { if (*p) { /* @@ -588,7 +588,7 @@ repeat: } memset(result->b_data, 0, BLOCK_SIZE); mark_buffer_uptodate(result, 1); - mark_buffer_dirty(result, 1); + mark_buffer_dirty(result); } else { *phys = tmp; *new = 1; @@ -600,7 +600,7 @@ repeat: } *p = tmp; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); *err = 0; out: brelse(bh); @@ -731,7 +731,7 @@ repeat: } memset(result->b_data, 0, BLOCK_SIZE); mark_buffer_uptodate(result, 1); - mark_buffer_dirty(result, 1); + mark_buffer_dirty(result); } else { if (*p) { /* @@ -799,7 +799,7 @@ repeat: } memset(result->b_data, 0, BLOCK_SIZE); mark_buffer_uptodate(result, 1); - mark_buffer_dirty(result, 1); + mark_buffer_dirty(result); } else { *phys = tmp; *new = 1; @@ -811,7 +811,7 @@ repeat: } *p = tmp; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); *err = 0; out: brelse(bh); @@ -934,7 +934,7 @@ struct buffer_head *minix_getblk(struct inode *inode, int block, int create) if (buffer_new(&dummy)) { memset(bh->b_data, 0, BLOCK_SIZE); mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); } return bh; } @@ -1130,7 +1130,7 @@ static struct buffer_head * V1_minix_update_inode(struct inode * inode) raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev); else for (block = 0; block < 9; block++) raw_inode->i_zone[block] = inode->u.minix_i.u.i1_data[block]; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); return bh; } @@ -1170,7 +1170,7 @@ static struct buffer_head * V2_minix_update_inode(struct inode * inode) raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev); else for (block = 0; block < 10; block++) raw_inode->i_zone[block] = inode->u.minix_i.u.i2_data[block]; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); return bh; } diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 0de210186..0f9c2a786 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -187,7 +187,7 @@ static int minix_add_entry(struct inode * dir, for (i = 0; i < info->s_namelen ; i++) de->name[i] = (i < namelen) ? name[i] : 0; dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); *res_dir = de; break; } @@ -228,7 +228,7 @@ static int minix_create(struct inode * dir, struct dentry *dentry, int mode) return error; } de->inode = inode->i_ino; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); d_instantiate(dentry, inode); return 0; @@ -257,7 +257,7 @@ static int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int return error; } de->inode = inode->i_ino; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); d_instantiate(dentry, inode); return 0; @@ -296,7 +296,7 @@ static int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode) de->inode = dir->i_ino; strcpy(de->name,".."); inode->i_nlink = 2; - mark_buffer_dirty(dir_block, 1); + mark_buffer_dirty(dir_block); brelse(dir_block); inode->i_mode = S_IFDIR | mode; if (dir->i_mode & S_ISGID) @@ -310,7 +310,7 @@ static int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode) return error; } de->inode = inode->i_ino; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); dir->i_nlink++; mark_inode_dirty(dir); brelse(bh); @@ -403,7 +403,7 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry) printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink); de->inode = 0; dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); inode->i_nlink=0; mark_inode_dirty(inode); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; @@ -437,7 +437,7 @@ static int minix_unlink(struct inode * dir, struct dentry *dentry) } de->inode = 0; dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); dir->i_ctime = dir->i_mtime = CURRENT_TIME; mark_inode_dirty(dir); inode->i_nlink--; @@ -482,7 +482,7 @@ static int minix_symlink(struct inode * dir, struct dentry *dentry, goto fail; de->inode = inode->i_ino; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); d_instantiate(dentry, inode); out: @@ -515,7 +515,7 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir, return error; } de->inode = inode->i_ino; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); inode->i_nlink++; inode->i_ctime = CURRENT_TIME; @@ -600,11 +600,11 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, new_inode->i_ctime = CURRENT_TIME; mark_inode_dirty(new_inode); } - mark_buffer_dirty(old_bh, 1); - mark_buffer_dirty(new_bh, 1); + mark_buffer_dirty(old_bh); + mark_buffer_dirty(new_bh); if (dir_bh) { PARENT_INO(dir_bh->b_data) = new_dir->i_ino; - mark_buffer_dirty(dir_bh, 1); + mark_buffer_dirty(dir_bh); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { diff --git a/fs/minix/truncate.c b/fs/minix/truncate.c index 70b01dc20..3f9f2cb85 100644 --- a/fs/minix/truncate.c +++ b/fs/minix/truncate.c @@ -109,7 +109,7 @@ repeat: continue; } *ind = 0; - mark_buffer_dirty(ind_bh, 1); + mark_buffer_dirty(ind_bh); bforget(bh); minix_free_block(inode,tmp); } @@ -156,7 +156,7 @@ repeat: goto repeat; dind = i+(unsigned short *) dind_bh->b_data; retry |= V1_trunc_indirect(inode,offset+(i<<9),dind); - mark_buffer_dirty(dind_bh, 1); + mark_buffer_dirty(dind_bh); } dind = (unsigned short *) dind_bh->b_data; for (i = 0; i < 512; i++) @@ -270,7 +270,7 @@ repeat: continue; } *ind = 0; - mark_buffer_dirty(ind_bh, 1); + mark_buffer_dirty(ind_bh); bforget(bh); minix_free_block(inode,tmp); } @@ -317,7 +317,7 @@ repeat: goto repeat; dind = i+(unsigned long *) dind_bh->b_data; retry |= V2_trunc_indirect(inode,offset+(i<<8),dind); - mark_buffer_dirty(dind_bh, 1); + mark_buffer_dirty(dind_bh); } dind = (unsigned long *) dind_bh->b_data; for (i = 0; i < 256; i++) @@ -363,7 +363,7 @@ repeat: goto repeat; tind = i+(unsigned long *) tind_bh->b_data; retry |= V2_trunc_dindirect(inode,offset+(i<<8),tind); - mark_buffer_dirty(tind_bh, 1); + mark_buffer_dirty(tind_bh); } tind = (unsigned long *) tind_bh->b_data; for (i = 0; i < 256; i++) diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 79f700650..d7e77a316 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c @@ -265,7 +265,7 @@ static int msdos_add_entry(struct inode *dir, const char *name, (*de)->starthi = 0; fat_date_unix2dos(dir->i_mtime,&(*de)->time,&(*de)->date); (*de)->size = 0; - fat_mark_buffer_dirty(sb, *bh, 1); + fat_mark_buffer_dirty(sb, *bh); return 0; } @@ -330,7 +330,7 @@ int msdos_rmdir(struct inode *dir, struct dentry *dentry) goto rmdir_done; de->name[0] = DELETED_FLAG; - fat_mark_buffer_dirty(sb, bh, 1); + fat_mark_buffer_dirty(sb, bh); fat_detach(inode); inode->i_nlink = 0; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; @@ -396,7 +396,7 @@ mkdir_error: mark_inode_dirty(inode); mark_inode_dirty(dir); de->name[0] = DELETED_FLAG; - fat_mark_buffer_dirty(sb, bh, 1); + fat_mark_buffer_dirty(sb, bh); fat_brelse(sb, bh); fat_detach(inode); iput(inode); @@ -424,7 +424,7 @@ int msdos_unlink( struct inode *dir, struct dentry *dentry) goto unlink_done; de->name[0] = DELETED_FLAG; - fat_mark_buffer_dirty(sb, bh, 1); + fat_mark_buffer_dirty(sb, bh); fat_detach(inode); fat_brelse(sb, bh); inode->i_nlink = 0; @@ -485,7 +485,7 @@ static int do_msdos_rename(struct inode *old_dir, char *old_name, if (new_inode) fat_detach(new_inode); old_de->name[0] = DELETED_FLAG; - fat_mark_buffer_dirty(sb, old_bh, 1); + fat_mark_buffer_dirty(sb, old_bh); fat_detach(old_inode); fat_attach(old_inode, new_ino); if (is_hid) @@ -504,7 +504,7 @@ static int do_msdos_rename(struct inode *old_dir, char *old_name, if (dotdot_bh) { dotdot_de->start = CT_LE_W(MSDOS_I(new_dir)->i_logstart); dotdot_de->starthi = CT_LE_W((MSDOS_I(new_dir)->i_logstart) >> 16); - fat_mark_buffer_dirty(sb, dotdot_bh, 1); + fat_mark_buffer_dirty(sb, dotdot_bh); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 64ef9274b..52283d234 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile @@ -9,7 +9,7 @@ O_TARGET := nfs.o O_OBJS := inode.o file.o read.o write.o dir.o symlink.o proc.o \ - nfs2xdr.o flushd.o + nfs2xdr.o flushd.o unlink.o ifdef CONFIG_ROOT_NFS O_OBJS += nfsroot.o mount_clnt.o diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 11b8e5d79..e370587be 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -606,16 +606,8 @@ static void nfs_dentry_release(struct dentry *dentry) static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) { if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { - struct dentry *dir = dentry->d_parent; - struct inode *dir_i = dir->d_inode; - int error; - lock_kernel(); - dir = dentry->d_parent; - dir_i = dir->d_inode; - nfs_zap_caches(dir_i); - NFS_CACHEINV(inode); - error = NFS_PROTO(dir_i)->remove(dir, &dentry->d_name); + nfs_complete_unlink(dentry); unlock_kernel(); } iput(inode); @@ -868,7 +860,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name); if (!error) { nfs_renew_times(dentry); d_move(dentry, sdentry); - dentry->d_flags |= DCACHE_NFSFS_RENAMED; + error = nfs_async_unlink(dentry); /* If we return 0 we don't unlink */ } dput(sdentry); diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 42191418f..369509a1f 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -267,6 +267,34 @@ nfs3_proc_remove(struct dentry *dir, struct qstr *name) } static int +nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name) +{ + struct nfs3_diropargs *arg; + struct nfs_fattr *res; + + arg = (struct nfs3_diropargs *)kmalloc(sizeof(*arg)+sizeof(*res), GFP_KERNEL); + if (!arg) + return -ENOMEM; + res = (struct nfs_fattr*)(arg + 1); + arg->fh = NFS_FH(dir); + arg->name = name->name; + arg->len = name->len; + msg->rpc_proc = NFS3PROC_REMOVE; + msg->rpc_argp = arg; + msg->rpc_resp = res; + return 0; +} + +static void +nfs3_proc_unlink_done(struct dentry *dir, struct rpc_message *msg) +{ + struct nfs_fattr *dir_attr = (struct nfs_fattr*)msg->rpc_resp; + + nfs_refresh_inode(dir->d_inode, dir_attr); + kfree(msg->rpc_argp); +} + +static int nfs3_proc_rename(struct dentry *old_dir, struct qstr *old_name, struct dentry *new_dir, struct qstr *new_name) { @@ -469,6 +497,8 @@ struct nfs_rpc_ops nfs_v3_clientops = { NULL, /* commit */ nfs3_proc_create, nfs3_proc_remove, + nfs3_proc_unlink_setup, + nfs3_proc_unlink_done, nfs3_proc_rename, nfs3_proc_link, nfs3_proc_symlink, diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 574c26a15..80ae95674 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -233,6 +233,29 @@ nfs_proc_remove(struct dentry *dir, struct qstr *name) } static int +nfs_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name) +{ + struct nfs_diropargs *arg; + + arg = (struct nfs_diropargs *)kmalloc(sizeof(*arg), GFP_KERNEL); + if (!arg) + return -ENOMEM; + arg->fh = NFS_FH(dir); + arg->name = name->name; + arg->len = name->len; + msg->rpc_proc = NFSPROC_REMOVE; + msg->rpc_argp = arg; + return 0; +} + +static void +nfs_proc_unlink_done(struct dentry *dir, struct rpc_message *msg) +{ + NFS_CACHEINV(dir->d_inode); + kfree(msg->rpc_argp); +} + +static int nfs_proc_rename(struct dentry *old_dir, struct qstr *old_name, struct dentry *new_dir, struct qstr *new_name) { @@ -365,6 +388,8 @@ struct nfs_rpc_ops nfs_v2_clientops = { NULL, /* commit */ nfs_proc_create, nfs_proc_remove, + nfs_proc_unlink_setup, + nfs_proc_unlink_done, nfs_proc_rename, nfs_proc_link, nfs_proc_symlink, diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c new file mode 100644 index 000000000..8739762b0 --- /dev/null +++ b/fs/nfs/unlink.c @@ -0,0 +1,212 @@ +/* + * linux/fs/nfs/unlink.c + * + * nfs sillydelete handling + * + * NOTE: we rely on holding the BKL for list manipulation protection. + */ + +#include +#include +#include +#include +#include +#include + + +struct nfs_unlinkdata { + struct nfs_unlinkdata *next; + struct dentry *dir, *dentry; + struct qstr name; + struct rpc_task task; + struct rpc_cred *cred; + unsigned int count; +}; + +static struct nfs_unlinkdata *nfs_deletes = NULL; +static struct rpc_wait_queue nfs_delete_queue = RPC_INIT_WAITQ("nfs_delete_queue"); + +/** + * nfs_detach_unlinkdata - Remove asynchronous unlink from global list + * @data: pointer to descriptor + */ +static inline void +nfs_detach_unlinkdata(struct nfs_unlinkdata *data) +{ + struct nfs_unlinkdata **q; + + for (q = &nfs_deletes; *q != NULL; q = &((*q)->next)) { + if (*q == data) { + *q = data->next; + break; + } + } +} + +/** + * nfs_put_unlinkdata - release data from a sillydelete operation. + * @data: pointer to unlink structure. + */ +static void +nfs_put_unlinkdata(struct nfs_unlinkdata *data) +{ + if (--data->count == 0) { + nfs_detach_unlinkdata(data); + if (data->name.name != NULL) + kfree(data->name.name); + kfree(data); + } +} + +#define NAME_ALLOC_LEN(len) ((len+16) & ~15) +/** + * nfs_copy_dname - copy dentry name to data structure + * @dentry: pointer to dentry + * @data: nfs_unlinkdata + */ +static inline void +nfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data) +{ + char *str; + int len = dentry->d_name.len; + + str = kmalloc(NAME_ALLOC_LEN(len), GFP_KERNEL); + if (!str) + return; + memcpy(str, dentry->d_name.name, len); + if (!data->name.len) { + data->name.len = len; + data->name.name = str; + } else + kfree(str); +} + +/** + * nfs_async_unlink_init - Initialize the RPC info + * @task: rpc_task of the sillydelete + * + * We delay initializing RPC info until after the call to dentry_iput() + * in order to minimize races against rename(). + */ +static void +nfs_async_unlink_init(struct rpc_task *task) +{ + struct nfs_unlinkdata *data = (struct nfs_unlinkdata *)task->tk_calldata; + struct dentry *dir = data->dir; + struct rpc_message msg; + int status = -ENOENT; + + if (!data->name.len) + goto out_err; + + memset(&msg, 0, sizeof(msg)); + msg.rpc_cred = data->cred; + status = NFS_PROTO(dir->d_inode)->unlink_setup(&msg, dir, &data->name); + if (status < 0) + goto out_err; + rpc_call_setup(task, &msg, 0); + return; + out_err: + rpc_exit(task, status); +} + +/** + * nfs_async_unlink_done - Sillydelete post-processing + * @task: rpc_task of the sillydelete + * + * Do the directory attribute update. + */ +static void +nfs_async_unlink_done(struct rpc_task *task) +{ + struct nfs_unlinkdata *data = (struct nfs_unlinkdata *)task->tk_calldata; + struct dentry *dir = data->dir; + struct inode *dir_i = dir->d_inode; + + nfs_zap_caches(dir_i); + NFS_PROTO(dir_i)->unlink_done(dir, &task->tk_msg); + rpcauth_releasecred(task->tk_auth, data->cred); + data->cred = NULL; + dput(dir); +} + +/** + * nfs_async_unlink_release - Release the sillydelete data. + * @task: rpc_task of the sillydelete + * + * We need to call nfs_put_unlinkdata as a 'tk_release' task since the + * rpc_task would be freed too. + */ +static void +nfs_async_unlink_release(struct rpc_task *task) +{ + struct nfs_unlinkdata *data = (struct nfs_unlinkdata *)task->tk_calldata; + nfs_put_unlinkdata(data); +} + +/** + * nfs_async_unlink - asynchronous unlinking of a file + * @dir: directory in which the file resides. + * @name: name of the file to unlink. + */ +int +nfs_async_unlink(struct dentry *dentry) +{ + struct dentry *dir = dentry->d_parent; + struct nfs_unlinkdata *data; + struct rpc_task *task; + struct rpc_clnt *clnt = NFS_CLIENT(dir->d_inode); + int status = -ENOMEM; + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + goto out; + memset(data, 0, sizeof(*data)); + + data->dir = dget(dir); + data->dentry = dentry; + + data->next = nfs_deletes; + nfs_deletes = data; + data->count = 1; + + task = &data->task; + rpc_init_task(task, clnt, nfs_async_unlink_done , RPC_TASK_ASYNC); + task->tk_calldata = data; + task->tk_action = nfs_async_unlink_init; + task->tk_release = nfs_async_unlink_release; + + dentry->d_flags |= DCACHE_NFSFS_RENAMED; + data->cred = rpcauth_lookupcred(clnt->cl_auth, 0); + + rpc_sleep_on(&nfs_delete_queue, task, NULL, NULL); + status = 0; + out: + return status; +} + +/** + * nfs_complete_remove - Initialize completion of the sillydelete + * @dentry: dentry to delete + * + * Since we're most likely to be called by dentry_iput(), we + * only use the dentry to find the sillydelete. We then copy the name + * into the qstr. + */ +void +nfs_complete_unlink(struct dentry *dentry) +{ + struct nfs_unlinkdata *data; + + for(data = nfs_deletes; data != NULL; data = data->next) { + if (dentry == data->dentry) + break; + } + if (!data) + return; + data->count++; + nfs_copy_dname(dentry, data); + if (data->task.tk_rpcwait == &nfs_delete_queue) + rpc_wake_up_task(&data->task); + nfs_put_unlinkdata(data); +} diff --git a/fs/ntfs/support.c b/fs/ntfs/support.c index 274465573..7e96f21ee 100644 --- a/fs/ntfs/support.c +++ b/fs/ntfs/support.c @@ -177,7 +177,7 @@ int ntfs_getput_clusters(ntfs_volume *vol, int cluster, ntfs_size_t start_offs, else { buf->fn_get(bh->b_data+start_offs,buf,to_copy); - mark_buffer_dirty(bh,1); + mark_buffer_dirty(bh); } unlock_buffer(bh); length-=to_copy; diff --git a/fs/qnx4/bitmap.c b/fs/qnx4/bitmap.c index 03e89e64d..09b94399a 100644 --- a/fs/qnx4/bitmap.c +++ b/fs/qnx4/bitmap.c @@ -134,7 +134,7 @@ int qnx4_set_bitmap(struct super_block *sb, long block, int busy) } else { (*g) |= (1 << (block % 8)); } - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); return 0; diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 34bfbaa6c..78dbc34f0 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -112,7 +112,7 @@ static void qnx4_write_inode(struct inode *inode, int unused) raw_inode->di_atime = cpu_to_le32(inode->i_atime); raw_inode->di_ctime = cpu_to_le32(inode->i_ctime); raw_inode->di_first_xtnt.xtnt_size = cpu_to_le32(inode->i_blocks); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); unlock_kernel(); } @@ -149,7 +149,7 @@ static int qnx4_remount(struct super_block *sb, int *flags, char *data) if (*flags & MS_RDONLY) { return 0; } - mark_buffer_dirty(qs->sb_buf, 1); + mark_buffer_dirty(qs->sb_buf); return 0; } diff --git a/fs/qnx4/namei.c b/fs/qnx4/namei.c index 3ef38467c..7366b757f 100644 --- a/fs/qnx4/namei.c +++ b/fs/qnx4/namei.c @@ -178,7 +178,7 @@ int qnx4_rmdir(struct inode *dir, struct dentry *dentry) de->di_status = 0; memset(de->di_fname, 0, sizeof de->di_fname); de->di_mode = 0; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); inode->i_nlink = 0; mark_inode_dirty(inode); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; @@ -221,7 +221,7 @@ int qnx4_unlink(struct inode *dir, struct dentry *dentry) de->di_status = 0; memset(de->di_fname, 0, sizeof de->di_fname); de->di_mode = 0; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); dir->i_ctime = dir->i_mtime = CURRENT_TIME; mark_inode_dirty(dir); inode->i_nlink--; diff --git a/fs/sysv/balloc.c b/fs/sysv/balloc.c index f5240a75c..978bc2a91 100644 --- a/fs/sysv/balloc.c +++ b/fs/sysv/balloc.c @@ -83,7 +83,7 @@ void sysv_free_block(struct super_block * sb, unsigned int block) } *flc_count = *sb->sv_sb_flc_count; /* = sb->sv_flc_size */ memcpy(flc_blocks, sb->sv_sb_flc_blocks, *flc_count * sizeof(sysv_zone_t)); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); mark_buffer_uptodate(bh, 1); brelse(bh); *sb->sv_sb_flc_count = 0; @@ -100,7 +100,7 @@ void sysv_free_block(struct super_block * sb, unsigned int block) } memset(bh->b_data, 0, sb->sv_block_size); /* this implies ((struct ..._freelist_chunk *) bh->b_data)->flc_count = 0; */ - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); mark_buffer_uptodate(bh, 1); brelse(bh); /* still *sb->sv_sb_flc_count = 0 */ @@ -119,8 +119,8 @@ void sysv_free_block(struct super_block * sb, unsigned int block) to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) + 1); else *sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks + 1; - mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */ - if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1); + mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */ + if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2); sb->s_dirt = 1; /* and needs time stamp */ unlock_super(sb); } @@ -207,7 +207,7 @@ int sysv_new_block(struct super_block * sb) return 0; } memset(bh->b_data, 0, sb->sv_block_size); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); mark_buffer_uptodate(bh, 1); brelse(bh); if (sb->sv_convert) @@ -215,8 +215,8 @@ int sysv_new_block(struct super_block * sb) to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) - 1); else *sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks - 1; - mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */ - if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1); + mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */ + if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2); sb->s_dirt = 1; /* and needs time stamp */ unlock_super(sb); return block; @@ -311,7 +311,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb) printk("sysv_count_free_blocks: free block count was %d, correcting to %d\n",old_count,count); if (!(sb->s_flags & MS_RDONLY)) { *sb->sv_sb_total_free_blocks = (sb->sv_convert ? to_coh_ulong(count) : count); - mark_buffer_dirty(sb->sv_bh2, 1); /* super-block has been modified */ + mark_buffer_dirty(sb->sv_bh2); /* super-block has been modified */ sb->s_dirt = 1; /* and needs time stamp */ } } diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c index bbd88336c..8469366cf 100644 --- a/fs/sysv/ialloc.c +++ b/fs/sysv/ialloc.c @@ -74,11 +74,11 @@ void sysv_free_inode(struct inode * inode) if (*sb->sv_sb_fic_count < sb->sv_fic_size) *sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)++) = ino; (*sb->sv_sb_total_free_inodes)++; - mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */ - if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1); + mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */ + if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2); sb->s_dirt = 1; /* and needs time stamp */ memset(raw_inode, 0, sizeof(struct sysv_inode)); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); unlock_super(sb); brelse(bh); } @@ -128,8 +128,8 @@ struct inode * sysv_new_inode(const struct inode * dir) } /* Now *sb->sv_sb_fic_count > 0. */ ino = *sv_sb_fic_inode(sb,--(*sb->sv_sb_fic_count)); - mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */ - if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1); + mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */ + if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2); sb->s_dirt = 1; /* and needs time stamp */ inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; @@ -147,7 +147,7 @@ struct inode * sysv_new_inode(const struct inode * dir) mark_inode_dirty(inode); /* cleared by sysv_write_inode() */ /* That's it. */ (*sb->sv_sb_total_free_inodes)--; - mark_buffer_dirty(sb->sv_bh2, 1); /* super-block has been modified again */ + mark_buffer_dirty(sb->sv_bh2); /* super-block has been modified again */ sb->s_dirt = 1; /* and needs time stamp again */ unlock_super(sb); return inode; @@ -185,7 +185,7 @@ unsigned long sysv_count_free_inodes(struct super_block * sb) printk("sysv_count_free_inodes: free inode count was %d, correcting to %d\n",(short)(*sb->sv_sb_total_free_inodes),count); if (!(sb->s_flags & MS_RDONLY)) { *sb->sv_sb_total_free_inodes = count; - mark_buffer_dirty(sb->sv_bh2, 1); /* super-block has been modified */ + mark_buffer_dirty(sb->sv_bh2); /* super-block has been modified */ sb->s_dirt = 1; /* and needs time stamp */ } } diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index b7a1068ce..7e5f6c54a 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -532,7 +532,7 @@ static void sysv_write_super(struct super_block *sb) if (sb->sv_convert) time = to_coh_ulong(time); *sb->sv_sb_time = time; - mark_buffer_dirty(sb->sv_bh2, 1); + mark_buffer_dirty(sb->sv_bh2); } sb->s_dirt = 0; } @@ -769,7 +769,7 @@ repeat: } memset(result->b_data, 0, sb->sv_block_size); mark_buffer_uptodate(result, 1); - mark_buffer_dirty(result, 1); + mark_buffer_dirty(result); } else { *phys = tmp; *new = 1; @@ -780,7 +780,7 @@ repeat: goto repeat; } *p = (sb->sv_convert ? to_coh_ulong(block) : block); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); *err = 0; out: brelse(bh); @@ -894,7 +894,7 @@ static struct buffer_head *sysv_getblk(struct inode *inode, unsigned int block, if (buffer_new(&dummy)) { memset(bh->b_data, 0, inode->i_sb->sv_block_size); mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); } return bh; } @@ -1126,7 +1126,7 @@ static struct buffer_head * sysv_update_inode(struct inode * inode) else for (block = 0; block < 10+1+1+1; block++) write3byte(&raw_inode->i_a.i_addb[3*block],inode->u.sysv_i.i_data[block]); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); return bh; } diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index 517371319..aba233768 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c @@ -179,7 +179,7 @@ static int sysv_add_entry(struct inode * dir, mark_inode_dirty(dir); for (i = 0; i < SYSV_NAMELEN ; i++) de->name[i] = (i < namelen) ? name[i] : 0; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); *res_dir = de; break; } @@ -217,7 +217,7 @@ static int sysv_create(struct inode * dir, struct dentry * dentry, int mode) return error; } de->inode = inode->i_ino; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); d_instantiate(dentry, inode); return 0; @@ -251,7 +251,7 @@ static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int return error; } de->inode = inode->i_ino; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); d_instantiate(dentry, inode); return 0; @@ -292,7 +292,7 @@ static int sysv_mkdir(struct inode * dir, struct dentry *dentry, int mode) de->inode = dir->i_ino; strcpy(de->name,".."); /* rest of de->name is zero, see sysv_new_block */ inode->i_nlink = 2; - mark_buffer_dirty(dir_block, 1); + mark_buffer_dirty(dir_block); brelse(dir_block); inode->i_mode = S_IFDIR | mode; if (dir->i_mode & S_ISGID) @@ -306,7 +306,7 @@ static int sysv_mkdir(struct inode * dir, struct dentry *dentry, int mode) return error; } de->inode = inode->i_ino; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); dir->i_nlink++; mark_inode_dirty(dir); brelse(bh); @@ -392,7 +392,7 @@ static int sysv_rmdir(struct inode * dir, struct dentry * dentry) if (inode->i_nlink != 2) printk("empty directory has nlink!=2 (%d)\n", inode->i_nlink); de->inode = 0; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); inode->i_nlink=0; dir->i_nlink--; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; @@ -422,7 +422,7 @@ static int sysv_unlink(struct inode * dir, struct dentry * dentry) inode->i_nlink=1; } de->inode = 0; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); dir->i_ctime = dir->i_mtime = CURRENT_TIME; mark_inode_dirty(dir); inode->i_nlink--; @@ -463,7 +463,7 @@ static int sysv_symlink(struct inode * dir, struct dentry * dentry, if (err) goto out_no_entry; de->inode = inode->i_ino; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); d_instantiate(dentry, inode); out: @@ -502,7 +502,7 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir, return error; } de->inode = oldinode->i_ino; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); brelse(bh); oldinode->i_nlink++; oldinode->i_ctime = CURRENT_TIME; @@ -578,11 +578,11 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, new_inode->i_ctime = CURRENT_TIME; mark_inode_dirty(new_inode); } - mark_buffer_dirty(old_bh, 1); - mark_buffer_dirty(new_bh, 1); + mark_buffer_dirty(old_bh); + mark_buffer_dirty(new_bh); if (dir_bh) { PARENT_INO(dir_bh->b_data) = new_dir->i_ino; - mark_buffer_dirty(dir_bh, 1); + mark_buffer_dirty(dir_bh); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { diff --git a/fs/sysv/truncate.c b/fs/sysv/truncate.c index 32bfccf6d..559af828d 100644 --- a/fs/sysv/truncate.c +++ b/fs/sysv/truncate.c @@ -124,7 +124,7 @@ repeat: continue; } *ind = 0; - mark_buffer_dirty(indbh, 1); + mark_buffer_dirty(indbh); brelse(bh); sysv_free_block(sb,block); } @@ -183,7 +183,7 @@ static int trunc_dindirect(struct inode * inode, unsigned long offset, sysv_zone continue; retry |= trunc_indirect(inode,offset+(i<sv_ind_per_block_bits),ind,sb->sv_convert,&dirty); if (dirty) - mark_buffer_dirty(indbh, 1); + mark_buffer_dirty(indbh); } for (i = 0; i < sb->sv_ind_per_block; i++) if (((sysv_zone_t *) indbh->b_data)[i]) @@ -240,7 +240,7 @@ static int trunc_tindirect(struct inode * inode, unsigned long offset, sysv_zone continue; retry |= trunc_dindirect(inode,offset+(i<sv_ind_per_block_2_bits),ind,sb->sv_convert,&dirty); if (dirty) - mark_buffer_dirty(indbh, 1); + mark_buffer_dirty(indbh); } for (i = 0; i < sb->sv_ind_per_block; i++) if (((sysv_zone_t *) indbh->b_data)[i]) diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index 2be4e8562..8d7fdfdee 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c @@ -268,7 +268,7 @@ do_more: } } } - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (overflow) { block += count; @@ -278,7 +278,7 @@ do_more: error_return: sb->s_dirt = 1; if (UDF_SB_LVIDBH(sb)) - mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1); + mark_buffer_dirty(UDF_SB_LVIDBH(sb)); unlock_super(sb); return; } @@ -334,7 +334,7 @@ repeat: bit ++; block ++; } - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (block_count > 0) goto repeat; out: @@ -342,7 +342,7 @@ out: { UDF_SB_LVID(sb)->freeSpaceTable[partition] = cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[partition])-alloc_count); - mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1); + mark_buffer_dirty(UDF_SB_LVIDBH(sb)); } sb->s_dirt = 1; unlock_super(sb); @@ -478,13 +478,13 @@ got_block: goto repeat; } - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (UDF_SB_LVIDBH(sb)) { UDF_SB_LVID(sb)->freeSpaceTable[partition] = cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[partition])-1); - mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1); + mark_buffer_dirty(UDF_SB_LVIDBH(sb)); } sb->s_dirt = 1; unlock_super(sb); diff --git a/fs/udf/file.c b/fs/udf/file.c index 0b3dce0d1..9ba4a6641 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -82,7 +82,7 @@ static int udf_adinicb_writepage(struct file *file, struct page *page) block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0); bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize); memcpy(bh->b_data + udf_ext0_offset(inode), kaddr, inode->i_size); - mark_buffer_dirty(bh, 0); + mark_buffer_dirty(bh); brelse(bh); SetPageUptodate(page); kunmap(page); @@ -107,7 +107,7 @@ static int udf_adinicb_commit_write(struct file *file, struct page *page, unsign bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize); memcpy(bh->b_data + udf_file_entry_alloc_offset(inode) + offset, kaddr + offset, to-offset); - mark_buffer_dirty(bh, 0); + mark_buffer_dirty(bh); brelse(bh); SetPageUptodate(page); kunmap(page); diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 11e5711f5..442d155d0 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -62,7 +62,7 @@ void udf_free_inode(struct inode * inode) UDF_SB_LVIDIU(sb)->numFiles = cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) - 1); - mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1); + mark_buffer_dirty(UDF_SB_LVIDBH(sb)); } unlock_super(sb); @@ -112,7 +112,7 @@ struct inode * udf_new_inode (const struct inode *dir, int mode, int * err) if (!(++uniqueID & 0x00000000FFFFFFFFUL)) uniqueID += 16; lvhd->uniqueID = cpu_to_le64(uniqueID); - mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1); + mark_buffer_dirty(UDF_SB_LVIDBH(sb)); } inode->i_mode = mode; inode->i_sb = sb; diff --git a/fs/udf/inode.c b/fs/udf/inode.c index e7e6c53e8..4219c505f 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -200,7 +200,7 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err) else UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG; inode->i_blocks = inode->i_sb->s_blocksize / 512; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); udf_release_data(bh); inode->i_data.a_ops->writepage(NULL, page); @@ -276,7 +276,7 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int return NULL; } } - mark_buffer_dirty(dbh, 1); + mark_buffer_dirty(dbh); memset(sbh->b_data + udf_file_entry_alloc_offset(inode), 0, UDF_I_LENALLOC(inode)); @@ -295,7 +295,7 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int /* UniqueID stuff */ inode->i_blocks = inode->i_sb->s_blocksize / 512; - mark_buffer_dirty(sbh, 1); + mark_buffer_dirty(sbh); udf_release_data(sbh); mark_inode_dirty(inode); inode->i_version ++; @@ -379,7 +379,7 @@ struct buffer_head * udf_getblk(struct inode * inode, long block, wait_on_buffer(bh); memset(bh->b_data, 0x00, inode->i_sb->s_blocksize); mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); } return bh; } @@ -1294,7 +1294,7 @@ udf_update_inode(struct inode *inode, int do_sync) eid->identSuffix[1] = UDF_OS_ID_LINUX; dsea->majorDeviceIdent = kdev_t_to_nr(inode->i_rdev) >> 8; dsea->minorDeviceIdent = kdev_t_to_nr(inode->i_rdev) & 0xFF; - mark_buffer_dirty(tbh, 1); + mark_buffer_dirty(tbh); udf_release_data(tbh); } @@ -1387,7 +1387,7 @@ udf_update_inode(struct inode *inode, int do_sync) fe->descTag.tagChecksum += ((Uint8 *)&(fe->descTag))[i]; /* write the data blocks */ - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (do_sync) { ll_rw_block(WRITE, 1, &bh); @@ -1557,7 +1557,7 @@ int udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset, } } udf_update_tag((*bh)->b_data, loffset); - mark_buffer_dirty(*bh, 1); + mark_buffer_dirty(*bh); udf_release_data(*bh); *bh = nbh; } @@ -1575,7 +1575,7 @@ int udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset, aed->lengthAllocDescs = cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize); udf_update_tag((*bh)->b_data, *extoffset + (inc ? 0 : adsize)); - mark_buffer_dirty(*bh, 1); + mark_buffer_dirty(*bh); } return ret; @@ -1634,7 +1634,7 @@ int udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset, else mark_inode_dirty(inode); - mark_buffer_dirty(*bh, 1); + mark_buffer_dirty(*bh); if (inc) *extoffset += adsize; @@ -1932,7 +1932,7 @@ int udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset, aed->lengthAllocDescs = cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - (2*adsize)); udf_update_tag((obh)->b_data, oextoffset - (2*adsize)); - mark_buffer_dirty(obh, 1); + mark_buffer_dirty(obh); } } else @@ -1949,7 +1949,7 @@ int udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset, aed->lengthAllocDescs = cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - adsize); udf_update_tag((obh)->b_data, oextoffset - adsize); - mark_buffer_dirty(obh, 1); + mark_buffer_dirty(obh); } } diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 16821704e..9cc2f3d29 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -133,8 +133,8 @@ int udf_write_fi(struct FileIdentDesc *cfi, struct FileIdentDesc *sfi, } if (fibh->sbh != fibh->ebh) - mark_buffer_dirty(fibh->ebh, 1); - mark_buffer_dirty(fibh->sbh, 1); + mark_buffer_dirty(fibh->ebh); + mark_buffer_dirty(fibh->sbh); return 0; } @@ -1040,7 +1040,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char * if (!(++uniqueID & 0x00000000FFFFFFFFUL)) uniqueID += 16; lvhd->uniqueID = cpu_to_le64(uniqueID); - mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb), 1); + mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb)); } udf_write_fi(&cfi, fi, &fibh, NULL, NULL); if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB) @@ -1093,7 +1093,7 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir, if (!(++uniqueID & 0x00000000FFFFFFFFUL)) uniqueID += 16; lvhd->uniqueID = cpu_to_le64(uniqueID); - mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb), 1); + mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb)); } udf_write_fi(&cfi, fi, &fibh, NULL, NULL); if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB) @@ -1224,7 +1224,7 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry, old_inode->i_version = ++event; } else - mark_buffer_dirty(dir_bh, 1); + mark_buffer_dirty(dir_bh); old_dir->i_nlink --; mark_inode_dirty(old_dir); if (new_inode) diff --git a/fs/udf/super.c b/fs/udf/super.c index e89a86e72..f5e9b0b44 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1219,7 +1219,7 @@ static void udf_open_lvid(struct super_block *sb) UDF_SB_LVID(sb)->descTag.tagChecksum += ((Uint8 *)&(UDF_SB_LVID(sb)->descTag))[i]; - mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1); + mark_buffer_dirty(UDF_SB_LVIDBH(sb)); sb->s_dirt = 0; } } @@ -1254,7 +1254,7 @@ static void udf_close_lvid(struct super_block *sb) UDF_SB_LVID(sb)->descTag.tagChecksum += ((Uint8 *)&(UDF_SB_LVID(sb)->descTag))[i]; - mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1); + mark_buffer_dirty(UDF_SB_LVIDBH(sb)); } } diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c index 262a411d6..29e059484 100644 --- a/fs/udf/truncate.c +++ b/fs/udf/truncate.c @@ -124,7 +124,7 @@ void udf_trunc(struct inode * inode) aed->lengthAllocDescs = cpu_to_le32(lenalloc); udf_update_tag(bh->b_data, lenalloc + sizeof(struct AllocExtDesc)); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); } } @@ -166,7 +166,7 @@ void udf_trunc(struct inode * inode) aed->lengthAllocDescs = cpu_to_le32(lenalloc); udf_update_tag(bh->b_data, lenalloc + sizeof(struct AllocExtDesc)); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); } } } diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 2f156b42a..fa83ba5be 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -110,8 +110,8 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count INC_SWAB32(ubh_cg_blktot (ucpi, cylno)); } - ubh_mark_buffer_dirty (USPI_UBH, 1); - ubh_mark_buffer_dirty (UCPI_UBH, 1); + ubh_mark_buffer_dirty (USPI_UBH); + ubh_mark_buffer_dirty (UCPI_UBH); if (sb->s_flags & MS_SYNCHRONOUS) { ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi); ubh_wait_on_buffer (UCPI_UBH); @@ -196,8 +196,8 @@ do_more: INC_SWAB32(ubh_cg_blktot(ucpi, cylno)); } - ubh_mark_buffer_dirty (USPI_UBH, 1); - ubh_mark_buffer_dirty (UCPI_UBH, 1); + ubh_mark_buffer_dirty (USPI_UBH); + ubh_mark_buffer_dirty (UCPI_UBH); if (sb->s_flags & MS_SYNCHRONOUS) { ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi); ubh_wait_on_buffer (UCPI_UBH); @@ -227,7 +227,7 @@ failed: bh = getblk (sb->s_dev, result + i, sb->s_blocksize); \ memset (bh->b_data, 0, sb->s_blocksize); \ mark_buffer_uptodate(bh, 1); \ - mark_buffer_dirty (bh, 1); \ + mark_buffer_dirty (bh); \ if (IS_SYNC(inode)) { \ ll_rw_block (WRITE, 1, &bh); \ wait_on_buffer (bh); \ @@ -364,7 +364,7 @@ unsigned ufs_new_fragments (struct inode * inode, u32 * p, unsigned fragment, { mark_buffer_clean (bh); bh->b_blocknr = result + i; - mark_buffer_dirty (bh, 0); + mark_buffer_dirty (bh); if (IS_SYNC(inode)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -458,8 +458,8 @@ unsigned ufs_add_fragments (struct inode * inode, unsigned fragment, SUB_SWAB32(sb->fs_cs(cgno).cs_nffree, count); SUB_SWAB32(usb1->fs_cstotal.cs_nffree, count); - ubh_mark_buffer_dirty (USPI_UBH, 1); - ubh_mark_buffer_dirty (UCPI_UBH, 1); + ubh_mark_buffer_dirty (USPI_UBH); + ubh_mark_buffer_dirty (UCPI_UBH); if (sb->s_flags & MS_SYNCHRONOUS) { ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi); ubh_wait_on_buffer (UCPI_UBH); @@ -582,8 +582,8 @@ cg_found: INC_SWAB32(ucg->cg_frsum[allocsize - count]); succed: - ubh_mark_buffer_dirty (USPI_UBH, 1); - ubh_mark_buffer_dirty (UCPI_UBH, 1); + ubh_mark_buffer_dirty (USPI_UBH); + ubh_mark_buffer_dirty (UCPI_UBH); if (sb->s_flags & MS_SYNCHRONOUS) { ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi); ubh_wait_on_buffer (UCPI_UBH); diff --git a/fs/ufs/cylinder.c b/fs/ufs/cylinder.c index ed261321d..4afc9d9d6 100644 --- a/fs/ufs/cylinder.c +++ b/fs/ufs/cylinder.c @@ -119,7 +119,7 @@ void ufs_put_cylinder (struct super_block * sb, unsigned bitmap_nr) ucg->cg_rotor = SWAB32(ucpi->c_rotor); ucg->cg_frotor = SWAB32(ucpi->c_frotor); ucg->cg_irotor = SWAB32(ucpi->c_irotor); - ubh_mark_buffer_dirty (UCPI_UBH, 1); + ubh_mark_buffer_dirty (UCPI_UBH); for (i = 1; i < UCPI_UBH->count; i++) { brelse (UCPI_UBH->bh[i]); } diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index f93a55c4e..167de8f5a 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -121,8 +121,8 @@ void ufs_free_inode (struct inode * inode) DEC_SWAB32(sb->fs_cs(cg).cs_ndir); } } - ubh_mark_buffer_dirty (USPI_UBH, 1); - ubh_mark_buffer_dirty (UCPI_UBH, 1); + ubh_mark_buffer_dirty (USPI_UBH); + ubh_mark_buffer_dirty (UCPI_UBH); if (sb->s_flags & MS_SYNCHRONOUS) { ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **) &ucpi); ubh_wait_on_buffer (UCPI_UBH); @@ -252,8 +252,8 @@ cg_found: INC_SWAB32(sb->fs_cs(cg).cs_ndir); } - ubh_mark_buffer_dirty (USPI_UBH, 1); - ubh_mark_buffer_dirty (UCPI_UBH, 1); + ubh_mark_buffer_dirty (USPI_UBH); + ubh_mark_buffer_dirty (UCPI_UBH); if (sb->s_flags & MS_SYNCHRONOUS) { ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **) &ucpi); ubh_wait_on_buffer (UCPI_UBH); diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 771069834..10a9d9be4 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -360,7 +360,7 @@ repeat: *new = 1; } - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (IS_SYNC(inode)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -493,7 +493,7 @@ struct buffer_head *ufs_getfrag(struct inode *inode, unsigned int fragment, if (buffer_new(&dummy)) { memset(bh->b_data, 0, inode->i_sb->s_blocksize); mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); } return bh; } @@ -711,7 +711,7 @@ static int ufs_update_inode(struct inode * inode, int do_sync) if (!inode->i_nlink) memset (ufs_inode, 0, sizeof(struct ufs_inode)); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (do_sync) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 7966998d9..70a29b393 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -321,7 +321,7 @@ static struct buffer_head * ufs_add_entry (struct inode * dir, dir->i_mtime = dir->i_ctime = CURRENT_TIME; mark_inode_dirty(dir); dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); *res_dir = de; *err = 0; @@ -428,7 +428,7 @@ static int ufs_create (struct inode * dir, struct dentry * dentry, int mode) de->d_ino = SWAB32(inode->i_ino); ufs_set_de_type (de, inode->i_mode); dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -467,7 +467,7 @@ static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, int r de->d_ino = SWAB32(inode->i_ino); ufs_set_de_type (de, inode->i_mode); dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -530,7 +530,7 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode) ufs_set_de_namlen(de,2); strcpy (de->d_name, ".."); inode->i_nlink = 2; - mark_buffer_dirty(dir_block, 1); + mark_buffer_dirty(dir_block); brelse (dir_block); inode->i_mode = S_IFDIR | mode; if (dir->i_mode & S_ISGID) @@ -542,7 +542,7 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode) de->d_ino = SWAB32(inode->i_ino); ufs_set_de_type (de, inode->i_mode); dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -657,7 +657,7 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry) dir->i_version = ++event; if (retval) goto end_rmdir; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -718,7 +718,7 @@ static int ufs_unlink(struct inode * dir, struct dentry *dentry) if (retval) goto end_unlink; dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -785,7 +785,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry, goto out_no_entry; de->d_ino = SWAB32(inode->i_ino); dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -825,7 +825,7 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir, de->d_ino = SWAB32(inode->i_ino); dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty(bh); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -930,7 +930,7 @@ static int ufs_rename (struct inode * old_dir, struct dentry * old_dentry, mark_inode_dirty(old_dir); if (dir_bh) { PARENT_INO(dir_bh->b_data) = SWAB32(new_dir->i_ino); - mark_buffer_dirty(dir_bh, 1); + mark_buffer_dirty(dir_bh); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { @@ -941,13 +941,13 @@ static int ufs_rename (struct inode * old_dir, struct dentry * old_dentry, mark_inode_dirty(new_dir); } } - mark_buffer_dirty(old_bh, 1); + mark_buffer_dirty(old_bh); if (IS_SYNC(old_dir)) { ll_rw_block (WRITE, 1, &old_bh); wait_on_buffer (old_bh); } - mark_buffer_dirty(new_bh, 1); + mark_buffer_dirty(new_bh); if (IS_SYNC(new_dir)) { ll_rw_block (WRITE, 1, &new_bh); wait_on_buffer (new_bh); diff --git a/fs/ufs/super.c b/fs/ufs/super.c index c41228adf..6d83d7c51 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -192,7 +192,7 @@ void ufs_error (struct super_block * sb, const char * function, if (!(sb->s_flags & MS_RDONLY)) { usb1->fs_clean = UFS_FSBAD; - ubh_mark_buffer_dirty(USPI_UBH, 1); + ubh_mark_buffer_dirty(USPI_UBH); sb->s_dirt = 1; sb->s_flags |= MS_RDONLY; } @@ -224,7 +224,7 @@ void ufs_panic (struct super_block * sb, const char * function, if (!(sb->s_flags & MS_RDONLY)) { usb1->fs_clean = UFS_FSBAD; - ubh_mark_buffer_dirty(USPI_UBH, 1); + ubh_mark_buffer_dirty(USPI_UBH); sb->s_dirt = 1; } va_start (args, fmt); @@ -422,7 +422,7 @@ void ufs_put_cylinder_structures (struct super_block * sb) { ubh_memcpyubh (ubh, space, size); space += size; ubh_mark_buffer_uptodate (ubh, 1); - ubh_mark_buffer_dirty (ubh, 0); + ubh_mark_buffer_dirty (ubh); ubh_brelse (ubh); } for (i = 0; i < sb->u.ufs_sb.s_cg_loaded; i++) { @@ -845,7 +845,7 @@ void ufs_write_super (struct super_block * sb) { if ((flags & UFS_ST_MASK) == UFS_ST_SUN || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) ufs_set_fs_state(usb1, usb3, UFS_FSOK - SWAB32(usb1->fs_time)); - ubh_mark_buffer_dirty (USPI_UBH, 1); + ubh_mark_buffer_dirty (USPI_UBH); } sb->s_dirt = 0; UFSD(("EXIT\n")) @@ -915,7 +915,7 @@ int ufs_remount (struct super_block * sb, int * mount_flags, char * data) if ((flags & UFS_ST_MASK) == UFS_ST_SUN || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) ufs_set_fs_state(usb1, usb3, UFS_FSOK - SWAB32(usb1->fs_time)); - ubh_mark_buffer_dirty (USPI_UBH, 1); + ubh_mark_buffer_dirty (USPI_UBH); sb->s_dirt = 0; sb->s_flags |= MS_RDONLY; } diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index 57de81eb8..183ccfb13 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c @@ -248,7 +248,7 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, u32 * p) bforget (bh); } *ind = SWAB32(0); - ubh_mark_buffer_dirty(ind_ubh, 1); + ubh_mark_buffer_dirty(ind_ubh); if (free_count == 0) { frag_to_free = tmp; free_count = uspi->s_fpb; @@ -334,7 +334,7 @@ static int ufs_trunc_dindirect (struct inode * inode, unsigned offset, u32 * p) if (!tmp) continue; retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind); - ubh_mark_buffer_dirty(dind_bh, 1); + ubh_mark_buffer_dirty(dind_bh); } for (i = 0; i < uspi->s_apb; i++) @@ -400,7 +400,7 @@ static int ufs_trunc_tindirect (struct inode * inode) tind = ubh_get_addr32 (tind_bh, i); retry |= ufs_trunc_dindirect(inode, UFS_NDADDR + uspi->s_apb + ((i + 1) << uspi->s_2apbshift), tind); - ubh_mark_buffer_dirty(tind_bh, 1); + ubh_mark_buffer_dirty(tind_bh); } for (i = 0; i < uspi->s_apb; i++) if (SWAB32(*ubh_get_addr32 (tind_bh, i))) @@ -466,7 +466,7 @@ void ufs_truncate (struct inode * inode) bh = ufs_bread (inode, inode->i_size >> uspi->s_fshift, 0, &err); if (bh) { memset (bh->b_data + offset, 0, uspi->s_fsize - offset); - mark_buffer_dirty (bh, 0); + mark_buffer_dirty (bh); brelse (bh); } } diff --git a/fs/ufs/util.c b/fs/ufs/util.c index e6d5f3a5b..334e0efdb 100644 --- a/fs/ufs/util.c +++ b/fs/ufs/util.c @@ -94,13 +94,13 @@ void ubh_brelse_uspi (struct ufs_sb_private_info * uspi) } } -void ubh_mark_buffer_dirty (struct ufs_buffer_head * ubh, int flag) +void ubh_mark_buffer_dirty (struct ufs_buffer_head * ubh) { unsigned i; if (!ubh) return; for ( i = 0; i < ubh->count; i++ ) - mark_buffer_dirty (ubh->bh[i], flag); + mark_buffer_dirty (ubh->bh[i]); } void ubh_mark_buffer_uptodate (struct ufs_buffer_head * ubh, int flag) diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 049b194ee..0def49d95 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -212,7 +212,7 @@ extern struct ufs_buffer_head * _ubh_bread_(struct ufs_sb_private_info *, kdev_t extern struct ufs_buffer_head * ubh_bread_uspi(struct ufs_sb_private_info *, kdev_t, unsigned, unsigned); extern void ubh_brelse (struct ufs_buffer_head *); extern void ubh_brelse_uspi (struct ufs_sb_private_info *); -extern void ubh_mark_buffer_dirty (struct ufs_buffer_head *, int); +extern void ubh_mark_buffer_dirty (struct ufs_buffer_head *); extern void ubh_mark_buffer_uptodate (struct ufs_buffer_head *, int); extern void ubh_ll_rw_block (int, unsigned, struct ufs_buffer_head **); extern void ubh_wait_on_buffer (struct ufs_buffer_head *); diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c index b5c14c221..63ee81b16 100644 --- a/fs/umsdos/dir.c +++ b/fs/umsdos/dir.c @@ -68,7 +68,8 @@ static int umsdos_dir_once ( void *buf, const char *name, int len, off_t offset, - ino_t ino) + ino_t ino, + unsigned type) { int ret = -EINVAL; struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf; diff --git a/fs/umsdos/emd.c b/fs/umsdos/emd.c index 48515aa5f..551c9662f 100644 --- a/fs/umsdos/emd.c +++ b/fs/umsdos/emd.c @@ -505,7 +505,7 @@ int umsdos_newentry (struct dentry *parent, struct umsdos_info *info) struct dentry *demd = umsdos_get_emd_dentry(parent); ret = PTR_ERR(demd); - if (IS_ERR(ret)) + if (IS_ERR(demd)) goto out; err = umsdos_find (demd, info); if (err && err == -ENOENT) { @@ -532,7 +532,7 @@ int umsdos_newhidden (struct dentry *parent, struct umsdos_info *info) int ret; struct dentry *demd = umsdos_get_emd_dentry(parent); ret = PTR_ERR(demd); - if (IS_ERR(ret)) + if (IS_ERR(demd)) goto out; umsdos_parse ("..LINK", 6, info); @@ -561,7 +561,7 @@ int umsdos_delentry (struct dentry *parent, struct umsdos_info *info, int isdir) struct dentry *demd = umsdos_get_emd_dentry(parent); ret = PTR_ERR(demd); - if (IS_ERR(ret)) + if (IS_ERR(demd)) goto out; ret = umsdos_find (demd, info); if (ret) @@ -642,7 +642,7 @@ int umsdos_findentry (struct dentry *parent, struct umsdos_info *info, struct dentry *demd = umsdos_get_emd_dentry(parent); ret = PTR_ERR(demd); - if (IS_ERR(ret)) + if (IS_ERR(demd)) goto out; ret = umsdos_find (demd, info); if (ret) diff --git a/fs/umsdos/ioctl.c b/fs/umsdos/ioctl.c index 8731f8ecd..0b09ce60a 100644 --- a/fs/umsdos/ioctl.c +++ b/fs/umsdos/ioctl.c @@ -29,7 +29,8 @@ static int umsdos_ioctl_fill ( const char *name, int name_len, off_t offset, - ino_t ino) + ino_t ino, + unsigned type) { int ret = -EINVAL; struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf; diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index b3fcf2088..0ac6d5314 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -973,7 +973,7 @@ static int vfat_add_entry(struct inode *dir,struct qstr* qname, goto cleanup; } memcpy(*de, ps, sizeof(struct msdos_dir_slot)); - fat_mark_buffer_dirty(sb, *bh, 1); + fat_mark_buffer_dirty(sb, *bh); } dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME; @@ -990,7 +990,7 @@ static int vfat_add_entry(struct inode *dir,struct qstr* qname, (*de)->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT; - fat_mark_buffer_dirty(sb, *bh, 1); + fat_mark_buffer_dirty(sb, *bh); /* slots can't be less than 1 */ sinfo_out->long_slots = slots - 1; @@ -1106,7 +1106,7 @@ static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo, dir->i_version = ++event; mark_inode_dirty(dir); de->name[0] = DELETED_FLAG; - fat_mark_buffer_dirty(sb, bh, 1); + fat_mark_buffer_dirty(sb, bh); /* remove the longname */ offset = sinfo->longname_offset; de = NULL; for (i = sinfo->long_slots; i > 0; --i) { @@ -1114,7 +1114,7 @@ static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo, continue; de->name[0] = DELETED_FLAG; de->attr = 0; - fat_mark_buffer_dirty(sb, bh, 1); + fat_mark_buffer_dirty(sb, bh); } if (bh) fat_brelse(sb, bh); } @@ -1276,7 +1276,7 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry, int start = MSDOS_I(new_dir)->i_logstart; dotdot_de->start = CT_LE_W(start); dotdot_de->starthi = CT_LE_W(start>>16); - fat_mark_buffer_dirty(sb, dotdot_bh, 1); + fat_mark_buffer_dirty(sb, dotdot_bh); old_dir->i_nlink--; if (new_inode) { new_inode->i_nlink--; diff --git a/include/linux/fat_cvf.h b/include/linux/fat_cvf.h index 6349e45cf..bfaf4b057 100644 --- a/include/linux/fat_cvf.h +++ b/include/linux/fat_cvf.h @@ -14,8 +14,7 @@ struct cvf_format struct buffer_head* (*cvf_getblk) (struct super_block*sb,int block); void (*cvf_brelse) (struct super_block *sb,struct buffer_head *bh); void (*cvf_mark_buffer_dirty) (struct super_block *sb, - struct buffer_head *bh, - int dirty_val); + struct buffer_head *bh); void (*cvf_set_uptodate) (struct super_block *sb, struct buffer_head *bh, int val); diff --git a/include/linux/fs.h b/include/linux/fs.h index 15b5aa888..c0157ad6d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -985,8 +985,8 @@ static inline void mark_buffer_protected(struct buffer_head * bh) __mark_buffer_protected(bh); } -extern void FASTCALL(__mark_buffer_dirty(struct buffer_head *bh, int flag)); -extern void FASTCALL(mark_buffer_dirty(struct buffer_head *bh, int flag)); +extern void FASTCALL(__mark_buffer_dirty(struct buffer_head *bh)); +extern void FASTCALL(mark_buffer_dirty(struct buffer_head *bh)); #define atomic_set_buffer_dirty(bh) test_and_set_bit(BH_Dirty, &(bh)->b_state) diff --git a/include/linux/hfs_sysdep.h b/include/linux/hfs_sysdep.h index 0c0b9bb91..a05e43014 100644 --- a/include/linux/hfs_sysdep.h +++ b/include/linux/hfs_sysdep.h @@ -150,7 +150,7 @@ extern inline void hfs_buffer_put(hfs_buffer buffer) { } extern inline void hfs_buffer_dirty(hfs_buffer buffer) { - mark_buffer_dirty(buffer, 1); + mark_buffer_dirty(buffer); } extern inline void hfs_buffer_sync(hfs_buffer buffer) { diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index ddd0563a5..b61722b15 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -184,6 +184,12 @@ extern struct inode_operations nfs_symlink_inode_operations; extern int nfs_lock(struct file *, int, struct file_lock *); /* + * linux/fs/nfs/unlink.c + */ +extern int nfs_async_unlink(struct dentry *); +extern void nfs_complete_unlink(struct dentry *); + +/* * linux/fs/nfs/write.c */ extern int nfs_writepage(struct file *file, struct page *); diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 63c3e1c7b..9863c06af 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -334,6 +334,9 @@ struct nfs_rpc_ops { int (*create) (struct dentry *, struct qstr *, struct iattr *, int, struct nfs_fh *, struct nfs_fattr *); int (*remove) (struct dentry *, struct qstr *); + int (*unlink_setup) (struct rpc_message *, + struct dentry *, struct qstr *); + void (*unlink_done) (struct dentry *, struct rpc_message *); int (*rename) (struct dentry *, struct qstr *, struct dentry *, struct qstr *); int (*link) (struct dentry *, struct dentry *, struct qstr *); diff --git a/include/linux/nfsd/interface.h b/include/linux/nfsd/interface.h index afa9edc08..cdce71e82 100644 --- a/include/linux/nfsd/interface.h +++ b/include/linux/nfsd/interface.h @@ -10,6 +10,8 @@ #ifndef LINUX_NFSD_INTERFACE_H #define LINUX_NFSD_INTERFACE_H +#include + #ifdef CONFIG_NFSD_MODULE extern struct nfsd_linkage { diff --git a/include/linux/sched.h b/include/linux/sched.h index 1530af1cc..e52d024a7 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -33,13 +33,14 @@ extern unsigned long event; #define CLONE_VM 0x00000100 /* set if VM shared between processes */ #define CLONE_FS 0x00000200 /* set if fs info shared between processes */ #define CLONE_FILES 0x00000400 /* set if open files shared between processes */ -#define CLONE_SIGNAL 0x00000800 /* set if signal handlers and blocked signals shared */ +#define CLONE_SIGHAND 0x00000800 /* set if signal handlers and blocked signals shared */ #define CLONE_PID 0x00001000 /* set if pid shared */ #define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */ #define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ #define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */ +#define CLONE_THREAD 0x00010000 /* Same thread group? */ -#define CLONE_SIGHAND CLONE_SIGNAL /* Old name */ +#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD) /* * These are the constant used to fake the fixed-point load-average @@ -717,7 +718,7 @@ extern fd_set *alloc_fdset(int); extern int expand_fdset(struct files_struct *, int nr); extern void free_fdset(fd_set *, int); -extern int copy_thread(int, unsigned long, unsigned long, struct task_struct *, struct pt_regs *); +extern int copy_thread(int, unsigned long, unsigned long, unsigned long, struct task_struct *, struct pt_regs *); extern void flush_thread(void); extern void exit_thread(void); @@ -728,7 +729,7 @@ extern void exit_sighand(struct task_struct *); extern void daemonize(void); extern int do_execve(char *, char **, char **, struct pt_regs *); -extern int do_fork(unsigned long, unsigned long, struct pt_regs *); +extern int do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long); extern void FASTCALL(add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait)); extern void FASTCALL(add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait)); diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 76e63aa75..fa82b5325 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -137,6 +137,7 @@ #define TYPE_MOD 0x07 /* Magneto-optical disk - * - treated as TYPE_DISK */ #define TYPE_MEDIUM_CHANGER 0x08 +#define TYPE_COMM 0x09 /* Communications device */ #define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */ #define TYPE_NO_LUN 0x7f diff --git a/kernel/fork.c b/kernel/fork.c index 07e0e9685..b93b0b0e4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -502,7 +502,7 @@ static inline int copy_sighand(unsigned long clone_flags, struct task_struct * t { struct signal_struct *sig; - if (clone_flags & CLONE_SIGNAL) { + if (clone_flags & CLONE_SIGHAND) { atomic_inc(¤t->sig->count); return 0; } @@ -531,10 +531,15 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p) /* * 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. + * 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. */ -int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) +int do_fork(unsigned long clone_flags, unsigned long stack_start, + struct pt_regs *regs, unsigned long stack_top) { int retval = -ENOMEM; struct task_struct *p; @@ -629,7 +634,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) goto bad_fork_cleanup_fs; if (copy_mm(clone_flags, p)) goto bad_fork_cleanup_sighand; - retval = copy_thread(0, clone_flags, usp, p, regs); + retval = copy_thread(0, clone_flags, stack_start, stack_top, p, regs); if (retval) goto bad_fork_cleanup_sighand; p->semundo = NULL; @@ -665,7 +670,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) p->tgid = retval; INIT_LIST_HEAD(&p->thread_group); write_lock_irq(&tasklist_lock); - if (clone_flags & CLONE_SIGNAL) { + if (clone_flags & CLONE_THREAD) { p->tgid = current->tgid; list_add(&p->thread_group, ¤t->thread_group); } diff --git a/kernel/info.c b/kernel/info.c index 3ee347444..d7abf6713 100644 --- a/kernel/info.c +++ b/kernel/info.c @@ -32,6 +32,42 @@ asmlinkage long sys_sysinfo(struct sysinfo *info) si_meminfo(&val); si_swapinfo(&val); + { + /* If the sum of all the available memory (i.e. ram + swap + + * highmem) is less then can be stored in a 32 bit unsigned long + * then we can be binary compatible with 2.2.x kernels. If not, + * well, who cares since in that case 2.2.x was broken anyways... + * + * -Erik Andersen */ + + unsigned long mem_total = val.totalram + val.totalswap; + if ( !(mem_total < val.totalram || mem_total < val.totalswap)) { + unsigned long mem_total2 = mem_total + val.totalhigh; + if (!(mem_total2 < mem_total || mem_total2 < val.totalhigh)) + { + /* If mem_total did not overflow. Divide all memory values by + * mem_unit and set mem_unit=1. This leaves things compatible with + * 2.2.x, and also retains compatibility with earlier 2.4.x + * kernels... */ + + int bitcount = 0; + while (val.mem_unit > 1) + { + bitcount++; + val.mem_unit >>= 1; + } + val.totalram <<= bitcount; + val.freeram <<= bitcount; + val.sharedram <<= bitcount; + val.bufferram <<= bitcount; + val.totalswap <<= bitcount; + val.freeswap <<= bitcount; + val.totalhigh <<= bitcount; + val.freehigh <<= bitcount; + } + } + } + if (copy_to_user(info, &val, sizeof(struct sysinfo))) return -EFAULT; return 0; diff --git a/kernel/signal.c b/kernel/signal.c index d0319aee6..57bca2926 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -153,9 +153,13 @@ flush_signal_handlers(struct task_struct *t) void block_all_signals(int (*notifier)(void *priv), void *priv, sigset_t *mask) { + unsigned long flags; + + spin_lock_irqsave(¤t->sigmask_lock, flags); current->notifier_mask = mask; current->notifier_data = priv; current->notifier = notifier; + spin_unlock_irqrestore(¤t->sigmask_lock, flags); } /* Notify the system that blocking has ended. */ @@ -163,9 +167,13 @@ block_all_signals(int (*notifier)(void *priv), void *priv, sigset_t *mask) void unblock_all_signals(void) { + unsigned long flags; + + spin_lock_irqsave(¤t->sigmask_lock, flags); current->notifier = NULL; current->notifier_data = NULL; recalc_sigpending(current); + spin_unlock_irqrestore(¤t->sigmask_lock, flags); } static int collect_signal(int sig, struct sigpending *list, siginfo_t *info) @@ -234,15 +242,7 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid, sig = next_signal(current, mask); if (current->notifier) { - sigset_t merged; - int i; - int altsig; - - for (i = 0; i < _NSIG_WORDS; i++) - merged.sig[i] = mask->sig[i] - | current->notifier_mask->sig[i]; - altsig = next_signal(current, &merged); - if (sig != altsig) { + if (sigismember(current->notifier_mask, sig)) { if (!(current->notifier)(current->notifier_data)) { current->sigpending = 0; return 0; -- 2.11.4.GIT