diff -Nru a/Makefile b/Makefile --- a/Makefile Mon Jun 16 21:04:35 2003 +++ b/Makefile Wed Jun 18 04:35:28 2003 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 SUBLEVEL = 72 -EXTRAVERSION = +EXTRAVERSION = -bk1 # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff -Nru a/arch/alpha/Kconfig b/arch/alpha/Kconfig --- a/arch/alpha/Kconfig Mon Jun 16 13:04:32 2003 +++ b/arch/alpha/Kconfig Sun Jun 15 08:55:30 2003 @@ -647,103 +647,7 @@ This driver is also available as a module and will be called srm_env then. -config BINFMT_AOUT - tristate "Kernel support for a.out (ECOFF) binaries" - ---help--- - A.out (Assembler.OUTput) is a set of formats for libraries and - executables used in the earliest versions of UNIX. Linux used the - a.out formats QMAGIC and ZMAGIC until they were replaced with the - ELF format. - - As more and more programs are converted to ELF, the use for a.out - will gradually diminish. If you disable this option it will reduce - your kernel by one page. This is not much and by itself does not - warrant removing support. However its removal is a good idea if you - wish to ensure that absolutely none of your programs will use this - older executable format. If you don't know what to answer at this - point then answer Y. If someone told you "You need a kernel with - QMAGIC support" then you'll have to say Y here. You may answer M to - compile a.out support as a module and later load the module when you - want to use a program or library in a.out format. The module will be - called binfmt_aout. Saying M or N here is dangerous though, - because some crucial programs on your system might still be in A.OUT - format. - -config OSF4_COMPAT - bool "OSF/1 v4 readv/writev compatibility" - depends on BINFMT_AOUT - help - Say Y if you are using OSF/1 binaries (like Netscape and Acrobat) - with v4 shared libraries freely available from Compaq. If you're - going to use shared libraries from Tru64 version 5.0 or later, say N. - -config BINFMT_ELF - tristate "Kernel support for ELF binaries" - ---help--- - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries - and enlarge it by about 13 KB. ELF support under Linux has now all - but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) - because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating systems - however) and makes building run-time libraries very easy. Many new - executables are distributed solely in ELF format. You definitely - want to say Y here. - - Information about ELF is contained in the ELF HOWTO available from - . - - If you find that after upgrading from Linux kernel 1.2 and saying Y - here, you still can't run any ELF binaries (they just crash), then - you'll have to install the newest ELF runtime libraries, including - ld.so (check the file for location and - latest version). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. - -config BINFMT_EM86 - tristate "Kernel support for Linux/Intel ELF binaries" - ---help--- - Say Y here if you want to be able to execute Linux/Intel ELF - binaries just like native Alpha binaries on your Alpha machine. For - this to work, you need to have the emulator /usr/bin/em86 in place. - - You can get the same functionality by saying N here and saying Y to - "Kernel support for MISC binaries". - - You may answer M to compile the emulation support as a module and - later load the module when you want to use a Linux/Intel binary. The - module will be called binfmt_em86. If unsure, say Y. +source "fs/Kconfig.binfmt" source "drivers/parport/Kconfig" diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig --- a/arch/arm/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/arm/Kconfig Sat Jun 14 15:25:46 2003 @@ -691,81 +691,7 @@ endchoice -config BINFMT_AOUT - tristate "Kernel support for a.out binaries" - ---help--- - A.out (Assembler.OUTput) is a set of formats for libraries and - executables used in the earliest versions of UNIX. Linux used the - a.out formats QMAGIC and ZMAGIC until they were replaced with the - ELF format. - - As more and more programs are converted to ELF, the use for a.out - will gradually diminish. If you disable this option it will reduce - your kernel by one page. This is not much and by itself does not - warrant removing support. However its removal is a good idea if you - wish to ensure that absolutely none of your programs will use this - older executable format. If you don't know what to answer at this - point then answer Y. If someone told you "You need a kernel with - QMAGIC support" then you'll have to say Y here. You may answer M to - compile a.out support as a module and later load the module when you - want to use a program or library in a.out format. The module will be - called binfmt_aout. Saying M or N here is dangerous though, - because some crucial programs on your system might still be in A.OUT - format. - -config BINFMT_ELF - tristate "Kernel support for ELF binaries" - ---help--- - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries - and enlarge it by about 13 KB. ELF support under Linux has now all - but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) - because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating systems - however) and makes building run-time libraries very easy. Many new - executables are distributed solely in ELF format. You definitely - want to say Y here. - - Information about ELF is contained in the ELF HOWTO available from - . - - If you find that after upgrading from Linux kernel 1.2 and saying Y - here, you still can't run any ELF binaries (they just crash), then - you'll have to install the newest ELF runtime libraries, including - ld.so (check the file for location and - latest version). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. +source "fs/Kconfig.binfmt" config PM bool "Power Management support" diff -Nru a/arch/cris/Kconfig b/arch/cris/Kconfig --- a/arch/cris/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/cris/Kconfig Thu Jun 12 10:41:27 2003 @@ -25,34 +25,7 @@ menu "General setup" -config BINFMT_ELF - tristate "Kernel support for ELF binaries" - ---help--- - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries - and enlarge it by about 13 KB. ELF support under Linux has now all - but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) - because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating systems - however) and makes building run-time libraries very easy. Many new - executables are distributed solely in ELF format. You definitely - want to say Y here. - - Information about ELF is contained in the ELF HOWTO available from - . - - If you find that after upgrading from Linux kernel 1.2 and saying Y - here, you still can't run any ELF binaries (they just crash), then - you'll have to install the newest ELF runtime libraries, including - ld.so (check the file for location and - latest version). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. +source "fs/Kconfig.binfmt" config ETRAX_KGDB bool "Use kernel gdb debugger" diff -Nru a/arch/h8300/Kconfig b/arch/h8300/Kconfig --- a/arch/h8300/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/h8300/Kconfig Thu Jun 12 10:41:27 2003 @@ -141,10 +141,7 @@ config KCORE_ELF default y -config BINFMT_FLAT - tristate "Kernel support for flat binaries" - help - Support uClinux FLAT format binaries. +source "fs/Kconfig.binfmt" endmenu diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Sat Jun 14 16:15:56 2003 +++ b/arch/i386/Kconfig Sat Jun 14 15:25:47 2003 @@ -1190,81 +1190,7 @@ endchoice -config BINFMT_AOUT - tristate "Kernel support for a.out binaries" - ---help--- - A.out (Assembler.OUTput) is a set of formats for libraries and - executables used in the earliest versions of UNIX. Linux used the - a.out formats QMAGIC and ZMAGIC until they were replaced with the - ELF format. - - As more and more programs are converted to ELF, the use for a.out - will gradually diminish. If you disable this option it will reduce - your kernel by one page. This is not much and by itself does not - warrant removing support. However its removal is a good idea if you - wish to ensure that absolutely none of your programs will use this - older executable format. If you don't know what to answer at this - point then answer Y. If someone told you "You need a kernel with - QMAGIC support" then you'll have to say Y here. You may answer M to - compile a.out support as a module and later load the module when you - want to use a program or library in a.out format. The module will be - called binfmt_aout. Saying M or N here is dangerous though, - because some crucial programs on your system might still be in A.OUT - format. - -config BINFMT_ELF - tristate "Kernel support for ELF binaries" - ---help--- - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries - and enlarge it by about 13 KB. ELF support under Linux has now all - but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) - because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating systems - however) and makes building run-time libraries very easy. Many new - executables are distributed solely in ELF format. You definitely - want to say Y here. - - Information about ELF is contained in the ELF HOWTO available from - . - - If you find that after upgrading from Linux kernel 1.2 and saying Y - here, you still can't run any ELF binaries (they just crash), then - you'll have to install the newest ELF runtime libraries, including - ld.so (check the file for location and - latest version). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. +source "fs/Kconfig.binfmt" endmenu diff -Nru a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c --- a/arch/i386/kernel/nmi.c Tue Jun 10 12:04:01 2003 +++ b/arch/i386/kernel/nmi.c Sun Jun 15 11:00:08 2003 @@ -23,17 +23,27 @@ #include #include #include +#include #include #include #include #include +#include unsigned int nmi_watchdog = NMI_NONE; static unsigned int nmi_hz = HZ; unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ extern void show_registers(struct pt_regs *regs); +/* nmi_active: + * +1: the lapic NMI watchdog is active, but can be disabled + * 0: the lapic NMI watchdog has not been set up, and cannot + * be enabled + * -1: the lapic NMI watchdog is disabled, but can be enabled + */ +static int nmi_active; + #define K7_EVNTSEL_ENABLE (1 << 22) #define K7_EVNTSEL_INT (1 << 20) #define K7_EVNTSEL_OS (1 << 17) @@ -91,6 +101,7 @@ continue; if (nmi_count(cpu) - prev_nmi_count[cpu] <= 5) { printk("CPU#%d: NMI appears to be stuck!\n", cpu); + nmi_active = 0; return -1; } } @@ -131,21 +142,15 @@ * We can enable the IO-APIC watchdog * unconditionally. */ - if (nmi == NMI_IO_APIC) + if (nmi == NMI_IO_APIC) { + nmi_active = 1; nmi_watchdog = nmi; + } return 1; } __setup("nmi_watchdog=", setup_nmi_watchdog); -/* nmi_active: - * +1: the lapic NMI watchdog is active, but can be disabled - * 0: the lapic NMI watchdog has not been set up, and cannot - * be enabled - * -1: the lapic NMI watchdog is disabled, but can be enabled - */ -static int nmi_active; - void disable_lapic_nmi_watchdog(void) { if (nmi_active <= 0) @@ -179,6 +184,27 @@ } } +void disable_timer_nmi_watchdog(void) +{ + if ((nmi_watchdog != NMI_IO_APIC) || (nmi_active <= 0)) + return; + + disable_irq(0); + unset_nmi_callback(); + nmi_active = -1; + nmi_watchdog = NMI_NONE; +} + +void enable_timer_nmi_watchdog(void) +{ + if (nmi_active < 0) { + nmi_watchdog = NMI_IO_APIC; + touch_nmi_watchdog(); + nmi_active = 1; + enable_irq(0); + } +} + #ifdef CONFIG_PM static int nmi_pm_active; /* nmi_active before suspend */ @@ -429,3 +455,5 @@ EXPORT_SYMBOL(nmi_watchdog); EXPORT_SYMBOL(disable_lapic_nmi_watchdog); EXPORT_SYMBOL(enable_lapic_nmi_watchdog); +EXPORT_SYMBOL(disable_timer_nmi_watchdog); +EXPORT_SYMBOL(enable_timer_nmi_watchdog); diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c --- a/arch/i386/kernel/setup.c Sat Jun 7 15:17:53 2003 +++ b/arch/i386/kernel/setup.c Wed Jun 11 20:06:29 2003 @@ -96,7 +96,6 @@ extern void generic_apic_probe(char *); extern int root_mountflags; extern char _text, _etext, _edata, _end; -extern int blk_nohighio; unsigned long saved_videomode; @@ -994,15 +993,6 @@ #endif #endif } - -static int __init highio_setup(char *str) -{ - printk("i386: disabling HIGHMEM block I/O\n"); - blk_nohighio = 1; - return 1; -} -__setup("nohighio", highio_setup); - #include "setup_arch_post.h" /* diff -Nru a/arch/i386/oprofile/Makefile b/arch/i386/oprofile/Makefile --- a/arch/i386/oprofile/Makefile Mon Apr 28 17:11:32 2003 +++ b/arch/i386/oprofile/Makefile Sun Jun 15 11:00:08 2003 @@ -9,3 +9,4 @@ oprofile-y := $(DRIVER_OBJS) init.o oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \ op_model_ppro.o op_model_p4.o +oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o diff -Nru a/arch/i386/oprofile/init.c b/arch/i386/oprofile/init.c --- a/arch/i386/oprofile/init.c Mon May 12 21:23:26 2003 +++ b/arch/i386/oprofile/init.c Sun Jun 15 11:05:04 2003 @@ -16,15 +16,21 @@ */ extern int nmi_init(struct oprofile_operations ** ops); +extern int nmi_timer_init(struct oprofile_operations **ops); extern void nmi_exit(void); int __init oprofile_arch_init(struct oprofile_operations ** ops) { + int ret = -ENODEV; #ifdef CONFIG_X86_LOCAL_APIC - return nmi_init(ops); -#else - return -ENODEV; + ret = nmi_init(ops); #endif + +#ifdef CONFIG_X86_IO_APIC + if (ret < 0) + ret = nmi_timer_init(ops); +#endif + return ret; } diff -Nru a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c --- a/arch/i386/oprofile/nmi_int.c Tue Jun 10 12:06:36 2003 +++ b/arch/i386/oprofile/nmi_int.c Sat Jun 14 18:10:08 2003 @@ -182,8 +182,8 @@ static void nmi_shutdown(void) { nmi_enabled = 0; - unset_nmi_callback(); on_each_cpu(nmi_cpu_shutdown, NULL, 0, 1); + unset_nmi_callback(); enable_lapic_nmi_watchdog(); } diff -Nru a/arch/i386/oprofile/nmi_timer_int.c b/arch/i386/oprofile/nmi_timer_int.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/oprofile/nmi_timer_int.c Sun Jun 15 11:04:34 2003 @@ -0,0 +1,57 @@ +/** + * @file nmi_timer_int.c + * + * @remark Copyright 2003 OProfile authors + * @remark Read the file COPYING + * + * @author Zwane Mwaikambo + */ + +#include +#include +#include +#include +#include + + +#include +#include +#include + +static int nmi_timer_callback(struct pt_regs * regs, int cpu) +{ + unsigned long eip = instruction_pointer(regs); + + oprofile_add_sample(eip, !user_mode(regs), 0, cpu); + return 1; +} + +static int timer_start(void) +{ + disable_timer_nmi_watchdog(); + set_nmi_callback(nmi_timer_callback); + return 0; +} + + +static void timer_stop(void) +{ + enable_timer_nmi_watchdog(); + unset_nmi_callback(); + synchronize_kernel(); +} + + +static struct oprofile_operations nmi_timer_ops = { + .start = timer_start, + .stop = timer_stop, + .cpu_type = "timer" +}; + + +int __init nmi_timer_init(struct oprofile_operations ** ops) +{ + *ops = &nmi_timer_ops; + printk(KERN_INFO "oprofile: using NMI timer interrupt.\n"); + return 0; +} diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig --- a/arch/ia64/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/ia64/Kconfig Sat Jun 14 15:25:48 2003 @@ -493,38 +493,7 @@ depends on SMP default "64" -config BINFMT_ELF - tristate "Kernel support for ELF binaries" - ---help--- - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries. - - Information about ELF is contained in the ELF HOWTO available from - . - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. Once you have registered such a binary class with the - kernel, you can start one of those programs simply by typing in its - name at a shell prompt; Linux will automatically feed it to the - correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. +source "fs/Kconfig.binfmt" if !IA64_HP_SIM diff -Nru a/arch/m68k/Kconfig b/arch/m68k/Kconfig --- a/arch/m68k/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/m68k/Kconfig Thu Jun 12 10:41:27 2003 @@ -376,81 +376,7 @@ endchoice -config BINFMT_AOUT - tristate "Kernel support for a.out binaries" - ---help--- - A.out (Assembler.OUTput) is a set of formats for libraries and - executables used in the earliest versions of UNIX. Linux used the - a.out formats QMAGIC and ZMAGIC until they were replaced with the - ELF format. - - As more and more programs are converted to ELF, the use for a.out - will gradually diminish. If you disable this option it will reduce - your kernel by one page. This is not much and by itself does not - warrant removing support. However its removal is a good idea if you - wish to ensure that absolutely none of your programs will use this - older executable format. If you don't know what to answer at this - point then answer Y. If someone told you "You need a kernel with - QMAGIC support" then you'll have to say Y here. You may answer M to - compile a.out support as a module and later load the module when you - want to use a program or library in a.out format. The module will be - called binfmt_aout. Saying M or N here is dangerous though, - because some crucial programs on your system might still be in A.OUT - format. - -config BINFMT_ELF - tristate "Kernel support for ELF binaries" - ---help--- - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries - and enlarge it by about 13 KB. ELF support under Linux has now all - but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) - because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating systems - however) and makes building run-time libraries very easy. Many new - executables are distributed solely in ELF format. You definitely - want to say Y here. - - Information about ELF is contained in the ELF HOWTO available from - . - - If you find that after upgrading from Linux kernel 1.2 and saying Y - here, you still can't run any ELF binaries (they just crash), then - you'll have to install the newest ELF runtime libraries, including - ld.so (check the file for location and - latest version). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. +source "fs/Kconfig.binfmt" config ZORRO bool "Amiga Zorro (AutoConfig) bus support" @@ -680,417 +606,7 @@ module if your root file system (the one containing the directory /) is located on a SCSI device. -comment "SCSI support type (disk, tape, CD-ROM)" - depends on SCSI - -config BLK_DEV_SD - tristate "SCSI disk support" - depends on SCSI - ---help--- - If you want to use a SCSI hard disk or the SCSI or parallel port - version of the IOMEGA ZIP drive under Linux, say Y and read the - SCSI-HOWTO, the Disk-HOWTO and the Multi-Disk-HOWTO, available from - . This is NOT for SCSI - CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sd_mod. If you want to compile it as a - module, say M here and read and - . Do not compile this driver as a - module if your root file system (the one containing the directory /) - is located on a SCSI disk. In this case, do not compile the driver - for your SCSI host adapter (below) as a module either. - -config SD_EXTRA_DEVS - int "Maximum number of SCSI disks that can be loaded as modules" - depends on BLK_DEV_SD - default "40" - ---help--- - This controls the amount of additional space allocated in tables for - drivers that are loaded as modules after the kernel is booted. In - the event that the SCSI core itself was loaded as a module, this - value is the number of additional disks that can be loaded after the - first host driver is loaded. - - Admittedly this isn't pretty, but there are tons of race conditions - involved with resizing the internal arrays on the fly. Someday this - flag will go away, and everything will work automatically. - - If you don't understand what's going on, go with the default. - -config CHR_DEV_ST - tristate "SCSI tape support" - depends on SCSI - ---help--- - If you want to use a SCSI tape drive under Linux, say Y and read the - SCSI-HOWTO, available from - , and - in the kernel source. This is NOT for - SCSI CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called st. If you want to compile it as a - module, say M here and read and - . - -config ST_EXTRA_DEVS - int "Maximum number of SCSI tapes that can be loaded as modules" - depends on CHR_DEV_ST - default "2" - ---help--- - This controls the amount of additional space allocated in tables for - drivers that are loaded as modules after the kernel is booted. In - the event that the SCSI core itself was loaded as a module, this - value is the number of additional tapes that can be loaded after the - first host driver is loaded. - - Admittedly this isn't pretty, but there are tons of race conditions - involved with resizing the internal arrays on the fly. Someday this - flag will go away, and everything will work automatically. - - If you don't understand what's going on, go with the default. - -config BLK_DEV_SR - tristate "SCSI CDROM support" - depends on SCSI - ---help--- - If you want to use a SCSI CD-ROM under Linux, say Y and read the - SCSI-HOWTO and the CD-ROM-HOWTO at - . Also make sure to say Y - or M to "ISO 9660 CD-ROM file system support" later. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sr_mod. If you want to compile it as a - module, say M here and read and - . - -config BLK_DEV_SR_VENDOR - bool "Enable vendor-specific extensions (for SCSI CDROM)" - depends on BLK_DEV_SR - help - This enables the usage of vendor specific SCSI commands. This is - required to support multisession CDs with old NEC/TOSHIBA cdrom - drives (and HP Writers). If you have such a drive and get the first - session only, try saying Y here; everybody else says N. - -config SR_EXTRA_DEVS - int "Maximum number of CDROM devices that can be loaded as modules" - depends on BLK_DEV_SR - default "2" - ---help--- - This controls the amount of additional space allocated in tables for - drivers that are loaded as modules after the kernel is booted. In - the event that the SCSI core itself was loaded as a module, this - value is the number of additional CD-ROMs that can be loaded after - the first host driver is loaded. - - Admittedly this isn't pretty, but there are tons of race conditions - involved with resizing the internal arrays on the fly. Someday this - flag will go away, and everything will work automatically. - - If you don't understand what's going on, go with the default. - -config CHR_DEV_SG - tristate "SCSI generic support" - depends on SCSI - ---help--- - If you want to use SCSI scanners, synthesizers or CD-writers or just - about anything having "SCSI" in its name other than hard disks, - CD-ROMs or tapes, say Y here. These won't be supported by the kernel - directly, so you need some additional software which knows how to - talk to these devices using the SCSI protocol: - - For scanners, look at SANE (). For CD - writer software look at Cdrtools - () - and for burning a "disk at once": CDRDAO - (). Cdparanoia is a high - quality digital reader of audio CDs (). - For other devices, it's possible that you'll have to write the - driver software yourself. Please read the file - for more information. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read and - . The module will be called sg. - If unsure, say N. - -comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs" - depends on SCSI - -config SCSI_MULTI_LUN - bool "Probe all LUNs on each SCSI device" - depends on SCSI - help - If you have a SCSI device that supports more than one LUN (Logical - Unit Number), e.g. a CD jukebox, and only one LUN is detected, you - can say Y here to force the SCSI driver to probe for multiple LUNs. - A SCSI device with multiple LUNs acts logically like multiple SCSI - devices. The vast majority of SCSI devices have only one LUN, and - so most people can say N here and should in fact do so, because it - is safer. - -config SCSI_CONSTANTS - bool "Verbose SCSI error reporting (kernel size +=12K)" - depends on SCSI - help - The error messages regarding your SCSI hardware will be easier to - understand if you say Y here; it will enlarge your kernel by about - 12 KB. If in doubt, say Y. - -config SCSI_LOGGING - bool "SCSI logging facility" - depends on SCSI - ---help--- - This turns on a logging facility that can be used to debug a number - of SCSI related problems. - - If you say Y here, no logging output will appear by default, but you - can enable logging by saying Y to "/proc file system support" and - "Sysctl support" below and executing the command - - echo "scsi log token [level]" > /proc/scsi/scsi - - at boot time after the /proc file system has been mounted. - - There are a number of things that can be used for 'token' (you can - find them in the source: ), and this - allows you to select the types of information you want, and the - level allows you to select the level of verbosity. - - If you say N here, it may be harder to track down some types of SCSI - problems. If you say Y here your kernel will be somewhat larger, but - there should be no noticeable performance impact as long as you have - logging turned off. - - -menu "SCSI low-level drivers" - depends on SCSI!=n - -config A3000_SCSI - tristate "A3000 WD33C93A support" - depends on AMIGA && SCSI - help - If you have an Amiga 3000 and have SCSI devices connected to the - built-in SCSI controller, say Y. Otherwise, say N. This driver is - also available as a module ( = code which can be inserted in and - removed from the running kernel whenever you want). The module is - called wd33c93. If you want to compile it as a module, say M here - and read . - -config A4000T_SCSI - bool "A4000T SCSI support (EXPERIMENTAL)" - depends on AMIGA && EXPERIMENTAL - help - Support for the NCR53C710 SCSI controller on the Amiga 4000T. - -config A2091_SCSI - tristate "A2091 WD33C93A support" - depends on ZORRO && SCSI - help - If you have a Commodore A2091 SCSI controller, say Y. Otherwise, - say N. This driver is also available as a module ( = code which can - be inserted in and removed from the running kernel whenever you - want). The module is called wd33c93. If you want to compile it as - a module, say M here and read . - -config GVP11_SCSI - tristate "GVP Series II WD33C93A support" - depends on ZORRO && SCSI - ---help--- - If you have a Great Valley Products Series II SCSI controller, - answer Y. Also say Y if you have a later model of GVP SCSI - controller (such as the GVP A4008 or a Combo board). Otherwise, - answer N. This driver does NOT work for the T-Rex series of - accelerators from TekMagic and GVP-M. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). The module will be called gvp11. If you want to compile it - as a module, say M here and read . - -config CYBERSTORM_SCSI - tristate "CyberStorm SCSI support" - depends on ZORRO && SCSI - help - If you have an Amiga with an original (MkI) Phase5 Cyberstorm - accelerator board and the optional Cyberstorm SCSI controller, - answer Y. Otherwise, say N. - -config CYBERSTORMII_SCSI - tristate "CyberStorm Mk II SCSI support" - depends on ZORRO && SCSI - help - If you have an Amiga with a Phase5 Cyberstorm MkII accelerator board - and the optional Cyberstorm SCSI controller, say Y. Otherwise, - answer N. - -config BLZ2060_SCSI - tristate "Blizzard 2060 SCSI support" - depends on ZORRO && SCSI - help - If you have an Amiga with a Phase5 Blizzard 2060 accelerator board - and want to use the onboard SCSI controller, say Y. Otherwise, - answer N. - -config BLZ1230_SCSI - tristate "Blizzard 1230IV/1260 SCSI support" - depends on ZORRO && SCSI - help - If you have an Amiga 1200 with a Phase5 Blizzard 1230IV or Blizzard - 1260 accelerator, and the optional SCSI module, say Y. Otherwise, - say N. - -config FASTLANE_SCSI - tristate "Fastlane SCSI support" - depends on ZORRO && SCSI - help - If you have the Phase5 Fastlane Z3 SCSI controller, or plan to use - one in the near future, say Y to this question. Otherwise, say N. - -config A4091_SCSI - bool "A4091 SCSI support (EXPERIMENTAL)" - depends on ZORRO && EXPERIMENTAL - help - Support for the NCR53C710 chip on the Amiga 4091 Z3 SCSI2 controller - (1993). Very obscure -- the 4091 was part of an Amiga 4000 upgrade - plan at the time the Amiga business was sold to DKB. - -config WARPENGINE_SCSI - bool "WarpEngine SCSI support (EXPERIMENTAL)" - depends on ZORRO && EXPERIMENTAL - help - Support for MacroSystem Development's WarpEngine Amiga SCSI-2 - controller. Info at - . - -config BLZ603EPLUS_SCSI - bool "Blizzard PowerUP 603e+ SCSI (EXPERIMENTAL)" - depends on ZORRO && EXPERIMENTAL - help - If you have an Amiga 1200 with a Phase5 Blizzard PowerUP 603e+ - accelerator, say Y. Otherwise, say N. - -config OKTAGON_SCSI - tristate "BSC Oktagon SCSI support (EXPERIMENTAL)" - depends on ZORRO && EXPERIMENTAL && SCSI - help - If you have the BSC Oktagon SCSI disk controller for the Amiga, say - Y to this question. If you're in doubt about whether you have one, - see the picture at - . - -# bool 'Cyberstorm Mk III SCSI support (EXPERIMENTAL)' CONFIG_CYBERSTORMIII_SCSI -# bool 'GVP Turbo 040/060 SCSI support (EXPERIMENTAL)' CONFIG_GVP_TURBO_SCSI -config ATARI_SCSI - tristate "Atari native SCSI support" - depends on ATARI && SCSI - ---help--- - If you have an Atari with built-in NCR5380 SCSI controller (TT, - Falcon, ...) say Y to get it supported. Of course also, if you have - a compatible SCSI controller (e.g. for Medusa). This driver is also - available as a module ( = code which can be inserted in and removed - from the running kernel whenever you want). The module is called - atari_scsi. If you want to compile it as a module, say M here and - read . This driver supports both - styles of NCR integration into the system: the TT style (separate - DMA), and the Falcon style (via ST-DMA, replacing ACSI). It does - NOT support other schemes, like in the Hades (without DMA). - -config ATARI_SCSI_TOSHIBA_DELAY - bool "Long delays for Toshiba CD-ROMs" - depends on ATARI_SCSI - help - This option increases the delay after a SCSI arbitration to - accommodate some flaky Toshiba CD-ROM drives. Say Y if you intend to - use a Toshiba CD-ROM drive; otherwise, the option is not needed and - would impact performance a bit, so say N. - -config ATARI_SCSI_RESET_BOOT - bool "Reset SCSI-devices at boottime" - depends on ATARI_SCSI - help - Reset the devices on your Atari whenever it boots. This makes the - boot process fractionally longer but may assist recovery from errors - that leave the devices with SCSI operations partway completed. - -config TT_DMA_EMUL - bool "Hades SCSI DMA emulator" - depends on ATARI_SCSI && HADES - help - This option enables code which emulates the TT SCSI DMA chip on the - Hades. This increases the SCSI transfer rates at least ten times - compared to PIO transfers. - -config MAC_SCSI - bool "Macintosh NCR5380 SCSI" - depends on MAC - help - This is the NCR 5380 SCSI controller included on most of the 68030 - based Macintoshes. If you have one of these say Y and read the - SCSI-HOWTO, available from - . - -config SCSI_MAC_ESP - tristate "Macintosh NCR53c9[46] SCSI" - depends on MAC && SCSI - help - This is the NCR 53c9x SCSI controller found on most of the 68040 - based Macintoshes. If you have one of these say Y and read the - SCSI-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called mac_esp. If you want to compile it as - a module, say M here and read . - -# dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI -config MVME147_SCSI - bool "WD33C93 SCSI driver for MVME147" - depends on MVME147 - help - Support for the on-board SCSI controller on the Motorola MVME147 - single-board computer. - -config MVME16x_SCSI - bool "NCR53C710 SCSI driver for MVME16x" - depends on MVME16x - help - The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710 - SCSI controller chip. Almost everyone using one of these boards - will want to say Y to this question. - -config BVME6000_SCSI - bool "NCR53C710 SCSI driver for BVME6000" - depends on BVME6000 - help - The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710 - SCSI controller chip. Almost everyone using one of these boards - will want to say Y to this question. - -config SUN3_SCSI - tristate "Sun3 NCR5380 SCSI" - depends on SUN3 && SCSI - help - This option will enable support for the OBIO (onboard io) NCR5380 - SCSI controller found in the Sun 3/50 and 3/60, as well as for - "Sun3" type VME scsi controllers also based on the NCR5380. - General Linux information on the Sun 3 series (now discontinued) - is at . - -config SUN3X_ESP - bool "Sun3x ESP SCSI" - depends on SUN3X - help - The ESP was an on-board SCSI controller used on Sun 3/80 - machines. Say Y here to compile in support for it. - -endmenu +source "drivers/scsi/Kconfig" endmenu diff -Nru a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig --- a/arch/m68knommu/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/m68knommu/Kconfig Sat Jun 14 15:25:48 2003 @@ -501,16 +501,7 @@ config KCORE_ELF default y -config BINFMT_FLAT - tristate "Kernel support for flat binaries" - help - Support uClinux FLAT format binaries. - -config BINFMT_ZFLAT - bool " Enable ZFLAT support" - depends on BINFMT_FLAT - help - Supoprt FLAT format compressed binaries +source "fs/Kconfig.binfmt" endmenu diff -Nru a/arch/mips/Kconfig b/arch/mips/Kconfig --- a/arch/mips/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/mips/Kconfig Thu Jun 12 10:41:27 2003 @@ -702,82 +702,7 @@ bool "ARC console support" depends on ARC32 -config BINFMT_AOUT - bool - ---help--- - A.out (Assembler.OUTput) is a set of formats for libraries and - executables used in the earliest versions of UNIX. Linux used the - a.out formats QMAGIC and ZMAGIC until they were replaced with the - ELF format. - - As more and more programs are converted to ELF, the use for a.out - will gradually diminish. If you disable this option it will reduce - your kernel by one page. This is not much and by itself does not - warrant removing support. However its removal is a good idea if you - wish to ensure that absolutely none of your programs will use this - older executable format. If you don't know what to answer at this - point then answer Y. If someone told you "You need a kernel with - QMAGIC support" then you'll have to say Y here. You may answer M to - compile a.out support as a module and later load the module when you - want to use a program or library in a.out format. The module will be - called binfmt_aout. Saying M or N here is dangerous though, - because some crucial programs on your system might still be in A.OUT - format. - -config BINFMT_ELF - bool - default y - ---help--- - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries - and enlarge it by about 13 KB. ELF support under Linux has now all - but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) - because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating systems - however) and makes building run-time libraries very easy. Many new - executables are distributed solely in ELF format. You definitely - want to say Y here. - - Information about ELF is contained in the ELF HOWTO available from - . - - If you find that after upgrading from Linux kernel 1.2 and saying Y - here, you still can't run any ELF binaries (they just crash), then - you'll have to install the newest ELF runtime libraries, including - ld.so (check the file for location and - latest version). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. +source "fs/Kconfig.binfmt" source "drivers/pci/Kconfig" diff -Nru a/arch/mips64/Kconfig b/arch/mips64/Kconfig --- a/arch/mips64/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/mips64/Kconfig Thu Jun 12 10:41:27 2003 @@ -335,34 +335,7 @@ bool "ARC console support" depends on ARC32 -config BINFMT_ELF - tristate "Kernel support for 64-bit ELF binaries" - ---help--- - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries - and enlarge it by about 13 KB. ELF support under Linux has now all - but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) - because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating systems - however) and makes building run-time libraries very easy. Many new - executables are distributed solely in ELF format. You definitely - want to say Y here. - - Information about ELF is contained in the ELF HOWTO available from - . - - If you find that after upgrading from Linux kernel 1.2 and saying Y - here, you still can't run any ELF binaries (they just crash), then - you'll have to install the newest ELF runtime libraries, including - ld.so (check the file for location and - latest version). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. +source "fs/Kconfig.binfmt" config MIPS32_COMPAT bool "Kernel support for Linux/MIPS 32-bit binary compatibility" @@ -378,36 +351,11 @@ config BINFMT_ELF32 bool - depends on MIPS32_COMPAT + depends on BINFMT_ELF && MIPS32_COMPAT default y help This allows you to run 32-bit Linux/ELF binaries on your Ultra. Everybody wants this; say Y. - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. endmenu diff -Nru a/arch/parisc/Kconfig b/arch/parisc/Kconfig --- a/arch/parisc/Kconfig Sun May 11 22:49:49 2003 +++ b/arch/parisc/Kconfig Thu Jun 12 10:41:27 2003 @@ -166,66 +166,7 @@ depends on PROC_FS default y -config BINFMT_SOM - tristate "Kernel support for SOM binaries" - depends on HPUX - help - SOM is a binary executable format inherited from HP/UX. Say Y here - to be able to load and execute SOM binaries directly. - -config BINFMT_ELF - tristate "Kernel support for ELF binaries" - ---help--- - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries - and enlarge it by about 13 KB. ELF support under Linux has now all - but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) - because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating systems - however) and makes building run-time libraries very easy. Many new - executables are distributed solely in ELF format. You definitely - want to say Y here. - - Information about ELF is contained in the ELF HOWTO available from - . - - If you find that after upgrading from Linux kernel 1.2 and saying Y - here, you still can't run any ELF binaries (they just crash), then - you'll have to install the newest ELF runtime libraries, including - ld.so (check the file for location and - latest version). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. +source "fs/Kconfig.binfmt" endmenu diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig --- a/arch/ppc/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/ppc/Kconfig Sat Jun 14 15:25:49 2003 @@ -808,42 +808,11 @@ "-g" option to preserve debugging information. It is mainly used for examining kernel data structures on the live kernel. -config BINFMT_ELF - bool - default y - help - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. - config KERNEL_ELF bool default y -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. +source "fs/Kconfig.binfmt" source "drivers/pci/Kconfig" diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig --- a/arch/ppc64/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/ppc64/Kconfig Sat Jun 14 15:25:50 2003 @@ -191,37 +191,7 @@ "-g" option to preserve debugging information. It is mainly used for examining kernel data structures on the live kernel. -config BINFMT_ELF - bool "Kernel support for 64-bit ELF binaries" - help - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. +source "fs/Kconfig.binfmt" source "drivers/pci/Kconfig" diff -Nru a/arch/s390/Kconfig b/arch/s390/Kconfig --- a/arch/s390/Kconfig Sun Apr 20 12:56:51 2003 +++ b/arch/s390/Kconfig Thu Jun 12 10:41:27 2003 @@ -192,78 +192,8 @@ config KCORE_ELF bool default y - ---help--- - If you enabled support for /proc file system then the file - /proc/kcore will contain the kernel core image. This can be used - in gdb: - $ cd /usr/src/linux ; gdb vmlinux /proc/kcore - - You have two choices here: ELF and A.OUT. Selecting ELF will make - /proc/kcore appear in ELF core format as defined by the Executable - and Linking Format specification. Selecting A.OUT will choose the - old "a.out" format which may be necessary for some old versions - of binutils or on some architectures. - - This is especially useful if you have compiled the kernel with the - "-g" option to preserve debugging information. It is mainly used - for examining kernel data structures on the live kernel so if you - don't understand what this means or are not a kernel hacker, just - leave it at its default value ELF. - -config BINFMT_ELF - tristate "Kernel support for ELF binaries" - ---help--- - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries - and enlarge it by about 13 KB. ELF support under Linux has now all - but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) - because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating systems - however) and makes building run-time libraries very easy. Many new - executables are distributed solely in ELF format. You definitely - want to say Y here. - - Information about ELF is contained in the ELF HOWTO available from - . - - If you find that after upgrading from Linux kernel 1.2 and saying Y - here, you still can't run any ELF binaries (they just crash), then - you'll have to install the newest ELF runtime libraries, including - ld.so (check the file for location and - latest version). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. +source "fs/Kconfig.binfmt" config PROCESS_DEBUG bool "Show crashed user process info" diff -Nru a/arch/sh/Kconfig b/arch/sh/Kconfig --- a/arch/sh/Kconfig Sat Jun 14 17:43:31 2003 +++ b/arch/sh/Kconfig Sat Jun 14 15:35:19 2003 @@ -763,62 +763,7 @@ endchoice -config BINFMT_ELF - tristate "Kernel support for ELF binaries" - ---help--- - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries - and enlarge it by about 13 KB. ELF support under Linux has now all - but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) - because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating systems - however) and makes building run-time libraries very easy. Many new - executables are distributed solely in ELF format. You definitely - want to say Y here. - - Information about ELF is contained in the ELF HOWTO available from - . - - If you find that after upgrading from Linux kernel 1.2 and saying Y - here, you still can't run any ELF binaries (they just crash), then - you'll have to install the newest ELF runtime libraries, including - ld.so (check the file for location and - latest version). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. - -config BINFMT_FLAT - tristate "Kernel support for FLAT binaries" - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. +source "fs/Kconfig.binfmt" endmenu diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig --- a/arch/sparc/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/sparc/Kconfig Thu Jun 12 10:41:27 2003 @@ -277,81 +277,7 @@ don't understand what this means or are not a kernel hacker, just leave it at its default value ELF. -config BINFMT_AOUT - tristate "Kernel support for a.out binaries" - ---help--- - A.out (Assembler.OUTput) is a set of formats for libraries and - executables used in the earliest versions of UNIX. Linux used the - a.out formats QMAGIC and ZMAGIC until they were replaced with the - ELF format. - - As more and more programs are converted to ELF, the use for a.out - will gradually diminish. If you disable this option it will reduce - your kernel by one page. This is not much and by itself does not - warrant removing support. However its removal is a good idea if you - wish to ensure that absolutely none of your programs will use this - older executable format. If you don't know what to answer at this - point then answer Y. If someone told you "You need a kernel with - QMAGIC support" then you'll have to say Y here. You may answer M to - compile a.out support as a module and later load the module when you - want to use a program or library in a.out format. The module will be - called binfmt_aout. Saying M or N here is dangerous though, - because some crucial programs on your system might still be in A.OUT - format. - -config BINFMT_ELF - tristate "Kernel support for ELF binaries" - ---help--- - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries - and enlarge it by about 13 KB. ELF support under Linux has now all - but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) - because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating systems - however) and makes building run-time libraries very easy. Many new - executables are distributed solely in ELF format. You definitely - want to say Y here. - - Information about ELF is contained in the ELF HOWTO available from - . - - If you find that after upgrading from Linux kernel 1.2 and saying Y - here, you still can't run any ELF binaries (they just crash), then - you'll have to install the newest ELF runtime libraries, including - ld.so (check the file for location and - latest version). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. +source "fs/Kconfig.binfmt" config SUNOS_EMUL bool "SunOS binary emulation" @@ -576,232 +502,7 @@ module if your root file system (the one containing the directory /) is located on a SCSI device. -comment "SCSI support type (disk, tape, CDrom)" - depends on SCSI - -config BLK_DEV_SD - tristate "SCSI disk support" - depends on SCSI - ---help--- - If you want to use a SCSI hard disk or the SCSI or parallel port - version of the IOMEGA ZIP drive under Linux, say Y and read the - SCSI-HOWTO, the Disk-HOWTO and the Multi-Disk-HOWTO, available from - . This is NOT for SCSI - CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sd_mod. If you want to compile it as a - module, say M here and read and - . Do not compile this driver as a - module if your root file system (the one containing the directory /) - is located on a SCSI disk. In this case, do not compile the driver - for your SCSI host adapter (below) as a module either. - -config SD_EXTRA_DEVS - int "Maximum number of SCSI disks that can be loaded as modules" - depends on BLK_DEV_SD - default "40" - ---help--- - This controls the amount of additional space allocated in tables for - drivers that are loaded as modules after the kernel is booted. In - the event that the SCSI core itself was loaded as a module, this - value is the number of additional disks that can be loaded after the - first host driver is loaded. - - Admittedly this isn't pretty, but there are tons of race conditions - involved with resizing the internal arrays on the fly. Someday this - flag will go away, and everything will work automatically. - - If you don't understand what's going on, go with the default. - -config CHR_DEV_ST - tristate "SCSI tape support" - depends on SCSI - ---help--- - If you want to use a SCSI tape drive under Linux, say Y and read the - SCSI-HOWTO, available from - , and - in the kernel source. This is NOT - for SCSI CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called st. If you want to compile it as a - module, say M here and read and - . - -config CHR_DEV_OSST - tristate "SCSI OnStream SC-x0 tape support" - depends on SCSI - ---help--- - The OnStream SC-x0 SCSI tape drives can not be driven by the - standard st driver, but instead need this special osst driver and - use the /dev/osstX char device nodes (major 206). Via usb-storage - and ide-scsi, you may be able to drive the USB-x0 and DI-x0 drives - as well. Note that there is also a second generation of OnStream - tape drives (ADR-x0) that supports the standard SCSI-2 commands for - tapes (QIC-157) and can be driven by the standard driver st. - For more information, you may have a look at the SCSI-HOWTO - and - in the kernel source. - More info on the OnStream driver may be found on - - Please also have a look at the standard st docu, as most of it - applies to osst as well. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called osst. If you want to compile it as a - module, say M here and read and - . - -config BLK_DEV_SR - tristate "SCSI CDROM support" - depends on SCSI - ---help--- - If you want to use a SCSI CD-ROM under Linux, say Y and read the - SCSI-HOWTO and the CD-ROM-HOWTO at - . Also make sure to say Y - or M to "ISO 9660 CD-ROM file system support" later. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sr_mod. If you want to compile it as a - module, say M here and read and - . - -config BLK_DEV_SR_VENDOR - bool "Enable vendor-specific extensions (for SCSI CDROM)" - depends on BLK_DEV_SR - help - This enables the usage of vendor specific SCSI commands. This is - required to support multisession CDs with old NEC/TOSHIBA cdrom - drives (and HP Writers). If you have such a drive and get the first - session only, try saying Y here; everybody else says N. - -config SR_EXTRA_DEVS - int "Maximum number of CDROM devices that can be loaded as modules" - depends on BLK_DEV_SR - default "2" - ---help--- - This controls the amount of additional space allocated in tables for - drivers that are loaded as modules after the kernel is booted. In - the event that the SCSI core itself was loaded as a module, this - value is the number of additional CD-ROMs that can be loaded after - the first host driver is loaded. - - Admittedly this isn't pretty, but there are tons of race conditions - involved with resizing the internal arrays on the fly. Someday this - flag will go away, and everything will work automatically. - - If you don't understand what's going on, go with the default. - -config CHR_DEV_SG - tristate "SCSI generic support" - depends on SCSI - ---help--- - If you want to use SCSI scanners, synthesizers or CD-writers or just - about anything having "SCSI" in its name other than hard disks, - CD-ROMs or tapes, say Y here. These won't be supported by the kernel - directly, so you need some additional software which knows how to - talk to these devices using the SCSI protocol: - - For scanners, look at SANE (). For CD - writer software look at Cdrtools - () - and for burning a "disk at once": CDRDAO - (). Cdparanoia is a high - quality digital reader of audio CDs (). - For other devices, it's possible that you'll have to write the - driver software yourself. Please read the file - for more information. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read and - . The module will be called sg. - If unsure, say N. - -comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs" - depends on SCSI - -config SCSI_MULTI_LUN - bool "Probe all LUNs on each SCSI device" - depends on SCSI - help - If you have a SCSI device that supports more than one LUN (Logical - Unit Number), e.g. a CD jukebox, and only one LUN is detected, you - can say Y here to force the SCSI driver to probe for multiple LUNs. - A SCSI device with multiple LUNs acts logically like multiple SCSI - devices. The vast majority of SCSI devices have only one LUN, and - so most people can say N here and should in fact do so, because it - is safer. - -config SCSI_CONSTANTS - bool "Verbose SCSI error reporting (kernel size +=12K)" - depends on SCSI - help - The error messages regarding your SCSI hardware will be easier to - understand if you say Y here; it will enlarge your kernel by about - 12 KB. If in doubt, say Y. - -config SCSI_LOGGING - bool "SCSI logging facility" - depends on SCSI - ---help--- - This turns on a logging facility that can be used to debug a number - of SCSI related problems. - - If you say Y here, no logging output will appear by default, but you - can enable logging by saying Y to "/proc file system support" and - "Sysctl support" below and executing the command - - echo "scsi log token [level]" > /proc/scsi/scsi - - at boot time after the /proc file system has been mounted. - - There are a number of things that can be used for 'token' (you can - find them in the source: ), and this - allows you to select the types of information you want, and the - level allows you to select the level of verbosity. - - If you say N here, it may be harder to track down some types of SCSI - problems. If you say Y here your kernel will be somewhat larger, but - there should be no noticeable performance impact as long as you have - logging turned off. - - -menu "SCSI low-level drivers" - depends on SCSI!=n - -config SCSI_SUNESP - tristate "Sparc ESP Scsi Driver" - depends on SCSI - help - This is the driver for the Sun ESP SCSI host adapter. The ESP - chipset is present in most SPARC SBUS-based computers. - - This support is also available as a module called esp ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -config SCSI_QLOGICPTI - tristate "PTI Qlogic,ISP Driver" - depends on SCSI - help - This driver supports SBUS SCSI controllers from PTI or QLogic. These - controllers are known under Solaris as qpti and in the openprom as - PTI,ptisp or QLGC,isp. Note that PCI QLogic SCSI controllers are - driven by a different driver. - - This support is also available as a module called qlogicpti ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -endmenu +source "drivers/scsi/Kconfig" endmenu diff -Nru a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c --- a/arch/sparc/kernel/time.c Sat Jun 14 16:16:07 2003 +++ b/arch/sparc/kernel/time.c Tue Jun 17 15:46:44 2003 @@ -408,9 +408,9 @@ mon = MSTK_REG_MONTH(mregs); year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - wall_to_monotonic.tv_sec = -xtime.tv_sec + INITIAL_JIFFIES / HZ; + wall_to_monotonic.tv_sec = -xtime.tv_sec; xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - wall_to_monotonic.tv_nsec = 0; + wall_to_monotonic.tv_nsec = -xtime.tv_nsec; mregs->creg &= ~MSTK_CREG_READ; spin_unlock_irq(&mostek_lock); #ifdef CONFIG_SUN4 @@ -441,9 +441,9 @@ intersil_start(iregs); xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - wall_to_monotonic.tv_sec = -xtime.tv_sec + INITIAL_JIFFIES / HZ; + wall_to_monotonic.tv_sec = -xtime.tv_sec; xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - wall_to_monotonic.tv_nsec = 0; + wall_to_monotonic.tv_nsec = -xtime.tv_nsec; printk("%u/%u/%u %u:%u:%u\n",day,mon,year,hour,min,sec); } #endif diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig --- a/arch/sparc64/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/sparc64/Kconfig Sat Jun 14 15:25:52 2003 @@ -415,59 +415,7 @@ If you want to run SunOS binaries (see SunOS binary emulation below) or other a.out binaries, say Y. If unsure, say N. -config BINFMT_ELF - tristate "Kernel support for 64-bit ELF binaries" - ---help--- - ELF (Executable and Linkable Format) is a format for libraries and - executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries - and enlarge it by about 13 KB. ELF support under Linux has now all - but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) - because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating systems - however) and makes building run-time libraries very easy. Many new - executables are distributed solely in ELF format. You definitely - want to say Y here. - - Information about ELF is contained in the ELF HOWTO available from - . - - If you find that after upgrading from Linux kernel 1.2 and saying Y - here, you still can't run any ELF binaries (they just crash), then - you'll have to install the newest ELF runtime libraries, including - ld.so (check the file for location and - latest version). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. It's also useful if you often run DOS executables under - the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have - registered such a binary class with the kernel, you can start one of - those programs simply by typing in its name at a shell prompt; Linux - will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. +source "fs/Kconfig.binfmt" config SUNOS_EMUL bool "SunOS binary emulation" @@ -748,642 +696,7 @@ module if your root file system (the one containing the directory /) is located on a SCSI device. -comment "SCSI support type (disk, tape, CDrom)" - depends on SCSI - -config BLK_DEV_SD - tristate "SCSI disk support" - depends on SCSI - ---help--- - If you want to use a SCSI hard disk or the SCSI or parallel port - version of the IOMEGA ZIP drive under Linux, say Y and read the - SCSI-HOWTO, the Disk-HOWTO and the Multi-Disk-HOWTO, available from - . This is NOT for SCSI - CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sd_mod. If you want to compile it as a - module, say M here and read and - . Do not compile this driver as a - module if your root file system (the one containing the directory /) - is located on a SCSI disk. In this case, do not compile the driver - for your SCSI host adapter (below) as a module either. - -config SD_EXTRA_DEVS - int "Maximum number of SCSI disks that can be loaded as modules" - depends on BLK_DEV_SD - default "40" - ---help--- - This controls the amount of additional space allocated in tables for - drivers that are loaded as modules after the kernel is booted. In - the event that the SCSI core itself was loaded as a module, this - value is the number of additional disks that can be loaded after the - first host driver is loaded. - - Admittedly this isn't pretty, but there are tons of race conditions - involved with resizing the internal arrays on the fly. Someday this - flag will go away, and everything will work automatically. - - If you don't understand what's going on, go with the default. - -config CHR_DEV_ST - tristate "SCSI tape support" - depends on SCSI - ---help--- - If you want to use a SCSI tape drive under Linux, say Y and read the - SCSI-HOWTO, available from - , and - in the kernel source. This is NOT - for SCSI CD-ROMs. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called st. If you want to compile it as a - module, say M here and read and - . - -config CHR_DEV_OSST - tristate "SCSI OnStream SC-x0 tape support" - depends on SCSI - ---help--- - The OnStream SC-x0 SCSI tape drives can not be driven by the - standard st driver, but instead need this special osst driver and - use the /dev/osstX char device nodes (major 206). Via usb-storage - and ide-scsi, you may be able to drive the USB-x0 and DI-x0 drives - as well. Note that there is also a second generation of OnStream - tape drives (ADR-x0) that supports the standard SCSI-2 commands for - tapes (QIC-157) and can be driven by the standard driver st. - For more information, you may have a look at the SCSI-HOWTO - and - in the kernel source. - More info on the OnStream driver may be found on - - Please also have a look at the standard st docu, as most of it - applies to osst as well. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called osst. If you want to compile it as a - module, say M here and read and - . - -config BLK_DEV_SR - tristate "SCSI CDROM support" - depends on SCSI - ---help--- - If you want to use a SCSI CD-ROM under Linux, say Y and read the - SCSI-HOWTO and the CD-ROM-HOWTO at - . Also make sure to say Y - or M to "ISO 9660 CD-ROM file system support" later. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sr_mod. If you want to compile it as a - module, say M here and read and - . - -config BLK_DEV_SR_VENDOR - bool "Enable vendor-specific extensions (for SCSI CDROM)" - depends on BLK_DEV_SR - help - This enables the usage of vendor specific SCSI commands. This is - required to support multisession CDs with old NEC/TOSHIBA cdrom - drives (and HP Writers). If you have such a drive and get the first - session only, try saying Y here; everybody else says N. - -config SR_EXTRA_DEVS - int "Maximum number of CDROM devices that can be loaded as modules" - depends on BLK_DEV_SR - default "2" - ---help--- - This controls the amount of additional space allocated in tables for - drivers that are loaded as modules after the kernel is booted. In - the event that the SCSI core itself was loaded as a module, this - value is the number of additional CD-ROMs that can be loaded after - the first host driver is loaded. - - Admittedly this isn't pretty, but there are tons of race conditions - involved with resizing the internal arrays on the fly. Someday this - flag will go away, and everything will work automatically. - - If you don't understand what's going on, go with the default. - -config CHR_DEV_SG - tristate "SCSI generic support" - depends on SCSI - ---help--- - If you want to use SCSI scanners, synthesizers or CD-writers or just - about anything having "SCSI" in its name other than hard disks, - CD-ROMs or tapes, say Y here. These won't be supported by the kernel - directly, so you need some additional software which knows how to - talk to these devices using the SCSI protocol: - - For scanners, look at SANE (). For CD - writer software look at Cdrtools - () - and for burning a "disk at once": CDRDAO - (). Cdparanoia is a high - quality digital reader of audio CDs (). - For other devices, it's possible that you'll have to write the - driver software yourself. Please read the file - for more information. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read and - . The module will be called sg. - If unsure, say N. - -comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs" - depends on SCSI - -config SCSI_MULTI_LUN - bool "Probe all LUNs on each SCSI device" - depends on SCSI - help - If you have a SCSI device that supports more than one LUN (Logical - Unit Number), e.g. a CD jukebox, and only one LUN is detected, you - can say Y here to force the SCSI driver to probe for multiple LUNs. - A SCSI device with multiple LUNs acts logically like multiple SCSI - devices. The vast majority of SCSI devices have only one LUN, and - so most people can say N here and should in fact do so, because it - is safer. - -config SCSI_CONSTANTS - bool "Verbose SCSI error reporting (kernel size +=12K)" - depends on SCSI - help - The error messages regarding your SCSI hardware will be easier to - understand if you say Y here; it will enlarge your kernel by about - 12 KB. If in doubt, say Y. - -config SCSI_LOGGING - bool "SCSI logging facility" - depends on SCSI - ---help--- - This turns on a logging facility that can be used to debug a number - of SCSI related problems. - - If you say Y here, no logging output will appear by default, but you - can enable logging by saying Y to "/proc file system support" and - "Sysctl support" below and executing the command - - echo "scsi log token [level]" > /proc/scsi/scsi - - at boot time after the /proc file system has been mounted. - - There are a number of things that can be used for 'token' (you can - find them in the source: ), and this - allows you to select the types of information you want, and the - level allows you to select the level of verbosity. - - If you say N here, it may be harder to track down some types of SCSI - problems. If you say Y here your kernel will be somewhat larger, but - there should be no noticeable performance impact as long as you have - logging turned off. - - -menu "SCSI low-level drivers" - depends on SCSI!=n - -config SCSI_SUNESP - tristate "Sparc ESP Scsi Driver" - depends on SCSI - help - This is the driver for the Sun ESP SCSI host adapter. The ESP - chipset is present in most SPARC SBUS-based computers. - - This support is also available as a module called esp ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - -config SCSI_QLOGICPTI - tristate "PTI Qlogic, ISP Driver" - depends on SCSI - help - This driver supports SBUS SCSI controllers from PTI or QLogic. These - controllers are known under Solaris as qpti and in the openprom as - PTI,ptisp or QLGC,isp. Note that PCI QLogic SCSI controllers are - driven by a different driver. - - This support is also available as a module called qlogicpti ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read . - - -choice - prompt "Adaptec AIC7xxx support" - optional - depends on SCSI && PCI - -source "drivers/scsi/aic7xxx/Kconfig.aic7xxx" - -config SCSI_AIC7XXX_OLD - tristate "Old driver" - ---help--- - WARNING This driver is an older aic7xxx driver and is no longer - under active development. Adaptec, Inc. is writing a new driver to - take the place of this one, and it is recommended that whenever - possible, people should use the new Adaptec written driver instead - of this one. This driver will eventually be phased out entirely. - - This is support for the various aic7xxx based Adaptec SCSI - controllers. These include the 274x EISA cards; 284x VLB cards; - 2902, 2910, 293x, 294x, 394x, 3985 and several other PCI and - motherboard based SCSI controllers from Adaptec. It does not support - the AAA-13x RAID controllers from Adaptec, nor will it likely ever - support them. It does not support the 2920 cards from Adaptec that - use the Future Domain SCSI controller chip. For those cards, you - need the "Future Domain 16xx SCSI support" driver. - - In general, if the controller is based on an Adaptec SCSI controller - chip from the aic777x series or the aic78xx series, this driver - should work. The only exception is the 7810 which is specifically - not supported (that's the RAID controller chip on the AAA-13x - cards). - - Note that the AHA2920 SCSI host adapter is *not* supported by this - driver; choose "Future Domain 16xx SCSI support" instead if you have - one of those. - - Information on the configuration options for this controller can be - found by checking the help file for each of the available - configuration options. You should read - at a minimum before - contacting the maintainer with any questions. The SCSI-HOWTO, - available from , can also - be of great help. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called aic7xxx_old. - -config AIC7XXX_OLD_TCQ_ON_BY_DEFAULT - bool "Enable Tagged Command Queueing (TCQ) by default" - depends on SCSI_AIC7XXX_OLD - ---help--- - This option causes the aic7xxx driver to attempt to use Tagged - Command Queueing (TCQ) on all devices that claim to support it. - - TCQ is a feature of SCSI-2 which improves performance: the host - adapter can send several SCSI commands to a device's queue even if - previous commands haven't finished yet. Because the device is - intelligent, it can optimize its operations (like head positioning) - based on its own request queue. Not all devices implement this - correctly. - - If you say Y here, you can still turn off TCQ on troublesome devices - with the use of the tag_info boot parameter. See the file - for more information on that and - other aic7xxx setup commands. If this option is turned off, you may - still enable TCQ on known good devices by use of the tag_info boot - parameter. - - If you are unsure about your devices then it is safest to say N - here. - - However, TCQ can increase performance on some hard drives by as much - as 50% or more, so it is recommended that if you say N here, you - should at least read the file so - you will know how to enable this option manually should your drives - prove to be safe in regards to TCQ. - - Conversely, certain drives are known to lock up or cause bus resets - when TCQ is enabled on them. If you have a Western Digital - Enterprise SCSI drive for instance, then don't even bother to enable - TCQ on it as the drive will become unreliable, and it will actually - reduce performance. - -config AIC7XXX_OLD_CMDS_PER_DEVICE - int "Maximum number of TCQ commands per device" - depends on SCSI_AIC7XXX_OLD - default "8" - ---help--- - Specify the number of commands you would like to allocate per SCSI - device when Tagged Command Queueing (TCQ) is enabled on that device. - - Reasonable figures are in the range of 8 to 24 commands per device, - but depending on hardware could be increased or decreased from that - figure. If the number is too high for any particular device, the - driver will automatically compensate usually after only 10 minutes - of uptime. It will not hinder performance if some of your devices - eventually have their command depth reduced, but is a waste of - memory if all of your devices end up reducing this number down to a - more reasonable figure. - - NOTE: Certain very broken drives are known to lock up when given - more commands than they like to deal with. Quantum Fireball drives - are the most common in this category. For the Quantum Fireball - drives it is suggested to use no more than 8 commands per device. - - Default: 8 - -config AIC7XXX_OLD_PROC_STATS - bool "Collect statistics to report in /proc" - depends on SCSI_AIC7XXX_OLD - ---help--- - This option tells the driver to keep track of how many commands have - been sent to each particular device and report that information to - the user via the /proc/scsi/aic7xxx/n file, where n is the number of - the aic7xxx controller you want the information on. This adds a - small amount of overhead to each and every SCSI command the aic7xxx - driver handles, so if you aren't really interested in this - information, it is best to leave it disabled. This will only work if - you also say Y to "/proc file system support", below. - - If unsure, say N. - -endchoice - -config SCSI_SYM53C8XX_2 - tristate "SYM53C8XX Version 2 SCSI support" - depends on PCI && SCSI - ---help--- - This driver supports the whole NCR53C8XX/SYM53C8XX family of - PCI-SCSI controllers. It also supports the subset of LSI53C10XX - Ultra-160 controllers that are based on the SYM53C8XX SCRIPTS - language. It does not support LSI53C10XX Ultra-320 PCI-X SCSI - controllers. - - If your system has problems using this new major version of the - SYM53C8XX driver, you may switch back to driver version 1. - - Please read for more - information. - -config SCSI_SYM53C8XX_DMA_ADDRESSING_MODE - int "DMA addressing mode" - depends on SCSI_SYM53C8XX_2 - default "1" - ---help--- - This option only applies to PCI-SCSI chip that are PCI DAC capable - (875A, 895A, 896, 1010-33, 1010-66, 1000). - - When set to 0, only PCI 32 bit DMA addressing (SAC) will be performed. - When set to 1, 40 bit DMA addressing (with upper 24 bits of address - set to zero) is supported. The addressable range is here 1 TB. - When set to 2, full 64 bits of address for DMA are supported, but only - 16 segments of 4 GB can be addressed. The addressable range is so - limited to 64 GB. - - The safest value is 0 (32 bit DMA addressing) that is guessed to still - fit most of real machines. - - The preferred value 1 (40 bit DMA addressing) should make happy - properly engineered PCI DAC capable host bridges. You may configure - this option for Intel platforms with more than 4 GB of memory. - - The still experimental value 2 (64 bit DMA addressing with 16 x 4GB - segments limitation) can be used on systems that require PCI address - bits past bit 39 to be set for the addressing of memory using PCI - DAC cycles. - -config SCSI_SYM53C8XX_DEFAULT_TAGS - int "default tagged command queue depth" - depends on SCSI_SYM53C8XX_2 - default "16" - help - This is the default value of the command queue depth the driver will - announce to the generic SCSI layer for devices that support tagged - command queueing. This value can be changed from the boot command line. - This is a soft limit that cannot exceed CONFIG_SCSI_SYM53C8XX_MAX_TAGS. - -config SCSI_SYM53C8XX_MAX_TAGS - int "maximum number of queued commands" - depends on SCSI_SYM53C8XX_2 - default "64" - help - This option allows you to specify the maximum number of commands - that can be queued to any device, when tagged command queuing is - possible. The driver supports up to 256 queued commands per device. - This value is used as a compiled-in hard limit. - -config SCSI_SYM53C8XX_IOMAPPED - bool "use normal IO" - depends on SCSI_SYM53C8XX_2 - help - If you say Y here, the driver will preferently use normal IO rather than - memory mapped IO. - -config SCSI_NCR53C8XX - tristate "NCR53C8XX SCSI support" - depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI - ---help--- - This is the BSD ncr driver adapted to Linux for the NCR53C8XX family - of PCI-SCSI controllers. This driver supports parity checking, - tagged command queuing and fast synchronous data transfers up to 80 - MB/s with wide FAST-40 LVD devices and controllers. - - Recent versions of the 53C8XX chips are better supported by the - option "SYM53C8XX SCSI support", below. - - Note: there is yet another driver for the 53c8xx family of - controllers ("NCR53c7,8xx SCSI support" above). If you want to use - them both, you need to say M to both and build them as modules, but - only one may be active at a time. If you have a 53c8xx board, you - probably do not want to use the "NCR53c7,8xx SCSI support". - - Please read for more - information. - -config SCSI_SYM53C8XX - tristate "SYM53C8XX SCSI support" - depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI - ---help--- - This driver supports all the features of recent 53C8XX chips (used - in PCI SCSI controllers), notably the hardware phase mismatch - feature of the SYM53C896. - - Older versions of the 53C8XX chips are not supported by this - driver. If your system uses either a 810 rev. < 16, a 815, or a 825 - rev. < 16 PCI SCSI processor, you must use the generic NCR53C8XX - driver ("NCR53C8XX SCSI support" above) or configure both the - NCR53C8XX and this SYM53C8XX drivers either as module or linked to - the kernel image. - - When both drivers are linked into the kernel, the SYM53C8XX driver - is called first at initialization and you can use the 'excl=ioaddr' - driver boot option to exclude attachment of adapters by the - SYM53C8XX driver. For example, entering - 'sym53c8xx=excl:0xb400,excl=0xc000' at the lilo prompt prevents - adapters at io address 0xb400 and 0xc000 from being attached by the - SYM53C8XX driver, thus allowing the NCR53C8XX driver to attach them. - The 'excl' option is also supported by the NCR53C8XX driver. - - Please read for more - information. - -config SCSI_NCR53C8XX_DEFAULT_TAGS - int "default tagged command queue depth" - depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX) - default "8" - ---help--- - "Tagged command queuing" is a feature of SCSI-2 which improves - performance: the host adapter can send several SCSI commands to a - device's queue even if previous commands haven't finished yet. - Because the device is intelligent, it can optimize its operations - (like head positioning) based on its own request queue. Some SCSI - devices don't implement this properly; if you want to disable this - feature, enter 0 or 1 here (it doesn't matter which). - - The default value is 8 and should be supported by most hard disks. - This value can be overridden from the boot command line using the - 'tags' option as follows (example): - 'ncr53c8xx=tags:4/t2t3q16/t0u2q10' will set default queue depth to - 4, set queue depth to 16 for target 2 and target 3 on controller 0 - and set queue depth to 10 for target 0 / lun 2 on controller 1. - - The normal answer therefore is to go with the default 8 and to use - a boot command line option for devices that need to use a different - command queue depth. - - There is no safe option other than using good SCSI devices. - -config SCSI_NCR53C8XX_MAX_TAGS - int "maximum number of queued commands" - depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX) - default "32" - ---help--- - This option allows you to specify the maximum number of commands - that can be queued to any device, when tagged command queuing is - possible. The default value is 32. Minimum is 2, maximum is 64. - Modern hard disks are able to support 64 tags and even more, but - do not seem to be faster when more than 32 tags are being used. - - So, the normal answer here is to go with the default value 32 unless - you are using very large hard disks with large cache (>= 1 MB) that - are able to take advantage of more than 32 tagged commands. - - There is no safe option and the default answer is recommended. - -config SCSI_NCR53C8XX_SYNC - int "synchronous transfers frequency in MHz" - depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX) - default "10" - ---help--- - The SCSI Parallel Interface-2 Standard defines 5 classes of transfer - rates: FAST-5, FAST-10, FAST-20, FAST-40 and FAST-80. The numbers - are respectively the maximum data transfer rates in mega-transfers - per second for each class. For example, a FAST-20 Wide 16 device is - able to transfer data at 20 million 16 bit packets per second for a - total rate of 40 MB/s. - - You may specify 0 if you want to only use asynchronous data - transfers. This is the safest and slowest option. Otherwise, specify - a value between 5 and 80, depending on the capability of your SCSI - controller. The higher the number, the faster the data transfer. - Note that 80 should normally be ok since the driver decreases the - value automatically according to the controller's capabilities. - - Your answer to this question is ignored for controllers with NVRAM, - since the driver will get this information from the user set-up. It - also can be overridden using a boot setup option, as follows - (example): 'ncr53c8xx=sync:12' will allow the driver to negotiate - for FAST-20 synchronous data transfer (20 mega-transfers per - second). - - The normal answer therefore is not to go with the default but to - select the maximum value 80 allowing the driver to use the maximum - value supported by each controller. If this causes problems with - your SCSI devices, you should come back and decrease the value. - - There is no safe option other than using good cabling, right - terminations and SCSI conformant devices. - -config SCSI_NCR53C8XX_PROFILE - bool "enable profiling" - depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX) - help - This option allows you to enable profiling information gathering. - These statistics are not very accurate due to the low frequency - of the kernel clock (100 Hz on i386) and have performance impact - on systems that use very fast devices. - - The normal answer therefore is N. - -config SCSI_NCR53C8XX_PQS_PDS - bool "include support for the NCR PQS/PDS SCSI card" - depends on (SCSI_NCR53C8XX || SCSI_SYM53C8XX) && SCSI_SYM53C8XX - help - Say Y here if you have a special SCSI adapter produced by NCR - corporation called a PCI Quad SCSI or PCI Dual SCSI. You do not need - this if you do not have one of these adapters. However, since this - device is detected as a specific PCI device, this option is quite - safe. - - The common answer here is N, but answering Y is safe. - -config SCSI_NCR53C8XX_NO_DISCONNECT - bool "not allow targets to disconnect" - depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX) && SCSI_NCR53C8XX_DEFAULT_TAGS=0 - help - This option is only provided for safety if you suspect some SCSI - device of yours to not support properly the target-disconnect - feature. In that case, you would say Y here. In general however, to - not allow targets to disconnect is not reasonable if there is more - than 1 device on a SCSI bus. The normal answer therefore is N. - -config SCSI_NCR53C8XX_SYMBIOS_COMPAT - bool "assume boards are SYMBIOS compatible (EXPERIMENTAL)" - depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX) && EXPERIMENTAL - ---help--- - This option allows you to enable some features depending on GPIO - wiring. These General Purpose Input/Output pins can be used for - vendor specific features or implementation of the standard SYMBIOS - features. Genuine SYMBIOS controllers use GPIO0 in output for - controller LED and GPIO3 bit as a flag indicating - singled-ended/differential interface. The Tekram DC-390U/F boards - uses a different GPIO wiring. - - Your answer to this question is ignored if all your controllers have - NVRAM, since the driver is able to detect the board type from the - NVRAM format. - - If all the controllers in your system are genuine SYMBIOS boards or - use BIOS and drivers from SYMBIOS, you would want to say Y here, - otherwise N. N is the safe answer. - -config SCSI_QLOGIC_ISP - tristate "Qlogic ISP SCSI support" - depends on PCI && SCSI - ---help--- - This driver works for all QLogic PCI SCSI host adapters (IQ-PCI, - IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card. (This latter - card is supported by the "AM53/79C974 PCI SCSI" driver.) - - If you say Y here, make sure to choose "BIOS" at the question "PCI - access mode". - - Please read the file . You - should also read the SCSI-HOWTO, available from - . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called qlogicisp. If you want to compile it as - a module, say M here and read . - -config SCSI_QLOGIC_FC - tristate "Qlogic ISP FC SCSI support" - depends on PCI && SCSI - help - This is a driver for the QLogic ISP2100 SCSI-FCP host adapter. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called qlogicfc. If you want to compile it as - a module, say M here and read . - -config SCSI_QLOGIC_FC_FIRMWARE - bool - depends on SCSI_QLOGIC_FC - default y - -endmenu +source "drivers/scsi/Kconfig" endmenu diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c --- a/arch/sparc64/kernel/time.c Sat Jun 14 16:15:59 2003 +++ b/arch/sparc64/kernel/time.c Tue Jun 17 14:51:27 2003 @@ -703,9 +703,9 @@ } xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - wall_to_monotonic.tv_sec = -xtime.tv_sec + INITIAL_JIFFIES / HZ; + wall_to_monotonic.tv_sec = -xtime.tv_sec; xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - wall_to_monotonic.tv_nsec = 0; + wall_to_monotonic.tv_nsec = -xtime.tv_nsec; if (mregs) { tmp = mostek_read(mregs + MOSTEK_CREG); @@ -743,9 +743,9 @@ (unsigned int) (long) &unix_tod); prom_feval(obp_gettod); xtime.tv_sec = unix_tod; - wall_to_monotonic.tv_sec = -xtime.tv_sec + INITIAL_JIFFIES / HZ; + wall_to_monotonic.tv_sec = -xtime.tv_sec; xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - wall_to_monotonic.tv_nsec = 0; + wall_to_monotonic.tv_nsec = -xtime.tv_nsec; return; } diff -Nru a/arch/um/Kconfig b/arch/um/Kconfig --- a/arch/um/Kconfig Sat Mar 8 14:50:37 2003 +++ b/arch/um/Kconfig Thu Jun 12 10:41:27 2003 @@ -62,14 +62,7 @@ config NET bool "Networking support" -config BINFMT_AOUT - tristate "Kernel support for a.out binaries" - -config BINFMT_ELF - tristate "Kernel support for ELF binaries" - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" +source "fs/Kconfig.binfmt" config HOSTFS tristate "Host filesystem" diff -Nru a/arch/v850/Kconfig b/arch/v850/Kconfig --- a/arch/v850/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/v850/Kconfig Sat Jun 14 15:25:52 2003 @@ -243,16 +243,7 @@ config KCORE_ELF default y -config BINFMT_FLAT - tristate "Kernel support for flat binaries" - help - Support uClinux FLAT format binaries. - -config BINFMT_ZFLAT - bool " Enable ZFLAT support" - depends on BINFMT_FLAT - help - Support FLAT format compressed binaries +source "fs/Kconfig.binfmt" endmenu diff -Nru a/arch/v850/vmlinux.lds.S b/arch/v850/vmlinux.lds.S --- a/arch/v850/vmlinux.lds.S Tue May 27 00:09:43 2003 +++ b/arch/v850/vmlinux.lds.S Mon Jun 16 22:23:12 2003 @@ -95,7 +95,10 @@ *(.initcall6.init) \ *(.initcall7.init) \ . = ALIGN (4) ; \ - ___initcall_end = . ; + ___initcall_end = . ; \ + ___con_initcall_start = .; \ + *(.con_initcall.init) \ + ___con_initcall_end = .; /* Contents of `init' section for a kernel that's loaded into RAM. */ #define RAMK_INIT_CONTENTS \ @@ -232,5 +235,15 @@ # include "rte_ma1_cb-rom.ld" # else # include "rte_ma1_cb.ld" +# endif +#endif + +#ifdef CONFIG_RTE_CB_NB85E +# ifdef CONFIG_ROM_KERNEL +# include "rte_nb85e_cb-rom.ld" +# elif defined(CONFIG_RTE_CB_MULTI) +# include "rte_nb85e_cb-multi.ld" +# else +# include "rte_nb85e_cb.ld" # endif #endif diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig --- a/arch/x86_64/Kconfig Wed Jun 11 18:15:04 2003 +++ b/arch/x86_64/Kconfig Sat Jun 14 15:25:52 2003 @@ -375,31 +375,7 @@ depends on PROC_FS default y -config BINFMT_ELF - bool - default y - -config BINFMT_MISC - tristate "Kernel support for MISC binaries" - ---help--- - If you say Y here, it will be possible to plug wrapper-driven binary - formats into the kernel. You will like this especially when you use - programs that need an interpreter to run like Java, Python or - Emacs-Lisp. Once you have registered such a binary class with the kernel, - you can start one of those programs simply by typing in its name at a shell - prompt; Linux will automatically feed it to the correct interpreter. - - You can do other nice things, too. Read the file - to learn how to use this - feature, and for information about how - to include Java support. - - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this part of the kernel. - - You may say M here for module support and later load the module when - you have use for it; the module is called binfmt_misc. If you - don't know what to answer at this point, say Y. +source "fs/Kconfig.binfmt" config IA32_EMULATION bool "IA32 Emulation" diff -Nru a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c --- a/drivers/block/cciss_scsi.c Mon May 12 07:33:45 2003 +++ b/drivers/block/cciss_scsi.c Mon Jun 2 17:42:21 2003 @@ -698,7 +698,7 @@ { struct Scsi_Host *sh; - sh = scsi_register(&cciss_driver_template, sizeof(struct ctlr_info *)); + sh = scsi_host_alloc(&cciss_driver_template, sizeof(struct ctlr_info *)); if (sh == NULL) return 0; @@ -1357,7 +1357,7 @@ if (sa->registered) { spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); scsi_remove_host(sa->scsi_host); - scsi_unregister(sa->scsi_host); + scsi_host_put(sa->scsi_host); spin_lock_irqsave(CCISS_LOCK(ctlr), flags); } diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Thu Jun 5 06:22:28 2003 +++ b/drivers/block/ll_rw_blk.c Mon Jun 2 18:32:46 2003 @@ -49,8 +49,6 @@ static int queue_nr_requests; unsigned long blk_max_low_pfn, blk_max_pfn; -int blk_nohighio = 0; - static wait_queue_head_t congestion_wqh[2]; /* @@ -2334,7 +2332,6 @@ EXPORT_SYMBOL(blk_queue_segment_boundary); EXPORT_SYMBOL(blk_queue_dma_alignment); EXPORT_SYMBOL(blk_rq_map_sg); -EXPORT_SYMBOL(blk_nohighio); EXPORT_SYMBOL(blk_dump_rq_flags); EXPORT_SYMBOL(submit_bio); EXPORT_SYMBOL(blk_phys_contig_segment); diff -Nru a/drivers/char/moxa.c b/drivers/char/moxa.c --- a/drivers/char/moxa.c Wed Jun 11 12:32:40 2003 +++ b/drivers/char/moxa.c Tue Jun 17 20:34:45 2003 @@ -339,7 +339,6 @@ { int i, n, numBoards; struct moxa_str *ch; - int ret1, ret2; printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION); moxaDriver = alloc_tty_driver(MAX_PORTS + 1); @@ -615,7 +614,7 @@ } ch->asyncflags |= ASYNC_CLOSING; - ch->cflag = *tty->termios->c_cflag; + ch->cflag = tty->termios->c_cflag; if (ch->asyncflags & ASYNC_INITIALIZED) { setup_empty_event(tty); tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ diff -Nru a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c --- a/drivers/ieee1394/sbp2.c Wed May 28 17:50:03 2003 +++ b/drivers/ieee1394/sbp2.c Mon Jun 2 17:42:21 2003 @@ -707,7 +707,7 @@ return hi; /* Register our host with the SCSI stack. */ - scsi_host = scsi_register (&scsi_driver_template, 0); + scsi_host = scsi_host_alloc(&scsi_driver_template, 0); if (!scsi_host) { SBP2_ERR("failed to register scsi host"); return NULL; @@ -716,7 +716,7 @@ hi = hpsb_create_hostinfo(&sbp2_highlevel, host, sizeof(*hi)); if (!hi) { SBP2_ERR("failed to allocate hostinfo"); - scsi_unregister(hi->scsi_host); + scsi_host_put(hi->scsi_host); } hpsb_set_hostinfo_key(&sbp2_highlevel, host, (unsigned long)scsi_host); @@ -732,7 +732,7 @@ * enabled (scsi-host uses classdata member of the device). */ if (scsi_add_host(hi->scsi_host, NULL)) { SBP2_ERR("failed to add scsi host"); - scsi_unregister(hi->scsi_host); + scsi_host_put(hi->scsi_host); hpsb_destroy_hostinfo(&sbp2_highlevel, host); } @@ -753,7 +753,7 @@ if (hi) { scsi_remove_host(hi->scsi_host); - scsi_unregister(hi->scsi_host); + scsi_host_put(hi->scsi_host); } } diff -Nru a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c --- a/drivers/md/dm-ioctl.c Sat Jun 14 16:16:11 2003 +++ b/drivers/md/dm-ioctl.c Mon Jun 16 13:20:05 2003 @@ -297,13 +297,14 @@ /* * rename and move the name cell. */ + unregister_with_devfs(hc); + list_del(&hc->name_list); old_name = hc->name; hc->name = new_name; list_add(&hc->name_list, _name_buckets + hash_str(new_name)); /* rename the device node in devfs */ - unregister_with_devfs(hc); register_with_devfs(hc); up_write(&_hash_lock); diff -Nru a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c --- a/drivers/message/i2o/i2o_scsi.c Thu Mar 13 17:14:29 2003 +++ b/drivers/message/i2o/i2o_scsi.c Sun Jun 8 12:18:41 2003 @@ -866,34 +866,6 @@ } /** - * internal_done - legacy scsi glue - * @SCPnt: command - * - * Completion function for a synchronous command - */ - -static void internal_done(Scsi_Cmnd * SCpnt) -{ - SCpnt->SCp.Status++; -} - -/** - * i2o_scsi_command - issue a scsi command and wait - * @SCPnt: command - * - * Issue a SCSI command and wait for it to complete. - */ - -static int i2o_scsi_command(Scsi_Cmnd * SCpnt) -{ - i2o_scsi_queuecommand(SCpnt, internal_done); - SCpnt->SCp.Status = 0; - while (!SCpnt->SCp.Status) - barrier(); - return SCpnt->result; -} - -/** * i2o_scsi_abort - abort a running command * @SCpnt: command to abort * @@ -1091,7 +1063,6 @@ .detect = i2o_scsi_detect, .release = i2o_scsi_release, .info = i2o_scsi_info, - .command = i2o_scsi_command, .queuecommand = i2o_scsi_queuecommand, .eh_abort_handler = i2o_scsi_abort, .eh_bus_reset_handler = i2o_scsi_bus_reset, diff -Nru a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c --- a/drivers/net/bonding/bond_main.c Mon May 26 21:45:02 2003 +++ b/drivers/net/bonding/bond_main.c Mon Jun 16 16:12:58 2003 @@ -952,8 +952,6 @@ add_timer(alb_timer); } - MOD_INC_USE_COUNT; - if (miimon > 0) { /* link check interval, in milliseconds. */ init_timer(timer); timer->expires = jiffies + (miimon * HZ / 1000); @@ -1027,7 +1025,6 @@ bond_alb_deinitialize(bond); } - MOD_DEC_USE_COUNT; return 0; } @@ -3694,6 +3691,8 @@ kfree(bond); return -ENOMEM; } + bond->bond_proc_dir->owner = THIS_MODULE; + bond->bond_proc_info_file = create_proc_info_entry("info", 0, bond->bond_proc_dir, bond_get_info); @@ -3705,6 +3704,7 @@ kfree(bond); return -ENOMEM; } + bond->bond_proc_info_file->owner = THIS_MODULE; #endif /* CONFIG_PROC_FS */ if (first_pass == 1) { diff -Nru a/drivers/net/shaper.c b/drivers/net/shaper.c --- a/drivers/net/shaper.c Thu Apr 3 07:19:43 2003 +++ b/drivers/net/shaper.c Mon Jun 16 14:26:40 2003 @@ -630,7 +630,7 @@ * Add a shaper device to the system */ -static int __init shaper_probe(struct net_device *dev) +static void __init shaper_setup(struct net_device *dev) { /* * Set up the shaper. @@ -642,6 +642,7 @@ dev->open = shaper_open; dev->stop = shaper_close; + dev->destructor = (void (*)(struct net_device *))kfree; dev->hard_start_xmit = shaper_start_xmit; dev->get_stats = shaper_get_stats; dev->set_multicast_list = NULL; @@ -669,12 +670,6 @@ dev->addr_len = 0; dev->tx_queue_len = 10; dev->flags = 0; - - /* - * Shaper is ok - */ - - return 0; } static int shapers = 1; @@ -695,35 +690,38 @@ #endif /* MODULE */ -static struct net_device *devs; +static struct net_device **devs; static unsigned int shapers_registered = 0; static int __init shaper_init(void) { - int i, err; + int i; size_t alloc_size; - struct shaper *sp; + struct net_device *dev; + char name[IFNAMSIZ]; if (shapers < 1) return -ENODEV; - alloc_size = (sizeof(*devs) * shapers) + - (sizeof(struct shaper) * shapers); + alloc_size = sizeof(*dev) * shapers; devs = kmalloc(alloc_size, GFP_KERNEL); if (!devs) return -ENOMEM; memset(devs, 0, alloc_size); - sp = (struct shaper *) &devs[shapers]; for (i = 0; i < shapers; i++) { - err = dev_alloc_name(&devs[i], "shaper%d"); - if (err < 0) + + snprintf(name, IFNAMSIZ, "shaper%d", i); + dev = alloc_netdev(sizeof(struct shaper), name, + shaper_setup); + if (!dev) break; - devs[i].init = shaper_probe; - devs[i].priv = &sp[i]; - if (register_netdev(&devs[i])) + + if (register_netdev(dev)) break; + + devs[i] = dev; shapers_registered++; } @@ -740,7 +738,8 @@ int i; for (i = 0; i < shapers_registered; i++) - unregister_netdev(&devs[i]); + if (devs[i]) + unregister_netdev(devs[i]); kfree(devs); devs = NULL; diff -Nru a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c --- a/drivers/net/wan/syncppp.c Wed Nov 27 11:25:41 2002 +++ b/drivers/net/wan/syncppp.c Fri May 30 12:33:58 2003 @@ -132,6 +132,9 @@ static struct timer_list sppp_keepalive_timer; static spinlock_t spppq_lock = SPIN_LOCK_UNLOCKED; +/* global xmit queue for sending packets while spinlock is held */ +static struct sk_buff_head tx_queue; + static void sppp_keepalive (unsigned long dummy); static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type, u8 ident, u16 len, void *data); @@ -150,6 +153,20 @@ static int debug; +/* Flush global outgoing packet queue to dev_queue_xmit(). + * + * dev_queue_xmit() must be called with interrupts enabled + * which means it can't be called with spinlocks held. + * If a packet needs to be sent while a spinlock is held, + * then put the packet into tx_queue, and call sppp_flush_xmit() + * after spinlock is released. + */ +static void sppp_flush_xmit() +{ + struct sk_buff *skb; + while ((skb = skb_dequeue(&tx_queue)) != NULL) + dev_queue_xmit(skb); +} /* * Interface down stub @@ -207,7 +224,8 @@ { struct ppp_header *h; struct sppp *sp = (struct sppp *)sppp_of(dev); - + unsigned long flags; + skb->dev=dev; skb->mac.raw=skb->data; @@ -223,7 +241,7 @@ if (sp->pp_flags & PP_DEBUG) printk (KERN_DEBUG "%s: input packet is too small, %d bytes\n", dev->name, skb->len); -drop: kfree_skb(skb); + kfree_skb(skb); return; } @@ -231,13 +249,11 @@ h = (struct ppp_header *)skb->data; skb_pull(skb,sizeof(struct ppp_header)); + spin_lock_irqsave(&sp->lock, flags); + switch (h->address) { default: /* Invalid PPP packet. */ -invalid: if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid input packet <0x%x 0x%x 0x%x>\n", - dev->name, - h->address, h->control, ntohs (h->protocol)); - goto drop; + goto invalid; case PPP_ALLSTATIONS: if (h->control != PPP_UI) goto invalid; @@ -261,15 +277,13 @@ goto drop; case PPP_LCP: sppp_lcp_input (sp, skb); - kfree_skb(skb); - return; + goto drop; case PPP_IPCP: if (sp->lcp.state == LCP_STATE_OPENED) sppp_ipcp_input (sp, skb); else printk(KERN_DEBUG "IPCP when still waiting LCP finish.\n"); - kfree_skb(skb); - return; + goto drop; case PPP_IP: if (sp->ipcp.state == IPCP_STATE_OPENED) { if(sp->pp_flags&PP_DEBUG) @@ -277,7 +291,7 @@ skb->protocol=htons(ETH_P_IP); netif_rx(skb); dev->last_rx = jiffies; - return; + goto done; } break; #ifdef IPX @@ -287,7 +301,7 @@ skb->protocol=htons(ETH_P_IPX); netif_rx(skb); dev->last_rx = jiffies; - return; + goto done; } break; #endif @@ -308,26 +322,36 @@ goto invalid; case CISCO_KEEPALIVE: sppp_cisco_input (sp, skb); - kfree_skb(skb); - return; + goto drop; #ifdef CONFIG_INET case ETH_P_IP: skb->protocol=htons(ETH_P_IP); netif_rx(skb); dev->last_rx = jiffies; - return; + goto done; #endif #ifdef CONFIG_IPX case ETH_P_IPX: skb->protocol=htons(ETH_P_IPX); netif_rx(skb); dev->last_rx = jiffies; - return; + goto done; #endif } break; } + goto drop; + +invalid: + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: invalid input packet <0x%x 0x%x 0x%x>\n", + dev->name, h->address, h->control, ntohs (h->protocol)); +drop: kfree_skb(skb); +done: + spin_unlock_irqrestore(&sp->lock, flags); + sppp_flush_xmit(); + return; } EXPORT_SYMBOL(sppp_input); @@ -394,10 +418,14 @@ ! (dev->flags & IFF_UP)) continue; + spin_lock(&sp->lock); + /* No keepalive in PPP mode if LCP not opened yet. */ if (! (sp->pp_flags & PP_CISCO) && - sp->lcp.state != LCP_STATE_OPENED) + sp->lcp.state != LCP_STATE_OPENED) { + spin_unlock(&sp->lock); continue; + } if (sp->pp_alivecnt == MAXALIVECNT) { /* No keepalive packets got. Stop the interface. */ @@ -424,8 +452,11 @@ sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REQ, sp->lcp.echoid, 4, &nmagic); } + + spin_unlock(&sp->lock); } spin_unlock_irqrestore(&spppq_lock, flags); + sppp_flush_xmit(); sppp_keepalive_timer.expires=jiffies+10*HZ; add_timer(&sppp_keepalive_timer); } @@ -757,6 +788,7 @@ } } + /* * Send PPP LCP packet. */ @@ -804,7 +836,7 @@ /* Control is high priority so it doesn't get queued behind data */ skb->priority=TC_PRIO_CONTROL; skb->dev = dev; - dev_queue_xmit(skb); + skb_queue_tail(&tx_queue, skb); } /* @@ -846,7 +878,7 @@ sp->obytes += skb->len; skb->priority=TC_PRIO_CONTROL; skb->dev = dev; - dev_queue_xmit(skb); + skb_queue_tail(&tx_queue, skb); } /** @@ -861,10 +893,15 @@ int sppp_close (struct net_device *dev) { struct sppp *sp = (struct sppp *)sppp_of(dev); + unsigned long flags; + + spin_lock_irqsave(&sp->lock, flags); sp->pp_link_state = SPPP_LINK_DOWN; sp->lcp.state = LCP_STATE_CLOSED; sp->ipcp.state = IPCP_STATE_CLOSED; sppp_clear_timeout (sp); + spin_unlock_irqrestore(&sp->lock, flags); + return 0; } @@ -883,11 +920,18 @@ int sppp_open (struct net_device *dev) { struct sppp *sp = (struct sppp *)sppp_of(dev); + unsigned long flags; + sppp_close(dev); + + spin_lock_irqsave(&sp->lock, flags); if (!(sp->pp_flags & PP_CISCO)) { sppp_lcp_open (sp); } sp->pp_link_state = SPPP_LINK_DOWN; + spin_unlock_irqrestore(&sp->lock, flags); + sppp_flush_xmit(); + return 0; } @@ -912,7 +956,11 @@ int sppp_reopen (struct net_device *dev) { struct sppp *sp = (struct sppp *)sppp_of(dev); + unsigned long flags; + sppp_close(dev); + + spin_lock_irqsave(&sp->lock, flags); if (!(sp->pp_flags & PP_CISCO)) { sp->lcp.magic = jiffies; @@ -923,6 +971,8 @@ sppp_set_timeout (sp, 1); } sp->pp_link_state=SPPP_LINK_DOWN; + spin_unlock_irqrestore(&sp->lock, flags); + return 0; } @@ -1040,6 +1090,7 @@ sp->lcp.state = LCP_STATE_CLOSED; sp->ipcp.state = IPCP_STATE_CLOSED; sp->pp_if = dev; + spin_lock_init(&sp->lock); /* * Device specific setup. All but interrupt handler and @@ -1290,11 +1341,11 @@ struct sppp *sp = (struct sppp*) arg; unsigned long flags; - spin_lock_irqsave(&spppq_lock, flags); + spin_lock_irqsave(&sp->lock, flags); sp->pp_flags &= ~PP_TIMO; if (! (sp->pp_if->flags & IFF_UP) || (sp->pp_flags & PP_CISCO)) { - spin_unlock_irqrestore(&spppq_lock, flags); + spin_unlock_irqrestore(&sp->lock, flags); return; } switch (sp->lcp.state) { @@ -1333,7 +1384,8 @@ } break; } - spin_unlock_irqrestore(&spppq_lock, flags); + spin_unlock_irqrestore(&sp->lock, flags); + sppp_flush_xmit(); } static char *sppp_lcp_type_name (u8 type) @@ -1393,6 +1445,8 @@ static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p) { + if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) + return NET_RX_DROP; sppp_input(dev,skb); return 0; } @@ -1400,6 +1454,7 @@ struct packet_type sppp_packet_type = { .type = __constant_htons(ETH_P_WAN_PPP), .func = sppp_rcv, + .data = (void*)1, /* must be non-NULL to indicate 'new' protocol */ }; static char banner[] __initdata = @@ -1412,6 +1467,7 @@ if(debug) debug=PP_DEBUG; printk(banner); + skb_queue_head_init(&tx_queue); dev_add_pack(&sppp_packet_type); return 0; } diff -Nru a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c --- a/drivers/oprofile/buffer_sync.c Wed Jun 11 18:05:19 2003 +++ b/drivers/oprofile/buffer_sync.c Sun Jun 15 07:34:47 2003 @@ -425,7 +425,7 @@ { struct mm_struct * mm = 0; struct task_struct * new; - unsigned long cookie; + unsigned long cookie = 0; int in_kernel = 1; unsigned int i; @@ -442,13 +442,15 @@ in_kernel = s->event; add_kernel_ctx_switch(s->event); } else { + struct mm_struct * oldmm = mm; + /* userspace context switch */ new = (struct task_struct *)s->event; - release_mm(mm); + release_mm(oldmm); mm = take_tasks_mm(new); - - cookie = get_exec_dcookie(mm); + if (mm != oldmm) + cookie = get_exec_dcookie(mm); add_user_ctx_switch(new, cookie); } } else { diff -Nru a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile --- a/drivers/pcmcia/Makefile Wed Jun 11 14:52:42 2003 +++ b/drivers/pcmcia/Makefile Mon Jun 16 08:06:42 2003 @@ -3,7 +3,7 @@ # obj-$(CONFIG_PCMCIA) += pcmcia_core.o ds.o -obj-$(CONFIG_YENTA) += yenta.o +obj-$(CONFIG_YENTA) += yenta_socket.o obj-$(CONFIG_I82365) += i82365.o obj-$(CONFIG_I82092) += i82092.o diff -Nru a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c --- a/drivers/pcmcia/cistpl.c Sun Jun 15 08:20:51 2003 +++ b/drivers/pcmcia/cistpl.c Mon Jun 16 08:46:25 2003 @@ -106,11 +106,10 @@ pccard_mem_map *mem = &s->cis_mem; if (!(s->features & SS_CAP_STATIC_MAP) && mem->sys_start == 0) { - int low = !(s->features & SS_CAP_PAGE_REGS); validate_mem(s); mem->sys_start = 0; if (find_mem_region(&mem->sys_start, s->map_size, - s->map_size, low, "card services", s)) { + s->map_size, 0, "card services", s)) { printk(KERN_NOTICE "cs: unable to map card memory!\n"); return NULL; } diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c --- a/drivers/pcmcia/cs.c Sun Jun 15 09:58:50 2003 +++ b/drivers/pcmcia/cs.c Tue Jun 17 01:06:34 2003 @@ -816,7 +816,8 @@ if ((skt->state & SOCKET_PRESENT) && !(status & SS_DETECT)) socket_shutdown(skt); - if (status & SS_DETECT) + if (!(skt->state & SOCKET_PRESENT) && + (status & SS_DETECT)) socket_insert(skt); } if (events & SS_BATDEAD) @@ -2043,8 +2044,7 @@ if (!(s->features & SS_CAP_STATIC_MAP) && find_mem_region(&win->base, win->size, align, - (req->Attributes & WIN_MAP_BELOW_1MB) || - !(s->features & SS_CAP_PAGE_REGS), + (req->Attributes & WIN_MAP_BELOW_1MB), (*handle)->dev_info, s)) return CS_IN_USE; (*handle)->state |= CLIENT_WIN_REQ(w); diff -Nru a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h --- a/drivers/pcmcia/cs_internal.h Sun Jun 15 04:42:53 2003 +++ b/drivers/pcmcia/cs_internal.h Mon Jun 16 08:46:25 2003 @@ -168,7 +168,7 @@ int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align, char *name, struct pcmcia_socket *s); int find_mem_region(u_long *base, u_long num, u_long align, - int force_low, char *name, struct pcmcia_socket *s); + int low, char *name, struct pcmcia_socket *s); int try_irq(u_int Attributes, int irq, int specific); void undo_irq(u_int Attributes, int irq); int adjust_resource_info(client_handle_t handle, adjust_t *adj); diff -Nru a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c --- a/drivers/pcmcia/rsrc_mgr.c Sun Jun 15 08:20:52 2003 +++ b/drivers/pcmcia/rsrc_mgr.c Mon Jun 16 08:46:26 2003 @@ -139,22 +139,6 @@ return 0; } -/* FIXME: Fundamentally racy. */ -static inline int check_mem_resource(unsigned long b, unsigned long n, - struct pci_dev *dev) -{ - struct resource *region; - - region = __request_region(resource_parent(b, n, IORESOURCE_MEM, dev), - b, n, "check_mem_resource"); - if (!region) - return -EBUSY; - - release_resource(region); - kfree(region); - return 0; -} - static struct resource *make_resource(unsigned long b, unsigned long n, int flags, char *name) { @@ -340,52 +324,103 @@ ======================================================================*/ /* Validation function for cards with a valid CIS */ -static int cis_readable(struct pcmcia_socket *s, u_long base) +static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *info) { - cisinfo_t info1, info2; - int ret; - s->cis_mem.sys_start = base; - s->cis_mem.sys_stop = base+s->map_size-1; - s->cis_virt = ioremap(base, s->map_size); - ret = pcmcia_validate_cis(s->clients, &info1); - /* invalidate mapping and CIS cache */ - iounmap(s->cis_virt); - destroy_cis_cache(s); - if ((ret != 0) || (info1.Chains == 0)) - return 0; - s->cis_mem.sys_start = base+s->map_size; - s->cis_mem.sys_stop = base+2*s->map_size-1; - s->cis_virt = ioremap(base+s->map_size, s->map_size); - ret = pcmcia_validate_cis(s->clients, &info2); - iounmap(s->cis_virt); - destroy_cis_cache(s); - return ((ret == 0) && (info1.Chains == info2.Chains)); + int ret = -1; + + s->cis_mem.sys_start = res->start; + s->cis_mem.sys_stop = res->end; + s->cis_virt = ioremap(res->start, s->map_size); + if (s->cis_virt) { + ret = pcmcia_validate_cis(s->clients, info); + /* invalidate mapping and CIS cache */ + iounmap(s->cis_virt); + s->cis_virt = NULL; + destroy_cis_cache(s); + } + s->cis_mem.sys_start = 0; + s->cis_mem.sys_stop = 0; + if ((ret != 0) || (info->Chains == 0)) + return 0; + return 1; } /* Validation function for simple memory cards */ -static int checksum(struct pcmcia_socket *s, u_long base) +static int checksum(struct pcmcia_socket *s, struct resource *res) { - int i, a, b, d; - s->cis_mem.sys_start = base; - s->cis_mem.sys_stop = base+s->map_size-1; - s->cis_virt = ioremap(base, s->map_size); - s->cis_mem.card_start = 0; - s->cis_mem.flags = MAP_ACTIVE; - s->ss_entry->set_mem_map(s, &s->cis_mem); - /* Don't bother checking every word... */ - a = 0; b = -1; - for (i = 0; i < s->map_size; i += 44) { - d = readl(s->cis_virt+i); - a += d; b &= d; - } - iounmap(s->cis_virt); - return (b == -1) ? -1 : (a>>1); + pccard_mem_map map; + int i, a = 0, b = -1, d; + void *virt; + + virt = ioremap(res->start, s->map_size); + if (virt) { + map.map = 0; + map.flags = MAP_ACTIVE; + map.speed = 0; + map.sys_start = res->start; + map.sys_stop = res->end; + map.card_start = 0; + s->ss_entry->set_mem_map(s, &map); + + /* Don't bother checking every word... */ + for (i = 0; i < s->map_size; i += 44) { + d = readl(virt+i); + a += d; + b &= d; + } + + map.flags = 0; + s->ss_entry->set_mem_map(s, &map); + + iounmap(virt); + } + + return (b == -1) ? -1 : (a>>1); } -static int checksum_match(struct pcmcia_socket *s, u_long base) +static int +cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size) { - int a = checksum(s, base), b = checksum(s, base+s->map_size); - return ((a == b) && (a >= 0)); + struct resource *res1, *res2; + cisinfo_t info1, info2; + int ret = 0; + + res1 = request_mem_region(base, size/2, "cs memory probe"); + res2 = request_mem_region(base + size/2, size/2, "cs memory probe"); + + if (res1 && res2) { + ret = readable(s, res1, &info1); + ret += readable(s, res2, &info2); + } + + if (res2) + release_resource(res2); + if (res1) + release_resource(res1); + + return (ret == 2) && (info1.Chains == info2.Chains); +} + +static int +checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size) +{ + struct resource *res1, *res2; + int a = -1, b = -1; + + res1 = request_mem_region(base, size/2, "cs memory probe"); + res2 = request_mem_region(base + size/2, size/2, "cs memory probe"); + + if (res1 && res2) { + a = checksum(s, res1); + b = checksum(s, res2); + } + + if (res2) + release_resource(res2); + if (res1) + release_resource(res1); + + return (a == b) && (a >= 0); } /*====================================================================== @@ -409,16 +444,16 @@ step = 2 * s->map_size; for (i = j = base; i < base+num; i = j + step) { if (!fail) { - for (j = i; j < base+num; j += step) - if ((check_mem_resource(j, step, s->cb_dev) == 0) && - cis_readable(s, j)) + for (j = i; j < base+num; j += step) { + if (cis_readable(s, j, step)) break; + } fail = ((i == base) && (j == base+num)); } if (fail) { for (j = i; j < base+num; j += 2*step) - if ((check_mem_resource(j, 2*step, s->cb_dev) == 0) && - checksum_match(s, j) && checksum_match(s, j + step)) + if (checksum_match(s, j, step) && + checksum_match(s, j + step, step)) break; } if (i != j) { @@ -555,17 +590,19 @@ } int find_mem_region(u_long *base, u_long num, u_long align, - int force_low, char *name, struct pcmcia_socket *s) + int low, char *name, struct pcmcia_socket *s) { u_long try; resource_map_t *m; int ret = -1; + low = low || !(s->features & SS_CAP_PAGE_REGS); + down(&rsrc_sem); while (1) { for (m = mem_db.next; m != &mem_db; m = m->next) { /* first pass >1MB, second pass <1MB */ - if ((force_low != 0) ^ (m->base < 0x100000)) + if ((low != 0) ^ (m->base < 0x100000)) continue; try = (m->base & ~(align-1)) + *base; @@ -581,9 +618,9 @@ break; } } - if (force_low) + if (low) break; - force_low++; + low++; } out: up(&rsrc_sem); diff -Nru a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c --- a/drivers/pcmcia/yenta.c Sun Jun 15 08:32:41 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,974 +0,0 @@ -/* - * Regular cardbus driver ("yenta") - * - * (C) Copyright 1999, 2000 Linus Torvalds - * - * Changelog: - * Aug 2002: Manfred Spraul - * Dynamically adjust the size of the bridge resource - * - * May 2003: Dominik Brodowski - * Merge pci_socket.c and yenta.c into one file - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "yenta.h" -#include "i82365.h" - - -#if 0 -#define DEBUG(x,args...) printk("%s: " x, __FUNCTION__, ##args) -#else -#define DEBUG(x,args...) -#endif - -/* Don't ask.. */ -#define to_cycles(ns) ((ns)/120) -#define to_ns(cycles) ((cycles)*120) - -/* - * Generate easy-to-use ways of reading a cardbus sockets - * regular memory space ("cb_xxx"), configuration space - * ("config_xxx") and compatibility space ("exca_xxxx") - */ -static inline u32 cb_readl(struct yenta_socket *socket, unsigned reg) -{ - u32 val = readl(socket->base + reg); - DEBUG("%p %04x %08x\n", socket, reg, val); - return val; -} - -static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val) -{ - DEBUG("%p %04x %08x\n", socket, reg, val); - writel(val, socket->base + reg); -} - -static inline u8 config_readb(struct yenta_socket *socket, unsigned offset) -{ - u8 val; - pci_read_config_byte(socket->dev, offset, &val); - DEBUG("%p %04x %02x\n", socket, offset, val); - return val; -} - -static inline u16 config_readw(struct yenta_socket *socket, unsigned offset) -{ - u16 val; - pci_read_config_word(socket->dev, offset, &val); - DEBUG("%p %04x %04x\n", socket, offset, val); - return val; -} - -static inline u32 config_readl(struct yenta_socket *socket, unsigned offset) -{ - u32 val; - pci_read_config_dword(socket->dev, offset, &val); - DEBUG("%p %04x %08x\n", socket, offset, val); - return val; -} - -static inline void config_writeb(struct yenta_socket *socket, unsigned offset, u8 val) -{ - DEBUG("%p %04x %02x\n", socket, offset, val); - pci_write_config_byte(socket->dev, offset, val); -} - -static inline void config_writew(struct yenta_socket *socket, unsigned offset, u16 val) -{ - DEBUG("%p %04x %04x\n", socket, offset, val); - pci_write_config_word(socket->dev, offset, val); -} - -static inline void config_writel(struct yenta_socket *socket, unsigned offset, u32 val) -{ - DEBUG("%p %04x %08x\n", socket, offset, val); - pci_write_config_dword(socket->dev, offset, val); -} - -static inline u8 exca_readb(struct yenta_socket *socket, unsigned reg) -{ - u8 val = readb(socket->base + 0x800 + reg); - DEBUG("%p %04x %02x\n", socket, reg, val); - return val; -} - -static inline u8 exca_readw(struct yenta_socket *socket, unsigned reg) -{ - u16 val; - val = readb(socket->base + 0x800 + reg); - val |= readb(socket->base + 0x800 + reg + 1) << 8; - DEBUG("%p %04x %04x\n", socket, reg, val); - return val; -} - -static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val) -{ - DEBUG("%p %04x %02x\n", socket, reg, val); - writeb(val, socket->base + 0x800 + reg); -} - -static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val) -{ - DEBUG("%p %04x %04x\n", socket, reg, val); - writeb(val, socket->base + 0x800 + reg); - writeb(val >> 8, socket->base + 0x800 + reg + 1); -} - -/* - * Ugh, mixed-mode cardbus and 16-bit pccard state: things depend - * on what kind of card is inserted.. - */ -static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value) -{ - struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); - unsigned int val; - u32 state = cb_readl(socket, CB_SOCKET_STATE); - - val = (state & CB_3VCARD) ? SS_3VCARD : 0; - val |= (state & CB_XVCARD) ? SS_XVCARD : 0; - val |= (state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD | CB_3VCARD - | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING; - - if (state & CB_CBCARD) { - val |= SS_CARDBUS; - val |= (state & CB_CARDSTS) ? SS_STSCHG : 0; - val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT; - val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0; - } else { - u8 status = exca_readb(socket, I365_STATUS); - val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0; - if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { - val |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG; - } else { - val |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD; - val |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN; - } - val |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0; - val |= (status & I365_CS_READY) ? SS_READY : 0; - val |= (status & I365_CS_POWERON) ? SS_POWERON : 0; - } - - *value = val; - return 0; -} - -static int yenta_Vcc_power(u32 control) -{ - switch (control & CB_SC_VCC_MASK) { - case CB_SC_VCC_5V: return 50; - case CB_SC_VCC_3V: return 33; - default: return 0; - } -} - -static int yenta_Vpp_power(u32 control) -{ - switch (control & CB_SC_VPP_MASK) { - case CB_SC_VPP_12V: return 120; - case CB_SC_VPP_5V: return 50; - case CB_SC_VPP_3V: return 33; - default: return 0; - } -} - -static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state) -{ - struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); - u8 reg; - u32 control; - - control = cb_readl(socket, CB_SOCKET_CONTROL); - - state->Vcc = yenta_Vcc_power(control); - state->Vpp = yenta_Vpp_power(control); - state->io_irq = socket->io_irq; - - if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { - u16 bridge = config_readw(socket, CB_BRIDGE_CONTROL); - if (bridge & CB_BRIDGE_CRST) - state->flags |= SS_RESET; - return 0; - } - - /* 16-bit card state.. */ - reg = exca_readb(socket, I365_POWER); - state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0; - state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0; - - reg = exca_readb(socket, I365_INTCTL); - state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET; - state->flags |= (reg & I365_PC_IOCARD) ? SS_IOCARD : 0; - - reg = exca_readb(socket, I365_CSCINT); - state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0; - if (state->flags & SS_IOCARD) { - state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0; - } else { - state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0; - state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0; - state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0; - } - - return 0; -} - -static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) -{ - u32 reg = 0; /* CB_SC_STPCLK? */ - switch (state->Vcc) { - case 33: reg = CB_SC_VCC_3V; break; - case 50: reg = CB_SC_VCC_5V; break; - default: reg = 0; break; - } - switch (state->Vpp) { - case 33: reg |= CB_SC_VPP_3V; break; - case 50: reg |= CB_SC_VPP_5V; break; - case 120: reg |= CB_SC_VPP_12V; break; - } - if (reg != cb_readl(socket, CB_SOCKET_CONTROL)) - cb_writel(socket, CB_SOCKET_CONTROL, reg); -} - -static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) -{ - struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); - u16 bridge; - - if (state->flags & SS_DEBOUNCED) { - /* The insertion debounce period has ended. Clear any pending insertion events */ - socket->events &= ~SS_DETECT; - state->flags &= ~SS_DEBOUNCED; /* SS_DEBOUNCED is oneshot */ - } - yenta_set_power(socket, state); - socket->io_irq = state->io_irq; - bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR); - if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { - u8 intr; - bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0; - - /* ISA interrupt control? */ - intr = exca_readb(socket, I365_INTCTL); - intr = (intr & ~0xf); - if (!socket->cb_irq) { - intr |= state->io_irq; - bridge |= CB_BRIDGE_INTR; - } - exca_writeb(socket, I365_INTCTL, intr); - } else { - u8 reg; - - reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA); - reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; - reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; - if (state->io_irq != socket->cb_irq) { - reg |= state->io_irq; - bridge |= CB_BRIDGE_INTR; - } - exca_writeb(socket, I365_INTCTL, reg); - - reg = exca_readb(socket, I365_POWER) & (I365_VCC_MASK|I365_VPP1_MASK); - reg |= I365_PWR_NORESET; - if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO; - if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT; - if (exca_readb(socket, I365_POWER) != reg) - exca_writeb(socket, I365_POWER, reg); - - /* CSC interrupt: no ISA irq for CSC */ - reg = I365_CSC_DETECT; - if (state->flags & SS_IOCARD) { - if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG; - } else { - if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1; - if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2; - if (state->csc_mask & SS_READY) reg |= I365_CSC_READY; - } - exca_writeb(socket, I365_CSCINT, reg); - exca_readb(socket, I365_CSC); - } - config_writew(socket, CB_BRIDGE_CONTROL, bridge); - /* Socket event mask: get card insert/remove events.. */ - cb_writel(socket, CB_SOCKET_EVENT, -1); - cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); - return 0; -} - -static int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) -{ - struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); - int map; - unsigned char ioctl, addr, enable; - - map = io->map; - - if (map > 1) - return -EINVAL; - - enable = I365_ENA_IO(map); - addr = exca_readb(socket, I365_ADDRWIN); - - /* Disable the window before changing it.. */ - if (addr & enable) { - addr &= ~enable; - exca_writeb(socket, I365_ADDRWIN, addr); - } - - exca_writew(socket, I365_IO(map)+I365_W_START, io->start); - exca_writew(socket, I365_IO(map)+I365_W_STOP, io->stop); - - ioctl = exca_readb(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map); - if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map); - if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map); - if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map); - exca_writeb(socket, I365_IOCTL, ioctl); - - if (io->flags & MAP_ACTIVE) - exca_writeb(socket, I365_ADDRWIN, addr | enable); - return 0; -} - -static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem) -{ - struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); - int map; - unsigned char addr, enable; - unsigned int start, stop, card_start; - unsigned short word; - - map = mem->map; - start = mem->sys_start; - stop = mem->sys_stop; - card_start = mem->card_start; - - if (map > 4 || start > stop || ((start ^ stop) >> 24) || - (card_start >> 26) || mem->speed > 1000) - return -EINVAL; - - enable = I365_ENA_MEM(map); - addr = exca_readb(socket, I365_ADDRWIN); - if (addr & enable) { - addr &= ~enable; - exca_writeb(socket, I365_ADDRWIN, addr); - } - - exca_writeb(socket, CB_MEM_PAGE(map), start >> 24); - - word = (start >> 12) & 0x0fff; - if (mem->flags & MAP_16BIT) - word |= I365_MEM_16BIT; - if (mem->flags & MAP_0WS) - word |= I365_MEM_0WS; - exca_writew(socket, I365_MEM(map) + I365_W_START, word); - - word = (stop >> 12) & 0x0fff; - switch (to_cycles(mem->speed)) { - case 0: break; - case 1: word |= I365_MEM_WS0; break; - case 2: word |= I365_MEM_WS1; break; - default: word |= I365_MEM_WS1 | I365_MEM_WS0; break; - } - exca_writew(socket, I365_MEM(map) + I365_W_STOP, word); - - word = ((card_start - start) >> 12) & 0x3fff; - if (mem->flags & MAP_WRPROT) - word |= I365_MEM_WRPROT; - if (mem->flags & MAP_ATTRIB) - word |= I365_MEM_REG; - exca_writew(socket, I365_MEM(map) + I365_W_OFF, word); - - if (mem->flags & MAP_ACTIVE) - exca_writeb(socket, I365_ADDRWIN, addr | enable); - return 0; -} - - -static unsigned int yenta_events(struct yenta_socket *socket) -{ - u8 csc; - u32 cb_event; - unsigned int events; - - /* Clear interrupt status for the event */ - cb_event = cb_readl(socket, CB_SOCKET_EVENT); - cb_writel(socket, CB_SOCKET_EVENT, cb_event); - - csc = exca_readb(socket, I365_CSC); - - events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ; - events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0; - if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { - events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; - } else { - events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0; - events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; - events |= (csc & I365_CSC_READY) ? SS_READY : 0; - } - return events; -} - - -static void yenta_bh(void *data) -{ - struct yenta_socket *socket = data; - unsigned int events; - - spin_lock_irq(&socket->event_lock); - events = socket->events; - socket->events = 0; - spin_unlock_irq(&socket->event_lock); - if (socket->handler) - socket->handler(socket->info, events); -} - -static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned int events; - struct yenta_socket *socket = (struct yenta_socket *) dev_id; - - events = yenta_events(socket); - if (events) { - spin_lock(&socket->event_lock); - socket->events |= events; - spin_unlock(&socket->event_lock); - schedule_work(&socket->tq_task); - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -static void yenta_interrupt_wrapper(unsigned long data) -{ - struct yenta_socket *socket = (struct yenta_socket *) data; - - yenta_interrupt(0, (void *)socket, NULL); - socket->poll_timer.expires = jiffies + HZ; - add_timer(&socket->poll_timer); -} - -/* - * Only probe "regular" interrupts, don't - * touch dangerous spots like the mouse irq, - * because there are mice that apparently - * get really confused if they get fondled - * too intimately. - * - * Default to 11, 10, 9, 7, 6, 5, 4, 3. - */ -static u32 isa_interrupts = 0x0ef8; - -static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask) -{ - int i; - unsigned long val; - u16 bridge_ctrl; - u32 mask; - - /* Set up ISA irq routing to probe the ISA irqs.. */ - bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL); - if (!(bridge_ctrl & CB_BRIDGE_INTR)) { - bridge_ctrl |= CB_BRIDGE_INTR; - config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl); - } - - /* - * Probe for usable interrupts using the force - * register to generate bogus card status events. - */ - cb_writel(socket, CB_SOCKET_EVENT, -1); - cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); - exca_writeb(socket, I365_CSCINT, 0); - val = probe_irq_on() & isa_irq_mask; - for (i = 1; i < 16; i++) { - if (!((val >> i) & 1)) - continue; - exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG | (i << 4)); - cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); - udelay(100); - cb_writel(socket, CB_SOCKET_EVENT, -1); - } - cb_writel(socket, CB_SOCKET_MASK, 0); - exca_writeb(socket, I365_CSCINT, 0); - - mask = probe_irq_mask(val) & 0xffff; - - bridge_ctrl &= ~CB_BRIDGE_INTR; - config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl); - - return mask; -} - -/* - * Set static data that doesn't need re-initializing.. - */ -static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_irq_mask) -{ - socket->socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS; - socket->socket.map_size = 0x1000; - socket->socket.pci_irq = socket->cb_irq; - socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask); - socket->socket.cb_dev = socket->dev; - - printk("Yenta IRQ list %04x, PCI irq%d\n", socket->socket.irq_mask, socket->cb_irq); -} - - -static void yenta_clear_maps(struct yenta_socket *socket) -{ - int i; - pccard_io_map io = { 0, 0, 0, 0, 1 }; - pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 }; - - mem.sys_stop = 0x0fff; - yenta_set_socket(&socket->socket, &dead_socket); - for (i = 0; i < 2; i++) { - io.map = i; - yenta_set_io_map(&socket->socket, &io); - } - for (i = 0; i < 5; i++) { - mem.map = i; - yenta_set_mem_map(&socket->socket, &mem); - } -} - -/* - * Initialize the standard cardbus registers - */ -static void yenta_config_init(struct yenta_socket *socket) -{ - u16 bridge; - struct pci_dev *dev = socket->dev; - - pci_set_power_state(socket->dev, 0); - - config_writel(socket, CB_LEGACY_MODE_BASE, 0); - config_writel(socket, PCI_BASE_ADDRESS_0, dev->resource[0].start); - config_writew(socket, PCI_COMMAND, - PCI_COMMAND_IO | - PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER | - PCI_COMMAND_WAIT); - - /* MAGIC NUMBERS! Fixme */ - config_writeb(socket, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4); - config_writeb(socket, PCI_LATENCY_TIMER, 168); - config_writel(socket, PCI_PRIMARY_BUS, - (176 << 24) | /* sec. latency timer */ - (dev->subordinate->subordinate << 16) | /* subordinate bus */ - (dev->subordinate->secondary << 8) | /* secondary bus */ - dev->subordinate->primary); /* primary bus */ - - /* - * Set up the bridging state: - * - enable write posting. - * - memory window 0 prefetchable, window 1 non-prefetchable - * - PCI interrupts enabled if a PCI interrupt exists.. - */ - bridge = config_readw(socket, CB_BRIDGE_CONTROL); - bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_INTR | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN); - bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN; - if (!socket->cb_irq) - bridge |= CB_BRIDGE_INTR; - config_writew(socket, CB_BRIDGE_CONTROL, bridge); - - exca_writeb(socket, I365_GBLCTL, 0x00); - exca_writeb(socket, I365_GENCTL, 0x00); - - /* Redo card voltage interrogation */ - cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST); -} - -/* Called at resume and initialization events */ -static int yenta_init(struct pcmcia_socket *sock) -{ - struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); - yenta_config_init(socket); - yenta_clear_maps(socket); - - /* Re-enable interrupts */ - cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); - return 0; -} - -static int yenta_suspend(struct pcmcia_socket *sock) -{ - struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); - - yenta_set_socket(sock, &dead_socket); - - /* Disable interrupts */ - cb_writel(socket, CB_SOCKET_MASK, 0x0); - - /* - * This does not work currently. The controller - * loses too much information during D3 to come up - * cleanly. We should probably fix yenta_init() - * to update all the critical registers, notably - * the IO and MEM bridging region data.. That is - * something that pci_set_power_state() should - * probably know about bridges anyway. - * - pci_set_power_state(socket->dev, 3); - */ - - return 0; -} - -/* - * Use an adaptive allocation for the memory resource, - * sometimes the memory behind pci bridges is limited: - * 1/8 of the size of the io window of the parent. - * max 4 MB, min 16 kB. - */ -#define BRIDGE_MEM_MAX 4*1024*1024 -#define BRIDGE_MEM_MIN 16*1024 - -#define BRIDGE_IO_MAX 256 -#define BRIDGE_IO_MIN 32 - -static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type) -{ - struct pci_bus *bus; - struct resource *root, *res; - u32 start, end; - u32 align, size, min; - unsigned offset; - unsigned mask; - - /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ - mask = ~0xfff; - if (type & IORESOURCE_IO) - mask = ~3; - - offset = 0x1c + 8*nr; - bus = socket->dev->subordinate; - res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; - res->name = bus->name; - res->flags = type; - res->start = 0; - res->end = 0; - root = pci_find_parent_resource(socket->dev, res); - - if (!root) - return; - - start = config_readl(socket, offset) & mask; - end = config_readl(socket, offset+4) | ~mask; - if (start && end > start) { - res->start = start; - res->end = end; - if (request_resource(root, res) == 0) - return; - printk(KERN_INFO "yenta %s: Preassigned resource %d busy, reconfiguring...\n", - socket->dev->slot_name, nr); - res->start = res->end = 0; - } - - if (type & IORESOURCE_IO) { - align = 1024; - size = BRIDGE_IO_MAX; - min = BRIDGE_IO_MIN; - start = PCIBIOS_MIN_IO; - end = ~0U; - } else { - unsigned long avail = root->end - root->start; - int i; - size = BRIDGE_MEM_MAX; - if (size > avail/8) { - size=(avail+1)/8; - /* round size down to next power of 2 */ - i = 0; - while ((size /= 2) != 0) - i++; - size = 1 << i; - } - if (size < BRIDGE_MEM_MIN) - size = BRIDGE_MEM_MIN; - min = BRIDGE_MEM_MIN; - align = size; - start = PCIBIOS_MIN_MEM; - end = ~0U; - } - - do { - if (allocate_resource(root, res, size, start, end, align, NULL, NULL)==0) { - config_writel(socket, offset, res->start); - config_writel(socket, offset+4, res->end); - return; - } - size = size/2; - align = size; - } while (size >= min); - printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n", - socket->dev->slot_name, type); - res->start = res->end = 0; -} - -/* - * Allocate the bridge mappings for the device.. - */ -static void yenta_allocate_resources(struct yenta_socket *socket) -{ - yenta_allocate_res(socket, 0, IORESOURCE_MEM|IORESOURCE_PREFETCH); - yenta_allocate_res(socket, 1, IORESOURCE_MEM); - yenta_allocate_res(socket, 2, IORESOURCE_IO); - yenta_allocate_res(socket, 3, IORESOURCE_IO); /* PCI isn't clever enough to use this one yet */ -} - - -/* - * Free the bridge mappings for the device.. - */ -static void yenta_free_resources(struct yenta_socket *socket) -{ - int i; - for (i=0;i<4;i++) { - struct resource *res; - res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i; - if (res->start != 0 && res->end != 0) - release_resource(res); - res->start = res->end = 0; - } -} - - -/* - * Close it down - release our resources and go home.. - */ -static void yenta_close(struct pci_dev *dev) -{ - struct yenta_socket *sock = pci_get_drvdata(dev); - - /* we don't want a dying socket registered */ - pcmcia_unregister_socket(&sock->socket); - - /* Disable all events so we don't die in an IRQ storm */ - cb_writel(sock, CB_SOCKET_MASK, 0x0); - exca_writeb(sock, I365_CSCINT, 0); - - if (sock->cb_irq) - free_irq(sock->cb_irq, sock); - else - del_timer_sync(&sock->poll_timer); - - if (sock->base) - iounmap(sock->base); - yenta_free_resources(sock); - - pci_set_drvdata(dev, NULL); -} - - -static int yenta_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info) -{ - struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); - - socket->handler = handler; - socket->info = info; - return 0; -} - - -static struct pccard_operations yenta_socket_operations = { - .owner = THIS_MODULE, - .init = yenta_init, - .suspend = yenta_suspend, - .register_callback = yenta_register_callback, - .get_status = yenta_get_status, - .get_socket = yenta_get_socket, - .set_socket = yenta_set_socket, - .set_io_map = yenta_set_io_map, - .set_mem_map = yenta_set_mem_map, -}; - - -#include "ti113x.h" -#include "ricoh.h" - -/* - * Different cardbus controllers have slightly different - * initialization sequences etc details. List them here.. - */ -#define PD(x,y) PCI_VENDOR_ID_##x, PCI_DEVICE_ID_##x##_##y -struct cardbus_override_struct { - unsigned short vendor; - unsigned short device; - int (*override) (struct yenta_socket *socket); -} cardbus_override[] = { - { PD(TI,1130), &ti113x_override }, - { PD(TI,1031), &ti_override }, - { PD(TI,1131), &ti113x_override }, - { PD(TI,1250), &ti1250_override }, - { PD(TI,1220), &ti_override }, - { PD(TI,1221), &ti_override }, - { PD(TI,1210), &ti_override }, - { PD(TI,1450), &ti_override }, - { PD(TI,1225), &ti_override }, - { PD(TI,1251A), &ti_override }, - { PD(TI,1211), &ti_override }, - { PD(TI,1251B), &ti_override }, - { PD(TI,1410), ti1250_override }, - { PD(TI,1420), &ti_override }, - { PD(TI,4410), &ti_override }, - { PD(TI,4451), &ti_override }, - - { PD(RICOH,RL5C465), &ricoh_override }, - { PD(RICOH,RL5C466), &ricoh_override }, - { PD(RICOH,RL5C475), &ricoh_override }, - { PD(RICOH,RL5C476), &ricoh_override }, - { PD(RICOH,RL5C478), &ricoh_override }, - - { }, /* all zeroes */ -}; - - -/* - * Initialize a cardbus controller. Make sure we have a usable - * interrupt, and that we can map the cardbus area. Fill in the - * socket information structure.. - */ -static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_id *id) -{ - struct yenta_socket *socket; - struct cardbus_override_struct *d; - - socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL); - if (!socket) - return -ENOMEM; - memset(socket, 0, sizeof(*socket)); - - /* prepare pcmcia_socket */ - socket->socket.ss_entry = ¥ta_socket_operations; - socket->socket.dev.dev = &dev->dev; - socket->socket.driver_data = socket; - - /* prepare struct yenta_socket */ - socket->dev = dev; - pci_set_drvdata(dev, socket); - spin_lock_init(&socket->event_lock); - - /* - * Do some basic sanity checking.. - */ - if (pci_enable_device(dev)) - return -1; - if (!pci_resource_start(dev, 0)) { - printk("No cardbus resource!\n"); - return -1; - } - - /* - * Ok, start setup.. Map the cardbus registers, - * and request the IRQ. - */ - socket->base = ioremap(pci_resource_start(dev, 0), 0x1000); - if (!socket->base) - return -1; - - yenta_config_init(socket); - - /* Disable all events */ - cb_writel(socket, CB_SOCKET_MASK, 0x0); - - /* Set up the bridge regions.. */ - yenta_allocate_resources(socket); - - socket->cb_irq = dev->irq; - - /* Do we have special options for the device? */ - d = cardbus_override; - while (d->override) { - if ((dev->vendor == d->vendor) && (dev->device == d->device)) { - int retval = d->override(socket); - if (retval < 0) - return retval; - } - d++; - } - - /* We must finish initialization here */ - - INIT_WORK(&socket->tq_task, yenta_bh, socket); - - if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->dev.name, socket)) { - /* No IRQ or request_irq failed. Poll */ - socket->cb_irq = 0; /* But zero is a valid IRQ number. */ - init_timer(&socket->poll_timer); - socket->poll_timer.function = yenta_interrupt_wrapper; - socket->poll_timer.data = (unsigned long)socket; - socket->poll_timer.expires = jiffies + HZ; - add_timer(&socket->poll_timer); - } - - /* Figure out what the dang thing can do for the PCMCIA layer... */ - yenta_get_socket_capabilities(socket, isa_interrupts); - printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); - - /* Register it with the pcmcia layer.. */ - return pcmcia_register_socket(&socket->socket); -} - - -static int yenta_dev_suspend (struct pci_dev *dev, u32 state) -{ - return pcmcia_socket_dev_suspend(&dev->dev, state, 0); -} - - -static int yenta_dev_resume (struct pci_dev *dev) -{ - return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE); -} - - -static struct pci_device_id yenta_table [] __devinitdata = { { - .class = PCI_CLASS_BRIDGE_CARDBUS << 8, - .class_mask = ~0, - - .vendor = PCI_ANY_ID, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, -}, { /* all zeroes */ } -}; -MODULE_DEVICE_TABLE(pci, yenta_table); - - -static struct pci_driver yenta_cardbus_driver = { - .name = "yenta_cardbus", - .id_table = yenta_table, - .probe = yenta_probe, - .remove = __devexit_p(yenta_close), - .suspend = yenta_dev_suspend, - .resume = yenta_dev_resume, -}; - - -static int __init yenta_socket_init(void) -{ - return pci_register_driver (¥ta_cardbus_driver); -} - - -static void __exit yenta_socket_exit (void) -{ - pci_unregister_driver (¥ta_cardbus_driver); -} - - -module_init(yenta_socket_init); -module_exit(yenta_socket_exit); - -MODULE_LICENSE("GPL"); diff -Nru a/drivers/pcmcia/yenta.h b/drivers/pcmcia/yenta.h --- a/drivers/pcmcia/yenta.h Sun Jun 15 08:20:53 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,116 +0,0 @@ -#ifndef __YENTA_H -#define __YENTA_H - -#include - -#define CB_SOCKET_EVENT 0x00 -#define CB_CSTSEVENT 0x00000001 /* Card status event */ -#define CB_CD1EVENT 0x00000002 /* Card detect 1 change event */ -#define CB_CD2EVENT 0x00000004 /* Card detect 2 change event */ -#define CB_PWREVENT 0x00000008 /* PWRCYCLE change event */ - -#define CB_SOCKET_MASK 0x04 -#define CB_CSTSMASK 0x00000001 /* Card status mask */ -#define CB_CDMASK 0x00000006 /* Card detect 1&2 mask */ -#define CB_PWRMASK 0x00000008 /* PWRCYCLE change mask */ - -#define CB_SOCKET_STATE 0x08 -#define CB_CARDSTS 0x00000001 /* CSTSCHG status */ -#define CB_CDETECT1 0x00000002 /* Card detect status 1 */ -#define CB_CDETECT2 0x00000004 /* Card detect status 2 */ -#define CB_PWRCYCLE 0x00000008 /* Socket powered */ -#define CB_16BITCARD 0x00000010 /* 16-bit card detected */ -#define CB_CBCARD 0x00000020 /* CardBus card detected */ -#define CB_IREQCINT 0x00000040 /* READY(xIRQ)/xCINT high */ -#define CB_NOTACARD 0x00000080 /* Unrecognizable PC card detected */ -#define CB_DATALOST 0x00000100 /* Potential data loss due to card removal */ -#define CB_BADVCCREQ 0x00000200 /* Invalid Vcc request by host software */ -#define CB_5VCARD 0x00000400 /* Card Vcc at 5.0 volts? */ -#define CB_3VCARD 0x00000800 /* Card Vcc at 3.3 volts? */ -#define CB_XVCARD 0x00001000 /* Card Vcc at X.X volts? */ -#define CB_YVCARD 0x00002000 /* Card Vcc at Y.Y volts? */ -#define CB_5VSOCKET 0x10000000 /* Socket Vcc at 5.0 volts? */ -#define CB_3VSOCKET 0x20000000 /* Socket Vcc at 3.3 volts? */ -#define CB_XVSOCKET 0x40000000 /* Socket Vcc at X.X volts? */ -#define CB_YVSOCKET 0x80000000 /* Socket Vcc at Y.Y volts? */ - -#define CB_SOCKET_FORCE 0x0C -#define CB_FCARDSTS 0x00000001 /* Force CSTSCHG */ -#define CB_FCDETECT1 0x00000002 /* Force CD1EVENT */ -#define CB_FCDETECT2 0x00000004 /* Force CD2EVENT */ -#define CB_FPWRCYCLE 0x00000008 /* Force PWREVENT */ -#define CB_F16BITCARD 0x00000010 /* Force 16-bit PCMCIA card */ -#define CB_FCBCARD 0x00000020 /* Force CardBus line */ -#define CB_FNOTACARD 0x00000080 /* Force NOTACARD */ -#define CB_FDATALOST 0x00000100 /* Force data lost */ -#define CB_FBADVCCREQ 0x00000200 /* Force bad Vcc request */ -#define CB_F5VCARD 0x00000400 /* Force 5.0 volt card */ -#define CB_F3VCARD 0x00000800 /* Force 3.3 volt card */ -#define CB_FXVCARD 0x00001000 /* Force X.X volt card */ -#define CB_FYVCARD 0x00002000 /* Force Y.Y volt card */ -#define CB_CVSTEST 0x00004000 /* Card VS test */ - -#define CB_SOCKET_CONTROL 0x10 -#define CB_SC_VPP_MASK 0x00000007 -#define CB_SC_VPP_OFF 0x00000000 -#define CB_SC_VPP_12V 0x00000001 -#define CB_SC_VPP_5V 0x00000002 -#define CB_SC_VPP_3V 0x00000003 -#define CB_SC_VPP_XV 0x00000004 -#define CB_SC_VPP_YV 0x00000005 -#define CB_SC_VCC_MASK 0x00000070 -#define CB_SC_VCC_OFF 0x00000000 -#define CB_SC_VCC_5V 0x00000020 -#define CB_SC_VCC_3V 0x00000030 -#define CB_SC_VCC_XV 0x00000040 -#define CB_SC_VCC_YV 0x00000050 -#define CB_SC_CCLK_STOP 0x00000080 - -#define CB_SOCKET_POWER 0x20 -#define CB_SKTACCES 0x02000000 /* A PC card access has occurred (clear on read) */ -#define CB_SKTMODE 0x01000000 /* Clock frequency has changed (clear on read) */ -#define CB_CLKCTRLEN 0x00010000 /* Clock control enabled (RW) */ -#define CB_CLKCTRL 0x00000001 /* Stop(0) or slow(1) CB clock (RW) */ - -/* - * Cardbus configuration space - */ -#define CB_BRIDGE_BASE(m) (0x1c + 8*(m)) -#define CB_BRIDGE_LIMIT(m) (0x20 + 8*(m)) -#define CB_BRIDGE_CONTROL 0x3e -#define CB_BRIDGE_CPERREN 0x00000001 -#define CB_BRIDGE_CSERREN 0x00000002 -#define CB_BRIDGE_ISAEN 0x00000004 -#define CB_BRIDGE_VGAEN 0x00000008 -#define CB_BRIDGE_MABTMODE 0x00000020 -#define CB_BRIDGE_CRST 0x00000040 -#define CB_BRIDGE_INTR 0x00000080 -#define CB_BRIDGE_PREFETCH0 0x00000100 -#define CB_BRIDGE_PREFETCH1 0x00000200 -#define CB_BRIDGE_POSTEN 0x00000400 -#define CB_LEGACY_MODE_BASE 0x44 - -/* - * ExCA area extensions in Yenta - */ -#define CB_MEM_PAGE(map) (0x40 + (map)) - -struct yenta_socket { - struct pci_dev *dev; - int cb_irq, io_irq; - void *base; - void (*handler)(void *, unsigned int); - void *info; - spinlock_t event_lock; - unsigned int events; - struct work_struct tq_task; - struct timer_list poll_timer; - - struct pcmcia_socket socket; - - /* A few words of private data for special stuff of overrides... */ - unsigned int private[8]; -}; - - -#endif diff -Nru a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pcmcia/yenta_socket.c Mon Jun 16 08:06:42 2003 @@ -0,0 +1,974 @@ +/* + * Regular cardbus driver ("yenta_socket") + * + * (C) Copyright 1999, 2000 Linus Torvalds + * + * Changelog: + * Aug 2002: Manfred Spraul + * Dynamically adjust the size of the bridge resource + * + * May 2003: Dominik Brodowski + * Merge pci_socket.c and yenta.c into one file + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "yenta_socket.h" +#include "i82365.h" + + +#if 0 +#define DEBUG(x,args...) printk("%s: " x, __FUNCTION__, ##args) +#else +#define DEBUG(x,args...) +#endif + +/* Don't ask.. */ +#define to_cycles(ns) ((ns)/120) +#define to_ns(cycles) ((cycles)*120) + +/* + * Generate easy-to-use ways of reading a cardbus sockets + * regular memory space ("cb_xxx"), configuration space + * ("config_xxx") and compatibility space ("exca_xxxx") + */ +static inline u32 cb_readl(struct yenta_socket *socket, unsigned reg) +{ + u32 val = readl(socket->base + reg); + DEBUG("%p %04x %08x\n", socket, reg, val); + return val; +} + +static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val) +{ + DEBUG("%p %04x %08x\n", socket, reg, val); + writel(val, socket->base + reg); +} + +static inline u8 config_readb(struct yenta_socket *socket, unsigned offset) +{ + u8 val; + pci_read_config_byte(socket->dev, offset, &val); + DEBUG("%p %04x %02x\n", socket, offset, val); + return val; +} + +static inline u16 config_readw(struct yenta_socket *socket, unsigned offset) +{ + u16 val; + pci_read_config_word(socket->dev, offset, &val); + DEBUG("%p %04x %04x\n", socket, offset, val); + return val; +} + +static inline u32 config_readl(struct yenta_socket *socket, unsigned offset) +{ + u32 val; + pci_read_config_dword(socket->dev, offset, &val); + DEBUG("%p %04x %08x\n", socket, offset, val); + return val; +} + +static inline void config_writeb(struct yenta_socket *socket, unsigned offset, u8 val) +{ + DEBUG("%p %04x %02x\n", socket, offset, val); + pci_write_config_byte(socket->dev, offset, val); +} + +static inline void config_writew(struct yenta_socket *socket, unsigned offset, u16 val) +{ + DEBUG("%p %04x %04x\n", socket, offset, val); + pci_write_config_word(socket->dev, offset, val); +} + +static inline void config_writel(struct yenta_socket *socket, unsigned offset, u32 val) +{ + DEBUG("%p %04x %08x\n", socket, offset, val); + pci_write_config_dword(socket->dev, offset, val); +} + +static inline u8 exca_readb(struct yenta_socket *socket, unsigned reg) +{ + u8 val = readb(socket->base + 0x800 + reg); + DEBUG("%p %04x %02x\n", socket, reg, val); + return val; +} + +static inline u8 exca_readw(struct yenta_socket *socket, unsigned reg) +{ + u16 val; + val = readb(socket->base + 0x800 + reg); + val |= readb(socket->base + 0x800 + reg + 1) << 8; + DEBUG("%p %04x %04x\n", socket, reg, val); + return val; +} + +static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val) +{ + DEBUG("%p %04x %02x\n", socket, reg, val); + writeb(val, socket->base + 0x800 + reg); +} + +static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val) +{ + DEBUG("%p %04x %04x\n", socket, reg, val); + writeb(val, socket->base + 0x800 + reg); + writeb(val >> 8, socket->base + 0x800 + reg + 1); +} + +/* + * Ugh, mixed-mode cardbus and 16-bit pccard state: things depend + * on what kind of card is inserted.. + */ +static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + unsigned int val; + u32 state = cb_readl(socket, CB_SOCKET_STATE); + + val = (state & CB_3VCARD) ? SS_3VCARD : 0; + val |= (state & CB_XVCARD) ? SS_XVCARD : 0; + val |= (state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD | CB_3VCARD + | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING; + + if (state & CB_CBCARD) { + val |= SS_CARDBUS; + val |= (state & CB_CARDSTS) ? SS_STSCHG : 0; + val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT; + val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0; + } else { + u8 status = exca_readb(socket, I365_STATUS); + val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0; + if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { + val |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG; + } else { + val |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD; + val |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN; + } + val |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0; + val |= (status & I365_CS_READY) ? SS_READY : 0; + val |= (status & I365_CS_POWERON) ? SS_POWERON : 0; + } + + *value = val; + return 0; +} + +static int yenta_Vcc_power(u32 control) +{ + switch (control & CB_SC_VCC_MASK) { + case CB_SC_VCC_5V: return 50; + case CB_SC_VCC_3V: return 33; + default: return 0; + } +} + +static int yenta_Vpp_power(u32 control) +{ + switch (control & CB_SC_VPP_MASK) { + case CB_SC_VPP_12V: return 120; + case CB_SC_VPP_5V: return 50; + case CB_SC_VPP_3V: return 33; + default: return 0; + } +} + +static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + u8 reg; + u32 control; + + control = cb_readl(socket, CB_SOCKET_CONTROL); + + state->Vcc = yenta_Vcc_power(control); + state->Vpp = yenta_Vpp_power(control); + state->io_irq = socket->io_irq; + + if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { + u16 bridge = config_readw(socket, CB_BRIDGE_CONTROL); + if (bridge & CB_BRIDGE_CRST) + state->flags |= SS_RESET; + return 0; + } + + /* 16-bit card state.. */ + reg = exca_readb(socket, I365_POWER); + state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0; + state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0; + + reg = exca_readb(socket, I365_INTCTL); + state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET; + state->flags |= (reg & I365_PC_IOCARD) ? SS_IOCARD : 0; + + reg = exca_readb(socket, I365_CSCINT); + state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0; + if (state->flags & SS_IOCARD) { + state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0; + } else { + state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0; + state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0; + state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0; + } + + return 0; +} + +static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) +{ + u32 reg = 0; /* CB_SC_STPCLK? */ + switch (state->Vcc) { + case 33: reg = CB_SC_VCC_3V; break; + case 50: reg = CB_SC_VCC_5V; break; + default: reg = 0; break; + } + switch (state->Vpp) { + case 33: reg |= CB_SC_VPP_3V; break; + case 50: reg |= CB_SC_VPP_5V; break; + case 120: reg |= CB_SC_VPP_12V; break; + } + if (reg != cb_readl(socket, CB_SOCKET_CONTROL)) + cb_writel(socket, CB_SOCKET_CONTROL, reg); +} + +static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + u16 bridge; + + if (state->flags & SS_DEBOUNCED) { + /* The insertion debounce period has ended. Clear any pending insertion events */ + socket->events &= ~SS_DETECT; + state->flags &= ~SS_DEBOUNCED; /* SS_DEBOUNCED is oneshot */ + } + yenta_set_power(socket, state); + socket->io_irq = state->io_irq; + bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR); + if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { + u8 intr; + bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0; + + /* ISA interrupt control? */ + intr = exca_readb(socket, I365_INTCTL); + intr = (intr & ~0xf); + if (!socket->cb_irq) { + intr |= state->io_irq; + bridge |= CB_BRIDGE_INTR; + } + exca_writeb(socket, I365_INTCTL, intr); + } else { + u8 reg; + + reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA); + reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; + reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; + if (state->io_irq != socket->cb_irq) { + reg |= state->io_irq; + bridge |= CB_BRIDGE_INTR; + } + exca_writeb(socket, I365_INTCTL, reg); + + reg = exca_readb(socket, I365_POWER) & (I365_VCC_MASK|I365_VPP1_MASK); + reg |= I365_PWR_NORESET; + if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO; + if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT; + if (exca_readb(socket, I365_POWER) != reg) + exca_writeb(socket, I365_POWER, reg); + + /* CSC interrupt: no ISA irq for CSC */ + reg = I365_CSC_DETECT; + if (state->flags & SS_IOCARD) { + if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG; + } else { + if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1; + if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2; + if (state->csc_mask & SS_READY) reg |= I365_CSC_READY; + } + exca_writeb(socket, I365_CSCINT, reg); + exca_readb(socket, I365_CSC); + } + config_writew(socket, CB_BRIDGE_CONTROL, bridge); + /* Socket event mask: get card insert/remove events.. */ + cb_writel(socket, CB_SOCKET_EVENT, -1); + cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); + return 0; +} + +static int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + int map; + unsigned char ioctl, addr, enable; + + map = io->map; + + if (map > 1) + return -EINVAL; + + enable = I365_ENA_IO(map); + addr = exca_readb(socket, I365_ADDRWIN); + + /* Disable the window before changing it.. */ + if (addr & enable) { + addr &= ~enable; + exca_writeb(socket, I365_ADDRWIN, addr); + } + + exca_writew(socket, I365_IO(map)+I365_W_START, io->start); + exca_writew(socket, I365_IO(map)+I365_W_STOP, io->stop); + + ioctl = exca_readb(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map); + if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map); + if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map); + if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map); + exca_writeb(socket, I365_IOCTL, ioctl); + + if (io->flags & MAP_ACTIVE) + exca_writeb(socket, I365_ADDRWIN, addr | enable); + return 0; +} + +static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + int map; + unsigned char addr, enable; + unsigned int start, stop, card_start; + unsigned short word; + + map = mem->map; + start = mem->sys_start; + stop = mem->sys_stop; + card_start = mem->card_start; + + if (map > 4 || start > stop || ((start ^ stop) >> 24) || + (card_start >> 26) || mem->speed > 1000) + return -EINVAL; + + enable = I365_ENA_MEM(map); + addr = exca_readb(socket, I365_ADDRWIN); + if (addr & enable) { + addr &= ~enable; + exca_writeb(socket, I365_ADDRWIN, addr); + } + + exca_writeb(socket, CB_MEM_PAGE(map), start >> 24); + + word = (start >> 12) & 0x0fff; + if (mem->flags & MAP_16BIT) + word |= I365_MEM_16BIT; + if (mem->flags & MAP_0WS) + word |= I365_MEM_0WS; + exca_writew(socket, I365_MEM(map) + I365_W_START, word); + + word = (stop >> 12) & 0x0fff; + switch (to_cycles(mem->speed)) { + case 0: break; + case 1: word |= I365_MEM_WS0; break; + case 2: word |= I365_MEM_WS1; break; + default: word |= I365_MEM_WS1 | I365_MEM_WS0; break; + } + exca_writew(socket, I365_MEM(map) + I365_W_STOP, word); + + word = ((card_start - start) >> 12) & 0x3fff; + if (mem->flags & MAP_WRPROT) + word |= I365_MEM_WRPROT; + if (mem->flags & MAP_ATTRIB) + word |= I365_MEM_REG; + exca_writew(socket, I365_MEM(map) + I365_W_OFF, word); + + if (mem->flags & MAP_ACTIVE) + exca_writeb(socket, I365_ADDRWIN, addr | enable); + return 0; +} + + +static unsigned int yenta_events(struct yenta_socket *socket) +{ + u8 csc; + u32 cb_event; + unsigned int events; + + /* Clear interrupt status for the event */ + cb_event = cb_readl(socket, CB_SOCKET_EVENT); + cb_writel(socket, CB_SOCKET_EVENT, cb_event); + + csc = exca_readb(socket, I365_CSC); + + events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ; + events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0; + if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { + events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; + } else { + events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0; + events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; + events |= (csc & I365_CSC_READY) ? SS_READY : 0; + } + return events; +} + + +static void yenta_bh(void *data) +{ + struct yenta_socket *socket = data; + unsigned int events; + + spin_lock_irq(&socket->event_lock); + events = socket->events; + socket->events = 0; + spin_unlock_irq(&socket->event_lock); + if (socket->handler) + socket->handler(socket->info, events); +} + +static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int events; + struct yenta_socket *socket = (struct yenta_socket *) dev_id; + + events = yenta_events(socket); + if (events) { + spin_lock(&socket->event_lock); + socket->events |= events; + spin_unlock(&socket->event_lock); + schedule_work(&socket->tq_task); + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +static void yenta_interrupt_wrapper(unsigned long data) +{ + struct yenta_socket *socket = (struct yenta_socket *) data; + + yenta_interrupt(0, (void *)socket, NULL); + socket->poll_timer.expires = jiffies + HZ; + add_timer(&socket->poll_timer); +} + +/* + * Only probe "regular" interrupts, don't + * touch dangerous spots like the mouse irq, + * because there are mice that apparently + * get really confused if they get fondled + * too intimately. + * + * Default to 11, 10, 9, 7, 6, 5, 4, 3. + */ +static u32 isa_interrupts = 0x0ef8; + +static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask) +{ + int i; + unsigned long val; + u16 bridge_ctrl; + u32 mask; + + /* Set up ISA irq routing to probe the ISA irqs.. */ + bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL); + if (!(bridge_ctrl & CB_BRIDGE_INTR)) { + bridge_ctrl |= CB_BRIDGE_INTR; + config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl); + } + + /* + * Probe for usable interrupts using the force + * register to generate bogus card status events. + */ + cb_writel(socket, CB_SOCKET_EVENT, -1); + cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); + exca_writeb(socket, I365_CSCINT, 0); + val = probe_irq_on() & isa_irq_mask; + for (i = 1; i < 16; i++) { + if (!((val >> i) & 1)) + continue; + exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG | (i << 4)); + cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); + udelay(100); + cb_writel(socket, CB_SOCKET_EVENT, -1); + } + cb_writel(socket, CB_SOCKET_MASK, 0); + exca_writeb(socket, I365_CSCINT, 0); + + mask = probe_irq_mask(val) & 0xffff; + + bridge_ctrl &= ~CB_BRIDGE_INTR; + config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl); + + return mask; +} + +/* + * Set static data that doesn't need re-initializing.. + */ +static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_irq_mask) +{ + socket->socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS; + socket->socket.map_size = 0x1000; + socket->socket.pci_irq = socket->cb_irq; + socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask); + socket->socket.cb_dev = socket->dev; + + printk("Yenta IRQ list %04x, PCI irq%d\n", socket->socket.irq_mask, socket->cb_irq); +} + + +static void yenta_clear_maps(struct yenta_socket *socket) +{ + int i; + pccard_io_map io = { 0, 0, 0, 0, 1 }; + pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 }; + + mem.sys_stop = 0x0fff; + yenta_set_socket(&socket->socket, &dead_socket); + for (i = 0; i < 2; i++) { + io.map = i; + yenta_set_io_map(&socket->socket, &io); + } + for (i = 0; i < 5; i++) { + mem.map = i; + yenta_set_mem_map(&socket->socket, &mem); + } +} + +/* + * Initialize the standard cardbus registers + */ +static void yenta_config_init(struct yenta_socket *socket) +{ + u16 bridge; + struct pci_dev *dev = socket->dev; + + pci_set_power_state(socket->dev, 0); + + config_writel(socket, CB_LEGACY_MODE_BASE, 0); + config_writel(socket, PCI_BASE_ADDRESS_0, dev->resource[0].start); + config_writew(socket, PCI_COMMAND, + PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | + PCI_COMMAND_WAIT); + + /* MAGIC NUMBERS! Fixme */ + config_writeb(socket, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4); + config_writeb(socket, PCI_LATENCY_TIMER, 168); + config_writel(socket, PCI_PRIMARY_BUS, + (176 << 24) | /* sec. latency timer */ + (dev->subordinate->subordinate << 16) | /* subordinate bus */ + (dev->subordinate->secondary << 8) | /* secondary bus */ + dev->subordinate->primary); /* primary bus */ + + /* + * Set up the bridging state: + * - enable write posting. + * - memory window 0 prefetchable, window 1 non-prefetchable + * - PCI interrupts enabled if a PCI interrupt exists.. + */ + bridge = config_readw(socket, CB_BRIDGE_CONTROL); + bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_INTR | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN); + bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN; + if (!socket->cb_irq) + bridge |= CB_BRIDGE_INTR; + config_writew(socket, CB_BRIDGE_CONTROL, bridge); + + exca_writeb(socket, I365_GBLCTL, 0x00); + exca_writeb(socket, I365_GENCTL, 0x00); + + /* Redo card voltage interrogation */ + cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST); +} + +/* Called at resume and initialization events */ +static int yenta_init(struct pcmcia_socket *sock) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + yenta_config_init(socket); + yenta_clear_maps(socket); + + /* Re-enable interrupts */ + cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); + return 0; +} + +static int yenta_suspend(struct pcmcia_socket *sock) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + + yenta_set_socket(sock, &dead_socket); + + /* Disable interrupts */ + cb_writel(socket, CB_SOCKET_MASK, 0x0); + + /* + * This does not work currently. The controller + * loses too much information during D3 to come up + * cleanly. We should probably fix yenta_init() + * to update all the critical registers, notably + * the IO and MEM bridging region data.. That is + * something that pci_set_power_state() should + * probably know about bridges anyway. + * + pci_set_power_state(socket->dev, 3); + */ + + return 0; +} + +/* + * Use an adaptive allocation for the memory resource, + * sometimes the memory behind pci bridges is limited: + * 1/8 of the size of the io window of the parent. + * max 4 MB, min 16 kB. + */ +#define BRIDGE_MEM_MAX 4*1024*1024 +#define BRIDGE_MEM_MIN 16*1024 + +#define BRIDGE_IO_MAX 256 +#define BRIDGE_IO_MIN 32 + +static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type) +{ + struct pci_bus *bus; + struct resource *root, *res; + u32 start, end; + u32 align, size, min; + unsigned offset; + unsigned mask; + + /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ + mask = ~0xfff; + if (type & IORESOURCE_IO) + mask = ~3; + + offset = 0x1c + 8*nr; + bus = socket->dev->subordinate; + res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; + res->name = bus->name; + res->flags = type; + res->start = 0; + res->end = 0; + root = pci_find_parent_resource(socket->dev, res); + + if (!root) + return; + + start = config_readl(socket, offset) & mask; + end = config_readl(socket, offset+4) | ~mask; + if (start && end > start) { + res->start = start; + res->end = end; + if (request_resource(root, res) == 0) + return; + printk(KERN_INFO "yenta %s: Preassigned resource %d busy, reconfiguring...\n", + socket->dev->slot_name, nr); + res->start = res->end = 0; + } + + if (type & IORESOURCE_IO) { + align = 1024; + size = BRIDGE_IO_MAX; + min = BRIDGE_IO_MIN; + start = PCIBIOS_MIN_IO; + end = ~0U; + } else { + unsigned long avail = root->end - root->start; + int i; + size = BRIDGE_MEM_MAX; + if (size > avail/8) { + size=(avail+1)/8; + /* round size down to next power of 2 */ + i = 0; + while ((size /= 2) != 0) + i++; + size = 1 << i; + } + if (size < BRIDGE_MEM_MIN) + size = BRIDGE_MEM_MIN; + min = BRIDGE_MEM_MIN; + align = size; + start = PCIBIOS_MIN_MEM; + end = ~0U; + } + + do { + if (allocate_resource(root, res, size, start, end, align, NULL, NULL)==0) { + config_writel(socket, offset, res->start); + config_writel(socket, offset+4, res->end); + return; + } + size = size/2; + align = size; + } while (size >= min); + printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n", + socket->dev->slot_name, type); + res->start = res->end = 0; +} + +/* + * Allocate the bridge mappings for the device.. + */ +static void yenta_allocate_resources(struct yenta_socket *socket) +{ + yenta_allocate_res(socket, 0, IORESOURCE_MEM|IORESOURCE_PREFETCH); + yenta_allocate_res(socket, 1, IORESOURCE_MEM); + yenta_allocate_res(socket, 2, IORESOURCE_IO); + yenta_allocate_res(socket, 3, IORESOURCE_IO); /* PCI isn't clever enough to use this one yet */ +} + + +/* + * Free the bridge mappings for the device.. + */ +static void yenta_free_resources(struct yenta_socket *socket) +{ + int i; + for (i=0;i<4;i++) { + struct resource *res; + res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i; + if (res->start != 0 && res->end != 0) + release_resource(res); + res->start = res->end = 0; + } +} + + +/* + * Close it down - release our resources and go home.. + */ +static void yenta_close(struct pci_dev *dev) +{ + struct yenta_socket *sock = pci_get_drvdata(dev); + + /* we don't want a dying socket registered */ + pcmcia_unregister_socket(&sock->socket); + + /* Disable all events so we don't die in an IRQ storm */ + cb_writel(sock, CB_SOCKET_MASK, 0x0); + exca_writeb(sock, I365_CSCINT, 0); + + if (sock->cb_irq) + free_irq(sock->cb_irq, sock); + else + del_timer_sync(&sock->poll_timer); + + if (sock->base) + iounmap(sock->base); + yenta_free_resources(sock); + + pci_set_drvdata(dev, NULL); +} + + +static int yenta_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + + socket->handler = handler; + socket->info = info; + return 0; +} + + +static struct pccard_operations yenta_socket_operations = { + .owner = THIS_MODULE, + .init = yenta_init, + .suspend = yenta_suspend, + .register_callback = yenta_register_callback, + .get_status = yenta_get_status, + .get_socket = yenta_get_socket, + .set_socket = yenta_set_socket, + .set_io_map = yenta_set_io_map, + .set_mem_map = yenta_set_mem_map, +}; + + +#include "ti113x.h" +#include "ricoh.h" + +/* + * Different cardbus controllers have slightly different + * initialization sequences etc details. List them here.. + */ +#define PD(x,y) PCI_VENDOR_ID_##x, PCI_DEVICE_ID_##x##_##y +struct cardbus_override_struct { + unsigned short vendor; + unsigned short device; + int (*override) (struct yenta_socket *socket); +} cardbus_override[] = { + { PD(TI,1130), &ti113x_override }, + { PD(TI,1031), &ti_override }, + { PD(TI,1131), &ti113x_override }, + { PD(TI,1250), &ti1250_override }, + { PD(TI,1220), &ti_override }, + { PD(TI,1221), &ti_override }, + { PD(TI,1210), &ti_override }, + { PD(TI,1450), &ti_override }, + { PD(TI,1225), &ti_override }, + { PD(TI,1251A), &ti_override }, + { PD(TI,1211), &ti_override }, + { PD(TI,1251B), &ti_override }, + { PD(TI,1410), ti1250_override }, + { PD(TI,1420), &ti_override }, + { PD(TI,4410), &ti_override }, + { PD(TI,4451), &ti_override }, + + { PD(RICOH,RL5C465), &ricoh_override }, + { PD(RICOH,RL5C466), &ricoh_override }, + { PD(RICOH,RL5C475), &ricoh_override }, + { PD(RICOH,RL5C476), &ricoh_override }, + { PD(RICOH,RL5C478), &ricoh_override }, + + { }, /* all zeroes */ +}; + + +/* + * Initialize a cardbus controller. Make sure we have a usable + * interrupt, and that we can map the cardbus area. Fill in the + * socket information structure.. + */ +static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_id *id) +{ + struct yenta_socket *socket; + struct cardbus_override_struct *d; + + socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL); + if (!socket) + return -ENOMEM; + memset(socket, 0, sizeof(*socket)); + + /* prepare pcmcia_socket */ + socket->socket.ss_entry = ¥ta_socket_operations; + socket->socket.dev.dev = &dev->dev; + socket->socket.driver_data = socket; + + /* prepare struct yenta_socket */ + socket->dev = dev; + pci_set_drvdata(dev, socket); + spin_lock_init(&socket->event_lock); + + /* + * Do some basic sanity checking.. + */ + if (pci_enable_device(dev)) + return -1; + if (!pci_resource_start(dev, 0)) { + printk("No cardbus resource!\n"); + return -1; + } + + /* + * Ok, start setup.. Map the cardbus registers, + * and request the IRQ. + */ + socket->base = ioremap(pci_resource_start(dev, 0), 0x1000); + if (!socket->base) + return -1; + + yenta_config_init(socket); + + /* Disable all events */ + cb_writel(socket, CB_SOCKET_MASK, 0x0); + + /* Set up the bridge regions.. */ + yenta_allocate_resources(socket); + + socket->cb_irq = dev->irq; + + /* Do we have special options for the device? */ + d = cardbus_override; + while (d->override) { + if ((dev->vendor == d->vendor) && (dev->device == d->device)) { + int retval = d->override(socket); + if (retval < 0) + return retval; + } + d++; + } + + /* We must finish initialization here */ + + INIT_WORK(&socket->tq_task, yenta_bh, socket); + + if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->dev.name, socket)) { + /* No IRQ or request_irq failed. Poll */ + socket->cb_irq = 0; /* But zero is a valid IRQ number. */ + init_timer(&socket->poll_timer); + socket->poll_timer.function = yenta_interrupt_wrapper; + socket->poll_timer.data = (unsigned long)socket; + socket->poll_timer.expires = jiffies + HZ; + add_timer(&socket->poll_timer); + } + + /* Figure out what the dang thing can do for the PCMCIA layer... */ + yenta_get_socket_capabilities(socket, isa_interrupts); + printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); + + /* Register it with the pcmcia layer.. */ + return pcmcia_register_socket(&socket->socket); +} + + +static int yenta_dev_suspend (struct pci_dev *dev, u32 state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state, 0); +} + + +static int yenta_dev_resume (struct pci_dev *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE); +} + + +static struct pci_device_id yenta_table [] __devinitdata = { { + .class = PCI_CLASS_BRIDGE_CARDBUS << 8, + .class_mask = ~0, + + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, +}, { /* all zeroes */ } +}; +MODULE_DEVICE_TABLE(pci, yenta_table); + + +static struct pci_driver yenta_cardbus_driver = { + .name = "yenta_cardbus", + .id_table = yenta_table, + .probe = yenta_probe, + .remove = __devexit_p(yenta_close), + .suspend = yenta_dev_suspend, + .resume = yenta_dev_resume, +}; + + +static int __init yenta_socket_init(void) +{ + return pci_register_driver (¥ta_cardbus_driver); +} + + +static void __exit yenta_socket_exit (void) +{ + pci_unregister_driver (¥ta_cardbus_driver); +} + + +module_init(yenta_socket_init); +module_exit(yenta_socket_exit); + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/pcmcia/yenta_socket.h b/drivers/pcmcia/yenta_socket.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pcmcia/yenta_socket.h Mon Jun 16 08:00:31 2003 @@ -0,0 +1,116 @@ +#ifndef __YENTA_H +#define __YENTA_H + +#include + +#define CB_SOCKET_EVENT 0x00 +#define CB_CSTSEVENT 0x00000001 /* Card status event */ +#define CB_CD1EVENT 0x00000002 /* Card detect 1 change event */ +#define CB_CD2EVENT 0x00000004 /* Card detect 2 change event */ +#define CB_PWREVENT 0x00000008 /* PWRCYCLE change event */ + +#define CB_SOCKET_MASK 0x04 +#define CB_CSTSMASK 0x00000001 /* Card status mask */ +#define CB_CDMASK 0x00000006 /* Card detect 1&2 mask */ +#define CB_PWRMASK 0x00000008 /* PWRCYCLE change mask */ + +#define CB_SOCKET_STATE 0x08 +#define CB_CARDSTS 0x00000001 /* CSTSCHG status */ +#define CB_CDETECT1 0x00000002 /* Card detect status 1 */ +#define CB_CDETECT2 0x00000004 /* Card detect status 2 */ +#define CB_PWRCYCLE 0x00000008 /* Socket powered */ +#define CB_16BITCARD 0x00000010 /* 16-bit card detected */ +#define CB_CBCARD 0x00000020 /* CardBus card detected */ +#define CB_IREQCINT 0x00000040 /* READY(xIRQ)/xCINT high */ +#define CB_NOTACARD 0x00000080 /* Unrecognizable PC card detected */ +#define CB_DATALOST 0x00000100 /* Potential data loss due to card removal */ +#define CB_BADVCCREQ 0x00000200 /* Invalid Vcc request by host software */ +#define CB_5VCARD 0x00000400 /* Card Vcc at 5.0 volts? */ +#define CB_3VCARD 0x00000800 /* Card Vcc at 3.3 volts? */ +#define CB_XVCARD 0x00001000 /* Card Vcc at X.X volts? */ +#define CB_YVCARD 0x00002000 /* Card Vcc at Y.Y volts? */ +#define CB_5VSOCKET 0x10000000 /* Socket Vcc at 5.0 volts? */ +#define CB_3VSOCKET 0x20000000 /* Socket Vcc at 3.3 volts? */ +#define CB_XVSOCKET 0x40000000 /* Socket Vcc at X.X volts? */ +#define CB_YVSOCKET 0x80000000 /* Socket Vcc at Y.Y volts? */ + +#define CB_SOCKET_FORCE 0x0C +#define CB_FCARDSTS 0x00000001 /* Force CSTSCHG */ +#define CB_FCDETECT1 0x00000002 /* Force CD1EVENT */ +#define CB_FCDETECT2 0x00000004 /* Force CD2EVENT */ +#define CB_FPWRCYCLE 0x00000008 /* Force PWREVENT */ +#define CB_F16BITCARD 0x00000010 /* Force 16-bit PCMCIA card */ +#define CB_FCBCARD 0x00000020 /* Force CardBus line */ +#define CB_FNOTACARD 0x00000080 /* Force NOTACARD */ +#define CB_FDATALOST 0x00000100 /* Force data lost */ +#define CB_FBADVCCREQ 0x00000200 /* Force bad Vcc request */ +#define CB_F5VCARD 0x00000400 /* Force 5.0 volt card */ +#define CB_F3VCARD 0x00000800 /* Force 3.3 volt card */ +#define CB_FXVCARD 0x00001000 /* Force X.X volt card */ +#define CB_FYVCARD 0x00002000 /* Force Y.Y volt card */ +#define CB_CVSTEST 0x00004000 /* Card VS test */ + +#define CB_SOCKET_CONTROL 0x10 +#define CB_SC_VPP_MASK 0x00000007 +#define CB_SC_VPP_OFF 0x00000000 +#define CB_SC_VPP_12V 0x00000001 +#define CB_SC_VPP_5V 0x00000002 +#define CB_SC_VPP_3V 0x00000003 +#define CB_SC_VPP_XV 0x00000004 +#define CB_SC_VPP_YV 0x00000005 +#define CB_SC_VCC_MASK 0x00000070 +#define CB_SC_VCC_OFF 0x00000000 +#define CB_SC_VCC_5V 0x00000020 +#define CB_SC_VCC_3V 0x00000030 +#define CB_SC_VCC_XV 0x00000040 +#define CB_SC_VCC_YV 0x00000050 +#define CB_SC_CCLK_STOP 0x00000080 + +#define CB_SOCKET_POWER 0x20 +#define CB_SKTACCES 0x02000000 /* A PC card access has occurred (clear on read) */ +#define CB_SKTMODE 0x01000000 /* Clock frequency has changed (clear on read) */ +#define CB_CLKCTRLEN 0x00010000 /* Clock control enabled (RW) */ +#define CB_CLKCTRL 0x00000001 /* Stop(0) or slow(1) CB clock (RW) */ + +/* + * Cardbus configuration space + */ +#define CB_BRIDGE_BASE(m) (0x1c + 8*(m)) +#define CB_BRIDGE_LIMIT(m) (0x20 + 8*(m)) +#define CB_BRIDGE_CONTROL 0x3e +#define CB_BRIDGE_CPERREN 0x00000001 +#define CB_BRIDGE_CSERREN 0x00000002 +#define CB_BRIDGE_ISAEN 0x00000004 +#define CB_BRIDGE_VGAEN 0x00000008 +#define CB_BRIDGE_MABTMODE 0x00000020 +#define CB_BRIDGE_CRST 0x00000040 +#define CB_BRIDGE_INTR 0x00000080 +#define CB_BRIDGE_PREFETCH0 0x00000100 +#define CB_BRIDGE_PREFETCH1 0x00000200 +#define CB_BRIDGE_POSTEN 0x00000400 +#define CB_LEGACY_MODE_BASE 0x44 + +/* + * ExCA area extensions in Yenta + */ +#define CB_MEM_PAGE(map) (0x40 + (map)) + +struct yenta_socket { + struct pci_dev *dev; + int cb_irq, io_irq; + void *base; + void (*handler)(void *, unsigned int); + void *info; + spinlock_t event_lock; + unsigned int events; + struct work_struct tq_task; + struct timer_list poll_timer; + + struct pcmcia_socket socket; + + /* A few words of private data for special stuff of overrides... */ + unsigned int private[8]; +}; + + +#endif diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c --- a/drivers/scsi/53c700.c Mon May 26 14:44:44 2003 +++ b/drivers/scsi/53c700.c Sun Jun 8 15:37:49 2003 @@ -168,7 +168,6 @@ STATIC int NCR_700_bus_reset(Scsi_Cmnd * SCpnt); STATIC int NCR_700_dev_reset(Scsi_Cmnd * SCpnt); STATIC int NCR_700_host_reset(Scsi_Cmnd * SCpnt); -STATIC int NCR_700_proc_directory_info(struct Scsi_Host *, char *, char **, off_t, int, int); STATIC void NCR_700_chip_setup(struct Scsi_Host *host); STATIC void NCR_700_chip_reset(struct Scsi_Host *host); STATIC int NCR_700_slave_configure(Scsi_Device *SDpnt); @@ -281,7 +280,6 @@ tpnt->sg_tablesize = NCR_700_SG_SEGMENTS; tpnt->cmd_per_lun = NCR_700_CMD_PER_LUN; tpnt->use_clustering = DISABLE_CLUSTERING; - tpnt->proc_info = NCR_700_proc_directory_info; tpnt->slave_configure = NCR_700_slave_configure; tpnt->slave_destroy = NCR_700_slave_destroy; tpnt->use_blk_tcq = 1; @@ -293,7 +291,8 @@ tpnt->proc_name = "53c700"; - if((host = scsi_register(tpnt, 4)) == NULL) + host = scsi_host_alloc(tpnt, 4); + if (!host) return NULL; memset(hostdata->slots, 0, sizeof(struct NCR_700_command_slot) * NCR_700_COMMAND_SLOTS_PER_HOST); @@ -1707,35 +1706,6 @@ out_unlock: spin_unlock_irqrestore(host->host_lock, flags); return IRQ_RETVAL(handled); -} - -STATIC int -NCR_700_proc_directory_info(struct Scsi_Host *host, char *proc_buf, char **startp, - off_t offset, int bytes_available, int write) -{ - static char buf[4096]; /* 1 page should be sufficient */ - int len = 0; - struct NCR_700_Host_Parameters *hostdata; - Scsi_Device *SDp; - - if(write) { - /* FIXME: Clear internal statistics here */ - return 0; - } - hostdata = (struct NCR_700_Host_Parameters *)host->hostdata[0]; - len += sprintf(&buf[len], "Total commands outstanding: %d\n", hostdata->command_slot_count); - len += sprintf(&buf[len],"\ -Target Active Next Tag\n\ -====== ====== ========\n"); - list_for_each_entry(SDp, &host->my_devices, siblings) { - len += sprintf(&buf[len]," %2d:%2d %4d %4d\n", SDp->id, SDp->lun, NCR_700_get_depth(SDp), SDp->current_tag); - } - if((len -= offset) <= 0) - return 0; - if(len > bytes_available) - len = bytes_available; - memcpy(proc_buf, buf + offset, len); - return len; } STATIC int diff -Nru a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h --- a/drivers/scsi/53c700.h Sat Apr 26 07:28:12 2003 +++ b/drivers/scsi/53c700.h Tue Jun 17 13:27:44 2003 @@ -12,6 +12,10 @@ #include +#if defined(CONFIG_53C700_MEM_MAPPED) && defined(CONFIG_53C700_IO_MAPPED) +#define CONFIG_53C700_BOTH_MAPPED +#endif + /* Turn on for general debugging---too verbose for normal use */ #undef NCR_700_DEBUG /* Debug the tag queues, checking hash queue allocation and deallocation @@ -178,6 +182,9 @@ /* NOTHING BELOW HERE NEEDS ALTERING */ __u32 fast:1; /* if we can alter the SCSI bus clock speed (so can negiotiate sync) */ +#ifdef CONFIG_53C700_BOTH_MAPPED + __u32 mem_mapped; /* set if memory mapped */ +#endif int sync_clock; /* The speed of the SYNC core */ __u32 *script; /* pointer to script location */ @@ -428,11 +435,8 @@ } \ } -#endif - -#ifdef CONFIG_53C700_MEM_MAPPED static inline __u8 -NCR_700_readb(struct Scsi_Host *host, __u32 reg) +NCR_700_mem_readb(struct Scsi_Host *host, __u32 reg) { const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) = (struct NCR_700_Host_Parameters *)host->hostdata[0]; @@ -441,7 +445,7 @@ } static inline __u32 -NCR_700_readl(struct Scsi_Host *host, __u32 reg) +NCR_700_mem_readl(struct Scsi_Host *host, __u32 reg) { __u32 value = __raw_readl(host->base + reg); const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) @@ -456,7 +460,7 @@ } static inline void -NCR_700_writeb(__u8 value, struct Scsi_Host *host, __u32 reg) +NCR_700_mem_writeb(__u8 value, struct Scsi_Host *host, __u32 reg) { const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) = (struct NCR_700_Host_Parameters *)host->hostdata[0]; @@ -465,7 +469,7 @@ } static inline void -NCR_700_writel(__u32 value, struct Scsi_Host *host, __u32 reg) +NCR_700_mem_writel(__u32 value, struct Scsi_Host *host, __u32 reg) { const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) = (struct NCR_700_Host_Parameters *)host->hostdata[0]; @@ -478,9 +482,9 @@ __raw_writel(bS_to_host(value), host->base + reg); } -#elif defined(CONFIG_53C700_IO_MAPPED) + static inline __u8 -NCR_700_readb(struct Scsi_Host *host, __u32 reg) +NCR_700_io_readb(struct Scsi_Host *host, __u32 reg) { const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) = (struct NCR_700_Host_Parameters *)host->hostdata[0]; @@ -489,7 +493,7 @@ } static inline __u32 -NCR_700_readl(struct Scsi_Host *host, __u32 reg) +NCR_700_io_readl(struct Scsi_Host *host, __u32 reg) { __u32 value = inl(host->base + reg); const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) @@ -505,7 +509,7 @@ } static inline void -NCR_700_writeb(__u8 value, struct Scsi_Host *host, __u32 reg) +NCR_700_io_writeb(__u8 value, struct Scsi_Host *host, __u32 reg) { const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) = (struct NCR_700_Host_Parameters *)host->hostdata[0]; @@ -514,7 +518,7 @@ } static inline void -NCR_700_writel(__u32 value, struct Scsi_Host *host, __u32 reg) +NCR_700_io_writel(__u32 value, struct Scsi_Host *host, __u32 reg) { const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) = (struct NCR_700_Host_Parameters *)host->hostdata[0]; @@ -527,4 +531,100 @@ outl(bS_to_host(value), host->base + reg); } + +#ifdef CONFIG_53C700_BOTH_MAPPED + +static inline __u8 +NCR_700_readb(struct Scsi_Host *host, __u32 reg) +{ + __u8 val; + + const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) + = (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + if(hostdata->mem_mapped) + val = NCR_700_mem_readb(host, reg); + else + val = NCR_700_io_readb(host, reg); + + return val; +} + +static inline __u32 +NCR_700_readl(struct Scsi_Host *host, __u32 reg) +{ + __u32 val; + + const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) + = (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + if(hostdata->mem_mapped) + val = NCR_700_mem_readl(host, reg); + else + val = NCR_700_io_readl(host, reg); + + return val; +} + +static inline void +NCR_700_writeb(__u8 value, struct Scsi_Host *host, __u32 reg) +{ + const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) + = (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + if(hostdata->mem_mapped) + NCR_700_mem_writeb(value, host, reg); + else + NCR_700_io_writeb(value, host, reg); +} + +static inline void +NCR_700_writel(__u32 value, struct Scsi_Host *host, __u32 reg) +{ + const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) + = (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + if(hostdata->mem_mapped) + NCR_700_mem_writel(value, host, reg); + else + NCR_700_io_writel(value, host, reg); +} + +static inline void +NCR_700_set_mem_mapped(struct NCR_700_Host_Parameters *hostdata) +{ + hostdata->mem_mapped = 1; +} + +static inline void +NCR_700_set_io_mapped(struct NCR_700_Host_Parameters *hostdata) +{ + hostdata->mem_mapped = 0; +} + + +#elif defined(CONFIG_53C700_IO_MAPPED) + +#define NCR_700_readb NCR_700_io_readb +#define NCR_700_readl NCR_700_io_readl +#define NCR_700_writeb NCR_700_io_writeb +#define NCR_700_writel NCR_700_io_writel + +#define NCR_700_set_io_mapped(x) +#define NCR_700_set_mem_mapped(x) error I/O mapped only + +#elif defined(CONFIG_53C700_MEM_MAPPED) + +#define NCR_700_readb NCR_700_mem_readb +#define NCR_700_readl NCR_700_mem_readl +#define NCR_700_writeb NCR_700_mem_writeb +#define NCR_700_writel NCR_700_mem_writel + +#define NCR_700_set_io_mapped(x) error MEM mapped only +#define NCR_700_set_mem_mapped(x) + +#else +#error neither CONFIG_53C700_MEM_MAPPED nor CONFIG_53C700_IO_MAPPED is set +#endif + #endif diff -Nru a/drivers/scsi/AM53C974.c b/drivers/scsi/AM53C974.c --- a/drivers/scsi/AM53C974.c Tue May 13 03:59:32 2003 +++ b/drivers/scsi/AM53C974.c Sun Jun 8 12:18:41 2003 @@ -817,22 +817,6 @@ return (info); } -/************************************************************************** -* Function : int AM53C974_command (Scsi_Cmnd *SCpnt) * -* * -* Purpose : the unqueued SCSI command function, replaced by the * -* AM53C974_queue_command function * -* * -* Inputs : SCpnt - pointer to command structure * -* * -* Returns :status, see hosts.h for details * -***************************************************************************/ -static int AM53C974_command(Scsi_Cmnd * SCpnt) -{ - DEB(printk("AM53C974_command called\n")); - return 0; -} - /************************************************************************** * Function : void initialize_SCp(Scsi_Cmnd *cmd) * * * @@ -2466,7 +2450,6 @@ .detect = AM53C974_pci_detect, .release = AM53C974_release, .info = AM53C974_info, - .command = AM53C974_command, .queuecommand = AM53C974_queue_command, .abort = AM53C974_abort, .reset = AM53C974_reset, diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig --- a/drivers/scsi/Kconfig Wed Jun 4 22:53:09 2003 +++ b/drivers/scsi/Kconfig Thu Jun 5 16:09:41 2003 @@ -27,8 +27,8 @@ If you want to use a SCSI tape drive under Linux, say Y and read the SCSI-HOWTO, available from , and - in the kernel source. This is NOT for - SCSI CD-ROMs. + in the kernel source. This is NOT + for SCSI CD-ROMs. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -131,11 +131,11 @@ depends on SCSI default y help - If you want to build with SCSI REPORT LUNS support in the kernel, say Y here. - The REPORT LUNS command is useful for devices (such as disk arrays) with - large numbers of LUNs where the LUN values are not contiguous (sparse LUN). - REPORT LUNS scanning is done only for SCSI-3 devices. Most users can safely - answer N here. + If you want support for SCSI REPORT LUNS, say Y here. + The REPORT LUNS command is useful for devices (such as disk arrays) + with large numbers of LUNs where the LUN values are not contiguous + (sparse LUN). REPORT LUNS scanning is done only for SCSI-3 devices. + Most users can safely answer N here. config SCSI_CONSTANTS bool "Verbose SCSI error reporting (kernel size +=12K)" @@ -207,7 +207,7 @@ config SCSI_7000FASST tristate "7000FASST SCSI support" - depends on SCSI && ISA + depends on ISA && SCSI help This driver supports the Western Digital 7000 SCSI host adapter family. Some information is in the source: @@ -220,7 +220,7 @@ config SCSI_ACARD tristate "ACARD SCSI support" - depends on SCSI + depends on PCI && SCSI help This driver supports the ACARD 870U/W SCSI host adapter. @@ -285,6 +285,7 @@ config SCSI_AIC7XXX_OLD tristate "Adaptec AIC7xxx support (old driver)" + depends on SCSI help WARNING This driver is an older aic7xxx driver and is no longer under active development. Adaptec, Inc. is writing a new driver to @@ -343,7 +344,7 @@ config SCSI_ADVANSYS tristate "AdvanSys SCSI support" - depends on SCSI + depends on (ISA || EISA || PCI) && SCSI help This is a driver for all SCSI host adapters manufactured by AdvanSys. It is documented in the kernel source in @@ -357,7 +358,7 @@ config SCSI_IN2000 tristate "Always IN2000 SCSI support" - depends on SCSI + depends on ISA && SCSI help This is support for an ISA bus SCSI host adapter. You'll find more information in . If it doesn't work @@ -369,10 +370,10 @@ say M here and read . The module will be called in2000. -# does not use pci dma and seems to be isa/onboard only for old machines +# does not use pci dma and seems to be onboard only for old machines config SCSI_AM53C974 tristate "AM53/79C974 PCI SCSI support" - depends on !X86_64 && SCSI && PCI + depends on X86 && PCI && SCSI ---help--- This is support for the AM53/79C974 SCSI host adapters. Please read for details. Also, the @@ -390,7 +391,7 @@ config SCSI_MEGARAID tristate "AMI MegaRAID support" - depends on SCSI + depends on PCI && SCSI help This driver supports the AMI MegaRAID 418, 428, 438, 466, 762, 490 and 467 SCSI host adapters. @@ -402,7 +403,7 @@ config SCSI_BUSLOGIC tristate "BusLogic SCSI support" - depends on SCSI + depends on (PCI || ISA) && SCSI ---help--- This is support for BusLogic MultiMaster and FlashPoint SCSI Host Adapters. Consult the SCSI-HOWTO, available from @@ -436,7 +437,7 @@ config SCSI_DMX3191D tristate "DMX3191D SCSI support" - depends on SCSI && PCI + depends on PCI && SCSI help This is support for Domex DMX3191D SCSI Host Adapters. @@ -447,7 +448,7 @@ config SCSI_DTC3280 tristate "DTC3180/3280 SCSI support" - depends on SCSI && ISA + depends on ISA && SCSI help This is support for DTC 3180/3280 SCSI Host Adapters. Please read the SCSI-HOWTO, available from @@ -461,7 +462,7 @@ config SCSI_EATA tristate "EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support" - depends on SCSI + depends on (ISA || EISA || PCI) && SCSI ---help--- This driver supports all EATA/DMA-compliant SCSI host adapters. DPT ISA and all EISA I/O addresses are probed looking for the "EATA" @@ -527,7 +528,7 @@ config SCSI_FUTURE_DOMAIN tristate "Future Domain 16xx SCSI/AHA-2920A support" - depends on SCSI + depends on (ISA || PCI) && SCSI ---help--- This is support for Future Domain's 16-bit SCSI host adapters (TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and @@ -563,7 +564,7 @@ config SCSI_GDTH tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support" - depends on SCSI + depends on (ISA || EISA || PCI) && SCSI ---help--- Formerly called GDT SCSI Disk Array Controller Support. @@ -579,7 +580,7 @@ config SCSI_GENERIC_NCR5380 tristate "Generic NCR5380/53c400 SCSI PIO support" - depends on SCSI + depends on ISA && SCSI ---help--- This is a driver for the old NCR 53c80 series of SCSI controllers on boards using PIO. Most boards such as the Trantor T130 fit this @@ -600,7 +601,7 @@ config SCSI_GENERIC_NCR5380_MMIO tristate "Generic NCR5380/53c400 SCSI MMIO support" - depends on SCSI + depends on ISA && SCSI ---help--- This is a driver for the old NCR 53c80 series of SCSI controllers on boards using memory mapped I/O. @@ -609,10 +610,11 @@ of the box, you may have to change some settings in . - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called g_NCR5380. If you want to compile it as - a module, say M here and read . + This driver is also available as a module ( = code which can + be inserted in and removed from the running kernel whenever + you want). The module will be called g_NCR5380_mmio. + If you want to compile it as a module, say M here and read + . config SCSI_GENERIC_NCR53C400 bool "Enable NCR53c400 extensions" @@ -699,7 +701,7 @@ config SCSI_IPS tristate "IBM ServeRAID support" - depends on X86 && SCSI && PCI + depends on X86 && PCI && SCSI ---help--- This is support for the IBM ServeRAID hardware RAID controllers. See @@ -715,7 +717,7 @@ config SCSI_INITIO tristate "Initio 9100U(W) support" - depends on SCSI && PCI + depends on PCI && SCSI help This is support for the Initio 91XXU(W) SCSI host adapter. Please read the SCSI-HOWTO, available from @@ -728,7 +730,7 @@ config SCSI_INIA100 tristate "Initio INI-A100U2W support" - depends on SCSI && PCI + depends on PCI && SCSI help This is support for the Initio INI-A100U2W SCSI host adapter. Please read the SCSI-HOWTO, available from @@ -828,7 +830,7 @@ config SCSI_NCR53C406A tristate "NCR53c406a SCSI support" - depends on SCSI && ISA + depends on ISA && SCSI help This is support for the NCR53c406a SCSI host adapter. For user configurable parameters, check out @@ -857,14 +859,12 @@ default y config SCSI_LASI700 - tristate "HP LASI SCSI support for 53c700/710" - depends on PARISC && SCSI + tristate "HP Lasi SCSI support for 53c700/710" + depends on GSC && SCSI help - This is a driver for the lasi baseboard in some parisc machines - which is based on the 53c700 chip. Will also support LASI subsystems - based on the 710 chip using 700 emulation mode. - - Unless you know you have a 53c700 or 53c710 based lasi, say N here + This is a driver for the SCSI controller in the Lasi chip found in + many PA-RISC workstations & servers. If you do not know whether you + have a Lasi chip, it is safe to say "Y" here. config 53C700_MEM_MAPPED bool @@ -876,72 +876,15 @@ depends on SCSI_LASI700 default y -config SCSI_NCR53C7xx - tristate "NCR53c7,8xx SCSI support" - depends on SCSI && PCI - ---help--- - This is a driver for the 53c7 and 8xx NCR family of SCSI - controllers, not to be confused with the NCR 5380 controllers. It - is explained in section 3.8 of the SCSI-HOWTO, available from - . If it doesn't work out - of the box, you may have to change some settings in - . Please read - for the available boot time - command line options. - - Note: there is another driver for the 53c8xx family of controllers - ("NCR53C8XX SCSI support" below). If you want to use them both, you - need to say M to both and build them as modules, but only one may be - active at a time. If you have a 53c8xx board, it's better to use the - other driver. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called 53c7,8xx. If you want to compile it as - a module, say M here and read . - -config SCSI_NCR53C7xx_sync - bool "always negotiate synchronous transfers" - depends on SCSI_NCR53C7xx - help - In general, this is good; however, it is a bit dangerous since there - are some broken SCSI devices out there. Take your chances. Safe bet - is N. - -config SCSI_NCR53C7xx_FAST - bool "allow FAST-SCSI [10MHz]" - depends on SCSI_NCR53C7xx - help - This will enable 10MHz FAST-SCSI transfers with your host - adapter. Some systems have problems with that speed, so it's safest - to say N here. - -config SCSI_NCR53C7xx_DISCONNECT - bool "allow DISCONNECT" - depends on SCSI_NCR53C7xx - help - This enables the disconnect/reconnect feature of the NCR SCSI - controller. When you say Y here, a slow SCSI device will not lock - the SCSI bus while processing a request, allowing simultaneous use - of e.g. a SCSI hard disk and SCSI tape or CD-ROM drive, and - providing much better performance when using slow and fast SCSI - devices at the same time. Some devices, however, do not operate - properly with this option enabled, and will cause your SCSI system - to hang, which might cause a system crash. The safe answer - therefore is to say N. - config SCSI_SYM53C8XX_2 tristate "SYM53C8XX Version 2 SCSI support" depends on PCI && SCSI ---help--- - This driver supports the whole NCR53C8XX/SYM53C8XX family of - PCI-SCSI controllers. It also supports the subset of LSI53C10XX - Ultra-160 controllers that are based on the SYM53C8XX SCRIPTS - language. It does not support LSI53C10XX Ultra-320 PCI-X SCSI - controllers. - - If your system has problems using this new major version of the - SYM53C8XX driver, you may switch back to driver version 1. + This driver supports the whole NCR53C8XX/SYM53C8XX family of + PCI-SCSI controllers. It also supports the subset of LSI53C10XX + Ultra-160 controllers that are based on the SYM53C8XX SCRIPTS + language. It does not support LSI53C10XX Ultra-320 PCI-X SCSI + controllers; you need to use the Fusion MPT driver for that. Please read for more information. @@ -1216,7 +1159,7 @@ config SCSI_PAS16 tristate "PAS16 SCSI support" - depends on SCSI && ISA + depends on ISA && SCSI ---help--- This is support for a SCSI host adapter. It is explained in section 3.10 of the SCSI-HOWTO, available from @@ -1231,7 +1174,7 @@ config SCSI_PCI2000 tristate "PCI2000 support" - depends on SCSI + depends on PCI && SCSI help This is support for the PCI2000I EIDE interface card which acts as a SCSI host adapter. Please read the SCSI-HOWTO, available from @@ -1244,7 +1187,7 @@ config SCSI_PCI2220I tristate "PCI2220i support" - depends on SCSI + depends on PCI && SCSI help This is support for the PCI2220i EIDE interface card which acts as a SCSI host adapter. Please read the SCSI-HOWTO, available from @@ -1257,7 +1200,7 @@ config SCSI_PSI240I tristate "PSI240i support" - depends on SCSI && ISA + depends on ISA && SCSI help This is support for the PSI240i EIDE interface card which acts as a SCSI host adapter. Please read the SCSI-HOWTO, available from @@ -1270,7 +1213,7 @@ config SCSI_QLOGIC_FAS tristate "Qlogic FAS SCSI support" - depends on SCSI && ISA + depends on ISA && SCSI ---help--- This is a driver for the ISA, VLB, and PCMCIA versions of the Qlogic FastSCSI! cards as well as any other card based on the FASXX chip @@ -1340,6 +1283,20 @@ The module will be called qla1280. If you want to compile it as a module, say M here and read . +config SCSI_QLOGICPTI + tristate "PTI Qlogic, ISP Driver" + depends on SBUS && SCSI + help + This driver supports SBUS SCSI controllers from PTI or QLogic. These + controllers are known under Solaris as qpti and in the openprom as + PTI,ptisp or QLGC,isp. Note that PCI QLogic SCSI controllers are + driven by a different driver. + + This support is also available as a module called qlogicpti ( = + code which can be inserted in and removed from the running kernel + whenever you want). If you want to compile it as a module, say M + here and read . + config SCSI_SEAGATE tristate "Seagate ST-02 and Future Domain TMC-8xx SCSI support" depends on X86 && ISA && SCSI @@ -1355,10 +1312,10 @@ The module will be called seagate. If you want to compile it as a module, say M here and read . -# definitely looks note 64bit safe: +# definitely looks not 64bit safe: config SCSI_SIM710 tristate "Simple 53c710 SCSI support (Compaq, NCR machines)" - depends on (EISA || MCA && !X86_64) && SCSI + depends on (EISA || MCA) && SCSI ---help--- This driver for NCR53c710 based SCSI host adapters. @@ -1371,7 +1328,7 @@ config SCSI_SYM53C416 tristate "Symbios 53c416 SCSI support" - depends on SCSI && ISA + depends on ISA && SCSI ---help--- This is support for the sym53c416 SCSI host adapter, the SCSI adapter that comes with some HP scanners. This driver requires that @@ -1392,7 +1349,7 @@ config SCSI_DC395x tristate "Tekram DC395(U/UW/F) and DC315(U) SCSI support (EXPERIMENTAL)" - depends on EXPERIMENTAL && PCI && SCSI + depends on PCI && SCSI && EXPERIMENTAL ---help--- This driver supports PCI SCSI host adapters based on the ASIC TRM-S1040 chip, e.g Tekram DC395(U/UW/F) and DC315(U) variants. @@ -1446,7 +1403,7 @@ config SCSI_T128 tristate "Trantor T128/T128F/T228 SCSI support" - depends on SCSI && ISA + depends on ISA && SCSI ---help--- This is support for a SCSI host adapter. It is explained in section 3.11 of the SCSI-HOWTO, available from @@ -1463,7 +1420,7 @@ config SCSI_U14_34F tristate "UltraStor 14F/34F support" - depends on SCSI + depends on ISA && SCSI ---help--- This is support for the UltraStor 14F and 34F SCSI-2 host adapters. The source at contains some @@ -1533,7 +1490,7 @@ config SCSI_NSP32 tristate "Workbit NinjaSCSI-32Bi/UDE support" - depends on SCSI + depends on PCI && SCSI help This is support for the Workbit NinjaSCSI-32Bi/UDE PCI/Cardbus SCSI host adapter. Please read the SCSI-HOWTO, available from @@ -1606,7 +1563,7 @@ config JAZZ_ESP bool "MIPS JAZZ FAS216 SCSI support" - depends on MIPS_JAZZ + depends on MIPS_JAZZ && SCSI help This is the driver for the onboard SCSI host adapter of MIPS Magnum 4000, Acer PICA, Olivetti M700-10 and a few other identical OEM @@ -1625,7 +1582,7 @@ config A4000T_SCSI bool "A4000T SCSI support (EXPERIMENTAL)" - depends on AMIGA && EXPERIMENTAL + depends on AMIGA && SCSI && EXPERIMENTAL help Support for the NCR53C710 SCSI controller on the Amiga 4000T. @@ -1695,7 +1652,7 @@ config A4091_SCSI bool "A4091 SCSI support (EXPERIMENTAL)" - depends on ZORRO && EXPERIMENTAL + depends on ZORRO && SCSI && EXPERIMENTAL help Support for the NCR53C710 chip on the Amiga 4091 Z3 SCSI2 controller (1993). Very obscure -- the 4091 was part of an Amiga 4000 upgrade @@ -1703,7 +1660,7 @@ config WARPENGINE_SCSI bool "WarpEngine SCSI support (EXPERIMENTAL)" - depends on ZORRO && EXPERIMENTAL + depends on ZORRO && SCSI && EXPERIMENTAL help Support for MacroSystem Development's WarpEngine Amiga SCSI-2 controller. Info at @@ -1711,19 +1668,142 @@ config BLZ603EPLUS_SCSI bool "Blizzard PowerUP 603e+ SCSI (EXPERIMENTAL)" - depends on ZORRO && EXPERIMENTAL + depends on ZORRO && SCSI && EXPERIMENTAL help If you have an Amiga 1200 with a Phase5 Blizzard PowerUP 603e+ accelerator, say Y. Otherwise, say N. config OKTAGON_SCSI tristate "BSC Oktagon SCSI support (EXPERIMENTAL)" - depends on ZORRO && EXPERIMENTAL && SCSI + depends on ZORRO && SCSI && EXPERIMENTAL help If you have the BSC Oktagon SCSI disk controller for the Amiga, say Y to this question. If you're in doubt about whether you have one, see the picture at . + +config ATARI_SCSI + tristate "Atari native SCSI support" + depends on ATARI && SCSI + ---help--- + If you have an Atari with built-in NCR5380 SCSI controller (TT, + Falcon, ...) say Y to get it supported. Of course also, if you have + a compatible SCSI controller (e.g. for Medusa). This driver is also + available as a module ( = code which can be inserted in and removed + from the running kernel whenever you want). The module is called + atari_scsi. If you want to compile it as a module, say M here and + read . This driver supports both + styles of NCR integration into the system: the TT style (separate + DMA), and the Falcon style (via ST-DMA, replacing ACSI). It does + NOT support other schemes, like in the Hades (without DMA). + +config ATARI_SCSI_TOSHIBA_DELAY + bool "Long delays for Toshiba CD-ROMs" + depends on ATARI_SCSI + help + This option increases the delay after a SCSI arbitration to + accommodate some flaky Toshiba CD-ROM drives. Say Y if you intend to + use a Toshiba CD-ROM drive; otherwise, the option is not needed and + would impact performance a bit, so say N. + +config ATARI_SCSI_RESET_BOOT + bool "Reset SCSI-devices at boottime" + depends on ATARI_SCSI + help + Reset the devices on your Atari whenever it boots. This makes the + boot process fractionally longer but may assist recovery from errors + that leave the devices with SCSI operations partway completed. + +config TT_DMA_EMUL + bool "Hades SCSI DMA emulator" + depends on ATARI_SCSI && HADES + help + This option enables code which emulates the TT SCSI DMA chip on the + Hades. This increases the SCSI transfer rates at least ten times + compared to PIO transfers. + +config MAC_SCSI + bool "Macintosh NCR5380 SCSI" + depends on MAC && SCSI + help + This is the NCR 5380 SCSI controller included on most of the 68030 + based Macintoshes. If you have one of these say Y and read the + SCSI-HOWTO, available from + . + +config SCSI_MAC_ESP + tristate "Macintosh NCR53c9[46] SCSI" + depends on MAC && SCSI + help + This is the NCR 53c9x SCSI controller found on most of the 68040 + based Macintoshes. If you have one of these say Y and read the + SCSI-HOWTO, available from + . + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called mac_esp. If you want to compile it as + a module, say M here and read . + +config MVME147_SCSI + bool "WD33C93 SCSI driver for MVME147" + depends on MVME147 && SCSI + help + Support for the on-board SCSI controller on the Motorola MVME147 + single-board computer. + +config MVME16x_SCSI + bool "NCR53C710 SCSI driver for MVME16x" + depends on MVME16x && SCSI + help + The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710 + SCSI controller chip. Almost everyone using one of these boards + will want to say Y to this question. + +config BVME6000_SCSI + bool "NCR53C710 SCSI driver for BVME6000" + depends on BVME6000 && SCSI + help + The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710 + SCSI controller chip. Almost everyone using one of these boards + will want to say Y to this question. + +config SCSI_NCR53C7xx_FAST + bool "allow FAST-SCSI [10MHz]" + depends on A4000T_SCSI || A4091_SCSI || BLZ603EPLUS_SCSI || WARPENGINE_SCSI || MVME16x_SCSI || BVME6000_SCSI + help + This will enable 10MHz FAST-SCSI transfers with your host + adapter. Some systems have problems with that speed, so it's safest + to say N here. + +config SUN3_SCSI + tristate "Sun3 NCR5380 SCSI" + depends on SUN3 && SCSI + help + This option will enable support for the OBIO (onboard io) NCR5380 + SCSI controller found in the Sun 3/50 and 3/60, as well as for + "Sun3" type VME scsi controllers also based on the NCR5380. + General Linux information on the Sun 3 series (now discontinued) + is at . + +config SUN3X_ESP + bool "Sun3x ESP SCSI" + depends on SUN3X && SCSI + help + The ESP was an on-board SCSI controller used on Sun 3/80 + machines. Say Y here to compile in support for it. + +config SCSI_SUNESP + tristate "Sparc ESP Scsi Driver" + depends on SBUS && SCSI + help + This is the driver for the Sun ESP SCSI host adapter. The ESP + chipset is present in most SPARC SBUS-based computers. + + This support is also available as a module called esp ( = code + which can be inserted in and removed from the running kernel + whenever you want). If you want to compile it as a module, say M + here and read . config SCSI_PC980155 tristate "NEC PC-9801-55 SCSI support" diff -Nru a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c --- a/drivers/scsi/NCR53c406a.c Sat Apr 26 07:28:14 2003 +++ b/drivers/scsi/NCR53c406a.c Sat Jun 14 08:39:19 2003 @@ -170,7 +170,6 @@ /* Static function prototypes */ static void NCR53c406a_intr(int, void *, struct pt_regs *); static irqreturn_t do_NCR53c406a_intr(int, void *, struct pt_regs *); -static void internal_done(Scsi_Cmnd *); static void wait_intr(void); static void chip_init(void); static void calc_port_addr(void); @@ -205,8 +204,6 @@ #endif static Scsi_Cmnd *current_SC; -static volatile int internal_done_flag; -static volatile int internal_done_errcode; static char info_msg[256]; /* ================================================================= */ @@ -544,10 +541,13 @@ } else if (irq_level == 0) { tpnt->can_queue = 0; DEB(printk("NCR53c406a: No interrupts detected\n")); + printk("NCR53c406a driver no longer supports polling interface\n"); + printk("Please email linux-scsi@vger.kernel.org\n"); + #if USE_DMA printk("NCR53c406a: No interrupts found and DMA mode defined. Giving up.\n"); - goto err_free_scsi; #endif /* USE_DMA */ + goto err_free_scsi; } else { DEB(printk("NCR53c406a: Shouldn't get here!\n")); goto err_free_scsi; @@ -590,6 +590,21 @@ return 0; } +static int NCR53c406a_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); +#ifdef USE_DMA + if (shost->dma_channel != 0xff) + free_dma(shost->dma_channel); +#endif + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + + scsi_unregister(shost); + return 0; +} + /* called from init/main.c */ static void __init NCR53c406a_setup(char *str, int *ints) { @@ -649,13 +664,6 @@ return (info_msg); } -static void internal_done(Scsi_Cmnd * SCpnt) -{ - internal_done_errcode = SCpnt->result; - ++internal_done_flag; -} - - static void wait_intr(void) { unsigned long i = jiffies + WATCHDOG; @@ -709,21 +717,6 @@ return 0; } -static int NCR53c406a_command(Scsi_Cmnd * SCpnt) -{ - DEB(printk("NCR53c406a_command called\n")); - NCR53c406a_queue(SCpnt, internal_done); - if (irq_level) - while (!internal_done_flag) - cpu_relax(); - else /* interrupts not supported */ - while (!internal_done_flag) - wait_intr(); - - internal_done_flag = 0; - return internal_done_errcode; -} - static int NCR53c406a_abort(Scsi_Cmnd * SCpnt) { DEB(printk("NCR53c406a_abort called\n")); @@ -1074,8 +1067,8 @@ .proc_name = "NCR53c406a" /* proc_name */, .name = "NCR53c406a" /* name */, .detect = NCR53c406a_detect /* detect */, + .release = NCR53c406a_release, .info = NCR53c406a_info /* info */, - .command = NCR53c406a_command /* command */, .queuecommand = NCR53c406a_queue /* queuecommand */, .eh_abort_handler = NCR53c406a_abort /* abort */, .eh_bus_reset_handler = NCR53c406a_bus_reset /* reset */, diff -Nru a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c --- a/drivers/scsi/NCR_D700.c Fri May 30 10:45:36 2003 +++ b/drivers/scsi/NCR_D700.c Tue Jun 17 13:27:44 2003 @@ -197,6 +197,8 @@ hostdata->differential = (((1<clock = NCR_D700_CLOCK_MHZ; + NCR_700_set_io_mapped(hostdata); + /* and register the siop */ host = NCR_700_detect(&NCR_D700_driver_template, hostdata); if (!host) { @@ -223,7 +225,7 @@ return 0; irq_failed: - scsi_unregister(host); + scsi_host_put(host); NCR_700_release(host); detect_failed: release_region(host->base, 64); diff -Nru a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c --- a/drivers/scsi/aha152x.c Mon May 12 07:26:11 2003 +++ b/drivers/scsi/aha152x.c Sun Jun 8 12:18:41 2003 @@ -1515,16 +1515,6 @@ up(SCSEM(SCpnt)); } -static int aha152x_command(Scsi_Cmnd * SCpnt) -{ - DECLARE_MUTEX_LOCKED(sem); - - aha152x_internal_queue(SCpnt, &sem, 0, 0, internal_done); - down(&sem); - - return SUCCESS; -} - /* * Abort a command * @@ -3876,7 +3866,6 @@ .proc_name = "aha152x", .proc_info = aha152x_proc_info, .detect = aha152x_detect, - .command = aha152x_command, .queuecommand = aha152x_queue, .eh_abort_handler = aha152x_abort, .eh_device_reset_handler = aha152x_device_reset, diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c --- a/drivers/scsi/aha1542.c Thu May 8 11:24:14 2003 +++ b/drivers/scsi/aha1542.c Sun Jun 8 12:18:41 2003 @@ -774,23 +774,6 @@ return 0; } -static void internal_done(Scsi_Cmnd * SCpnt) -{ - SCpnt->SCp.Status++; -} - -static int aha1542_command(Scsi_Cmnd * SCpnt) -{ - DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n")); - - aha1542_queuecommand(SCpnt, internal_done); - - SCpnt->SCp.Status = 0; - while (!SCpnt->SCp.Status) - barrier(); - return SCpnt->result; -} - /* Initialize mailboxes */ static void setup_mailboxes(int bse, struct Scsi_Host *shpnt) { @@ -1325,6 +1308,18 @@ return count; } +static int aha1542_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->dma_channel != 0xff) + free_dma(shost->dma_channel); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + static int aha1542_restart(struct Scsi_Host *shost) { int i; @@ -1817,7 +1812,7 @@ .proc_name = "aha1542", .name = "Adaptec 1542", .detect = aha1542_detect, - .command = aha1542_command, + .release = aha1542_release, .queuecommand = aha1542_queuecommand, .eh_abort_handler = aha1542_abort, .eh_device_reset_handler= aha1542_dev_reset, diff -Nru a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c --- a/drivers/scsi/aha1740.c Mon May 12 07:26:11 2003 +++ b/drivers/scsi/aha1740.c Tue Jun 17 15:36:55 2003 @@ -102,6 +102,7 @@ if (len > length) len = length; return len; +} static int aha1740_makecode(unchar *sense, unchar *status) @@ -476,23 +477,6 @@ return 0; } -static void internal_done(Scsi_Cmnd * SCpnt) -{ - SCpnt->SCp.Status++; -} - -static int aha1740_command(Scsi_Cmnd * SCpnt) -{ - aha1740_queuecommand(SCpnt, internal_done); - SCpnt->SCp.Status = 0; - while (!SCpnt->SCp.Status) - { - cpu_relax(); - barrier(); - } - return SCpnt->result; -} - /* Query the board for its irq_level. Nothing else matters in enhanced mode on an EISA bus. */ @@ -567,6 +551,16 @@ return count; } +static int aha1740_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + static int aha1740_biosparam(struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int* ip) { @@ -596,7 +590,7 @@ .proc_info = aha1740_proc_info, .name = "Adaptec 174x (EISA)", .detect = aha1740_detect, - .command = aha1740_command, + .release = aha1740_release, .queuecommand = aha1740_queuecommand, .bios_param = aha1740_biosparam, .can_queue = AHA1740_ECBS, diff -Nru a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c --- a/drivers/scsi/aic7xxx/aic79xx_osm.c Fri May 23 10:58:23 2003 +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c Mon Jun 2 17:42:21 2003 @@ -2098,7 +2098,7 @@ u_long target; template->name = ahd->description; - host = scsi_register(template, sizeof(struct ahd_softc *)); + host = scsi_host_alloc(template, sizeof(struct ahd_softc *)); if (host == NULL) return (ENOMEM); @@ -2308,7 +2308,7 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) scsi_remove_host(ahd->platform_data->host); #endif - scsi_unregister(ahd->platform_data->host); + scsi_host_put(ahd->platform_data->host); } /* destroy all of the device and target objects */ diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c Fri May 23 12:29:22 2003 +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c Mon Jun 2 17:42:21 2003 @@ -1725,7 +1725,7 @@ u_int targ_offset; template->name = ahc->description; - host = scsi_register(template, sizeof(struct ahc_softc *)); + host = scsi_host_alloc(template, sizeof(struct ahc_softc *)); if (host == NULL) return (ENOMEM); @@ -1978,7 +1978,7 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) scsi_remove_host(ahc->platform_data->host); #endif - scsi_unregister(ahc->platform_data->host); + scsi_host_put(ahc->platform_data->host); } /* destroy all of the device and target objects */ diff -Nru a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c --- a/drivers/scsi/amiga7xx.c Sun Feb 9 07:21:12 2003 +++ b/drivers/scsi/amiga7xx.c Mon Jun 2 17:27:44 2003 @@ -134,9 +134,22 @@ return num; } +static int amiga7xx_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->dma_channel != 0xff) + free_dma(shost->dma_channel); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + static Scsi_Host_Template driver_template = { .name = "Amiga NCR53c710 SCSI", .detect = amiga7xx_detect, + .release = amiga7xx_release, .queuecommand = NCR53c7xx_queue_command, .abort = NCR53c7xx_abort, .reset = NCR53c7xx_reset, diff -Nru a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c --- a/drivers/scsi/arm/acornscsi.c Mon May 19 19:40:43 2003 +++ b/drivers/scsi/arm/acornscsi.c Mon Jun 2 17:42:21 2003 @@ -2993,7 +2993,7 @@ AS_Host *ashost; int ret = -ENOMEM; - host = scsi_register(&acornscsi_template, sizeof(AS_Host)); + host = scsi_host_alloc(&acornscsi_template, sizeof(AS_Host)); if (!host) goto out; @@ -3060,7 +3060,7 @@ err_2: release_region(host->io_port + 0x800, 2); err_1: - scsi_unregister(host); + scsi_host_put(host); out: return ret; } @@ -3089,6 +3089,7 @@ msgqueue_free(&ashost->scsi.msgs); queue_free(&ashost->queues.disconnected); queue_free(&ashost->queues.issue); + scsi_host_put(host); } static const struct ecard_id acornscsi_cids[] = { diff -Nru a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c --- a/drivers/scsi/arm/arxescsi.c Mon May 19 19:40:44 2003 +++ b/drivers/scsi/arm/arxescsi.c Sun Jun 8 12:18:41 2003 @@ -264,7 +264,6 @@ .proc_info = arxescsi_proc_info, .name = "ARXE SCSI card", .info = arxescsi_info, - .command = fas216_command, .queuecommand = fas216_queue_command, .eh_host_reset_handler = fas216_eh_host_reset, .eh_bus_reset_handler = fas216_eh_bus_reset, diff -Nru a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c --- a/drivers/scsi/arm/cumana_1.c Mon May 19 19:40:44 2003 +++ b/drivers/scsi/arm/cumana_1.c Mon Jun 2 17:42:21 2003 @@ -262,7 +262,7 @@ struct Scsi_Host *host; int ret = -ENOMEM; - host = scsi_register(&cumanascsi_template, sizeof(struct NCR5380_hostdata)); + host = scsi_host_alloc(&cumanascsi_template, sizeof(struct NCR5380_hostdata)); if (!host) goto out; @@ -304,7 +304,7 @@ out_release: release_region(host->io_port, host->n_io_port); out_free: - scsi_unregister(host); + scsi_host_put(host); out: return ret; } @@ -318,7 +318,7 @@ scsi_remove_host(host); free_irq(host->irq, host); release_region(host->io_port, host->n_io_port); - scsi_unregister(host); + scsi_host_put(host); } static const struct ecard_id cumanascsi1_cids[] = { diff -Nru a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c --- a/drivers/scsi/arm/cumana_2.c Mon May 19 19:40:45 2003 +++ b/drivers/scsi/arm/cumana_2.c Sun Jun 8 12:18:41 2003 @@ -386,7 +386,6 @@ .proc_info = cumanascsi_2_proc_info, .name = "Cumana SCSI II", .info = cumanascsi_2_info, - .command = fas216_command, .queuecommand = fas216_queue_command, .eh_host_reset_handler = fas216_eh_host_reset, .eh_bus_reset_handler = fas216_eh_bus_reset, diff -Nru a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c --- a/drivers/scsi/arm/ecoscsi.c Tue May 27 07:52:55 2003 +++ b/drivers/scsi/arm/ecoscsi.c Mon Jun 2 17:42:21 2003 @@ -177,7 +177,7 @@ static int __init ecoscsi_init(void) { - host = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); + host = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata)); if (!host) return 0; @@ -211,7 +211,7 @@ release_reg: release_region(host->io_port, host->n_io_port); unregister_scsi: - scsi_unregister(host); + scsi_host_put(host); return -ENODEV; } @@ -224,7 +224,7 @@ if (shpnt->io_port) release_region(shpnt->io_port, shpnt->n_io_port); - scsi_unregister(host); + scsi_host_put(host); return 0; } diff -Nru a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c --- a/drivers/scsi/arm/eesox.c Mon May 19 19:40:46 2003 +++ b/drivers/scsi/arm/eesox.c Sun Jun 8 12:18:41 2003 @@ -492,7 +492,6 @@ .proc_info = eesoxscsi_proc_info, .name = "EESOX SCSI", .info = eesoxscsi_info, - .command = fas216_command, .queuecommand = fas216_queue_command, .eh_host_reset_handler = fas216_eh_host_reset, .eh_bus_reset_handler = fas216_eh_bus_reset, diff -Nru a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c --- a/drivers/scsi/arm/fas216.c Sat May 17 06:52:33 2003 +++ b/drivers/scsi/arm/fas216.c Sun Jun 8 12:18:41 2003 @@ -225,8 +225,7 @@ printk(" dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n", info->dma.transfer_type, info->dma.setup, info->dma.pseudo, info->dma.stop); - printk(" internal_done=%X magic_end=%lX }\n", - info->internal_done, info->magic_end); + printk(" magic_end=%lX }\n", info->magic_end); } #ifdef CHECK_STRUCTURE @@ -2253,74 +2252,6 @@ return result; } -/** - * fas216_internal_done - trigger restart of a waiting thread in fas216_command - * @SCpnt: Command to wake - * - * Trigger restart of a waiting thread in fas216_command - */ -static void fas216_internal_done(Scsi_Cmnd *SCpnt) -{ - FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; - - fas216_checkmagic(info); - - info->internal_done = 1; -} - -/** - * fas216_command - queue a command for adapter to process. - * @SCpnt: Command to queue - * - * Queue a command for adapter to process. - * Returns: scsi result code. - * Notes: io_request_lock is held, interrupts are disabled. - */ -int fas216_command(Scsi_Cmnd *SCpnt) -{ - FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; - - fas216_checkmagic(info); - - /* - * We should only be using this if we don't have an interrupt. - * Provide some "incentive" to use the queueing code. - */ - if (info->scsi.irq != NO_IRQ) - BUG(); - - info->internal_done = 0; - fas216_queue_command(SCpnt, fas216_internal_done); - - /* - * This wastes time, since we can't return until the command is - * complete. We can't sleep either since we may get re-entered! - * However, we must re-enable interrupts, or else we'll be - * waiting forever. - */ - spin_unlock_irq(info->host->host_lock); - - while (!info->internal_done) { - /* - * If we don't have an IRQ, then we must poll the card for - * it's interrupt, and use that to call this driver's - * interrupt routine. That way, we keep the command - * progressing. Maybe we can add some inteligence here - * and go to sleep if we know that the device is going - * to be some time (eg, disconnected). - */ - if (fas216_readb(info, REG_STAT) & STAT_INT) { - spin_lock_irq(info->host->host_lock); - fas216_intr(info); - spin_unlock_irq(info->host->host_lock); - } - } - - spin_lock_irq(info->host->host_lock); - - return SCpnt->result; -} - /* * Error handler timeout function. Indicate that we timed out, * and wake up any error handler process so it can continue. @@ -2942,6 +2873,7 @@ scsi_remove_host(host); fas216_writeb(info, REG_CMD, CMD_RESETCHIP); + scsi_host_put(host); } /** diff -Nru a/drivers/scsi/arm/fas216.h b/drivers/scsi/arm/fas216.h --- a/drivers/scsi/arm/fas216.h Thu May 15 17:33:17 2003 +++ b/drivers/scsi/arm/fas216.h Sun Jun 8 12:18:41 2003 @@ -310,8 +310,6 @@ } dma; /* miscellaneous */ - int internal_done; /* flag to indicate request done */ - unsigned long magic_end; } FAS216_Info; @@ -336,13 +334,6 @@ * Returns : 0 - success, else error */ extern int fas216_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); - -/* Function: int fas216_command (Scsi_Cmnd *SCpnt) - * Purpose : queue a command for adapter to process. - * Params : SCpnt - Command to queue - * Returns : scsi result code - */ -extern int fas216_command (Scsi_Cmnd *); /* Function: irqreturn_t fas216_intr (FAS216_Info *info) * Purpose : handle interrupts from the interface to progress a command diff -Nru a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c --- a/drivers/scsi/arm/oak.c Mon May 19 19:40:46 2003 +++ b/drivers/scsi/arm/oak.c Mon Jun 2 17:42:21 2003 @@ -135,7 +135,7 @@ struct Scsi_Host *host; int ret = -ENOMEM; - host = scsi_register(&oakscsi_template, sizeof(struct NCR5380_hostdata)); + host = scsi_host_alloc(&oakscsi_template, sizeof(struct NCR5380_hostdata)); if (!host) goto out; @@ -163,7 +163,7 @@ release_region(host->io_port, host->n_io_port); unreg: - scsi_unregister(host); + scsi_host_put(host); out: return ret; } @@ -176,7 +176,7 @@ scsi_remove_host(host); release_region(host->io_port, host->n_io_port); - scsi_unregister(host); + scsi_host_put(host); } static const struct ecard_id oakscsi_cids[] = { diff -Nru a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c --- a/drivers/scsi/arm/powertec.c Mon May 19 19:40:47 2003 +++ b/drivers/scsi/arm/powertec.c Sun Jun 8 12:18:41 2003 @@ -296,7 +296,6 @@ .proc_info = powertecscsi_proc_info, .name = "PowerTec SCSI", .info = powertecscsi_info, - .command = fas216_command, .queuecommand = fas216_queue_command, .eh_host_reset_handler = fas216_eh_host_reset, .eh_bus_reset_handler = fas216_eh_bus_reset, diff -Nru a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c --- a/drivers/scsi/atp870u.c Mon Jun 9 16:02:25 2003 +++ b/drivers/scsi/atp870u.c Wed Jun 11 20:06:30 2003 @@ -829,25 +829,6 @@ } -static void internal_done(Scsi_Cmnd * SCpnt) -{ - SCpnt->SCp.Status++; -} - -static int atp870u_command(Scsi_Cmnd * SCpnt) -{ - - atp870u_queuecommand(SCpnt, internal_done); - - SCpnt->SCp.Status = 0; - while (!SCpnt->SCp.Status) - { - cpu_relax(); - barrier(); - } - return SCpnt->result; -} - static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val) { unsigned int tmport; @@ -2728,7 +2709,6 @@ .detect = atp870u_detect, .release = atp870u_release, .info = atp870u_info, - .command = atp870u_command, .queuecommand = atp870u_queuecommand, .eh_abort_handler = atp870u_abort, .bios_param = atp870u_biosparam, diff -Nru a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h --- a/drivers/scsi/atp870u.h Mon May 12 07:26:11 2003 +++ b/drivers/scsi/atp870u.h Sun Jun 8 12:18:41 2003 @@ -18,7 +18,6 @@ #define MAX_SENSE 14 static int atp870u_detect(Scsi_Host_Template *); -static int atp870u_command(Scsi_Cmnd *); static int atp870u_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); static int atp870u_abort(Scsi_Cmnd *); static int atp870u_biosparam(struct scsi_device *, struct block_device *, diff -Nru a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c --- a/drivers/scsi/blz1230.c Wed Feb 5 09:05:18 2003 +++ b/drivers/scsi/blz1230.c Sun Jun 8 12:18:41 2003 @@ -334,7 +334,6 @@ .name = "Blizzard1230 SCSI IV", .detect = blz1230_esp_detect, .release = blz1230_esp_release, - .command = esp_command, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, .eh_bus_reset_handler = esp_reset, diff -Nru a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c --- a/drivers/scsi/bvme6000.c Wed Nov 20 03:36:29 2002 +++ b/drivers/scsi/bvme6000.c Mon Jun 2 17:27:44 2003 @@ -51,9 +51,22 @@ return 1; } +static int mvme6000_scsi_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->dma_channel != 0xff) + free_dma(shost->dma_channel); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + static Scsi_Host_Template driver_template = { .name = "BVME6000 NCR53c710 SCSI", .detect = bvme6000_scsi_detect, + .release = bvme6000_scsi_release, .queuecommand = NCR53c7xx_queue_command, .abort = NCR53c7xx_abort, .reset = NCR53c7xx_reset, diff -Nru a/drivers/scsi/constants.c b/drivers/scsi/constants.c --- a/drivers/scsi/constants.c Fri Jan 3 10:58:49 2003 +++ b/drivers/scsi/constants.c Sun Jun 1 14:27:22 2003 @@ -1004,16 +1004,14 @@ #endif } -void print_sense(const char * devclass, Scsi_Cmnd * SCpnt) +void print_sense(const char *devclass, struct scsi_cmnd *cmd) { - print_sense_internal(devclass, SCpnt->sense_buffer, - SCpnt->request); + print_sense_internal(devclass, cmd->sense_buffer, cmd->request); } -void print_req_sense(const char * devclass, Scsi_Request * SRpnt) +void print_req_sense(const char *devclass, struct scsi_request *sreq) { - print_sense_internal(devclass, SRpnt->sr_sense_buffer, - SRpnt->sr_request); + print_sense_internal(devclass, sreq->sr_sense_buffer, sreq->sr_request); } #if (CONSTANTS & CONST_MSG) @@ -1116,13 +1114,13 @@ return len; } -void print_Scsi_Cmnd (Scsi_Cmnd *cmd) { +void print_Scsi_Cmnd(struct scsi_cmnd *cmd) { printk("scsi%d : destination target %d, lun %d\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun); printk(" command = "); - print_command (cmd->cmnd); + print_command(cmd->cmnd); } #if (CONSTANTS & CONST_HOST) diff -Nru a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c --- a/drivers/scsi/dc395x.c Wed May 28 03:05:43 2003 +++ b/drivers/scsi/dc395x.c Fri Jun 6 04:28:47 2003 @@ -5726,9 +5726,9 @@ /* *$$$$$$$$$$$ MEMORY ALLOCATE FOR ADAPTER CONTROL BLOCK $$$$$$$$$$$$ */ - host = scsi_register(host_template, sizeof(struct AdapterCtlBlk)); + host = scsi_host_alloc(host_template, sizeof(struct AdapterCtlBlk)); if (!host) { - dprintkl(KERN_INFO, "pSH scsi_register ERROR\n"); + dprintkl(KERN_INFO, "pSH scsi_host_alloc ERROR\n"); return 0; } DC395x_print_eeprom_settings(index); @@ -5736,7 +5736,7 @@ pACB = (struct AdapterCtlBlk *) host->hostdata; if (DC395x_initACB(host, io_port, irq, index)) { - scsi_unregister(host); + scsi_host_put(host); return 0; } DC395x_print_config(pACB); @@ -5755,7 +5755,7 @@ } else { dprintkl(KERN_INFO, "DC395x_initAdapter initial ERROR\n"); - scsi_unregister(host); + scsi_host_put(host); host = NULL; } return host; diff -Nru a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c --- a/drivers/scsi/dec_esp.c Sun Dec 22 02:33:54 2002 +++ b/drivers/scsi/dec_esp.c Sun Jun 8 12:18:41 2003 @@ -109,13 +109,23 @@ int dec_esp_detect(Scsi_Host_Template * tpnt); +static int dec_esp_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + static Scsi_Host_Template driver_template = { .proc_name = "esp", .proc_info = &esp_proc_info, .name = "NCR53C94", .detect = dec_esp_detect, + .release = dec_esp_release, .info = esp_info, - .command = esp_command, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, .eh_bus_reset_handler = esp_reset, diff -Nru a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c --- a/drivers/scsi/dpt_i2o.c Sat Jun 14 16:16:14 2003 +++ b/drivers/scsi/dpt_i2o.c Mon Jun 16 17:22:17 2003 @@ -1949,26 +1949,6 @@ case I2ORESCANCMD: adpt_rescan(pHba); break; - case DPT_TARGET_BUSY & 0xFFFF: - case DPT_TARGET_BUSY: - { - TARGET_BUSY_T busy; - struct adpt_device* d; - - if (copy_from_user((void*)&busy, (void*)arg, sizeof(TARGET_BUSY_T))) { - return -EFAULT; - } - - d = adpt_find_device(pHba, busy.channel, busy.id, busy.lun); - if(d == NULL){ - return -ENODEV; - } - busy.isBusy = ((d->pScsi_dev) && (0 != d->pScsi_dev->access_count)) ? 1 : 0; - if (copy_to_user ((char*)arg, &busy, sizeof(busy))) { - return -EFAULT; - } - break; - } default: return -EINVAL; } @@ -2492,10 +2472,6 @@ printk(KERN_WARNING"%s: Device (%d,%d,%d) offline\n",pHba->name,pDev->scsi_channel,pDev->scsi_id,pDev->scsi_lun); if (pDev->pScsi_dev) { pDev->pScsi_dev->online = FALSE; - if (pDev->pScsi_dev->access_count) { - // A drive that was mounted is no longer there... bad! - printk(KERN_WARNING"%s:Mounted drive taken offline\n",pHba->name); - } } } } diff -Nru a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c --- a/drivers/scsi/dtc.c Sun May 4 02:56:43 2003 +++ b/drivers/scsi/dtc.c Mon Jun 2 17:27:45 2003 @@ -447,9 +447,20 @@ #include "NCR5380.c" +static int dtc_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + static Scsi_Host_Template driver_template = { .name = "DTC 3180/3280 ", .detect = dtc_detect, + .release = dtc_release, .queuecommand = dtc_queue_command, .eh_abort_handler = dtc_abort, .eh_bus_reset_handler = dtc_bus_reset, diff -Nru a/drivers/scsi/eata.c b/drivers/scsi/eata.c --- a/drivers/scsi/eata.c Mon Jun 9 16:03:59 2003 +++ b/drivers/scsi/eata.c Tue Jun 3 10:54:22 2003 @@ -1,6 +1,36 @@ /* * eata.c - Low-level driver for EATA/DMA SCSI host adapters. * + * 03 Jun 2003 Rev. 8.10 for linux-2.5.70 + * + Update for new IRQ API. + * + Use "goto" when appropriate. + * + Drop eata.h. + * + Update for new module_param API. + * + Module parameters can now be specified only in the + * same format as the kernel boot options. + * + * boot option old module param + * ----------- ------------------ + * addr,... io_port=addr,... + * lc:[y|n] linked_comm=[1|0] + * mq:xx max_queue_depth=xx + * tm:[0|1|2] tag_mode=[0|1|2] + * et:[y|n] ext_tran=[1|0] + * rs:[y|n] rev_scan=[1|0] + * ip:[y|n] isa_probe=[1|0] + * ep:[y|n] eisa_probe=[1|0] + * pp:[y|n] pci_probe=[1|0] + * + * A valid example using the new parameter format is: + * modprobe eata "eata=0x7410,0x230,lc:y,tm:0,mq:4,ep:n" + * + * which is equivalent to the old format: + * modprobe eata io_port=0x7410,0x230 linked_comm=1 tag_mode=0 \ + * max_queue_depth=4 eisa_probe=0 + * + * 12 Feb 2003 Rev. 8.04 for linux 2.5.60 + * + Release irq before calling scsi_register. + * * 12 Nov 2002 Rev. 8.02 for linux 2.5.47 * + Release driver_lock before calling scsi_register. * @@ -279,7 +309,7 @@ * This driver is based on the CAM (Common Access Method Committee) * EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol. * - * Copyright (C) 1994-2002 Dario Ballabio (ballabio_dario@emc.com) + * Copyright (C) 1994-2003 Dario Ballabio (ballabio_dario@emc.com) * * Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it * @@ -447,31 +477,8 @@ * the driver sets host->wish_block = TRUE for all ISA boards. */ -#include - -#define MAX_INT_PARAM 10 - -#if defined(MODULE) -#include - -MODULE_PARM(boot_options, "s"); -MODULE_PARM(io_port, "1-" __MODULE_STRING(MAX_INT_PARAM) "i"); -MODULE_PARM(linked_comm, "i"); -MODULE_PARM(link_statistics, "i"); -MODULE_PARM(max_queue_depth, "i"); -MODULE_PARM(tag_mode, "i"); -MODULE_PARM(ext_tran, "i"); -MODULE_PARM(rev_scan, "i"); -MODULE_PARM(isa_probe, "i"); -MODULE_PARM(eisa_probe, "i"); -MODULE_PARM(pci_probe, "i"); -MODULE_AUTHOR("Dario Ballabio"); - -#endif - #include #include -#include #include #include #include @@ -491,8 +498,31 @@ #include "hosts.h" #include #include -#include "eata.h" +static int eata2x_detect(Scsi_Host_Template *); +static int eata2x_release(struct Scsi_Host *); +static int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +static int eata2x_eh_abort(Scsi_Cmnd *); +static int eata2x_eh_host_reset(Scsi_Cmnd *); +static int eata2x_bios_param(struct scsi_device *, struct block_device *, + sector_t, int *); +static int eata2x_slave_configure(Scsi_Device *); + +static Scsi_Host_Template driver_template = { + .name = "EATA/DMA 2.0x rev. 8.10.00 ", + .detect = eata2x_detect, + .release = eata2x_release, + .queuecommand = eata2x_queuecommand, + .eh_abort_handler = eata2x_eh_abort, + .eh_device_reset_handler = NULL, + .eh_bus_reset_handler = NULL, + .eh_host_reset_handler = eata2x_eh_host_reset, + .bios_param = eata2x_bios_param, + .slave_configure = eata2x_slave_configure, + .this_id = 7, + .unchecked_isa_dma = 1, + .use_clustering = ENABLE_CLUSTERING + }; #if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD) #error "Adjust your defines" #endif @@ -818,7 +848,6 @@ static int link_statistics; static int ext_tran = FALSE; static int rev_scan = TRUE; -static char *boot_options; #if defined(CONFIG_SCSI_EATA_TAGGED_QUEUE) static int tag_mode = TAG_SIMPLE; @@ -856,6 +885,23 @@ static int pci_probe = FALSE; #endif +#define MAX_INT_PARAM 10 +#define MAX_BOOT_OPTIONS_SIZE 256 +static char boot_options[MAX_BOOT_OPTIONS_SIZE]; + +#if defined(MODULE) +#include +#include + +module_param_string(eata, boot_options, MAX_BOOT_OPTIONS_SIZE, 0); +MODULE_PARM_DESC(eata, " equivalent to the \"eata=...\" kernel boot option." \ +" Example: modprobe eata \"eata=0x7410,0x230,lc:y,tm:0,mq:4,ep:n\""); +MODULE_AUTHOR("Dario Ballabio"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("EATA/DMA SCSI Driver"); + +#endif + static int eata2x_slave_configure(Scsi_Device *dev) { int j, tqd, utqd; char *tag_suffix, *link_suffix; @@ -1011,19 +1057,20 @@ sprintf(name, "%s%d", driver_name, j); - if(!request_region(port_base, REGION_SIZE, driver_name)) { + if (!request_region(port_base, REGION_SIZE, driver_name)) { #if defined(DEBUG_DETECT) printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base); #endif - return FALSE; + goto fail; } + spin_lock_irq(&driver_lock); + if (do_dma(port_base, 0, READ_CONFIG_PIO)) { #if defined(DEBUG_DETECT) printk("%s: detect, do_dma failed at 0x%03lx.\n", name, port_base); #endif - release_region(port_base, REGION_SIZE); - return FALSE; + goto freelock; } /* Read the info structure */ @@ -1031,8 +1078,7 @@ #if defined(DEBUG_DETECT) printk("%s: detect, read_pio failed at 0x%03lx.\n", name, port_base); #endif - release_region(port_base, REGION_SIZE); - return FALSE; + goto freelock; } info.data_len = DEV2H(info.data_len); @@ -1048,15 +1094,13 @@ #if defined(DEBUG_DETECT) printk("%s: signature 0x%04x discarded.\n", name, info.sign); #endif - release_region(port_base, REGION_SIZE); - return FALSE; + goto freelock; } if (info.data_len < EATA_2_0A_SIZE) { printk("%s: config structure size (%d bytes) too short, detaching.\n", name, info.data_len); - release_region(port_base, REGION_SIZE); - return FALSE; + goto freelock; } else if (info.data_len == EATA_2_0A_SIZE) protocol_rev = 'A'; @@ -1097,8 +1141,7 @@ if (!info.haaval || info.ata) { printk("%s: address 0x%03lx, unusable %s board (%d%d), detaching.\n", name, port_base, bus_type, info.haaval, info.ata); - release_region(port_base, REGION_SIZE); - return FALSE; + goto freelock; } if (info.drqvld) { @@ -1145,16 +1188,13 @@ SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0), driver_name, (void *) &sha[j])) { printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); - release_region(port_base, REGION_SIZE); - return FALSE; + goto freelock; } if (subversion == ISA && request_dma(dma_channel, driver_name)) { printk("%s: unable to allocate DMA channel %u, detaching.\n", name, dma_channel); - free_irq(irq, &sha[j]); - release_region(port_base, REGION_SIZE); - return FALSE; + goto freeirq; } #if defined(FORCE_CONFIG) @@ -1166,8 +1206,7 @@ if (!cf) { printk("%s: config, pci_alloc_consistent failed, detaching.\n", name); - release_region(port_base, REGION_SIZE); - return FALSE; + goto freedma; } /* Set board configuration */ @@ -1178,8 +1217,7 @@ if (do_dma(port_base, cf_dma_addr, SET_CONFIG_DMA)) { printk("%s: busy timeout sending configuration, detaching.\n", name); pci_free_consistent(pdev, sizeof(struct eata_config), cf, cf_dma_addr); - release_region(port_base, REGION_SIZE); - return FALSE; + goto freedma; } } @@ -1191,13 +1229,7 @@ if (sh[j] == NULL) { printk("%s: unable to register host, detaching.\n", name); - - free_irq(irq, &sha[j]); - - if (subversion == ISA) free_dma(dma_channel); - - release_region(port_base, REGION_SIZE); - return FALSE; + goto freedma; } sh[j]->io_port = port_base; @@ -1268,6 +1300,8 @@ if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "BMST"); else sprintf(dma_name, "DMA %u", dma_channel); + spin_unlock_irq(&driver_lock); + for (i = 0; i < sh[j]->can_queue; i++) HD(j)->cp[i].cp_dma_addr = pci_map_single(HD(j)->pdev, &HD(j)->cp[i], sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL); @@ -1277,15 +1311,13 @@ sh[j]->sg_tablesize * sizeof(struct sg_list), (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) { printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i); - eata2x_release(sh[j]); - return FALSE; + goto release; } if (! (HD(j)->sp_cpu_addr = pci_alloc_consistent(HD(j)->pdev, sizeof(struct mssp), &HD(j)->sp_dma_addr))) { printk("%s: pci_alloc_consistent failed, detaching.\n", BN(j)); - eata2x_release(sh[j]); - return FALSE; + goto release; } if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN) @@ -1297,7 +1329,7 @@ tag_mode = TAG_ORDERED; if (j == 0) { - printk("EATA/DMA 2.0x: Copyright (C) 1994-2002 Dario Ballabio.\n"); + printk("EATA/DMA 2.0x: Copyright (C) 1994-2003 Dario Ballabio.\n"); printk("%s config options -> tm:%d, lc:%c, mq:%d, rs:%c, et:%c, "\ "ip:%c, ep:%c, pp:%c.\n", driver_name, tag_mode, YESNO(linked_comm), max_queue_depth, YESNO(rev_scan), @@ -1342,6 +1374,20 @@ } return TRUE; + +freedma: + if (subversion == ISA) free_dma(dma_channel); +freeirq: + free_irq(irq, &sha[j]); +freelock: + spin_unlock_irq(&driver_lock); + release_region(port_base, REGION_SIZE); +fail: + return FALSE; + +release: + eata2x_release(sh[j]); + return FALSE; } static void internal_setup(char *str, int *ints) { @@ -1440,11 +1486,9 @@ static int eata2x_detect(Scsi_Host_Template *tpnt) { unsigned int j = 0, k; - spin_lock_irq(&driver_lock); - tpnt->proc_name = "eata2x"; - if(boot_options) option_setup(boot_options); + if(strlen(boot_options)) option_setup(boot_options); #if defined(MODULE) /* io_port could have been modified when loading as a module */ @@ -1478,7 +1522,6 @@ } num_boards = j; - spin_unlock_irq(&driver_lock); return j; } @@ -2091,7 +2134,7 @@ } -static void ihdlr(int irq, unsigned int j) { +static irqreturn_t ihdlr(int irq, unsigned int j) { Scsi_Cmnd *SCpnt; unsigned int i, k, c, status, tstatus, reg; struct mssp *spp; @@ -2101,7 +2144,7 @@ panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq); /* Check if this board need to be serviced */ - if (!(inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED)) return; + if (!(inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED)) goto none; HD(j)->iocount++; @@ -2113,7 +2156,7 @@ reg = inb(sh[j]->io_port + REG_STATUS); printk("%s: ihdlr, busy timeout error, irq %d, reg 0x%x, count %d.\n", BN(j), irq, reg, HD(j)->iocount); - return; + goto none; } spp = &HD(j)->sp; @@ -2148,7 +2191,7 @@ printk("%s: ihdlr, bad spp->cpp_index %d, irq %d, reg 0x%x, count %d.\n", BN(j), spp->cpp_index, irq, reg, HD(j)->iocount); if (spp->eoc == FALSE || spp->cpp_index < 0 - || spp->cpp_index >= sh[j]->can_queue) return; + || spp->cpp_index >= sh[j]->can_queue) goto handled; /* Find the mailbox to be serviced on this board */ i = spp->cpp_index; @@ -2156,23 +2199,23 @@ cpp = &(HD(j)->cp[i]); #if defined(DEBUG_GENERATE_ABORTS) - if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) return; + if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) goto handled; #endif if (HD(j)->cp_stat[i] == IGNORE) { HD(j)->cp_stat[i] = FREE; - return; + goto handled; } else if (HD(j)->cp_stat[i] == LOCKED) { HD(j)->cp_stat[i] = FREE; printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i, HD(j)->iocount); - return; + goto handled; } else if (HD(j)->cp_stat[i] == FREE) { printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i, HD(j)->iocount); - return; + goto handled; } else if (HD(j)->cp_stat[i] == IN_RESET) printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i); @@ -2319,22 +2362,25 @@ if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq, HD(j)->iocount); - return; +handled: + return IRQ_HANDLED; +none: + return IRQ_NONE; } static irqreturn_t do_interrupt_handler(int irq, void *shap, - struct pt_regs *regs) { + struct pt_regs *regs) { unsigned int j; unsigned long spin_flags; + irqreturn_t ret; /* Check if the interrupt must be processed by this handler */ - if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) - return IRQ_NONE; + if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return IRQ_NONE; spin_lock_irqsave(sh[j]->host_lock, spin_flags); - ihdlr(irq, j); + ret = ihdlr(irq, j); spin_unlock_irqrestore(sh[j]->host_lock, spin_flags); - return IRQ_HANDLED; + return ret; } static int eata2x_release(struct Scsi_Host *shpnt) { @@ -2365,22 +2411,8 @@ return FALSE; } -static Scsi_Host_Template driver_template = { - .name = "EATA/DMA 2.0x rev. " EATA_VERSION " ", - .detect = eata2x_detect, - .release = eata2x_release, - .queuecommand = eata2x_queuecommand, - .eh_abort_handler = eata2x_eh_abort, - .eh_host_reset_handler = eata2x_eh_host_reset, - .bios_param = eata2x_bios_param, - .slave_configure = eata2x_slave_configure, - .this_id = 7, - .unchecked_isa_dma = 1, - .use_clustering = ENABLE_CLUSTERING, -}; #include "scsi_module.c" #ifndef MODULE __setup("eata=", option_setup); #endif /* end MODULE */ -MODULE_LICENSE("GPL"); diff -Nru a/drivers/scsi/eata.h b/drivers/scsi/eata.h --- a/drivers/scsi/eata.h Sun May 4 02:56:43 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,15 +0,0 @@ -/* - * eata.h - used by the low-level driver for EATA/DMA SCSI host adapters. - */ - -static int eata2x_detect(Scsi_Host_Template *); -static int eata2x_release(struct Scsi_Host *); -static int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -static int eata2x_eh_abort(Scsi_Cmnd *); -static int eata2x_eh_host_reset(Scsi_Cmnd *); -static int eata2x_bios_param(struct scsi_device *, struct block_device *, - sector_t, int *); -static int eata2x_slave_configure(Scsi_Device *); - -#define EATA_VERSION "8.03.00" - diff -Nru a/drivers/scsi/esp.c b/drivers/scsi/esp.c --- a/drivers/scsi/esp.c Mon May 26 18:54:35 2003 +++ b/drivers/scsi/esp.c Sun Jun 8 12:18:41 2003 @@ -1237,6 +1237,17 @@ return 0; } +/* this is clearly wrong for esp.. */ +static int esp_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + /* The info function will return whatever useful * information the developer sees fit. If not provided, then * the name field will be used instead. @@ -1871,15 +1882,6 @@ return 0; } -/* Only queuing supported in this ESP driver. */ -static int esp_command(Scsi_Cmnd *SCpnt) -{ - struct esp *esp = (struct esp *) SCpnt->device->host->hostdata; - - ESPLOG(("esp%d: esp_command() called...\n", esp->esp_id)); - return -1; -} - /* Dump driver state. */ static void esp_dump_cmd(Scsi_Cmnd *SCptr) { @@ -4384,17 +4386,16 @@ SDptr->hostdata = NULL; } - static Scsi_Host_Template driver_template = { .proc_name = "esp", .proc_info = esp_proc_info, .name = "Sun ESP 100/100a/200", .detect = esp_detect, + .release = esp_release, .slave_alloc = esp_slave_alloc, .slave_destroy = esp_slave_destroy, .release = esp_release, .info = esp_info, - .command = esp_command, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, .eh_bus_reset_handler = esp_reset, diff -Nru a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c --- a/drivers/scsi/fd_mcs.c Mon May 12 07:26:12 2003 +++ b/drivers/scsi/fd_mcs.c Sun Jun 8 12:18:41 2003 @@ -1186,24 +1186,6 @@ return 0; } -static void internal_done(Scsi_Cmnd * SCpnt) -{ - /* flag it done */ - SCpnt->host_scribble = (unsigned char *) 1; -} - -int fd_mcs_command(Scsi_Cmnd * SCpnt) -{ - fd_mcs_queue(SCpnt, internal_done); - /* host_scribble is used for status here */ - SCpnt->host_scribble = NULL; - while (!SCpnt->host_scribble) { - cpu_relax(); - barrier(); - } - return SCpnt->result; -} - #if DEBUG_ABORT || DEBUG_RESET static void fd_mcs_print_info(Scsi_Cmnd * SCpnt) { @@ -1431,7 +1413,6 @@ .detect = fd_mcs_detect, .release = fd_mcs_release, .info = fd_mcs_info, - .command = fd_mcs_command, .queuecommand = fd_mcs_queue, .eh_abort_handler = fd_mcs_abort, .eh_bus_reset_handler = fd_mcs_bus_reset, diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c --- a/drivers/scsi/fdomain.c Mon May 12 07:26:12 2003 +++ b/drivers/scsi/fdomain.c Sun Jun 8 12:18:41 2003 @@ -255,11 +255,6 @@ be increased by changing this value to values which are close to 2. Please let me know if you try any different values. - DO_DETECT: This activates some old scan code which was needed before the - high level drivers got fixed. If you are having trouble with the driver, - turning this on should not hurt, and might help. Please let me know if - this is the case, since this code will be removed from future drivers. - RESELECTION: This is no longer an option, since I gave up trying to implement it in version 4.x of this driver. It did not improve performance at all and made the driver unstable (because I never found one @@ -303,7 +298,6 @@ #define DEBUG 0 /* Enable debugging output */ #define ENABLE_PARITY 1 /* Enable SCSI Parity */ #define FIFO_COUNT 2 /* Number of 512 byte blocks before INTR */ -#define DO_DETECT 0 /* Do device detection here (see scsi.c) */ /* END OF USER DEFINABLE OPTIONS */ @@ -863,17 +857,6 @@ int retcode; struct Scsi_Host *shpnt; struct pci_dev *pdev = NULL; -#if DO_DETECT - int i = 0; - int j = 0; - const int buflen = 255; - Scsi_Cmnd SCinit; - unsigned char do_inquiry[] = { INQUIRY, 0, 0, 0, buflen, 0 }; - unsigned char do_request_sense[] = { REQUEST_SENSE, 0, 0, 0, buflen, 0 }; - unsigned char do_read_capacity[] = { READ_CAPACITY, - 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - unsigned char buf[buflen]; -#endif if (setup_called) { #if DEBUG_DETECT @@ -984,59 +967,6 @@ /* Log I/O ports with kernel */ request_region( port_base, 0x10, "fdomain" ); -#if DO_DETECT - - /* These routines are here because of the way the SCSI bus behaves after - a reset. This appropriate behavior was not handled correctly by the - higher level SCSI routines when I first wrote this driver. Now, - however, correct scan routines are part of scsi.c and these routines - are no longer needed. However, this code is still good for - debugging. */ - - SCinit.request_buffer = SCinit.buffer = buf; - SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1; - SCinit.use_sg = 0; - SCinit.lun = 0; - - printk( "scsi: detection routine scanning for devices:\n" ); - for (i = 0; i < 8; i++) { - SCinit.target = i; - if (i == tpnt->this_id) /* Skip host adapter */ - continue; - memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); - retcode = fdomain_16x0_command(&SCinit); - if (!retcode) { - memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry)); - retcode = fdomain_16x0_command(&SCinit); - if (!retcode) { - printk( " SCSI ID %d: ", i ); - for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++) - printk( "%c", buf[j] >= 20 ? buf[j] : ' ' ); - memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity)); - retcode = fdomain_16x0_command(&SCinit); - if (!retcode) { - unsigned long blocks, size, capacity; - - blocks = (buf[0] << 24) | (buf[1] << 16) - | (buf[2] << 8) | buf[3]; - size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; - capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L; - - printk( "%lu MB (%lu byte blocks)", - ((capacity + 5L) / 10L), size ); - } else { - memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); - retcode = fdomain_16x0_command(&SCinit); - } - printk ("\n" ); - } else { - memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); - retcode = fdomain_16x0_command(&SCinit); - } - } - } -#endif - return shpnt; } @@ -1508,31 +1438,6 @@ return 0; } -/* The following code, which simulates the old-style command function, was - taken from Tommy Thorn's aha1542.c file. This code is Copyright (C) - 1992 Tommy Thorn. */ - -static volatile int internal_done_flag = 0; -static volatile int internal_done_errcode = 0; - -static void internal_done(Scsi_Cmnd *SCpnt) -{ - internal_done_errcode = SCpnt->result; - ++internal_done_flag; -} - -static int fdomain_16x0_command(Scsi_Cmnd *SCpnt) -{ - fdomain_16x0_queue(SCpnt, internal_done); - - while (!internal_done_flag) - cpu_relax(); - internal_done_flag = 0; - return internal_done_errcode; -} - -/* End of code derived from Tommy Thorn's work. */ - #if DEBUG_ABORT static void print_info(Scsi_Cmnd *SCpnt) { @@ -1833,7 +1738,6 @@ .proc_name = "fdomain", .detect = fdomain_16x0_detect, .info = fdomain_16x0_info, - .command = fdomain_16x0_command, .queuecommand = fdomain_16x0_queue, .eh_abort_handler = fdomain_16x0_abort, .eh_bus_reset_handler = fdomain_16x0_bus_reset, diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c --- a/drivers/scsi/hosts.c Mon May 26 09:10:33 2003 +++ b/drivers/scsi/hosts.c Thu Jun 5 11:52:51 2003 @@ -20,25 +20,15 @@ * September 04, 2002 Mike Anderson (andmike@us.ibm.com) */ - -/* - * This file contains the medium level SCSI - * host interface initialization, as well as the scsi_hosts list of SCSI - * hosts currently present in the system. - */ - -#include #include -#include +#include #include #include #include #include -#include #include #include #include -#include #include "scsi.h" #include "hosts.h" @@ -47,152 +37,7 @@ #include "scsi_logging.h" -static LIST_HEAD(scsi_host_list); -static spinlock_t scsi_host_list_lock = SPIN_LOCK_UNLOCKED; - static int scsi_host_next_hn; /* host_no for next new host */ -static char *scsihosts; - -MODULE_PARM(scsihosts, "s"); -MODULE_PARM_DESC(scsihosts, "scsihosts=driver1,driver2,driver3"); -#ifndef MODULE -int __init scsi_setup(char *str) -{ - scsihosts = str; - return 1; -} - -__setup("scsihosts=", scsi_setup); -#endif - -/** - * scsi_find_host_by_num - get a Scsi_Host by host no - * - * @host_no: host number to locate - * - * Return value: - * A pointer to located Scsi_Host or NULL. - **/ -static struct Scsi_Host *scsi_find_host_by_num(unsigned short host_no) -{ - struct Scsi_Host *shost, *shost_found = NULL; - - spin_lock(&scsi_host_list_lock); - list_for_each_entry(shost, &scsi_host_list, sh_list) { - if (shost->host_no > host_no) { - /* - * The list is sorted. - */ - break; - } else if (shost->host_no == host_no) { - shost_found = shost; - break; - } - } - spin_unlock(&scsi_host_list_lock); - return shost_found; -} - -/** - * scsi_alloc_hostnum - choose new SCSI host number based on host name. - * @name: String to store in name field - * - * Return value: - * Pointer to a new Scsi_Host_Name - **/ -static int scsi_alloc_host_num(const char *name) -{ - int hostnum; - int namelen; - const char *start, *end; - - if (name) { - hostnum = 0; - namelen = strlen(name); - start = scsihosts; - while (1) { - int hostlen; - - if (start && start[0] != '\0') { - end = strpbrk(start, ",:"); - if (end) { - hostlen = (end - start); - end++; - } else - hostlen = strlen(start); - /* - * Look for a match on the scsihosts list. - */ - if ((hostlen == namelen) && - (strncmp(name, start, hostlen) == 0) && - (!scsi_find_host_by_num(hostnum))) - return hostnum; - start = end; - } else { - /* - * Look for any unused numbers. - */ - if (!scsi_find_host_by_num(hostnum)) - return hostnum; - } - hostnum++; - } - } else - return scsi_host_next_hn++; -} - - -/** - * scsi_tp_for_each_host - call function for each scsi host off a template - * @shost_tp: a pointer to a scsi host template - * @callback: a pointer to callback function - * - * Return value: - * 0 on Success / 1 on Failure - **/ -int scsi_tp_for_each_host(Scsi_Host_Template *shost_tp, int - (*callback)(struct Scsi_Host *shost)) -{ - struct list_head *lh, *lh_sf; - struct Scsi_Host *shost; - - spin_lock(&scsi_host_list_lock); - - list_for_each_safe(lh, lh_sf, &scsi_host_list) { - shost = list_entry(lh, struct Scsi_Host, sh_list); - if (shost->hostt == shost_tp) { - spin_unlock(&scsi_host_list_lock); - callback(shost); - spin_lock(&scsi_host_list_lock); - } - } - - spin_unlock(&scsi_host_list_lock); - - return 0; -} - -/** - * scsi_host_legacy_release - default release function for hosts - * @shost: - * - * Description: - * This is the default case for the release function. Its completely - * useless for anything but old ISA adapters - **/ -static int scsi_host_legacy_release(struct Scsi_Host *shost) -{ - if (shost->irq) - free_irq(shost->irq, NULL); -#ifdef CONFIG_GENERIC_ISA_DMA - if (shost->dma_channel != 0xff) - free_dma(shost->dma_channel); -#endif - if (shost->io_port && shost->n_io_port) - release_region(shost->io_port, shost->n_io_port); - - return 0; -} /** * scsi_remove_host - check a scsi host for release and release @@ -217,9 +62,6 @@ scsi_forget_host(shost); scsi_sysfs_remove_host(shost); - if (shost->hostt->release) - (*shost->hostt->release)(shost); - return 0; } @@ -233,7 +75,7 @@ **/ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) { - Scsi_Host_Template *sht = shost->hostt; + struct scsi_host_template *sht = shost->hostt; int error; printk(KERN_INFO "scsi%d : %s\n", shost->host_no, @@ -243,34 +85,17 @@ if (!error) { scsi_proc_host_add(shost); scsi_scan_host(shost); - }; + } return error; } /** - * scsi_unregister - unregister a scsi host - * @shost: scsi host to be unregistered - **/ -void scsi_unregister(struct Scsi_Host *shost) -{ - scsi_host_put(shost); -} - -/** * scsi_free_sdev - free a scsi hosts resources * @shost: scsi host to free **/ void scsi_free_shost(struct Scsi_Host *shost) { - /* Remove shost from scsi_host_list */ - spin_lock(&scsi_host_list_lock); - list_del(&shost->sh_list); - spin_unlock(&scsi_host_list_lock); - - /* - * Next, kill the kernel error recovery thread for this host. - */ if (shost->ehandler) { DECLARE_COMPLETION(sem); shost->eh_notify = &sem; @@ -286,60 +111,58 @@ } /** - * scsi_register - register a scsi host adapter instance. - * @shost_tp: pointer to scsi host template - * @xtr_bytes: extra bytes to allocate for driver + * scsi_host_alloc - register a scsi host adapter instance. + * @sht: pointer to scsi host template + * @privsize: extra bytes to allocate for driver * * Note: - * We call this when we come across a new host adapter. We only do - * this once we are 100% sure that we want to use this host adapter - - * it is a pain to reverse this, so we try to avoid it + * Allocate a new Scsi_Host and perform basic initialization. + * The host is not published to the scsi midlayer until scsi_add_host + * is called. * * Return value: * Pointer to a new Scsi_Host **/ -extern int blk_nohighio; -struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes) +struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) { - struct Scsi_Host *shost, *shost_scr; - int gfp_mask, rval; - DECLARE_COMPLETION(sem); + struct Scsi_Host *shost; + int gfp_mask = GFP_KERNEL, rval; + DECLARE_COMPLETION(complete); + + if (sht->unchecked_isa_dma && privsize) + gfp_mask |= __GFP_DMA; /* Check to see if this host has any error handling facilities */ - if(shost_tp->eh_strategy_handler == NULL && - shost_tp->eh_abort_handler == NULL && - shost_tp->eh_device_reset_handler == NULL && - shost_tp->eh_bus_reset_handler == NULL && - shost_tp->eh_host_reset_handler == NULL) { - printk(KERN_ERR "ERROR: SCSI host `%s' has no error handling\nERROR: This is not a safe way to run your SCSI host\nERROR: The error handling must be added to this driver\n", shost_tp->proc_name); + if (!sht->eh_strategy_handler && !sht->eh_abort_handler && + !sht->eh_device_reset_handler && !sht->eh_bus_reset_handler && + !sht->eh_host_reset_handler) { + printk(KERN_ERR "ERROR: SCSI host `%s' has no error handling\n" + "ERROR: This is not a safe way to run your " + "SCSI host\n" + "ERROR: The error handling must be added to " + "this driver\n", sht->proc_name); dump_stack(); } - if(shost_tp->shost_attrs == NULL) - /* if its not set in the template, use the default */ - shost_tp->shost_attrs = scsi_sysfs_shost_attrs; - if(shost_tp->sdev_attrs == NULL) - shost_tp->sdev_attrs = scsi_sysfs_sdev_attrs; - gfp_mask = GFP_KERNEL; - if (shost_tp->unchecked_isa_dma && xtr_bytes) - gfp_mask |= __GFP_DMA; - - shost = kmalloc(sizeof(struct Scsi_Host) + xtr_bytes, gfp_mask); - if (!shost) { - printk(KERN_ERR "%s: out of memory.\n", __FUNCTION__); - return NULL; - } - memset(shost, 0, sizeof(struct Scsi_Host) + xtr_bytes); + /* if its not set in the template, use the default */ + if (!sht->shost_attrs) + sht->shost_attrs = scsi_sysfs_shost_attrs; + if (!sht->sdev_attrs) + sht->sdev_attrs = scsi_sysfs_sdev_attrs; - shost->host_no = scsi_alloc_host_num(shost_tp->proc_name); + shost = kmalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask); + if (!shost) + return NULL; + memset(shost, 0, sizeof(struct Scsi_Host) + privsize); spin_lock_init(&shost->default_lock); scsi_assign_lock(shost, &shost->default_lock); INIT_LIST_HEAD(&shost->my_devices); INIT_LIST_HEAD(&shost->eh_cmd_q); INIT_LIST_HEAD(&shost->starved_list); - init_waitqueue_head(&shost->host_wait); + + shost->host_no = scsi_host_next_hn++; /* XXX(hch): still racy */ shost->dma_channel = 0xff; /* These three are default values which can be overridden */ @@ -354,54 +177,29 @@ * they actually do something sensible with such commands. */ shost->max_cmd_len = 12; - shost->hostt = shost_tp; - shost->host_blocked = 0; - shost->host_self_blocked = FALSE; - shost->max_host_blocked = shost_tp->max_host_blocked ? shost_tp->max_host_blocked : SCSI_DEFAULT_HOST_BLOCKED; - -#ifdef DEBUG - printk("%s: %x %x: %d\n", __FUNCTION_ (int)shost, - (int)shost->hostt, xtr_bytes); -#endif + shost->hostt = sht; + shost->this_id = sht->this_id; + shost->can_queue = sht->can_queue; + shost->sg_tablesize = sht->sg_tablesize; + shost->cmd_per_lun = sht->cmd_per_lun; + shost->unchecked_isa_dma = sht->unchecked_isa_dma; + shost->use_clustering = sht->use_clustering; + shost->use_blk_tcq = sht->use_blk_tcq; + shost->highmem_io = sht->highmem_io; + + if (!sht->max_host_blocked) + shost->max_host_blocked = sht->max_host_blocked; + else + shost->max_host_blocked = SCSI_DEFAULT_HOST_BLOCKED; /* - * The next six are the default values which can be overridden if - * need be + * If the driver imposes no hard sector transfer limit, start at + * machine infinity initially. */ - shost->this_id = shost_tp->this_id; - shost->can_queue = shost_tp->can_queue; - shost->sg_tablesize = shost_tp->sg_tablesize; - shost->cmd_per_lun = shost_tp->cmd_per_lun; - shost->unchecked_isa_dma = shost_tp->unchecked_isa_dma; - shost->use_clustering = shost_tp->use_clustering; - if (!blk_nohighio) - shost->highmem_io = shost_tp->highmem_io; - if (!shost_tp->max_sectors) { - /* - * Driver imposes no hard sector transfer limit. - * start at machine infinity initially. - */ + if (sht->max_sectors) + shost->max_sectors = sht->max_sectors; + else shost->max_sectors = SCSI_DEFAULT_MAX_SECTORS; - } else - shost->max_sectors = shost_tp->max_sectors; - shost->use_blk_tcq = shost_tp->use_blk_tcq; - - spin_lock(&scsi_host_list_lock); - /* - * FIXME When device naming is complete remove this step that - * orders the scsi_host_list by host number and just do a - * list_add_tail. - */ - list_for_each_entry(shost_scr, &scsi_host_list, sh_list) { - if (shost->host_no < shost_scr->host_no) { - __list_add(&shost->sh_list, shost_scr->sh_list.prev, - &shost_scr->sh_list); - goto found; - } - } - list_add_tail(&shost->sh_list, &scsi_host_list); -found: - spin_unlock(&scsi_host_list_lock); rval = scsi_setup_command_freelist(shost); if (rval) @@ -409,85 +207,37 @@ scsi_sysfs_init_host(shost); - shost->eh_notify = &sem; - kernel_thread((int (*)(void *)) scsi_error_handler, (void *) shost, 0); - /* - * Now wait for the kernel error thread to initialize itself - * as it might be needed when we scan the bus. - */ - wait_for_completion(&sem); + shost->eh_notify = &complete; + /* XXX(hch): handle error return */ + kernel_thread((int (*)(void *))scsi_error_handler, shost, 0); + wait_for_completion(&complete); shost->eh_notify = NULL; shost->hostt->present++; return shost; - -fail: - spin_lock(&scsi_host_list_lock); - list_del(&shost->sh_list); - spin_unlock(&scsi_host_list_lock); + fail: kfree(shost); return NULL; } -/** - * scsi_register_host - register a low level host driver - * @shost_tp: pointer to a scsi host driver template - * - * Return value: - * 0 on Success / 1 on Failure. - **/ -int scsi_register_host(Scsi_Host_Template *shost_tp) +struct Scsi_Host *scsi_register(struct scsi_host_template *sht, int privsize) { - struct Scsi_Host *shost; - - BUG_ON(!shost_tp->detect); + struct Scsi_Host *shost = scsi_host_alloc(sht, privsize); - if (!shost_tp->release) { - printk(KERN_WARNING - "scsi HBA driver %s didn't set a release method, " - "please fix the template\n", shost_tp->name); - shost_tp->release = &scsi_host_legacy_release; + if (!sht->detect) { + printk(KERN_WARNING "scsi_register() called on new-style " + "template for driver %s\n", sht->name); + dump_stack(); } - shost_tp->detect(shost_tp); - if (!shost_tp->present) - return 0; - - /* - * XXX(hch) use scsi_tp_for_each_host() once it propagates - * error returns properly. - */ - list_for_each_entry(shost, &scsi_host_list, sh_list) - if (shost->hostt == shost_tp) - if (scsi_add_host(shost, NULL)) - goto out_of_space; - - return 0; - -out_of_space: - scsi_unregister_host(shost_tp); /* easiest way to clean up?? */ - return 1; + if (shost) + list_add_tail(&shost->sht_legacy_list, &sht->legacy_hosts); + return shost; } -/** - * scsi_unregister_host - unregister a low level host adapter driver - * @shost_tp: scsi host template to unregister. - * - * Description: - * Similarly, this entry point should be called by a loadable module - * if it is trying to remove a low level scsi driver from the system. - * - * Return value: - * 0 on Success / 1 on Failure - * - * Notes: - * rmmod does not care what we return here the module will be - * removed. - **/ -int scsi_unregister_host(Scsi_Host_Template *shost_tp) +void scsi_unregister(struct Scsi_Host *shost) { - scsi_tp_for_each_host(shost_tp, scsi_remove_host); - return 0; - + list_del(&shost->sht_legacy_list); + scsi_host_put(shost); } /** @@ -536,50 +286,6 @@ **/ void scsi_host_put(struct Scsi_Host *shost) { - class_device_put(&shost->class_dev); put_device(&shost->host_gendev); -} - -/** - * scsi_host_init - set up the scsi host number list based on any entries - * scsihosts. - **/ -void __init scsi_host_init(void) -{ - char *shost_hn; - - shost_hn = scsihosts; - while (shost_hn) { - scsi_host_next_hn++; - shost_hn = strpbrk(shost_hn, ":,"); - if (shost_hn) - shost_hn++; - } -} - -void scsi_host_busy_inc(struct Scsi_Host *shost, Scsi_Device *sdev) -{ - unsigned long flags; - - spin_lock_irqsave(shost->host_lock, flags); - shost->host_busy++; - sdev->device_busy++; - spin_unlock_irqrestore(shost->host_lock, flags); -} - -void scsi_host_busy_dec_and_test(struct Scsi_Host *shost, Scsi_Device *sdev) -{ - unsigned long flags; - - spin_lock_irqsave(shost->host_lock, flags); - shost->host_busy--; - if (shost->in_recovery && shost->host_failed && - (shost->host_busy == shost->host_failed)) - { - up(shost->eh_wait); - SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler" - " thread\n")); - } - spin_unlock_irqrestore(shost->host_lock, flags); } diff -Nru a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h --- a/drivers/scsi/hosts.h Mon May 26 03:02:43 2003 +++ b/drivers/scsi/hosts.h Sun Jun 8 15:03:00 2003 @@ -28,519 +28,7 @@ #include #include -struct scsi_host_cmd_pool; - - -/* It is senseless to set SG_ALL any higher than this - the performance - * does not get any better, and it wastes memory - */ -#define SG_NONE 0 -#define SG_ALL 0xff - -#define DISABLE_CLUSTERING 0 -#define ENABLE_CLUSTERING 1 - -/* The various choices mean: - * NONE: Self evident. Host adapter is not capable of scatter-gather. - * ALL: Means that the host adapter module can do scatter-gather, - * and that there is no limit to the size of the table to which - * we scatter/gather data. - * Anything else: Indicates the maximum number of chains that can be - * used in one scatter-gather request. - */ - -/* - * The Scsi_Host_Template type has all that is needed to interface with a SCSI - * host in a device independent matter. There is one entry for each different - * type of host adapter that is supported on the system. - */ - -typedef struct SHT -{ - /* Used with loadable modules so that we know when it is safe to unload */ - struct module * module; - - /* The pointer to the /proc/scsi directory entry */ - struct proc_dir_entry *proc_dir; - - /* proc-fs info function. - * Can be used to export driver statistics and other infos to the world - * outside the kernel ie. userspace and it also provides an interface - * to feed the driver with information. Check eata_dma_proc.c for reference - */ - int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int); - - /* - * The name pointer is a pointer to the name of the SCSI - * device detected. - */ - const char *name; - - /* - * The detect function shall return non zero on detection, - * indicating the number of host adapters of this particular - * type were found. It should also - * initialize all data necessary for this particular - * SCSI driver. It is passed the host number, so this host - * knows where the first entry is in the scsi_hosts[] array. - * - * Note that the detect routine MUST not call any of the mid level - * functions to queue commands because things are not guaranteed - * to be set up yet. The detect routine can send commands to - * the host adapter as long as the program control will not be - * passed to scsi.c in the processing of the command. Note - * especially that scsi_malloc/scsi_free must not be called. - */ - int (* detect)(struct SHT *); - - /* Used with loadable modules to unload the host structures. Note: - * there is a default action built into the modules code which may - * be sufficient for most host adapters. Thus you may not have to supply - * this at all. - */ - int (*release)(struct Scsi_Host *); - - /* - * The info function will return whatever useful - * information the developer sees fit. If not provided, then - * the name field will be used instead. - */ - const char *(* info)(struct Scsi_Host *); - - /* - * ioctl interface - */ - int (*ioctl)(Scsi_Device *dev, int cmd, void *arg); - - /* - * The command function takes a target, a command (this is a SCSI - * command formatted as per the SCSI spec, nothing strange), a - * data buffer pointer, and data buffer length pointer. The return - * is a status int, bit fielded as follows : - * Byte What - * 0 SCSI status code - * 1 SCSI 1 byte message - * 2 host error return. - * 3 mid level error return - */ - int (* command)(Scsi_Cmnd *); - - /* - * The QueueCommand function works in a similar manner - * to the command function. It takes an additional parameter, - * void (* done)(int host, int code) which is passed the host - * # and exit result when the command is complete. - * Host number is the POSITION IN THE hosts array of THIS - * host adapter. - * - * if queuecommand returns 0, then the HBA has accepted the - * command. The done() function must be called on the command - * when the driver has finished with it. (you may call done on the - * command before queuecommand returns, but in this case you - * *must* return 0 from queuecommand). - * - * queuecommand may also reject the command, in which case it may - * not touch the command and must not call done() for it. - * - * There are two possible rejection returns: - * - * SCSI_MLQUEUE_DEVICE_BUSY: Block this device temporarily, but - * allow commands to other devices serviced by this host. - * - * SCSI_MLQUEUE_HOST_BUSY: Block all devices served by this - * host temporarily. - * - * for compatibility, any other non-zero return is treated the - * same as SCSI_MLQUEUE_HOST_BUSY. - * - * NOTE: "temporarily" means either until the next command for - * this device/host completes, or a period of time determined by - * I/O pressure in the system if there are no other outstanding - * commands. - * */ - int (* queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); - - /* - * This is an error handling strategy routine. You don't need to - * define one of these if you don't want to - there is a default - * routine that is present that should work in most cases. For those - * driver authors that have the inclination and ability to write their - * own strategy routine, this is where it is specified. Note - the - * strategy routine is *ALWAYS* run in the context of the kernel eh - * thread. Thus you are guaranteed to *NOT* be in an interrupt handler - * when you execute this, and you are also guaranteed to *NOT* have any - * other commands being queued while you are in the strategy routine. - * When you return from this function, operations return to normal. - * - * See scsi_error.c scsi_unjam_host for additional comments about what - * this function should and should not be attempting to do. - */ - int (*eh_strategy_handler)(struct Scsi_Host *); - int (*eh_abort_handler)(Scsi_Cmnd *); - int (*eh_device_reset_handler)(Scsi_Cmnd *); - int (*eh_bus_reset_handler)(Scsi_Cmnd *); - int (*eh_host_reset_handler)(Scsi_Cmnd *); - - /* - * Old EH handlers, no longer used. Make them warn the user of old - * drivers by using a wrong type - */ - int (*abort)(int); - int (*reset)(int,int); - - /* - * slave_alloc() - Optional - * - * Before the mid layer attempts to scan for a new device where none - * currently exists, it will call this entry in your driver. Should - * your driver need to allocate any structs or perform any other init - * items in order to send commands to a currently unused target/lun - * combo, then this is where you can perform those allocations. This - * is specifically so that drivers won't have to perform any kind of - * "is this a new device" checks in their queuecommand routine, - * thereby making the hot path a bit quicker. - * - * Return values: 0 on success, non-0 on failure - * - * Deallocation: If we didn't find any devices at this ID, you will - * get an immediate call to slave_destroy(). If we find something here - * then you will get a call to slave_configure(), then the device will be - * used for however long it is kept around, then when the device is - * removed from the system (or * possibly at reboot time), you will - * then get a call to slave_detach(). This is assuming you implement - * slave_configure and slave_destroy. However, if you allocate memory - * and hang it off the device struct, then you must implement the - * slave_destroy() routine at a minimum in order to avoid leaking memory - * each time a device is tore down. - */ - int (* slave_alloc)(Scsi_Device *); - - /* - * slave_configure() - Optional - * - * Once the device has responded to an INQUIRY and we know the device - * is online, we call into the low level driver with the Scsi_Device * - * If the low level device driver implements this function, it *must* - * perform the task of setting the queue depth on the device. All other - * tasks are optional and depend on what the driver supports and various - * implementation details. - * - * Things currently recommended to be handled at this time include: - * - * 1. Setting the device queue depth. Proper setting of this is - * described in the comments for scsi_adjust_queue_depth. - * 2. Determining if the device supports the various synchronous - * negotiation protocols. The device struct will already have - * responded to INQUIRY and the results of the standard items - * will have been shoved into the various device flag bits, eg. - * device->sdtr will be true if the device supports SDTR messages. - * 3. Allocating command structs that the device will need. - * 4. Setting the default timeout on this device (if needed). - * 5. Anything else the low level driver might want to do on a device - * specific setup basis... - * 6. Return 0 on success, non-0 on error. The device will be marked - * as offline on error so that no access will occur. If you return - * non-0, your slave_detach routine will never get called for this - * device, so don't leave any loose memory hanging around, clean - * up after yourself before returning non-0 - */ - int (* slave_configure)(Scsi_Device *); - - /* - * slave_destroy() - Optional - * - * Immediately prior to deallocating the device and after all activity - * has ceased the mid layer calls this point so that the low level driver - * may completely detach itself from the scsi device and vice versa. - * The low level driver is responsible for freeing any memory it allocated - * in the slave_alloc or slave_configure calls. - */ - void (* slave_destroy)(Scsi_Device *); - - /* - * This function determines the bios parameters for a given - * harddisk. These tend to be numbers that are made up by - * the host adapter. Parameters: - * size, device, list (heads, sectors, cylinders) - */ - int (* bios_param)(struct scsi_device *, struct block_device *, - sector_t, int []); - - /* - * This determines if we will use a non-interrupt driven - * or an interrupt driven scheme, It is set to the maximum number - * of simultaneous commands a given host adapter will accept. - */ - int can_queue; - - /* - * In many instances, especially where disconnect / reconnect are - * supported, our host also has an ID on the SCSI bus. If this is - * the case, then it must be reserved. Please set this_id to -1 if - * your setup is in single initiator mode, and the host lacks an - * ID. - */ - int this_id; - - /* - * This determines the degree to which the host adapter is capable - * of scatter-gather. - */ - short unsigned int sg_tablesize; - - /* - * if the host adapter has limitations beside segment count - */ - short unsigned int max_sectors; - - /* - * True if this host adapter can make good use of linked commands. - * This will allow more than one command to be queued to a given - * unit on a given host. Set this to the maximum number of command - * blocks to be provided for each device. Set this to 1 for one - * command block per lun, 2 for two, etc. Do not set this to 0. - * You should make sure that the host adapter will do the right thing - * before you try setting this above 1. - */ - short cmd_per_lun; - - /* - * present contains counter indicating how many boards of this - * type were found when we did the scan. - */ - unsigned char present; - - /* - * true if this host adapter uses unchecked DMA onto an ISA bus. - */ - unsigned unchecked_isa_dma:1; - - /* - * true if this host adapter can make good use of clustering. - * I originally thought that if the tablesize was large that it - * was a waste of CPU cycles to prepare a cluster list, but - * it works out that the Buslogic is faster if you use a smaller - * number of segments (i.e. use clustering). I guess it is - * inefficient. - */ - unsigned use_clustering:1; - - /* - * True for emulated SCSI host adapters (e.g. ATAPI) - */ - unsigned emulated:1; - - unsigned highmem_io:1; - - /* - * True if the driver wishes to use the generic block layer - * tag queueing functions - */ - unsigned use_blk_tcq:1; - - /* - * Name of proc directory - */ - char *proc_name; - - /* - * countdown for host blocking with no commands outstanding - */ - unsigned int max_host_blocked; - - /* - * Default value for the blocking. If the queue is empty, host_blocked - * counts down in the request_fn until it restarts host operations as - * zero is reached. - * - * FIXME: This should probably be a value in the template */ - #define SCSI_DEFAULT_HOST_BLOCKED 7 - - /* - * pointer to the sysfs class properties for this host - */ - struct class_device_attribute **shost_attrs; - - /* - * Pointer to the SCSI device properties for this host - */ - struct device_attribute **sdev_attrs; - -} Scsi_Host_Template; - -/* - * The scsi_hosts array is the array containing the data for all - * possible scsi hosts. This is similar to the - * Scsi_Host_Template, except that we have one entry for each - * actual physical host adapter on the system, stored as a linked - * list. Note that if there are 2 aha1542 boards, then there will - * be two Scsi_Host entries, but only 1 Scsi_Host_Template entry. - */ - -struct Scsi_Host -{ -/* private: */ - /* - * This information is private to the scsi mid-layer. Wrapping it in a - * struct private is a way of marking it in a sort of C++ type of way. - */ - struct list_head sh_list; - struct list_head my_devices; - - struct scsi_host_cmd_pool *cmd_pool; - spinlock_t free_list_lock; - struct list_head free_list; /* backup store of cmd structs */ - struct list_head starved_list; - - spinlock_t default_lock; - spinlock_t *host_lock; - - struct list_head eh_cmd_q; - struct task_struct * ehandler; /* Error recovery thread. */ - struct semaphore * eh_wait; /* The error recovery thread waits on - this. */ - struct completion * eh_notify; /* wait for eh to begin or end */ - struct semaphore * eh_action; /* Wait for specific actions on the - host. */ - unsigned int eh_active:1; /* Indicates the eh thread is awake and active if - this is true. */ - unsigned int eh_kill:1; /* set when killing the eh thread */ - wait_queue_head_t host_wait; - Scsi_Host_Template * hostt; - volatile unsigned short host_busy; /* commands actually active on low-level */ - volatile unsigned short host_failed; /* commands that failed. */ - -/* public: */ - unsigned short host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ - int resetting; /* if set, it means that last_reset is a valid value */ - unsigned long last_reset; - - /* - * These three parameters can be used to allow for wide scsi, - * and for host adapters that support multiple busses - * The first two should be set to 1 more than the actual max id - * or lun (i.e. 8 for normal systems). - */ - unsigned int max_id; - unsigned int max_lun; - unsigned int max_channel; - - /* These parameters should be set by the detect routine */ - unsigned long base; - unsigned long io_port; - unsigned char n_io_port; - unsigned char dma_channel; - unsigned int irq; - - /* - * This is a unique identifier that must be assigned so that we - * have some way of identifying each detected host adapter properly - * and uniquely. For hosts that do not support more than one card - * in the system at one time, this does not need to be set. It is - * initialized to 0 in scsi_register. - */ - unsigned int unique_id; - - /* - * The rest can be copied from the template, or specifically - * initialized, as required. - */ - - /* - * The maximum length of SCSI commands that this host can accept. - * Probably 12 for most host adapters, but could be 16 for others. - * For drivers that don't set this field, a value of 12 is - * assumed. I am leaving this as a number rather than a bit - * because you never know what subsequent SCSI standards might do - * (i.e. could there be a 20 byte or a 24-byte command a few years - * down the road?). - */ - unsigned char max_cmd_len; - - int this_id; - int can_queue; - short cmd_per_lun; - short unsigned int sg_tablesize; - short unsigned int max_sectors; - - unsigned in_recovery:1; - unsigned unchecked_isa_dma:1; - unsigned use_clustering:1; - unsigned highmem_io:1; - unsigned use_blk_tcq:1; - - /* - * Host has requested that no further requests come through for the - * time being. - */ - unsigned host_self_blocked:1; - - /* - * Host uses correct SCSI ordering not PC ordering. The bit is - * set for the minority of drivers whose authors actually read the spec ;) - */ - unsigned reverse_ordering:1; - - /* - * Host has rejected a command because it was busy. - */ - unsigned int host_blocked; - - /* - * Value host_blocked counts down from - */ - unsigned int max_host_blocked; - - /* - * Support for sysfs - */ - struct device host_gendev; - struct class_device class_dev; - - /* - * We should ensure that this is aligned, both for better performance - * and also because some compilers (m68k) don't automatically force - * alignment to a long boundary. - */ - unsigned long hostdata[0] /* Used for storage of host specific stuff */ - __attribute__ ((aligned (sizeof(unsigned long)))); -}; - -#define dev_to_shost(d) \ - container_of(d, struct Scsi_Host, host_gendev) -#define class_to_shost(d) \ - container_of(d, struct Scsi_Host, class_dev) - -/* - * These two functions are used to allocate and free a pseudo device - * which will connect to the host adapter itself rather than any - * physical device. You must deallocate when you are done with the - * thing. This physical pseudo-device isn't real and won't be available - * from any high-level drivers. - */ -extern void scsi_free_host_dev(Scsi_Device *); -extern Scsi_Device * scsi_get_host_dev(struct Scsi_Host *); - -extern void scsi_unblock_requests(struct Scsi_Host *); -extern void scsi_block_requests(struct Scsi_Host *); -extern void scsi_report_bus_reset(struct Scsi_Host *, int); -extern void scsi_report_device_reset(struct Scsi_Host *, int, int); - -static inline void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock) -{ - shost->host_lock = lock; -} - -static inline void scsi_set_device(struct Scsi_Host *shost, - struct device *dev) -{ - shost->host_gendev.parent = dev; -} - -static inline struct device *scsi_get_device(struct Scsi_Host *shost) -{ - return shost->host_gendev.parent; -} +#include struct scsi_driver { struct module *owner; @@ -560,23 +48,6 @@ #define scsi_unregister_interface(intf) \ class_interface_unregister(intf) -/* - * HBA allocation/freeing. - */ -extern struct Scsi_Host * scsi_register(Scsi_Host_Template *, int); -extern void scsi_unregister(struct Scsi_Host *); - -/* - * HBA registration/unregistration. - */ -extern int scsi_add_host(struct Scsi_Host *, struct device *); -extern int scsi_remove_host(struct Scsi_Host *); - -/* - * Legacy HBA template registration/unregistration. - */ -extern int scsi_register_host(Scsi_Host_Template *); -extern int scsi_unregister_host(Scsi_Host_Template *); /** * scsi_find_device - find a device given the host @@ -585,9 +56,9 @@ * @pun: SCSI target number (physical unit number) * @lun: SCSI Logical Unit Number **/ -static inline Scsi_Device *scsi_find_device(struct Scsi_Host *shost, +static inline struct scsi_device *scsi_find_device(struct Scsi_Host *shost, int channel, int pun, int lun) { - Scsi_Device *sdev; + struct scsi_device *sdev; list_for_each_entry (sdev, &shost->my_devices, siblings) if (sdev->channel == channel && sdev->id == pun @@ -595,7 +66,5 @@ return sdev; return NULL; } - -extern void scsi_sysfs_release_attributes(struct SHT *hostt); #endif diff -Nru a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c --- a/drivers/scsi/ibmmca.c Mon May 12 07:26:12 2003 +++ b/drivers/scsi/ibmmca.c Sun Jun 8 12:18:41 2003 @@ -1793,15 +1793,6 @@ return shpnt; } -static int ibmmca_command(Scsi_Cmnd * cmd) -{ - ibmmca_queuecommand(cmd, internal_done); - cmd->SCp.Status = 0; - while (!cmd->SCp.Status) - barrier(); - return cmd->result; -} - static int ibmmca_release(struct Scsi_Host *shpnt) { release_region(shpnt->io_port, shpnt->n_io_port); @@ -2490,7 +2481,6 @@ .name = "IBM SCSI-Subsystem", .detect = ibmmca_detect, .release = ibmmca_release, - .command = ibmmca_command, .queuecommand = ibmmca_queuecommand, .eh_abort_handler = ibmmca_abort, .eh_host_reset_handler = ibmmca_host_reset, diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c --- a/drivers/scsi/ide-scsi.c Mon May 26 03:12:22 2003 +++ b/drivers/scsi/ide-scsi.c Mon Jun 2 17:42:21 2003 @@ -612,7 +612,7 @@ drive->disk->fops = ide_fops; scsi_remove_host(scsihost); - scsi_unregister(scsihost); + scsi_host_put(scsihost); return 0; } @@ -964,7 +964,7 @@ if (!strstr("ide-scsi", drive->driver_req) || !drive->present || drive->media == ide_disk || - !(host = scsi_register(&idescsi_template,sizeof(idescsi_scsi_t)))) + !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t)))) return 1; host->max_id = 1; @@ -984,7 +984,7 @@ ide_unregister_subdriver(drive); } - scsi_unregister(host); + scsi_host_put(host); return err; } diff -Nru a/drivers/scsi/imm.c b/drivers/scsi/imm.c --- a/drivers/scsi/imm.c Tue May 27 09:05:29 2003 +++ b/drivers/scsi/imm.c Sun Jun 8 12:18:41 2003 @@ -113,7 +113,6 @@ .name = "Iomega VPI2 (imm) interface", .detect = imm_detect, .release = imm_release, - .command = imm_command, .queuecommand = imm_queuecommand, .eh_abort_handler = imm_abort, .eh_bus_reset_handler = imm_reset, @@ -856,39 +855,6 @@ return 0; } return 1; /* FINISH_RETURN */ -} - -/* deprecated synchronous interface */ -int imm_command(Scsi_Cmnd * cmd) -{ - static int first_pass = 1; - int host_no = cmd->device->host->unique_id; - - if (first_pass) { - printk("imm: using non-queuing interface\n"); - first_pass = 0; - } - if (imm_hosts[host_no].cur_cmd) { - printk("IMM: bug in imm_command\n"); - return 0; - } - imm_hosts[host_no].failed = 0; - imm_hosts[host_no].jstart = jiffies; - imm_hosts[host_no].cur_cmd = cmd; - cmd->result = DID_ERROR << 16; /* default return code */ - cmd->SCp.phase = 0; - - imm_pb_claim(host_no); - - while (imm_engine(&imm_hosts[host_no], cmd)) - schedule(); - - if (cmd->SCp.phase) /* Only disconnect if we have connected */ - imm_disconnect(cmd->device->host->unique_id); - - imm_pb_release(host_no); - imm_hosts[host_no].cur_cmd = 0; - return cmd->result; } /* diff -Nru a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c --- a/drivers/scsi/ini9100u.c Sun May 4 02:56:43 2003 +++ b/drivers/scsi/ini9100u.c Sun Jun 8 12:18:41 2003 @@ -147,7 +147,6 @@ .name = i91u_REVID, .detect = i91u_detect, .release = i91u_release, - .command = i91u_command, .queuecommand = i91u_queue, .abort = i91u_abort, .reset = i91u_reset, @@ -555,15 +554,6 @@ i91uBuildSCB(pHCB, pSCB, SCpnt); tul_exec_scb(pHCB, pSCB); /* Start execute SCB */ return (0); -} - -/* - * We only support command in interrupt-driven fashion - */ -int i91u_command(Scsi_Cmnd * SCpnt) -{ - printk("i91u: interrupt driven driver; use i91u_queue()\n"); - return -1; } /* diff -Nru a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c --- a/drivers/scsi/inia100.c Mon Jun 9 16:05:03 2003 +++ b/drivers/scsi/inia100.c Mon Jun 16 08:48:22 2003 @@ -156,11 +156,11 @@ spin_lock_irqsave(&(pHCB->pSRB_lock), flags); - pSRB->next = NULL; /* Pointer to next */ + pSRB->SCp.ptr = NULL; /* Pointer to next */ if (pHCB->pSRB_head == NULL) pHCB->pSRB_head = pSRB; else - pHCB->pSRB_tail->next = pSRB; /* Pointer to next */ + pHCB->pSRB_tail->SCp.ptr = (char *)pSRB; /* Pointer to next */ pHCB->pSRB_tail = pSRB; spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags); return; @@ -179,8 +179,8 @@ ULONG flags; spin_lock_irqsave(&(pHCB->pSRB_lock), flags); if ((pSRB = (Scsi_Cmnd *) pHCB->pSRB_head) != NULL) { - pHCB->pSRB_head = pHCB->pSRB_head->next; - pSRB->next = NULL; + pHCB->pSRB_head = (Scsi_Cmnd *) pHCB->pSRB_head->SCp.ptr; + pSRB->SCp.ptr = NULL; } spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags); return (pSRB); diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c --- a/drivers/scsi/ips.c Mon May 12 07:26:13 2003 +++ b/drivers/scsi/ips.c Thu Jun 5 11:39:39 2003 @@ -725,7 +725,7 @@ free_irq(ha->irq, ha); IPS_REMOVE_HOST(sh); - scsi_unregister(sh); + scsi_host_put(sh); ips_released_controllers++; @@ -6732,7 +6732,7 @@ ips_register_scsi( int index){ struct Scsi_Host *sh; ips_ha_t *ha, *oldha = ips_ha[index]; - sh = scsi_register(&ips_driver_template, sizeof(ips_ha_t)); + sh = scsi_host_alloc(&ips_driver_template, sizeof(ips_ha_t)); if(!sh) { IPS_PRINTK(KERN_WARNING, oldha->pcidev, "Unable to register controller with SCSI subsystem\n"); return -1; @@ -6743,7 +6743,7 @@ /* Install the interrupt handler with the new ha */ if (request_irq(ha->irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) { IPS_PRINTK(KERN_WARNING, ha->pcidev, "Unable to install interrupt handler\n" ); - scsi_unregister(sh); + scsi_host_put(sh); return -1; } diff -Nru a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c --- a/drivers/scsi/jazz_esp.c Mon Nov 11 13:23:24 2002 +++ b/drivers/scsi/jazz_esp.c Sun Jun 8 12:18:41 2003 @@ -139,6 +139,18 @@ return 0; } +static int jazz_esp_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->dma_channel != 0xff) + free_dma(shost->dma_channel); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + /************************************************************* DMA Functions */ static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count) { @@ -278,8 +290,8 @@ .proc_info = &esp_proc_info, .name = "ESP 100/100a/200", .detect = jazz_esp_detect, + .release = jazz_esp_release, .info = esp_info, - .command = esp_command, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, .eh_bus_reset_handler = esp_reset, diff -Nru a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c --- a/drivers/scsi/lasi700.c Sun May 4 02:56:44 2003 +++ b/drivers/scsi/lasi700.c Tue Jun 17 13:27:45 2003 @@ -31,19 +31,14 @@ * machines for me to debug the driver on. */ -#ifndef __hppa__ -#error "lasi700 only compiles on hppa architecture" -#endif - #include +#include #include #include #include #include -#include +#include #include -#include -#include #include #include @@ -54,65 +49,27 @@ #include #include -#include - #include "scsi.h" #include "hosts.h" #include "lasi700.h" #include "53c700.h" -#ifdef MODULE - -char *lasi700; /* command line from insmod */ - MODULE_AUTHOR("James Bottomley"); MODULE_DESCRIPTION("lasi700 SCSI Driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(lasi700, "s"); - -#endif -#ifdef MODULE -#define ARG_SEP ' ' -#else -#define ARG_SEP ',' -#endif - -static unsigned long __initdata opt_base; -static int __initdata opt_irq; - -static int __init -param_setup(char *string) -{ - char *pos = string, *next; - - while(pos != NULL && (next = strchr(pos, ':')) != NULL) { - int val = (int)simple_strtoul(++next, NULL, 0); - - if(!strncmp(pos, "addr:", 5)) - opt_base = val; - else if(!strncmp(pos, "irq:", 4)) - opt_irq = val; - - if((pos = strchr(pos, ARG_SEP)) != NULL) - pos++; - } - return 1; -} - -#ifndef MODULE -__setup("lasi700=", param_setup); -#endif - -static Scsi_Host_Template __initdata *host_tpnt = NULL; -static int __initdata host_count = 0; static struct parisc_device_id lasi700_scsi_tbl[] = { LASI700_ID_TABLE, LASI710_ID_TABLE, { 0 } }; +static Scsi_Host_Template lasi700_template = { + .name = "LASI SCSI 53c700", + .proc_name = "lasi700", + .this_id = 7, +}; MODULE_DEVICE_TABLE(parisc, lasi700_scsi_tbl); static struct parisc_driver lasi700_driver = { @@ -122,50 +79,36 @@ }; static int __init -lasi700_detect(Scsi_Host_Template *tpnt) -{ - host_tpnt = tpnt; - -#ifdef MODULE - if(lasi700) - param_setup(lasi700); -#endif - - register_parisc_driver(&lasi700_driver); - - return (host_count != 0); -} - -static int __init lasi700_driver_callback(struct parisc_device *dev) { unsigned long base = dev->hpa + LASI_SCSI_CORE_OFFSET; - char *driver_name; + struct NCR_700_Host_Parameters *hostdata; struct Scsi_Host *host; - struct NCR_700_Host_Parameters *hostdata = - kmalloc(sizeof(struct NCR_700_Host_Parameters), - GFP_KERNEL); - if(dev->id.sversion == LASI_700_SVERSION) { - driver_name = "lasi700"; - } else { - driver_name = "lasi710"; - } - snprintf(dev->dev.name, sizeof(dev->dev.name), "%s", driver_name); - if(hostdata == NULL) { + + snprintf(dev->dev.name, sizeof(dev->dev.name), "%s", + (dev->id.sversion == LASI_700_SVERSION) ? + "lasi700" : "lasi710"); + + hostdata = kmalloc(sizeof(*hostdata), GFP_KERNEL); + if (!hostdata) { printk(KERN_ERR "%s: Failed to allocate host data\n", - driver_name); + dev->dev.name); return 1; } memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); - if(request_mem_region(base, 64, driver_name) == NULL) { + + if (!request_mem_region(base, 64, dev->dev.name)) { printk(KERN_ERR "%s: Failed to claim memory region\n", - driver_name); - kfree(hostdata); - return 1; + dev->dev.name); + goto out_kfree; } + + hostdata->dev = &dev->dev; + dma_set_mask(&dev->dev, 0xffffffffUL); hostdata->base = base; hostdata->differential = 0; - if(dev->id.sversion == LASI_700_SVERSION) { + + if (dev->id.sversion == LASI_700_SVERSION) { hostdata->clock = LASI700_CLOCK; hostdata->force_le_on_be = 1; } else { @@ -174,26 +117,34 @@ hostdata->chip710 = 1; hostdata->dmode_extra = DMODE_FC2; } - hostdata->dev = &dev->dev; - dma_set_mask(&dev->dev, 0xffffffffUL); - if((host = NCR_700_detect(host_tpnt, hostdata)) == NULL) { - kfree(hostdata); - release_mem_region(host->base, 64); - return 1; - } - scsi_set_device(host, &dev->dev); + + NCR_700_set_mem_mapped(hostdata); + + host = NCR_700_detect(&lasi700_template, hostdata); + if (!host) + goto out_release_mem_region; + host->irq = dev->irq; - if(request_irq(dev->irq, NCR_700_intr, SA_SHIRQ, driver_name, host)) { + if (request_irq(dev->irq, NCR_700_intr, SA_SHIRQ, + dev->dev.name, host)) { printk(KERN_ERR "%s: irq problem, detaching\n", - driver_name); - scsi_unregister(host); - NCR_700_release(host); - return 1; + dev->dev.name); + goto out_put_host; } - host_count++; + + scsi_add_host(host, &dev->dev); return 0; + + out_put_host: + scsi_host_put(host); + out_release_mem_region: + release_mem_region(base, 64); + out_kfree: + kfree(hostdata); + return 1; } +#if 0 static int lasi700_release(struct Scsi_Host *host) { @@ -207,12 +158,12 @@ unregister_parisc_driver(&lasi700_driver); return 1; } +#endif + +static int __init +lasi700_init(void) +{ + return register_parisc_driver(&lasi700_driver); +} -static Scsi_Host_Template driver_template = { - .name = "LASI SCSI 53c700", - .proc_name = "lasi700", - .detect = lasi700_detect, - .release = lasi700_release, - .this_id = 7, -}; -#include "scsi_module.c" +module_init(lasi700_init); diff -Nru a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c --- a/drivers/scsi/mac_esp.c Fri May 9 03:21:35 2003 +++ b/drivers/scsi/mac_esp.c Sun Jun 8 12:18:41 2003 @@ -464,6 +464,16 @@ return chipspresent; } +static int mac_esp_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + /* * I've been wondering what this is supposed to do, for some time. Talking * to Allen Briggs: These machines have an extra register someplace where the @@ -717,8 +727,8 @@ .proc_name = "esp", .name = "Mac 53C9x SCSI", .detect = mac_esp_detect, + .release = mac_esp_release, .info = esp_info, - /* .command = esp_command, */ .queuecommand = esp_queue, .eh_abort_handler = esp_abort, .eh_bus_reset_handler = esp_reset, diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c --- a/drivers/scsi/megaraid.c Tue Jun 3 00:25:23 2003 +++ b/drivers/scsi/megaraid.c Fri Jun 6 02:41:26 2003 @@ -723,7 +723,7 @@ { dma_addr_t prod_info_dma_handle; mega_inquiry3 *inquiry3; - u8 raw_mbox[sizeof(mbox_t)]; + u8 raw_mbox[sizeof(struct mbox_out)]; mbox_t *mbox; int retval; @@ -732,14 +732,14 @@ mbox = (mbox_t *)raw_mbox; memset((void *)adapter->mega_buffer, 0, MEGA_BUFFER_SIZE); - memset(mbox, 0, sizeof(*mbox)); + memset(&mbox->m_out, 0, sizeof(raw_mbox)); /* * Try to issue Inquiry3 command * if not succeeded, then issue MEGA_MBOXCMD_ADAPTERINQ command and * update enquiry3 structure */ - mbox->xferaddr = (u32)adapter->buf_dma_handle; + mbox->m_out.xferaddr = (u32)adapter->buf_dma_handle; inquiry3 = (mega_inquiry3 *)adapter->mega_buffer; @@ -762,10 +762,10 @@ inq = &ext_inq->raid_inq; - mbox->xferaddr = (u32)dma_handle; + mbox->m_out.xferaddr = (u32)dma_handle; /*issue old 0x04 command to adapter */ - mbox->cmd = MEGA_MBOXCMD_ADPEXTINQ; + mbox->m_out.cmd = MEGA_MBOXCMD_ADPEXTINQ; issue_scb_block(adapter, raw_mbox); @@ -790,7 +790,7 @@ &adapter->product_info, sizeof(mega_product_info), PCI_DMA_FROMDEVICE); - mbox->xferaddr = prod_info_dma_handle; + mbox->m_out.xferaddr = prod_info_dma_handle; raw_mbox[0] = FC_NEW_CONFIG; /* i.e. mbox->cmd=0xA1 */ raw_mbox[2] = NC_SUBOP_PRODUCT_INFO; /* i.e. 0x0E */ @@ -1141,10 +1141,10 @@ memcpy(pthru->cdb, cmd->cmnd, cmd->cmd_len); if( adapter->has_64bit_addr ) { - mbox->cmd = MEGA_MBOXCMD_PASSTHRU64; + mbox->m_out.cmd = MEGA_MBOXCMD_PASSTHRU64; } else { - mbox->cmd = MEGA_MBOXCMD_PASSTHRU; + mbox->m_out.cmd = MEGA_MBOXCMD_PASSTHRU; } scb->dma_direction = PCI_DMA_FROMDEVICE; @@ -1152,7 +1152,7 @@ pthru->numsgelements = mega_build_sglist(adapter, scb, &pthru->dataxferaddr, &pthru->dataxferlen); - mbox->xferaddr = scb->pthru_dma_addr; + mbox->m_out.xferaddr = scb->pthru_dma_addr; return scb; @@ -1175,19 +1175,19 @@ mbox = (mbox_t *)scb->raw_mbox; memset(mbox, 0, sizeof(scb->raw_mbox)); - mbox->logdrv = ldrv_num; + mbox->m_out.logdrv = ldrv_num; /* * A little hack: 2nd bit is zero for all scsi read * commands and is set for all scsi write commands */ if( adapter->has_64bit_addr ) { - mbox->cmd = (*cmd->cmnd & 0x02) ? + mbox->m_out.cmd = (*cmd->cmnd & 0x02) ? MEGA_MBOXCMD_LWRITE64: MEGA_MBOXCMD_LREAD64 ; } else { - mbox->cmd = (*cmd->cmnd & 0x02) ? + mbox->m_out.cmd = (*cmd->cmnd & 0x02) ? MEGA_MBOXCMD_LWRITE: MEGA_MBOXCMD_LREAD ; } @@ -1196,13 +1196,13 @@ * 6-byte READ(0x08) or WRITE(0x0A) cdb */ if( cmd->cmd_len == 6 ) { - mbox->numsectors = (u32) cmd->cmnd[4]; - mbox->lba = + mbox->m_out.numsectors = (u32) cmd->cmnd[4]; + mbox->m_out.lba = ((u32)cmd->cmnd[1] << 16) | ((u32)cmd->cmnd[2] << 8) | (u32)cmd->cmnd[3]; - mbox->lba &= 0x1FFFFF; + mbox->m_out.lba &= 0x1FFFFF; #if MEGA_HAVE_STATS /* @@ -1213,11 +1213,11 @@ if (*cmd->cmnd == READ_6) { adapter->nreads[ldrv_num%0x80]++; adapter->nreadblocks[ldrv_num%0x80] += - mbox->numsectors; + mbox->m_out.numsectors; } else { adapter->nwrites[ldrv_num%0x80]++; adapter->nwriteblocks[ldrv_num%0x80] += - mbox->numsectors; + mbox->m_out.numsectors; } #endif } @@ -1226,10 +1226,10 @@ * 10-byte READ(0x28) or WRITE(0x2A) cdb */ if( cmd->cmd_len == 10 ) { - mbox->numsectors = + mbox->m_out.numsectors = (u32)cmd->cmnd[8] | ((u32)cmd->cmnd[7] << 8); - mbox->lba = + mbox->m_out.lba = ((u32)cmd->cmnd[2] << 24) | ((u32)cmd->cmnd[3] << 16) | ((u32)cmd->cmnd[4] << 8) | @@ -1239,11 +1239,11 @@ if (*cmd->cmnd == READ_10) { adapter->nreads[ldrv_num%0x80]++; adapter->nreadblocks[ldrv_num%0x80] += - mbox->numsectors; + mbox->m_out.numsectors; } else { adapter->nwrites[ldrv_num%0x80]++; adapter->nwriteblocks[ldrv_num%0x80] += - mbox->numsectors; + mbox->m_out.numsectors; } #endif } @@ -1252,13 +1252,13 @@ * 12-byte READ(0xA8) or WRITE(0xAA) cdb */ if( cmd->cmd_len == 12 ) { - mbox->lba = + mbox->m_out.lba = ((u32)cmd->cmnd[2] << 24) | ((u32)cmd->cmnd[3] << 16) | ((u32)cmd->cmnd[4] << 8) | (u32)cmd->cmnd[5]; - mbox->numsectors = + mbox->m_out.numsectors = ((u32)cmd->cmnd[6] << 24) | ((u32)cmd->cmnd[7] << 16) | ((u32)cmd->cmnd[8] << 8) | @@ -1268,11 +1268,11 @@ if (*cmd->cmnd == READ_12) { adapter->nreads[ldrv_num%0x80]++; adapter->nreadblocks[ldrv_num%0x80] += - mbox->numsectors; + mbox->m_out.numsectors; } else { adapter->nwrites[ldrv_num%0x80]++; adapter->nwriteblocks[ldrv_num%0x80] += - mbox->numsectors; + mbox->m_out.numsectors; } #endif } @@ -1288,8 +1288,8 @@ } /* Calculate Scatter-Gather info */ - mbox->numsgelements = mega_build_sglist(adapter, scb, - (u32 *)&mbox->xferaddr, (u32 *)&seg); + mbox->m_out.numsgelements = mega_build_sglist(adapter, scb, + (u32 *)&mbox->m_out.xferaddr, (u32 *)&seg); return scb; @@ -1357,9 +1357,9 @@ epthru = mega_prepare_extpassthru(adapter, scb, cmd, channel, target); - mbox->cmd = MEGA_MBOXCMD_EXTPTHRU; + mbox->m_out.cmd = MEGA_MBOXCMD_EXTPTHRU; - mbox->xferaddr = scb->epthru_dma_addr; + mbox->m_out.xferaddr = scb->epthru_dma_addr; } else { @@ -1369,13 +1369,13 @@ /* Initialize mailbox */ if( adapter->has_64bit_addr ) { - mbox->cmd = MEGA_MBOXCMD_PASSTHRU64; + mbox->m_out.cmd = MEGA_MBOXCMD_PASSTHRU64; } else { - mbox->cmd = MEGA_MBOXCMD_PASSTHRU; + mbox->m_out.cmd = MEGA_MBOXCMD_PASSTHRU; } - mbox->xferaddr = scb->pthru_dma_addr; + mbox->m_out.xferaddr = scb->pthru_dma_addr; } return scb; @@ -1593,20 +1593,21 @@ volatile mbox_t *mbox = adapter->mbox; unsigned int i = 0; - if(unlikely(mbox->busy)) { + if(unlikely(mbox->m_in.busy)) { do { udelay(1); i++; - } while( mbox->busy && (i < max_mbox_busy_wait) ); + } while( mbox->m_in.busy && (i < max_mbox_busy_wait) ); - if(mbox->busy) return -1; + if(mbox->m_in.busy) return -1; } /* Copy mailbox data into host structure */ - memcpy((char *)mbox, (char *)scb->raw_mbox, 16); + memcpy((char *)&mbox->m_out, (char *)scb->raw_mbox, + sizeof(struct mbox_out)); - mbox->cmdid = scb->idx; /* Set cmdid */ - mbox->busy = 1; /* Set busy */ + mbox->m_out.cmdid = scb->idx; /* Set cmdid */ + mbox->m_in.busy = 1; /* Set busy */ /* @@ -1614,14 +1615,14 @@ */ atomic_inc(&adapter->pend_cmds); - switch (mbox->cmd) { + switch (mbox->m_out.cmd) { case MEGA_MBOXCMD_LREAD64: case MEGA_MBOXCMD_LWRITE64: case MEGA_MBOXCMD_PASSTHRU64: case MEGA_MBOXCMD_EXTPTHRU: - mbox64->xfer_segment_lo = mbox->xferaddr; + mbox64->xfer_segment_lo = mbox->m_out.xferaddr; mbox64->xfer_segment_hi = 0; - mbox->xferaddr = 0xFFFFFFFF; + mbox->m_out.xferaddr = 0xFFFFFFFF; break; default: mbox64->xfer_segment_lo = 0; @@ -1634,8 +1635,8 @@ scb->state |= SCB_ISSUED; if( likely(adapter->flag & BOARD_MEMMAP) ) { - mbox->poll = 0; - mbox->ack = 0; + mbox->m_in.poll = 0; + mbox->m_in.ack = 0; WRINDOOR(adapter, adapter->mbox_dma | 0x1); } else { @@ -1661,24 +1662,23 @@ volatile mbox_t *mbox = adapter->mbox; u8 byte; - raw_mbox[0x1] = 0xFE; /* Set cmdid */ - raw_mbox[0xF] = 1; /* Set busy */ - /* Wait until mailbox is free */ if(mega_busywait_mbox (adapter)) goto bug_blocked_mailbox; /* Copy mailbox data into host structure */ - memcpy((char *) mbox, raw_mbox, 16); + memcpy((char *) mbox, raw_mbox, sizeof(struct mbox_out)); + mbox->m_out.cmdid = 0xFE; + mbox->m_in.busy = 1; switch (raw_mbox[0]) { case MEGA_MBOXCMD_LREAD64: case MEGA_MBOXCMD_LWRITE64: case MEGA_MBOXCMD_PASSTHRU64: case MEGA_MBOXCMD_EXTPTHRU: - mbox64->xfer_segment_lo = mbox->xferaddr; + mbox64->xfer_segment_lo = mbox->m_out.xferaddr; mbox64->xfer_segment_hi = 0; - mbox->xferaddr = 0xFFFFFFFF; + mbox->m_out.xferaddr = 0xFFFFFFFF; break; default: mbox64->xfer_segment_lo = 0; @@ -1686,22 +1686,22 @@ } if( likely(adapter->flag & BOARD_MEMMAP) ) { - mbox->poll = 0; - mbox->ack = 0; - mbox->numstatus = 0xFF; - mbox->status = 0xFF; + mbox->m_in.poll = 0; + mbox->m_in.ack = 0; + mbox->m_in.numstatus = 0xFF; + mbox->m_in.status = 0xFF; WRINDOOR(adapter, adapter->mbox_dma | 0x1); - while((volatile u8)mbox->numstatus == 0xFF) + while((volatile u8)mbox->m_in.numstatus == 0xFF) cpu_relax(); - mbox->numstatus = 0xFF; + mbox->m_in.numstatus = 0xFF; - while( (volatile u8)mbox->poll != 0x77 ) + while( (volatile u8)mbox->m_in.poll != 0x77 ) cpu_relax(); - mbox->poll = 0; - mbox->ack = 0x77; + mbox->m_in.poll = 0; + mbox->m_in.ack = 0x77; WRINDOOR(adapter, adapter->mbox_dma | 0x2); @@ -1720,7 +1720,7 @@ irq_ack(adapter); } - return mbox->status; + return mbox->m_in.status; bug_blocked_mailbox: printk(KERN_WARNING "megaraid: Blocked mailbox......!!\n"); @@ -1767,19 +1767,20 @@ } set_irq_state(adapter, byte); - while((nstatus = (volatile u8)adapter->mbox->numstatus) + while((nstatus = (volatile u8)adapter->mbox->m_in.numstatus) == 0xFF) cpu_relax(); - adapter->mbox->numstatus = 0xFF; + adapter->mbox->m_in.numstatus = 0xFF; - status = adapter->mbox->status; + status = adapter->mbox->m_in.status; /* * decrement the pending queue counter */ atomic_sub(nstatus, &adapter->pend_cmds); - memcpy(completed, (void *)adapter->mbox->completed, nstatus); + memcpy(completed, (void *)adapter->mbox->m_in.completed, + nstatus); /* Acknowledge interrupt */ irq_ack(adapter); @@ -1843,20 +1844,21 @@ } WROUTDOOR(adapter, 0x10001234); - while((nstatus = (volatile u8)adapter->mbox->numstatus) + while((nstatus = (volatile u8)adapter->mbox->m_in.numstatus) == 0xFF) { cpu_relax(); } - adapter->mbox->numstatus = 0xFF; + adapter->mbox->m_in.numstatus = 0xFF; - status = adapter->mbox->status; + status = adapter->mbox->m_in.status; /* * decrement the pending queue counter */ atomic_sub(nstatus, &adapter->pend_cmds); - memcpy(completed, (void *)adapter->mbox->completed, nstatus); + memcpy(completed, (void *)adapter->mbox->m_in.completed, + nstatus); /* Acknowledge interrupt */ WRINDOOR(adapter, 0x2); @@ -1986,7 +1988,7 @@ #if MEGA_HAVE_STATS { - int logdrv = mbox->logdrv; + int logdrv = mbox->m_out.logdrv; islogical = adapter->logdrv_chan[cmd->channel]; /* @@ -2065,8 +2067,8 @@ SCSI_STATUS_CHECK_CONDITION */ /* set sense_buffer and result fields */ - if( mbox->cmd == MEGA_MBOXCMD_PASSTHRU || - mbox->cmd == MEGA_MBOXCMD_PASSTHRU64 ) { + if( mbox->m_out.cmd == MEGA_MBOXCMD_PASSTHRU || + mbox->m_out.cmd == MEGA_MBOXCMD_PASSTHRU64 ) { memcpy(cmd->sense_buffer, pthru->reqsensearea, 14); @@ -2076,7 +2078,7 @@ (CHECK_CONDITION << 1); } else { - if (mbox->cmd == MEGA_MBOXCMD_EXTPTHRU) { + if (mbox->m_out.cmd == MEGA_MBOXCMD_EXTPTHRU) { memcpy(cmd->sense_buffer, epthru->reqsensearea, 14); @@ -2233,7 +2235,7 @@ static inline int mega_busywait_mbox (adapter_t *adapter) { - if (adapter->mbox->busy) + if (adapter->mbox->m_in.busy) return __mega_busywait_mbox(adapter); return 0; } @@ -2245,7 +2247,7 @@ long counter; for (counter = 0; counter < 10000; counter++) { - if (!mbox->busy) + if (!mbox->m_in.busy) return 0; udelay(100); yield(); } @@ -2400,7 +2402,7 @@ { adapter_t *adapter; mbox_t *mbox; - u_char raw_mbox[sizeof(mbox_t)]; + u_char raw_mbox[sizeof(struct mbox_out)]; char buf[12] = { 0 }; adapter = (adapter_t *)host->hostdata; @@ -2409,7 +2411,7 @@ printk(KERN_NOTICE "megaraid: being unloaded..."); /* Flush adapter cache */ - memset(mbox, 0, sizeof(*mbox)); + memset(&mbox->m_out, 0, sizeof(raw_mbox)); raw_mbox[0] = FLUSH_ADAPTER; irq_disable(adapter); @@ -2419,7 +2421,7 @@ issue_scb_block(adapter, raw_mbox); /* Flush disks cache */ - memset(mbox, 0, sizeof(*mbox)); + memset(&mbox->m_out, 0, sizeof(raw_mbox)); raw_mbox[0] = FLUSH_SYSTEM; /* Issue a blocking (interrupts disabled) command to the card */ @@ -2569,35 +2571,6 @@ return buffer; } -volatile static int internal_done_flag = 0; -volatile static int internal_done_errcode = 0; - -static DECLARE_WAIT_QUEUE_HEAD (internal_wait); - -static void internal_done (Scsi_Cmnd *cmd) -{ - internal_done_errcode = cmd->result; - internal_done_flag++; - wake_up (&internal_wait); -} - -/* shouldn't be used, but included for completeness */ - -static int -megaraid_command (Scsi_Cmnd *cmd) -{ - internal_done_flag = 0; - - /* Queue command, and wait until it has completed */ - megaraid_queue (cmd, internal_done); - - while (!internal_done_flag) - interruptible_sleep_on (&internal_wait); - - return internal_done_errcode; -} - - /* * Abort a previous SCSI request. Only commands on the pending list can be * aborted. All the commands issued to the F/W must complete. @@ -2979,16 +2952,24 @@ int len = 0; len = sprintf(page, "Contents of Mail Box Structure\n"); - len += sprintf(page+len, " Fw Command = 0x%02x\n", mbox->cmd); - len += sprintf(page+len, " Cmd Sequence = 0x%02x\n", mbox->cmdid); - len += sprintf(page+len, " No of Sectors= %04d\n", mbox->numsectors); - len += sprintf(page+len, " LBA = 0x%02x\n", mbox->lba); - len += sprintf(page+len, " DTA = 0x%08x\n", mbox->xferaddr); - len += sprintf(page+len, " Logical Drive= 0x%02x\n", mbox->logdrv); + len += sprintf(page+len, " Fw Command = 0x%02x\n", + mbox->m_out.cmd); + len += sprintf(page+len, " Cmd Sequence = 0x%02x\n", + mbox->m_out.cmdid); + len += sprintf(page+len, " No of Sectors= %04d\n", + mbox->m_out.numsectors); + len += sprintf(page+len, " LBA = 0x%02x\n", + mbox->m_out.lba); + len += sprintf(page+len, " DTA = 0x%08x\n", + mbox->m_out.xferaddr); + len += sprintf(page+len, " Logical Drive= 0x%02x\n", + mbox->m_out.logdrv); len += sprintf(page+len, " No of SG Elmt= 0x%02x\n", - mbox->numsgelements); - len += sprintf(page+len, " Busy = %01x\n", mbox->busy); - len += sprintf(page+len, " Status = 0x%02x\n", mbox->status); + mbox->m_out.numsgelements); + len += sprintf(page+len, " Busy = %01x\n", + mbox->m_in.busy); + len += sprintf(page+len, " Status = 0x%02x\n", + mbox->m_in.status); *eof = 1; @@ -3881,7 +3862,7 @@ { adapter_t *adapter; struct Scsi_Host *host; - u8 raw_mbox[sizeof(mbox_t)]; + u8 raw_mbox[sizeof(struct mbox_out)]; mbox_t *mbox; int i,j; @@ -3897,7 +3878,7 @@ mbox = (mbox_t *)raw_mbox; /* Flush adapter cache */ - memset(mbox, 0, sizeof(*mbox)); + memset(&mbox->m_out, 0, sizeof(raw_mbox)); raw_mbox[0] = FLUSH_ADAPTER; irq_disable(adapter); @@ -3910,7 +3891,7 @@ issue_scb_block(adapter, raw_mbox); /* Flush disks cache */ - memset(mbox, 0, sizeof(*mbox)); + memset(&mbox->m_out, 0, sizeof(raw_mbox)); raw_mbox[0] = FLUSH_SYSTEM; issue_scb_block(adapter, raw_mbox); @@ -4643,17 +4624,17 @@ static int mega_is_bios_enabled(adapter_t *adapter) { - unsigned char raw_mbox[sizeof(mbox_t)]; + unsigned char raw_mbox[sizeof(struct mbox_out)]; mbox_t *mbox; int ret; mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, sizeof(*mbox)); + memset(&mbox->m_out, 0, sizeof(raw_mbox)); memset((void *)adapter->mega_buffer, 0, MEGA_BUFFER_SIZE); - mbox->xferaddr = (u32)adapter->buf_dma_handle; + mbox->m_out.xferaddr = (u32)adapter->buf_dma_handle; raw_mbox[0] = IS_BIOS_ENABLED; raw_mbox[2] = GET_BIOS; @@ -4676,13 +4657,13 @@ static void mega_enum_raid_scsi(adapter_t *adapter) { - unsigned char raw_mbox[sizeof(mbox_t)]; + unsigned char raw_mbox[sizeof(struct mbox_out)]; mbox_t *mbox; int i; mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, sizeof(*mbox)); + memset(&mbox->m_out, 0, sizeof(raw_mbox)); /* * issue command to find out what channels are raid/scsi @@ -4692,7 +4673,7 @@ memset((void *)adapter->mega_buffer, 0, MEGA_BUFFER_SIZE); - mbox->xferaddr = (u32)adapter->buf_dma_handle; + mbox->m_out.xferaddr = (u32)adapter->buf_dma_handle; /* * Non-ROMB firware fail this command, so all channels @@ -4731,7 +4712,7 @@ mega_get_boot_drv(adapter_t *adapter) { struct private_bios_data *prv_bios_data; - unsigned char raw_mbox[sizeof(mbox_t)]; + unsigned char raw_mbox[sizeof(struct mbox_out)]; mbox_t *mbox; u16 cksum = 0; u8 *cksum_p; @@ -4740,14 +4721,14 @@ mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, sizeof(raw_mbox)); + memset(&mbox->m_out, 0, sizeof(raw_mbox)); raw_mbox[0] = BIOS_PVT_DATA; raw_mbox[2] = GET_BIOS_PVT_DATA; memset((void *)adapter->mega_buffer, 0, MEGA_BUFFER_SIZE); - mbox->xferaddr = (u32)adapter->buf_dma_handle; + mbox->m_out.xferaddr = (u32)adapter->buf_dma_handle; adapter->boot_ldrv_enabled = 0; adapter->boot_ldrv = 0; @@ -4797,13 +4778,13 @@ static int mega_support_random_del(adapter_t *adapter) { - unsigned char raw_mbox[sizeof(mbox_t)]; + unsigned char raw_mbox[sizeof(struct mbox_out)]; mbox_t *mbox; int rval; mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, sizeof(*mbox)); + memset(&mbox->m_out, 0, sizeof(raw_mbox)); /* * issue command @@ -4826,13 +4807,13 @@ static int mega_support_ext_cdb(adapter_t *adapter) { - unsigned char raw_mbox[sizeof(mbox_t)]; + unsigned char raw_mbox[sizeof(struct mbox_out)]; mbox_t *mbox; int rval; mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, sizeof(*mbox)); + memset(&mbox->m_out, 0, sizeof(raw_mbox)); /* * issue command to find out if controller supports extended CDBs. */ @@ -4944,7 +4925,7 @@ static void mega_get_max_sgl(adapter_t *adapter) { - unsigned char raw_mbox[sizeof(mbox_t)]; + unsigned char raw_mbox[sizeof(struct mbox_out)]; mbox_t *mbox; mbox = (mbox_t *)raw_mbox; @@ -4953,7 +4934,7 @@ memset((void *)adapter->mega_buffer, 0, MEGA_BUFFER_SIZE); - mbox->xferaddr = (u32)adapter->buf_dma_handle; + mbox->m_out.xferaddr = (u32)adapter->buf_dma_handle; raw_mbox[0] = MAIN_MISC_OPCODE; raw_mbox[2] = GET_MAX_SG_SUPPORT; @@ -4989,7 +4970,7 @@ static int mega_support_cluster(adapter_t *adapter) { - unsigned char raw_mbox[sizeof(mbox_t)]; + unsigned char raw_mbox[sizeof(struct mbox_out)]; mbox_t *mbox; mbox = (mbox_t *)raw_mbox; @@ -4998,7 +4979,7 @@ memset((void *)adapter->mega_buffer, 0, MEGA_BUFFER_SIZE); - mbox->xferaddr = (u32)adapter->buf_dma_handle; + mbox->m_out.xferaddr = (u32)adapter->buf_dma_handle; /* * Try to get the initiator id. This command will succeed iff the @@ -5367,7 +5348,6 @@ .detect = megaraid_detect, .release = megaraid_release, .info = megaraid_info, - .command = megaraid_command, .queuecommand = megaraid_queue, .bios_param = megaraid_biosparam, .max_sectors = MAX_SECTORS_PER_IO, diff -Nru a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h --- a/drivers/scsi/megaraid.h Mon May 12 07:26:13 2003 +++ b/drivers/scsi/megaraid.h Fri Jun 6 02:33:13 2003 @@ -120,8 +120,7 @@ #define NVIRT_CHAN 4 /* # of virtual channels to represent up to 60 logical drives */ - -typedef struct { +struct mbox_out { /* 0x0 */ u8 cmd; /* 0x1 */ u8 cmdid; /* 0x2 */ u16 numsectors; @@ -130,12 +129,20 @@ /* 0xC */ u8 logdrv; /* 0xD */ u8 numsgelements; /* 0xE */ u8 resvd; +} __attribute__ ((packed)); + +struct mbox_in { /* 0xF */ volatile u8 busy; /* 0x10 */ volatile u8 numstatus; /* 0x11 */ volatile u8 status; /* 0x12 */ volatile u8 completed[MAX_FIRMWARE_STATUS]; volatile u8 poll; volatile u8 ack; +} __attribute__ ((packed)); + +typedef struct { + struct mbox_out m_out; + struct mbox_in m_in; } __attribute__ ((packed)) mbox_t; typedef struct { @@ -1001,7 +1008,6 @@ static void mega_free_scb(adapter_t *, scb_t *); static int megaraid_release (struct Scsi_Host *); -static int megaraid_command (Scsi_Cmnd *); static int megaraid_abort(Scsi_Cmnd *); static int megaraid_reset(Scsi_Cmnd *); static int megaraid_abort_and_reset(adapter_t *, Scsi_Cmnd *, int); diff -Nru a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c --- a/drivers/scsi/mesh.c Wed Apr 23 06:09:26 2003 +++ b/drivers/scsi/mesh.c Sun Jun 8 12:18:41 2003 @@ -2047,11 +2047,8 @@ .name = "MESH", .detect = mesh_detect, .release = mesh_release, - .command = NULL, .queuecommand = mesh_queue, .eh_abort_handler = mesh_abort, - .eh_device_reset_handler = NULL, - .eh_bus_reset_handler = NULL, .eh_host_reset_handler = mesh_host_reset, .can_queue = 20, .this_id = 7, diff -Nru a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c --- a/drivers/scsi/mvme16x.c Wed Nov 20 03:36:31 2002 +++ b/drivers/scsi/mvme16x.c Mon Jun 2 17:27:45 2003 @@ -53,9 +53,22 @@ return 1; } +static int mvme16x_scsi_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->dma_channel != 0xff) + free_dma(shost->dma_channel); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + static Scsi_Host_Template driver_template = { .name = "MVME16x NCR53c710 SCSI", .detect = mvme16x_scsi_detect, + .release = mvme16x_scsi_release, .queuecommand = NCR53c7xx_queue_command, .abort = NCR53c7xx_abort, .reset = NCR53c7xx_reset, diff -Nru a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c --- a/drivers/scsi/nsp32.c Tue May 27 07:52:55 2003 +++ b/drivers/scsi/nsp32.c Mon Jun 2 17:42:21 2003 @@ -1621,7 +1621,7 @@ /* * register this HBA as SCSI device */ - host = scsi_register(&nsp32_template, sizeof(nsp32_hw_data)); + host = scsi_host_alloc(&nsp32_template, sizeof(nsp32_hw_data)); if (host == NULL) { nsp32_msg (KERN_ERR, "failed to scsi register"); goto err; @@ -1840,7 +1840,7 @@ kfree(data->lunt_list); scsi_unregister: - scsi_unregister(host); + scsi_host_put(host); err: return 1; diff -Nru a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c --- a/drivers/scsi/pas16.c Sun May 4 02:56:44 2003 +++ b/drivers/scsi/pas16.c Mon Jun 2 17:27:44 2003 @@ -600,9 +600,22 @@ #include "NCR5380.c" +static int pas16_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->dma_channel != 0xff) + free_dma(shost->dma_channel); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + static Scsi_Host_Template driver_template = { .name = "Pro Audio Spectrum-16 SCSI", .detect = pas16_detect, + .release = pas16_release, .queuecommand = pas16_queue_command, .eh_abort_handler = pas16_abort, .eh_bus_reset_handler = pas16_bus_reset, diff -Nru a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c --- a/drivers/scsi/pci2000.c Mon Jun 9 16:05:35 2003 +++ b/drivers/scsi/pci2000.c Wed Jun 11 20:06:30 2003 @@ -612,41 +612,6 @@ return 0; } /**************************************************************** - * Name: internal_done :LOCAL - * - * Description: Done handler for non-queued commands - * - * Parameters: SCpnt - Pointer to SCSI command structure. - * - * Returns: Nothing. - * - ****************************************************************/ -static void internal_done (Scsi_Cmnd * SCpnt) - { - SCpnt->SCp.Status++; - } -/**************************************************************** - * Name: Pci2000_Command - * - * Description: Process a command from the SCSI manager. - * - * Parameters: SCpnt - Pointer to SCSI command structure. - * - * Returns: Status code. - * - ****************************************************************/ -int Pci2000_Command (Scsi_Cmnd *SCpnt) - { - DEB(printk("pci2000_command: ..calling pci2000_queuecommand\n")); - - Pci2000_QueueCommand (SCpnt, internal_done); - - SCpnt->SCp.Status = 0; - while (!SCpnt->SCp.Status) - barrier (); - return SCpnt->result; - } -/**************************************************************** * Name: Pci2000_Detect * * Description: Detect and initialize our boards. @@ -856,7 +821,6 @@ .name = "PCI-2000 SCSI Intelligent Disk Controller", .detect = Pci2000_Detect, .release = Pci2000_Release, - .command = Pci2000_Command, .queuecommand = Pci2000_QueueCommand, .abort = Pci2000_Abort, .reset = Pci2000_Reset, diff -Nru a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c --- a/drivers/scsi/pci2220i.c Mon Jun 9 16:06:04 2003 +++ b/drivers/scsi/pci2220i.c Wed Jun 11 20:06:31 2003 @@ -2307,28 +2307,6 @@ } return 0; } -static void internal_done(Scsi_Cmnd *SCpnt) - { - SCpnt->SCp.Status++; - } -/**************************************************************** - * Name: Pci2220i_Command - * - * Description: Process a command from the SCSI manager. - * - * Parameters: SCpnt - Pointer to SCSI command structure. - * - * Returns: Status code. - * - ****************************************************************/ -int Pci2220i_Command (Scsi_Cmnd *SCpnt) - { - Pci2220i_QueueCommand (SCpnt, internal_done); - SCpnt->SCp.Status = 0; - while (!SCpnt->SCp.Status) - barrier (); - return SCpnt->result; - } /**************************************************************** * Name: ReadFlash * @@ -2924,7 +2902,6 @@ .name = "PCI-2220I/PCI-2240I", .detect = Pci2220i_Detect, .release = Pci2220i_Release, - .command = Pci2220i_Command, .queuecommand = Pci2220i_QueueCommand, .abort = Pci2220i_Abort, .reset = Pci2220i_Reset, diff -Nru a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c --- a/drivers/scsi/pcmcia/nsp_cs.c Mon May 12 08:14:55 2003 +++ b/drivers/scsi/pcmcia/nsp_cs.c Mon Jun 2 17:42:21 2003 @@ -1222,7 +1222,7 @@ DEBUG(0, "%s: this_id=%d\n", __FUNCTION__, sht->this_id); request_region(data->BaseAddress, data->NumAddress, "nsp_cs"); - host = scsi_register(sht, 0); + host = scsi_host_alloc(sht, 0); if(host == NULL) return NULL; diff -Nru a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c --- a/drivers/scsi/ppa.c Tue May 27 08:56:01 2003 +++ b/drivers/scsi/ppa.c Sun Jun 8 12:18:41 2003 @@ -103,7 +103,6 @@ .name = "Iomega VPI0 (ppa) interface", .detect = ppa_detect, .release = ppa_release, - .command = ppa_command, .queuecommand = ppa_queuecommand, .eh_abort_handler = ppa_abort, .eh_bus_reset_handler = ppa_reset, @@ -759,39 +758,6 @@ return 0; } return 1; /* FINISH_RETURN */ -} - -/* deprecated synchronous interface */ -int ppa_command(Scsi_Cmnd * cmd) -{ - static int first_pass = 1; - int host_no = cmd->device->host->unique_id; - - if (first_pass) { - printk("ppa: using non-queuing interface\n"); - first_pass = 0; - } - if (ppa_hosts[host_no].cur_cmd) { - printk("PPA: bug in ppa_command\n"); - return 0; - } - ppa_hosts[host_no].failed = 0; - ppa_hosts[host_no].jstart = jiffies; - ppa_hosts[host_no].cur_cmd = cmd; - cmd->result = DID_ERROR << 16; /* default return code */ - cmd->SCp.phase = 0; - - ppa_pb_claim(host_no); - - while (ppa_engine(&ppa_hosts[host_no], cmd)) - schedule(); - - if (cmd->SCp.phase) /* Only disconnect if we have connected */ - ppa_disconnect(cmd->device->host->unique_id); - - ppa_pb_release(host_no); - ppa_hosts[host_no].cur_cmd = 0; - return cmd->result; } /* diff -Nru a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c --- a/drivers/scsi/psi240i.c Sun May 4 02:56:45 2003 +++ b/drivers/scsi/psi240i.c Sun Jun 8 12:18:41 2003 @@ -496,31 +496,6 @@ return 0; } -static void internal_done(Scsi_Cmnd * SCpnt) - { - SCpnt->SCp.Status++; - } -/**************************************************************** - * Name: Psi240i_Command - * - * Description: Process a command from the SCSI manager. - * - * Parameters: SCpnt - Pointer to SCSI command structure. - * - * Returns: Status code. - * - ****************************************************************/ -int Psi240i_Command (Scsi_Cmnd *SCpnt) - { - DEB(printk("psi240i_command: ..calling psi240i_queuecommand\n")); - - Psi240i_QueueCommand (SCpnt, internal_done); - - SCpnt->SCp.Status = 0; - while (!SCpnt->SCp.Status) - barrier (); - return SCpnt->result; - } /*************************************************************************** * Name: ReadChipMemory * @@ -655,6 +630,17 @@ } return count; } + +static int Psi240i_Release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + /**************************************************************** * Name: Psi240i_Abort * @@ -722,7 +708,7 @@ .proc_name = "psi240i", .name = "PSI-240I EIDE Disk Controller", .detect = Psi240i_Detect, - .command = Psi240i_Command, + .release = Psi240i_Release, .queuecommand = Psi240i_QueueCommand, .abort = Psi240i_Abort, .reset = Psi240i_Reset, diff -Nru a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c --- a/drivers/scsi/qlogicfas.c Sat Apr 26 07:28:27 2003 +++ b/drivers/scsi/qlogicfas.c Sun Jun 8 12:18:41 2003 @@ -544,46 +544,6 @@ #if QL_USE_IRQ -static void qlidone(Scsi_Cmnd * cmd) -{ -} /* null function */ - -#endif - -/* - * Synchronous command processing - */ - -static int qlogicfas_command(Scsi_Cmnd * cmd) -{ - int k; -#if QL_USE_IRQ - if (qlirq >= 0) { - qlogicfas_queuecommand(cmd, qlidone); - while (qlcmd != NULL) - { - cpu_relax(); - barrier(); - } - return cmd->result; - } -#endif - - /* - * Non-irq version - */ - - if (cmd->device->id == qinitid) - return (DID_BAD_TARGET << 16); - ql_icmd(cmd); - if ((k = ql_wai())) - return (k << 16); - return ql_pcmd(cmd); - -} - -#if QL_USE_IRQ - /* * Queued command */ @@ -739,6 +699,18 @@ return (__qlogicfas_detect(sht) != NULL); } +static int qlogicfas_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->dma_channel != 0xff) + free_dma(shost->dma_channel); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + /* * Return bios parameters */ @@ -826,8 +798,8 @@ .name = "qlogicfas", .proc_name = "qlogicfas", .detect = qlogicfas_detect, + .release = qlogicfas_release, .info = qlogicfas_info, - .command = qlogicfas_command, .queuecommand = qlogicfas_queuecommand, .eh_abort_handler = qlogicfas_abort, .eh_bus_reset_handler = qlogicfas_bus_reset, diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c --- a/drivers/scsi/scsi.c Mon May 26 02:50:43 2003 +++ b/drivers/scsi/scsi.c Sun Jun 8 13:31:57 2003 @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -82,7 +83,6 @@ * Data declarations. */ unsigned long scsi_pid; -struct scsi_cmnd *last_cmnd; static unsigned long serial_number; /* @@ -108,26 +108,6 @@ "Enclosure ", }; -MODULE_PARM(scsi_logging_level, "i"); -MODULE_PARM_DESC(scsi_logging_level, "SCSI logging level; should be zero or nonzero"); - -#ifndef MODULE -static int __init scsi_logging_setup(char *str) -{ - int tmp; - - if (get_option(&str, &tmp) == 1) { - scsi_logging_level = (tmp ? ~0 : 0); - return 1; - } else { - printk(KERN_INFO "scsi_logging_setup : usage scsi_logging_level=n " - "(n should be 0 or non-zero)\n"); - return 0; - } -} -__setup("scsi_logging=", scsi_logging_setup); -#endif - /* * Function: scsi_allocate_request * @@ -460,29 +440,18 @@ goto out; } - if (host->can_queue) { - SCSI_LOG_MLQUEUE(3, printk("queuecommand : routine at %p\n", - host->hostt->queuecommand)); + SCSI_LOG_MLQUEUE(3, printk("queuecommand : routine at %p\n", + host->hostt->queuecommand)); - spin_lock_irqsave(host->host_lock, flags); - rtn = host->hostt->queuecommand(cmd, scsi_done); - spin_unlock_irqrestore(host->host_lock, flags); - if (rtn) { - scsi_queue_insert(cmd, + spin_lock_irqsave(host->host_lock, flags); + rtn = host->hostt->queuecommand(cmd, scsi_done); + spin_unlock_irqrestore(host->host_lock, flags); + if (rtn) { + scsi_queue_insert(cmd, (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ? - rtn : SCSI_MLQUEUE_HOST_BUSY); - SCSI_LOG_MLQUEUE(3, - printk("queuecommand : request rejected\n")); - } - } else { - SCSI_LOG_MLQUEUE(3, printk("command() : routine at %p\n", - host->hostt->command)); - - spin_lock_irqsave(host->host_lock, flags); - cmd->result = host->hostt->command(cmd); - scsi_done(cmd); - spin_unlock_irqrestore(host->host_lock, flags); - rtn = 0; + rtn : SCSI_MLQUEUE_HOST_BUSY); + SCSI_LOG_MLQUEUE(3, + printk("queuecommand : request rejected\n")); } out: @@ -752,16 +721,8 @@ struct scsi_device *sdev = cmd->device; struct Scsi_Host *shost = sdev->host; struct scsi_request *sreq; - unsigned long flags; - scsi_host_busy_dec_and_test(shost, sdev); - - /* - * XXX(hch): We really want a nice helper for this.. - */ - spin_lock_irqsave(&sdev->sdev_lock, flags); - sdev->device_busy--; - spin_unlock_irqrestore(&sdev->sdev_lock, flags); + scsi_device_unbusy(sdev); /* * Clear the flags which say that the device/host is no longer @@ -983,6 +944,9 @@ MODULE_DESCRIPTION("SCSI core"); MODULE_LICENSE("GPL"); +module_param(scsi_logging_level, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(scsi_logging_level, "a bit mask of logging levels"); + static int __init init_scsi(void) { int error, i; @@ -1003,7 +967,6 @@ for (i = 0; i < NR_CPUS; i++) INIT_LIST_HEAD(&done_q[i]); - scsi_host_init(); devfs_mk_dir("scsi"); open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL); printk(KERN_NOTICE "SCSI subsystem initialized\n"); diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h --- a/drivers/scsi/scsi.h Mon May 26 02:50:43 2003 +++ b/drivers/scsi/scsi.h Sun Jun 8 15:03:00 2003 @@ -16,6 +16,12 @@ #define _SCSI_H #include /* for CONFIG_SCSI_LOGGING */ + +#include +#include +#include +#include +#include #include /* @@ -112,19 +118,6 @@ #define SOFT_ERROR 0x2005 #define ADD_TO_MLQUEUE 0x2006 -/* - * These are the values that scsi_cmd->state can take. - */ -#define SCSI_STATE_TIMEOUT 0x1000 -#define SCSI_STATE_FINISHED 0x1001 -#define SCSI_STATE_FAILED 0x1002 -#define SCSI_STATE_QUEUED 0x1003 -#define SCSI_STATE_UNUSED 0x1006 -#define SCSI_STATE_DISCONNECTING 0x1008 -#define SCSI_STATE_INITIALIZING 0x1009 -#define SCSI_STATE_BHQUEUE 0x100a -#define SCSI_STATE_MLQUEUE 0x100b - #define IDENTIFY_BASE 0x80 #define IDENTIFY(can_disconnect, lun) (IDENTIFY_BASE |\ ((can_disconnect) ? 0x40 : 0) |\ @@ -169,9 +162,6 @@ #define DRIVER_MASK 0x0f #define SUGGEST_MASK 0xf0 -#define MAX_COMMAND_SIZE 16 -#define SCSI_SENSE_BUFFERSIZE 64 - /* * SCSI command sets */ @@ -204,96 +194,20 @@ #define ASKED_FOR_SENSE 0x20 #define SYNC_RESET 0x40 -/* - * This specifies "machine infinity" for host templates which don't - * limit the transfer size. Note this limit represents an absolute - * maximum, and may be over the transfer limits allowed for individual - * devices (e.g. 256 for SCSI-1) - */ -#define SCSI_DEFAULT_MAX_SECTORS 1024 - -/* - * This is the crap from the old error handling code. We have it in a special - * place so that we can more easily delete it later on. - */ -#include "scsi_obsolete.h" - -/* - * Forward-declaration of structs for prototypes. - */ struct Scsi_Host; +struct scsi_cmnd; +struct scsi_device; struct scsi_target; struct scatterlist; /* - * Add some typedefs so that we can prototyope a bunch of the functions. - */ -typedef struct scsi_device Scsi_Device; -typedef struct scsi_cmnd Scsi_Cmnd; -typedef struct scsi_request Scsi_Request; - -/* - * These are the error handling functions defined in scsi_error.c - */ -extern void scsi_add_timer(Scsi_Cmnd * SCset, int timeout, - void (*complete) (Scsi_Cmnd *)); -extern int scsi_delete_timer(Scsi_Cmnd * SCset); -extern int scsi_block_when_processing_errors(Scsi_Device *); -extern void scsi_sleep(int); - -/* - * Prototypes for functions in scsicam.c - */ -extern int scsi_partsize(unsigned char *buf, unsigned long capacity, - unsigned int *cyls, unsigned int *hds, - unsigned int *secs); - -/* - * Prototypes for functions in scsi_lib.c - */ -extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors, - int block_sectors); - -/* - * Prototypes for functions in scsi.c - */ -extern struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int flags); -extern void scsi_put_command(struct scsi_cmnd *cmd); -extern void scsi_adjust_queue_depth(Scsi_Device *, int, int); -extern int scsi_track_queue_full(Scsi_Device *, int); -extern int scsi_device_get(struct scsi_device *); -extern void scsi_device_put(struct scsi_device *); -extern void scsi_set_device_offline(struct scsi_device *); - -/* - * Newer request-based interfaces. - */ -extern Scsi_Request *scsi_allocate_request(Scsi_Device *); -extern void scsi_release_request(Scsi_Request *); -extern void scsi_wait_req(Scsi_Request *, const void *cmnd, - void *buffer, unsigned bufflen, - int timeout, int retries); -extern void scsi_do_req(Scsi_Request *, const void *cmnd, - void *buffer, unsigned bufflen, - void (*done) (struct scsi_cmnd *), - int timeout, int retries); - -/* - * Prototypes for functions in scsi_scan.c - */ -extern struct scsi_device *scsi_add_device(struct Scsi_Host *, - uint, uint, uint); -extern int scsi_remove_device(struct scsi_device *); -extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *); - -/* * Prototypes for functions in constants.c * Some of these used to live in constants.h */ -extern void print_Scsi_Cmnd (Scsi_Cmnd *); +extern void print_Scsi_Cmnd(struct scsi_cmnd *); extern void print_command(unsigned char *); -extern void print_sense(const char *, Scsi_Cmnd *); -extern void print_req_sense(const char *, Scsi_Request *); +extern void print_sense(const char *, struct scsi_cmnd *); +extern void print_req_sense(const char *, struct scsi_request *); extern void print_driverbyte(int scsiresult); extern void print_hostbyte(int scsiresult); extern void print_status(unsigned char status); @@ -301,286 +215,6 @@ extern const char *scsi_sense_key_string(unsigned char); extern const char *scsi_extd_sense_format(unsigned char, unsigned char); - -/* - * The scsi_device struct contains what we know about each given scsi - * device. - * - * FIXME(eric) - One of the great regrets that I have is that I failed to - * define these structure elements as something like sdev_foo instead of foo. - * This would make it so much easier to grep through sources and so forth. - * I propose that all new elements that get added to these structures follow - * this convention. As time goes on and as people have the stomach for it, - * it should be possible to go back and retrofit at least some of the elements - * here with with the prefix. - */ - -struct scsi_device { - struct class_device sdev_classdev; - /* - * This information is private to the scsi mid-layer. - */ - struct list_head siblings; /* list of all devices on this host */ - struct list_head same_target_siblings; /* just the devices sharing same target id */ - struct Scsi_Host *host; - request_queue_t *request_queue; - volatile unsigned short device_busy; /* commands actually active on low-level */ - spinlock_t sdev_lock; /* also the request queue_lock */ - spinlock_t list_lock; - struct list_head cmd_list; /* queue of in use SCSI Command structures */ - struct list_head starved_entry; - Scsi_Cmnd *current_cmnd; /* currently active command */ - unsigned short queue_depth; /* How deep of a queue we want */ - unsigned short last_queue_full_depth; /* These two are used by */ - unsigned short last_queue_full_count; /* scsi_track_queue_full() */ - unsigned long last_queue_full_time;/* don't let QUEUE_FULLs on the same - jiffie count on our counter, they - could all be from the same event. */ - - unsigned int id, lun, channel; - - unsigned int manufacturer; /* Manufacturer of device, for using - * vendor-specific cmd's */ - unsigned sector_size; /* size in bytes */ - - int access_count; /* Count of open channels/mounts */ - - void *hostdata; /* available to low-level driver */ - char devfs_name[256]; /* devfs junk */ - char type; - char scsi_level; - unsigned char inquiry_len; /* valid bytes in 'inquiry' */ - unsigned char * inquiry; /* INQUIRY response data */ - char * vendor; /* [back_compat] point into 'inquiry' ... */ - char * model; /* ... after scan; point to static string */ - char * rev; /* ... "nullnullnullnull" before scan */ - unsigned char current_tag; /* current tag */ -// unsigned char sync_min_period; /* Not less than this period */ -// unsigned char sync_max_offset; /* Not greater than this offset */ - struct scsi_target *sdev_target; /* used only for single_lun */ - - unsigned online:1; - unsigned writeable:1; - unsigned removable:1; - unsigned random:1; - unsigned changed:1; /* Data invalid due to media change */ - unsigned busy:1; /* Used to prevent races */ - unsigned lockable:1; /* Able to prevent media removal */ - unsigned locked:1; /* Media removal disabled */ - unsigned borken:1; /* Tell the Seagate driver to be - * painfully slow on this device */ - unsigned disconnect:1; /* can disconnect */ - unsigned soft_reset:1; /* Uses soft reset option */ - unsigned sdtr:1; /* Device supports SDTR messages */ - unsigned wdtr:1; /* Device supports WDTR messages */ - unsigned ppr:1; /* Device supports PPR messages */ - unsigned tagged_supported:1; /* Supports SCSI-II tagged queuing */ - unsigned tagged_queue:1;/* This is going away!!!! Look at simple_tags - instead!!! Please fix your driver now!! */ - unsigned simple_tags:1; /* simple queue tag messages are enabled */ - unsigned ordered_tags:1;/* ordered queue tag messages are enabled */ - unsigned single_lun:1; /* Indicates we should only allow I/O to - * one of the luns for the device at a - * time. */ - unsigned was_reset:1; /* There was a bus reset on the bus for - * this device */ - unsigned expecting_cc_ua:1; /* Expecting a CHECK_CONDITION/UNIT_ATTN - * because we did a bus reset. */ - unsigned use_10_for_rw:1; /* first try 10-byte read / write */ - unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */ - unsigned remap:1; /* support remapping */ -// unsigned sync:1; /* Sync transfer state, managed by host */ -// unsigned wide:1; /* WIDE transfer state, managed by host */ - unsigned no_start_on_add:1; /* do not issue start on add */ - - unsigned int device_blocked; /* Device returned QUEUE_FULL. */ - - unsigned int max_device_blocked; /* what device_blocked counts down from */ - /* default value if the device doesn't override */ - #define SCSI_DEFAULT_DEVICE_BLOCKED 3 - - struct device sdev_driverfs_dev; -}; -#define to_scsi_device(d) \ - container_of(d, struct scsi_device, sdev_driverfs_dev) - - -typedef struct scsi_pointer { - char *ptr; /* data pointer */ - int this_residual; /* left in this buffer */ - struct scatterlist *buffer; /* which buffer */ - int buffers_residual; /* how many buffers left */ - - dma_addr_t dma_handle; - - volatile int Status; - volatile int Message; - volatile int have_data_in; - volatile int sent_command; - volatile int phase; -} Scsi_Pointer; - -/* - * This is essentially a slimmed down version of Scsi_Cmnd. The point of - * having this is that requests that are injected into the queue as result - * of things like ioctls and character devices shouldn't be using a - * Scsi_Cmnd until such a time that the command is actually at the head - * of the queue and being sent to the driver. - */ -struct scsi_request { - int sr_magic; - int sr_result; /* Status code from lower level driver */ - unsigned char sr_sense_buffer[SCSI_SENSE_BUFFERSIZE]; /* obtained by REQUEST SENSE - * when CHECK CONDITION is - * received on original command - * (auto-sense) */ - - struct Scsi_Host *sr_host; - Scsi_Device *sr_device; - Scsi_Cmnd *sr_command; - struct request *sr_request; /* A copy of the command we are - working on */ - unsigned sr_bufflen; /* Size of data buffer */ - void *sr_buffer; /* Data buffer */ - int sr_allowed; - unsigned char sr_data_direction; - unsigned char sr_cmd_len; - unsigned char sr_cmnd[MAX_COMMAND_SIZE]; - void (*sr_done) (struct scsi_cmnd *); /* Mid-level done function */ - int sr_timeout_per_command; - unsigned short sr_use_sg; /* Number of pieces of scatter-gather */ - unsigned short sr_sglist_len; /* size of malloc'd scatter-gather list */ - unsigned sr_underflow; /* Return error if less than - this amount is transferred */ - void * upper_private_data; /* reserved for owner (usually upper - level driver) of this request */ -}; - -/* - * FIXME(eric) - one of the great regrets that I have is that I failed to - * define these structure elements as something like sc_foo instead of foo. - * This would make it so much easier to grep through sources and so forth. - * I propose that all new elements that get added to these structures follow - * this convention. As time goes on and as people have the stomach for it, - * it should be possible to go back and retrofit at least some of the elements - * here with with the prefix. - */ -struct scsi_cmnd { - int sc_magic; - - struct scsi_device *device; - unsigned short state; - unsigned short owner; - Scsi_Request *sc_request; - - struct list_head list; /* scsi_cmnd participates in queue lists */ - - struct list_head eh_entry; /* entry for the host eh_cmd_q */ - int eh_state; /* Used for state tracking in error handlr */ - int eh_eflags; /* Used by error handlr */ - void (*done) (struct scsi_cmnd *); /* Mid-level done function */ - /* - A SCSI Command is assigned a nonzero serial_number when internal_cmnd - passes it to the driver's queue command function. The serial_number - is cleared when scsi_done is entered indicating that the command has - been completed. If a timeout occurs, the serial number at the moment - of timeout is copied into serial_number_at_timeout. By subsequently - comparing the serial_number and serial_number_at_timeout fields - during abort or reset processing, we can detect whether the command - has already completed. This also detects cases where the command has - completed and the SCSI Command structure has already being reused - for another command, so that we can avoid incorrectly aborting or - resetting the new command. - */ - - unsigned long serial_number; - unsigned long serial_number_at_timeout; - - int retries; - int allowed; - int timeout_per_command; - int timeout_total; - int timeout; - - /* - * We handle the timeout differently if it happens when a reset, - * abort, etc are in process. - */ - unsigned volatile char internal_timeout; - - unsigned char cmd_len; - unsigned char old_cmd_len; - unsigned char sc_data_direction; - unsigned char sc_old_data_direction; - - /* These elements define the operation we are about to perform */ - unsigned char cmnd[MAX_COMMAND_SIZE]; - unsigned request_bufflen; /* Actual request size */ - - struct timer_list eh_timeout; /* Used to time out the command. */ - void *request_buffer; /* Actual requested buffer */ - - /* These elements define the operation we ultimately want to perform */ - unsigned char data_cmnd[MAX_COMMAND_SIZE]; - unsigned short old_use_sg; /* We save use_sg here when requesting - * sense info */ - unsigned short use_sg; /* Number of pieces of scatter-gather */ - unsigned short sglist_len; /* size of malloc'd scatter-gather list */ - unsigned short abort_reason; /* If the mid-level code requests an - * abort, this is the reason. */ - unsigned bufflen; /* Size of data buffer */ - void *buffer; /* Data buffer */ - - unsigned underflow; /* Return error if less than - this amount is transferred */ - unsigned old_underflow; /* save underflow here when reusing the - * command for error handling */ - - unsigned transfersize; /* How much we are guaranteed to - transfer with each SCSI transfer - (ie, between disconnect / - reconnects. Probably == sector - size */ - - int resid; /* Number of bytes requested to be - transferred less actual number - transferred (0 if not supported) */ - - struct request *request; /* The command we are - working on */ - - unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE]; /* obtained by REQUEST SENSE - * when CHECK CONDITION is - * received on original command - * (auto-sense) */ - - unsigned flags; - - /* Low-level done function - can be used by low-level driver to point - * to completion function. Not used by mid/upper level code. */ - void (*scsi_done) (struct scsi_cmnd *); - - /* - * The following fields can be written to by the host specific code. - * Everything else should be left alone. - */ - - Scsi_Pointer SCp; /* Scratchpad used by some host adapters */ - - unsigned char *host_scribble; /* The host adapter is allowed to - * call scsi_malloc and get some memory - * and hang it here. The host adapter - * is also expected to call scsi_free - * to release this memory. (The memory - * obtained by scsi_malloc is guaranteed - * to be at an address < 16Mb). */ - - int result; /* Status code from lower level driver */ - - unsigned char tag; /* SCSI-II queued command tag */ - unsigned long pid; /* Process ID, starts at 0 */ -}; - /* * Definitions and prototypes used for scsi mid-level queue. */ @@ -588,104 +222,18 @@ #define SCSI_MLQUEUE_DEVICE_BUSY 0x1056 #define SCSI_MLQUEUE_EH_RETRY 0x1057 -/* - * Reset request from external source - */ -#define SCSI_TRY_RESET_DEVICE 1 -#define SCSI_TRY_RESET_BUS 2 -#define SCSI_TRY_RESET_HOST 3 - -extern int scsi_reset_provider(Scsi_Device *, int); - -#define MSG_SIMPLE_TAG 0x20 -#define MSG_HEAD_TAG 0x21 -#define MSG_ORDERED_TAG 0x22 - -#define SCSI_NO_TAG (-1) /* identify no tag in use */ - -/** - * scsi_activate_tcq - turn on tag command queueing - * @SDpnt: device to turn on TCQ for - * @depth: queue depth - * - * Notes: - * Eventually, I hope depth would be the maximum depth - * the device could cope with and the real queue depth - * would be adjustable from 0 to depth. - **/ -static inline void scsi_activate_tcq(Scsi_Device *SDpnt, int depth) { - if(SDpnt->tagged_supported) { - if(!blk_queue_tagged(SDpnt->request_queue)) - blk_queue_init_tags(SDpnt->request_queue, depth); - scsi_adjust_queue_depth(SDpnt, MSG_ORDERED_TAG, depth); - } -} - -/** - * scsi_deactivate_tcq - turn off tag command queueing - * @SDpnt: device to turn off TCQ for - **/ -static inline void scsi_deactivate_tcq(Scsi_Device *SDpnt, int depth) { - if(blk_queue_tagged(SDpnt->request_queue)) - blk_queue_free_tags(SDpnt->request_queue); - scsi_adjust_queue_depth(SDpnt, 0, depth); -} - -/** - * scsi_populate_tag_msg - place a tag message in a buffer - * @SCpnt: pointer to the Scsi_Cmnd for the tag - * @msg: pointer to the area to place the tag - * - * Notes: - * designed to create the correct type of tag message for the - * particular request. Returns the size of the tag message. - * May return 0 if TCQ is disabled for this device. - **/ -static inline int scsi_populate_tag_msg(Scsi_Cmnd *SCpnt, char *msg) { - struct request *req = SCpnt->request; - - if(!blk_rq_tagged(req)) - return 0; - - if (req->flags & REQ_HARDBARRIER) - *msg++ = MSG_ORDERED_TAG; - else - *msg++ = MSG_SIMPLE_TAG; - - *msg++ = SCpnt->request->tag; - - return 2; -} - -/** - * scsi_find_tag - find a tagged command by device - * @SDpnt: pointer to the ScSI device - * @tag: the tag number - * - * Notes: - * Only works with tags allocated by the generic blk layer. - **/ -static inline Scsi_Cmnd *scsi_find_tag(Scsi_Device *SDpnt, int tag) { - - struct request *req; - - if(tag == SCSI_NO_TAG) - /* single command, look in space */ - return SDpnt->current_cmnd; - - req = blk_queue_find_tag(SDpnt->request_queue, tag); - - if(req == NULL) - return NULL; - - return (Scsi_Cmnd *)req->special; -} - -int scsi_set_medium_removal(Scsi_Device *dev, char state); - extern int scsi_sysfs_modify_sdev_attribute(struct device_attribute ***dev_attrs, struct device_attribute *attr); extern int scsi_sysfs_modify_shost_attribute(struct class_device_attribute ***class_attrs, struct class_device_attribute *attr); + +/* + * This is the crap from the old error handling code. We have it in a special + * place so that we can more easily delete it later on. + */ +#include "scsi_obsolete.h" + +/* obsolete typedef junk. */ +#include "scsi_typedefs.h" #endif /* _SCSI_H */ diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c --- a/drivers/scsi/scsi_debug.c Mon May 12 07:26:14 2003 +++ b/drivers/scsi/scsi_debug.c Mon Jun 2 17:42:21 2003 @@ -1681,7 +1681,7 @@ sdbg_host = to_sdebug_host(dev); - hpnt = scsi_register(&sdebug_driver_template, sizeof(sdbg_host)); + hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host)); if (NULL == hpnt) { printk(KERN_ERR "%s: scsi_register failed\n", __FUNCTION__); error = -ENODEV; @@ -1700,7 +1700,7 @@ if (error) { printk(KERN_ERR "%s: scsi_add_host failed\n", __FUNCTION__); error = -ENODEV; - scsi_unregister(hpnt); + scsi_host_put(hpnt); } @@ -1726,8 +1726,6 @@ return -EBUSY; } - scsi_unregister(sdbg_host->shost); - list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) { sdbg_devinfo = list_entry(lh, struct sdebug_dev_info, dev_list); @@ -1735,5 +1733,6 @@ kfree(sdbg_devinfo); } + scsi_host_put(sdbg_host->shost); return 0; } diff -Nru a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c --- a/drivers/scsi/scsi_devinfo.c Fri May 23 04:01:50 2003 +++ b/drivers/scsi/scsi_devinfo.c Wed Jun 11 14:07:46 2003 @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -23,9 +24,9 @@ static const char spaces[] = " "; /* 16 of them */ -static char *scsi_dev_flags; static unsigned scsi_default_dev_flags; static LIST_HEAD(scsi_dev_info_list); +static __init char scsi_dev_flags[256]; /* * scsi_static_device_list: deprecated list of devices that require @@ -180,6 +181,7 @@ {"SGI", "TP9400", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"SGI", "TP9500", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"MYLEX", "DACARMRB", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, { NULL, NULL, NULL, 0 }, }; @@ -450,35 +452,15 @@ return err; } -MODULE_PARM(scsi_dev_flags, "s"); -MODULE_PARM_DESC(scsi_dev_flags, - "Given scsi_dev_flags=vendor:model:flags, add a black/white list" - " entry for vendor and model with an integer value of flags" +module_param_string(dev_flags, scsi_dev_flags, sizeof(scsi_dev_flags), 0); +MODULE_PARM_DESC(dev_flags, + "Given scsi_dev_flags=vendor:model:flags[,v:m:f] add black/white" + " list entries for vendor and model with an integer value of flags" " to the scsi device info list"); -MODULE_PARM(scsi_default_dev_flags, "i"); -MODULE_PARM_DESC(scsi_default_dev_flags, - "scsi default device flag integer value"); -static int __init setup_scsi_dev_flags(char *str) -{ - scsi_dev_flags = str; - return 1; -} - -static int __init setup_scsi_default_dev_flags(char *str) -{ - unsigned int tmp; - if (get_option(&str, &tmp) == 1) { - scsi_default_dev_flags = tmp; - printk(KERN_WARNING "%s %d\n", __FUNCTION__, - scsi_default_dev_flags); - return 1; - } else { - printk(KERN_WARNING "%s: usage scsi_default_dev_flags=intr\n", - __FUNCTION__); - return 0; - } -} +module_param_named(default_dev_flags, scsi_default_dev_flags, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(default_dev_flags, + "scsi default device flag integer value"); /** * scsi_dev_info_list_delete: called from scsi.c:exit_scsi to remove @@ -540,6 +522,3 @@ scsi_exit_devinfo(); return error; } - -__setup("scsi_dev_flags=", setup_scsi_dev_flags); -__setup("scsi_default_dev_flags=", setup_scsi_default_dev_flags); diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c --- a/drivers/scsi/scsi_error.c Mon May 12 20:52:56 2003 +++ b/drivers/scsi/scsi_error.c Sun Jun 8 13:31:57 2003 @@ -44,6 +44,16 @@ #define BUS_RESET_SETTLE_TIME 10*HZ #define HOST_RESET_SETTLE_TIME 10*HZ +/* called with shost->host_lock held */ +void scsi_eh_wakeup(struct Scsi_Host *shost) +{ + if (shost->host_busy == shost->host_failed) { + up(shost->eh_wait); + SCSI_LOG_ERROR_RECOVERY(5, + printk("Waking error handler thread\n")); + } +} + /** * scsi_eh_scmd_add - add scsi cmd to error handling. * @scmd: scmd to run eh on. @@ -76,14 +86,8 @@ list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); shost->in_recovery = 1; shost->host_failed++; - if (shost->host_busy == shost->host_failed) { - up(shost->eh_wait); - SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler" - " thread\n")); - } - + scsi_eh_wakeup(shost); spin_unlock_irqrestore(shost->host_lock, flags); - return 1; } @@ -431,6 +435,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout) { struct Scsi_Host *host = scmd->device->host; + DECLARE_MUTEX_LOCKED(sem); unsigned long flags; int rtn = SUCCESS; @@ -444,71 +449,53 @@ scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) | (scmd->device->lun << 5 & 0xe0); - if (host->can_queue) { - DECLARE_MUTEX_LOCKED(sem); + scsi_add_timer(scmd, timeout, scsi_eh_times_out); - scsi_add_timer(scmd, timeout, scsi_eh_times_out); + /* + * set up the semaphore so we wait for the command to complete. + */ + scmd->device->host->eh_action = &sem; + scmd->request->rq_status = RQ_SCSI_BUSY; - /* - * set up the semaphore so we wait for the command to complete. - */ - scmd->device->host->eh_action = &sem; - scmd->request->rq_status = RQ_SCSI_BUSY; + spin_lock_irqsave(scmd->device->host->host_lock, flags); + host->hostt->queuecommand(scmd, scsi_eh_done); + spin_unlock_irqrestore(scmd->device->host->host_lock, flags); - spin_lock_irqsave(scmd->device->host->host_lock, flags); - host->hostt->queuecommand(scmd, scsi_eh_done); - spin_unlock_irqrestore(scmd->device->host->host_lock, flags); + down(&sem); - down(&sem); + scmd->device->host->eh_action = NULL; - scmd->device->host->eh_action = NULL; + /* + * see if timeout. if so, tell the host to forget about it. + * in other words, we don't want a callback any more. + */ + if (scsi_eh_eflags_chk(scmd, SCSI_EH_REC_TIMEOUT)) { + scsi_eh_eflags_clr(scmd, SCSI_EH_REC_TIMEOUT); + scmd->owner = SCSI_OWNER_LOWLEVEL; /* - * see if timeout. if so, tell the host to forget about it. - * in other words, we don't want a callback any more. + * as far as the low level driver is + * concerned, this command is still active, so + * we must give the low level driver a chance + * to abort it. (db) + * + * FIXME(eric) - we are not tracking whether we could + * abort a timed out command or not. not sure how + * we should treat them differently anyways. */ - if (scsi_eh_eflags_chk(scmd, SCSI_EH_REC_TIMEOUT)) { - scsi_eh_eflags_clr(scmd, SCSI_EH_REC_TIMEOUT); - scmd->owner = SCSI_OWNER_LOWLEVEL; - - /* - * as far as the low level driver is - * concerned, this command is still active, so - * we must give the low level driver a chance - * to abort it. (db) - * - * FIXME(eric) - we are not tracking whether we could - * abort a timed out command or not. not sure how - * we should treat them differently anyways. - */ - spin_lock_irqsave(scmd->device->host->host_lock, flags); - if (scmd->device->host->hostt->eh_abort_handler) - scmd->device->host->hostt->eh_abort_handler(scmd); - spin_unlock_irqrestore(scmd->device->host->host_lock, - flags); + spin_lock_irqsave(scmd->device->host->host_lock, flags); + if (scmd->device->host->hostt->eh_abort_handler) + scmd->device->host->hostt->eh_abort_handler(scmd); + spin_unlock_irqrestore(scmd->device->host->host_lock, flags); - scmd->request->rq_status = RQ_SCSI_DONE; - scmd->owner = SCSI_OWNER_ERROR_HANDLER; + scmd->request->rq_status = RQ_SCSI_DONE; + scmd->owner = SCSI_OWNER_ERROR_HANDLER; - rtn = FAILED; - } - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd: %p, rtn:%x\n", - __FUNCTION__, scmd, rtn)); - } else { - int temp; - - /* - * we damn well had better never use this code. there is no - * timeout protection here, since we would end up waiting in - * the actual low level driver, we don't know how to wake it up. - */ - spin_lock_irqsave(host->host_lock, flags); - temp = host->hostt->command(scmd); - spin_unlock_irqrestore(host->host_lock, flags); - - scmd->result = temp; - /* fall through to code below to examine status. */ + rtn = FAILED; } + + SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd: %p, rtn:%x\n", + __FUNCTION__, scmd, rtn)); /* * now examine the actual status codes to see whether the command diff -Nru a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c --- a/drivers/scsi/scsi_ioctl.c Sat Apr 26 13:04:25 2003 +++ b/drivers/scsi/scsi_ioctl.c Sun Jun 1 14:27:11 2003 @@ -90,75 +90,70 @@ * The output area is then filled in starting from the command byte. */ -static int ioctl_internal_command(Scsi_Device * dev, char *cmd, +static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, int timeout, int retries) { + struct scsi_request *sreq; int result; - Scsi_Request *SRpnt; - Scsi_Device *SDpnt; + SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); - SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", cmd[0])); - if (NULL == (SRpnt = scsi_allocate_request(dev))) { + sreq = scsi_allocate_request(sdev); + if (!sreq) { printk("SCSI internal ioctl failed, no memory\n"); return -ENOMEM; } - SRpnt->sr_data_direction = SCSI_DATA_NONE; - scsi_wait_req(SRpnt, cmd, NULL, 0, timeout, retries); + sreq->sr_data_direction = SCSI_DATA_NONE; + scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); - SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", SRpnt->sr_result)); + SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result)); - if (driver_byte(SRpnt->sr_result) != 0) - switch (SRpnt->sr_sense_buffer[2] & 0xf) { + if (driver_byte(sreq->sr_result)) { + switch (sreq->sr_sense_buffer[2] & 0xf) { case ILLEGAL_REQUEST: if (cmd[0] == ALLOW_MEDIUM_REMOVAL) - dev->lockable = 0; + sdev->lockable = 0; else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n"); break; case NOT_READY: /* This happens if there is no disc in drive */ - if (dev->removable && (cmd[0] != TEST_UNIT_READY)) { + if (sdev->removable && (cmd[0] != TEST_UNIT_READY)) { printk(KERN_INFO "Device not ready. Make sure there is a disc in the drive.\n"); break; } case UNIT_ATTENTION: - if (dev->removable) { - dev->changed = 1; - SRpnt->sr_result = 0; /* This is no longer considered an error */ - /* gag this error, VFS will log it anyway /axboe */ - /* printk(KERN_INFO "Disc change detected.\n"); */ + if (sdev->removable) { + sdev->changed = 1; + sreq->sr_result = 0; /* This is no longer considered an error */ break; } default: /* Fall through for non-removable media */ printk("SCSI error: host %d id %d lun %d return code = %x\n", - dev->host->host_no, - dev->id, - dev->lun, - SRpnt->sr_result); + sdev->host->host_no, + sdev->id, + sdev->lun, + sreq->sr_result); printk("\tSense class %x, sense error %x, extended sense %x\n", - sense_class(SRpnt->sr_sense_buffer[0]), - sense_error(SRpnt->sr_sense_buffer[0]), - SRpnt->sr_sense_buffer[2] & 0xf); + sense_class(sreq->sr_sense_buffer[0]), + sense_error(sreq->sr_sense_buffer[0]), + sreq->sr_sense_buffer[2] & 0xf); } + } - result = SRpnt->sr_result; - + result = sreq->sr_result; SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); - SDpnt = SRpnt->sr_device; - scsi_release_request(SRpnt); - SRpnt = NULL; - + scsi_release_request(sreq); return result; } -int scsi_set_medium_removal(Scsi_Device *dev, char state) +int scsi_set_medium_removal(struct scsi_device *sdev, char state) { char scsi_cmd[MAX_COMMAND_SIZE]; int ret; - if (!dev->removable || !dev->lockable) + if (!sdev->removable || !sdev->lockable) return 0; scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; @@ -168,11 +163,10 @@ scsi_cmd[4] = state; scsi_cmd[5] = 0; - ret = ioctl_internal_command(dev, scsi_cmd, IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES); - + ret = ioctl_internal_command(sdev, scsi_cmd, + IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES); if (ret == 0) - dev->locked = state == SCSI_REMOVAL_PREVENT; - + sdev->locked = (state == SCSI_REMOVAL_PREVENT); return ret; } @@ -209,13 +203,13 @@ */ #define OMAX_SB_LEN 16 /* Old sense buffer length */ -int scsi_ioctl_send_command(Scsi_Device * dev, Scsi_Ioctl_Command * sic) +int scsi_ioctl_send_command(struct scsi_device *sdev, + struct scsi_ioctl_command *sic) { char *buf; unsigned char cmd[MAX_COMMAND_SIZE]; char *cmd_in; - Scsi_Request *SRpnt; - Scsi_Device *SDpnt; + struct scsi_request *sreq; unsigned char opcode; unsigned int inlen, outlen, cmdlen; unsigned int needed, buf_needed; @@ -225,7 +219,7 @@ if (!sic) return -EINVAL; - if (dev->host->unchecked_isa_dma) + if (sdev->host->unchecked_isa_dma) gfp_mask |= GFP_DMA; /* @@ -259,11 +253,11 @@ buf_needed = (buf_needed + 511) & ~511; if (buf_needed > MAX_BUF) buf_needed = MAX_BUF; - buf = (char *) kmalloc(buf_needed, gfp_mask); + buf = kmalloc(buf_needed, gfp_mask); if (!buf) return -ENOMEM; memset(buf, 0, buf_needed); - if( inlen == 0 ) { + if (inlen == 0) { data_direction = SCSI_DATA_READ; } else if (outlen == 0 ) { data_direction = SCSI_DATA_WRITE; @@ -327,62 +321,34 @@ break; } -#ifndef DEBUG_NO_CMD - - - SRpnt = scsi_allocate_request(dev); - if( SRpnt == NULL ) - { + sreq = scsi_allocate_request(sdev); + if (sreq) { result = -EINTR; goto error; } - SRpnt->sr_data_direction = data_direction; - scsi_wait_req(SRpnt, cmd, buf, needed, timeout, retries); + sreq->sr_data_direction = data_direction; + scsi_wait_req(sreq, cmd, buf, needed, timeout, retries); /* * If there was an error condition, pass the info back to the user. */ - - result = SRpnt->sr_result; - - if (SRpnt->sr_result) { - int sb_len = sizeof(SRpnt->sr_sense_buffer); + result = sreq->sr_result; + if (result) { + int sb_len = sizeof(sreq->sr_sense_buffer); sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len; - if (copy_to_user(cmd_in, SRpnt->sr_sense_buffer, sb_len)) + if (copy_to_user(cmd_in, sreq->sr_sense_buffer, sb_len)) result = -EFAULT; } else { if (copy_to_user(cmd_in, buf, outlen)) result = -EFAULT; } - SDpnt = SRpnt->sr_device; - scsi_release_request(SRpnt); - SRpnt = NULL; - + scsi_release_request(sreq); error: - if (buf) - kfree(buf); - - + kfree(buf); return result; -#else - { - int i; - printk("scsi_ioctl : device %d. command = ", dev->id); - for (i = 0; i < cmdlen; ++i) - printk("%02x ", cmd[i]); - printk("\nbuffer ="); - for (i = 0; i < 20; ++i) - printk("%02x ", buf[i]); - printk("\n"); - printk("inlen = %d, outlen = %d, cmdlen = %d\n", - inlen, outlen, cmdlen); - printk("buffer = %d, cmd_in = %d\n", buffer, cmd_in); - } - return 0; -#endif } /* @@ -395,14 +361,13 @@ * device) * any copy_to_user() error on failure there */ -static int -scsi_ioctl_get_pci(Scsi_Device * sdev, void *arg) +static int scsi_ioctl_get_pci(struct scsi_device *sdev, void *arg) { struct device *dev = scsi_get_device(sdev->host); - if (!dev) return -ENXIO; - return copy_to_user(arg, dev->bus_id, - sizeof(dev->bus_id)); + if (!dev) + return -ENXIO; + return copy_to_user(arg, dev->bus_id, sizeof(dev->bus_id)); } @@ -411,12 +376,12 @@ * not take a major/minor number as the dev field. Rather, it takes * a pointer to a scsi_devices[] element, a structure. */ -int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg) +int scsi_ioctl(struct scsi_device *sdev, int cmd, void *arg) { char scsi_cmd[MAX_COMMAND_SIZE]; /* No idea how this happens.... */ - if (!dev) + if (!sdev) return -ENXIO; /* @@ -425,24 +390,24 @@ * may try and take the device offline, in which case all further * access to the device is prohibited. */ - if (!scsi_block_when_processing_errors(dev)) { + if (!scsi_block_when_processing_errors(sdev)) return -ENODEV; - } switch (cmd) { case SCSI_IOCTL_GET_IDLUN: - if (verify_area(VERIFY_WRITE, arg, sizeof(Scsi_Idlun))) + if (verify_area(VERIFY_WRITE, arg, sizeof(struct scsi_idlun))) return -EFAULT; - __put_user((dev->id & 0xff) - + ((dev->lun & 0xff) << 8) - + ((dev->channel & 0xff) << 16) - + ((dev->host->host_no & 0xff) << 24), - &((Scsi_Idlun *) arg)->dev_id); - __put_user(dev->host->unique_id, &((Scsi_Idlun *) arg)->host_unique_id); + __put_user((sdev->id & 0xff) + + ((sdev->lun & 0xff) << 8) + + ((sdev->channel & 0xff) << 16) + + ((sdev->host->host_no & 0xff) << 24), + &((struct scsi_idlun *)arg)->dev_id); + __put_user(sdev->host->unique_id, + &((struct scsi_idlun *)arg)->host_unique_id); return 0; case SCSI_IOCTL_GET_BUS_NUMBER: - return put_user(dev->host->host_no, (int *) arg); + return put_user(sdev->host->host_no, (int *)arg); /* * The next two ioctls either need to go or need to be changed to * pass tagged queueing changes through the low level drivers. @@ -454,61 +419,56 @@ case SCSI_IOCTL_TAGGED_ENABLE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (!dev->tagged_supported) + if (!sdev->tagged_supported) return -EINVAL; - dev->tagged_queue = 1; - dev->current_tag = 1; + sdev->tagged_queue = 1; + sdev->current_tag = 1; return 0; case SCSI_IOCTL_TAGGED_DISABLE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (!dev->tagged_supported) + if (!sdev->tagged_supported) return -EINVAL; - dev->tagged_queue = 0; - dev->current_tag = 0; + sdev->tagged_queue = 0; + sdev->current_tag = 0; return 0; case SCSI_IOCTL_PROBE_HOST: - return ioctl_probe(dev->host, arg); + return ioctl_probe(sdev->host, arg); case SCSI_IOCTL_SEND_COMMAND: if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; - return scsi_ioctl_send_command((Scsi_Device *) dev, - (Scsi_Ioctl_Command *) arg); + return scsi_ioctl_send_command(sdev, + (struct scsi_ioctl_command *)arg); case SCSI_IOCTL_DOORLOCK: - return scsi_set_medium_removal(dev, SCSI_REMOVAL_PREVENT); + return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); case SCSI_IOCTL_DOORUNLOCK: - return scsi_set_medium_removal(dev, SCSI_REMOVAL_ALLOW); + return scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); case SCSI_IOCTL_TEST_UNIT_READY: scsi_cmd[0] = TEST_UNIT_READY; scsi_cmd[1] = 0; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 0; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, + return ioctl_internal_command(sdev, scsi_cmd, IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES); - break; case SCSI_IOCTL_START_UNIT: scsi_cmd[0] = START_STOP; scsi_cmd[1] = 0; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 1; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, + return ioctl_internal_command(sdev, scsi_cmd, START_STOP_TIMEOUT, NORMAL_RETRIES); - break; case SCSI_IOCTL_STOP_UNIT: scsi_cmd[0] = START_STOP; scsi_cmd[1] = 0; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 0; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, + return ioctl_internal_command(sdev, scsi_cmd, START_STOP_TIMEOUT, NORMAL_RETRIES); - break; case SCSI_IOCTL_GET_PCI: - return scsi_ioctl_get_pci(dev, arg); - break; + return scsi_ioctl_get_pci(sdev, arg); default: - if (dev->host->hostt->ioctl) - return dev->host->hostt->ioctl(dev, cmd, arg); - return -EINVAL; + if (sdev->host->hostt->ioctl) + return sdev->host->hostt->ioctl(sdev, cmd, arg); } return -EINVAL; } @@ -518,13 +478,13 @@ * fs segment fiddling. */ -int kernel_scsi_ioctl(Scsi_Device * dev, int cmd, void *arg) +int kernel_scsi_ioctl(struct scsi_device *sdev, int cmd, void *arg) { mm_segment_t oldfs; int tmp; oldfs = get_fs(); set_fs(get_ds()); - tmp = scsi_ioctl(dev, cmd, arg); + tmp = scsi_ioctl(sdev, cmd, arg); set_fs(oldfs); return tmp; } diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c Mon May 26 02:50:43 2003 +++ b/drivers/scsi/scsi_lib.c Wed Jun 4 04:43:01 2003 @@ -95,7 +95,6 @@ { struct Scsi_Host *host = cmd->device->host; struct scsi_device *device = cmd->device; - unsigned long flags; SCSI_LOG_MLQUEUE(1, printk("Inserting command %p into mlqueue\n", cmd)); @@ -134,10 +133,7 @@ * Decrement the counters, since these commands are no longer * active on the host/device. */ - spin_lock_irqsave(device->request_queue->queue_lock, flags); - device->device_busy--; - spin_unlock_irqrestore(device->request_queue->queue_lock, flags); - scsi_host_busy_dec_and_test(host, device); + scsi_device_unbusy(device); /* * Insert this command at the head of the queue for it's device. @@ -314,6 +310,21 @@ cmd->underflow = cmd->old_underflow; } +void scsi_device_unbusy(struct scsi_device *sdev) +{ + struct Scsi_Host *shost = sdev->host; + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + shost->host_busy--; + if (unlikely(shost->in_recovery && shost->host_failed)) + scsi_eh_wakeup(shost); + spin_unlock(shost->host_lock); + spin_lock(&sdev->sdev_lock); + sdev->device_busy--; + spin_unlock_irqrestore(&sdev->sdev_lock, flags); +} + /* * Called for single_lun devices on IO completion. Clear starget_sdev_user, * and call blk_run_queue for all the scsi_devices on the target - @@ -730,17 +741,6 @@ * can choose a block to remap, etc. */ if (driver_byte(result) != 0) { - if (suggestion(result) == SUGGEST_REMAP) { -#ifdef REMAP - /* - * Not yet implemented. A read will fail after being remapped, - * a write will call the strategy routine again. - */ - if (cmd->device->remap) { - result = 0; - } -#endif - } if ((cmd->sense_buffer[0] & 0x7f) == 0x70) { /* * If the device is in the process of becoming ready, @@ -944,6 +944,18 @@ } else cmd = req->special; } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { + /* + * Just check to see if the device is online. If + * it isn't, we refuse to process ordinary commands + * (we will allow specials just in case someone needs + * to send a command to an offline device without bringing + * it back online) + */ + if(!sdev->online) { + printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n", + sdev->host->host_no, sdev->id, sdev->lun); + return BLKPREP_KILL; + } /* * Now try and find a command block that we can use. */ diff -Nru a/drivers/scsi/scsi_module.c b/drivers/scsi/scsi_module.c --- a/drivers/scsi/scsi_module.c Tue Feb 5 07:23:03 2002 +++ b/drivers/scsi/scsi_module.c Thu Jun 5 11:52:51 2003 @@ -1,71 +1,73 @@ /* - * scsi_module.c Copyright (1994, 1995) Eric Youngdale. + * Copyright (C) 2003 Christoph Hellwig. + * Released under GPL v2. * - * Support for loading low-level scsi drivers using the linux kernel loadable - * module interface. + * Support for old-style host templates. * - * To use, the host adapter should first define and initialize the variable - * driver_template (datatype Scsi_Host_Template), and then include this file. - * This should also be wrapped in a #ifdef MODULE/#endif. - * - * The low -level driver must also define a release function which will - * free any irq assignments, release any dma channels, release any I/O - * address space that might be reserved, and otherwise clean up after itself. - * The idea is that the same driver should be able to be reloaded without - * any difficulty. This makes debugging new drivers easier, as you should - * be able to load the driver, test it, unload, modify and reload. - * - * One *very* important caveat. If the driver may need to do DMA on the - * ISA bus, you must have unchecked_isa_dma set in the device template, - * even if this might be changed during the detect routine. This is - * because the shpnt structure will be allocated in a special way so that - * it will be below the appropriate DMA limit - thus if your driver uses - * the hostdata field of shpnt, and the board must be able to access this - * via DMA, the shpnt structure must be in a DMA accessible region of - * memory. This comment would be relevant for something like the buslogic - * driver where there are many boards, only some of which do DMA onto the - * ISA bus. There is no convenient way of specifying whether the host - * needs to be in a ISA DMA accessible region of memory when you call - * scsi_register. + * NOTE: Do not use this for new drivers ever. */ -#include #include +#include +#include + +#include "scsi.h" +#include "hosts.h" + static int __init init_this_scsi_driver(void) { - driver_template.module = THIS_MODULE; - scsi_register_host(&driver_template); - if (driver_template.present) - return 0; - - scsi_unregister_host(&driver_template); - return -ENODEV; + struct scsi_host_template *sht = &driver_template; + struct Scsi_Host *shost; + struct list_head *l; + int error; + + if (!sht->release) { + printk(KERN_ERR + "scsi HBA driver %s didn't set a release method.\n", + sht->name); + return -EINVAL; + } + + sht->module = THIS_MODULE; + INIT_LIST_HEAD(&sht->legacy_hosts); + + sht->detect(sht); + if (!sht->present) + return -ENODEV; + + list_for_each_entry(shost, &sht->legacy_hosts, sht_legacy_list) { + error = scsi_add_host(shost, NULL); + if (error) + goto fail; + } + return 0; + fail: + l = &shost->sht_legacy_list; + while ((l = l->prev) != &sht->legacy_hosts) + scsi_remove_host(list_entry(l, struct Scsi_Host, sht_legacy_list)); + return error; } static void __exit exit_this_scsi_driver(void) { - scsi_unregister_host(&driver_template); + struct scsi_host_template *sht = &driver_template; + struct Scsi_Host *shost, *s; + + list_for_each_entry(shost, &sht->legacy_hosts, sht_legacy_list) + scsi_remove_host(shost); + list_for_each_entry_safe(shost, s, &sht->legacy_hosts, sht_legacy_list) + sht->release(shost); + + if (list_empty(&sht->legacy_hosts)) + return; + + printk(KERN_WARNING "%s did not call scsi_unregister\n", sht->name); + dump_stack(); + + list_for_each_entry_safe(shost, s, &sht->legacy_hosts, sht_legacy_list) + scsi_unregister(shost); } module_init(init_this_scsi_driver); module_exit(exit_this_scsi_driver); - -/* - * Overrides for Emacs so that we almost 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: - */ diff -Nru a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h --- a/drivers/scsi/scsi_priv.h Mon May 26 09:09:20 2003 +++ b/drivers/scsi/scsi_priv.h Thu Jun 5 11:49:12 2003 @@ -52,13 +52,6 @@ }; -/* hosts.c */ -extern void scsi_host_busy_inc(struct Scsi_Host *, Scsi_Device *); -extern void scsi_host_busy_dec_and_test(struct Scsi_Host *, Scsi_Device *); -extern struct Scsi_Host *scsi_host_lookup(unsigned short); -extern void scsi_host_put(struct Scsi_Host *); -extern void scsi_host_init(void); - /* scsi.c */ extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); extern int scsi_setup_command_freelist(struct Scsi_Host *shost); @@ -80,11 +73,13 @@ extern void scsi_times_out(struct scsi_cmnd *cmd); extern void scsi_error_handler(void *host); extern int scsi_decide_disposition(struct scsi_cmnd *cmd); +extern void scsi_eh_wakeup(struct Scsi_Host *shost); extern int scsi_eh_scmd_add(struct scsi_cmnd *, int); /* scsi_lib.c */ extern int scsi_maybe_unblock_host(struct scsi_device *sdev); extern void scsi_setup_cmd_retry(struct scsi_cmnd *cmd); +extern void scsi_device_unbusy(struct scsi_device *sdev); extern int scsi_queue_insert(struct scsi_cmnd *cmd, int reason); extern void scsi_next_command(struct scsi_cmnd *cmd); extern void scsi_run_host_queues(struct Scsi_Host *shost); @@ -107,12 +102,11 @@ #endif /* CONFIG_PROC_FS */ /* scsi_scan.c */ -extern void scsi_scan_host(struct Scsi_Host *shost); -extern void scsi_forget_host(struct Scsi_Host *shost); +extern void scsi_scan_host(struct Scsi_Host *); +extern void scsi_forget_host(struct Scsi_Host *); extern void scsi_free_sdev(struct scsi_device *); extern void scsi_free_shost(struct Scsi_Host *); -extern void scsi_host_get(struct Scsi_Host *); -extern void scsi_rescan_device(struct device *dev); +extern void scsi_rescan_device(struct device *); /* scsi_sysfs.c */ extern int scsi_device_register(struct scsi_device *); diff -Nru a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c --- a/drivers/scsi/scsi_proc.c Mon May 26 09:04:01 2003 +++ b/drivers/scsi/scsi_proc.c Wed Jun 11 19:47:21 2003 @@ -42,48 +42,15 @@ EXPORT_SYMBOL(proc_scsi); -/* Used if the driver currently has no own support for /proc/scsi */ -static int generic_proc_info(char *buffer, char **start, off_t offset, - int count, const char *(*info)(struct Scsi_Host *), - struct Scsi_Host *shost) -{ - int len, pos, begin = 0; - static const char noprocfs[] = - "The driver does not yet support the proc-fs\n"; - - if (info && shost) - len = sprintf(buffer, "%s\n", info(shost)); - else - len = sprintf(buffer, "%s\n", noprocfs); - - pos = len; - if (pos < offset) { - len = 0; - begin = pos; - } - - *start = buffer + (offset - begin); - len -= (offset - begin); - if (len > count) - len = count; - - return len; -} - static int proc_scsi_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data) { struct Scsi_Host *shost = data; int n; - if (shost->hostt->proc_info == NULL) - n = generic_proc_info(buffer, start, offset, length, - shost->hostt->info, shost); - else - n = shost->hostt->proc_info(shost, buffer, start, offset, - length, 0); - + n = shost->hostt->proc_info(shost, buffer, start, offset, length, 0); *eof = (n < length); + return n; } @@ -95,8 +62,6 @@ char *page; char *start; - if (!shost->hostt->proc_info) - return -ENOSYS; if (count > PROC_BLOCK_SIZE) return -EOVERFLOW; @@ -114,10 +79,13 @@ void scsi_proc_host_add(struct Scsi_Host *shost) { - Scsi_Host_Template *sht = shost->hostt; + struct scsi_host_template *sht = shost->hostt; struct proc_dir_entry *p; char name[10]; + if (!sht->proc_info) + return; + if (!sht->proc_dir) { sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi); if (!sht->proc_dir) { @@ -130,27 +98,29 @@ sprintf(name,"%d", shost->host_no); p = create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR, - shost->hostt->proc_dir, proc_scsi_read, shost); + sht->proc_dir, proc_scsi_read, shost); if (!p) { printk(KERN_ERR "%s: Failed to register host %d in" "%s\n", __FUNCTION__, shost->host_no, - shost->hostt->proc_name); + sht->proc_name); return; } p->write_proc = proc_scsi_write_proc; p->owner = shost->hostt->module; - } void scsi_proc_host_rm(struct Scsi_Host *shost) { + struct scsi_host_template *sht = shost->hostt; char name[10]; - sprintf(name,"%d", shost->host_no); - remove_proc_entry(name, shost->hostt->proc_dir); - if (!shost->hostt->present) - remove_proc_entry(shost->hostt->proc_name, proc_scsi); + if (sht->proc_info) { + sprintf(name,"%d", shost->host_no); + remove_proc_entry(name, sht->proc_dir); + if (!sht->present) + remove_proc_entry(sht->proc_name, proc_scsi); + } } static int proc_print_scsidevice(struct device *dev, void *data) @@ -244,8 +214,8 @@ return error; } -static int proc_scsi_write(struct file *file, const char* buf, - size_t length, loff_t *ppos) +static ssize_t proc_scsi_write(struct file *file, const char __user *buf, + size_t length, loff_t *ppos) { int host, channel, id, lun; char *buffer, *p; diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Sun Jun 15 13:38:43 2003 +++ b/drivers/scsi/scsi_scan.c Mon Jun 16 17:22:18 2003 @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -72,29 +73,9 @@ static unsigned int max_scsi_luns = 1; #endif -#ifdef MODULE -MODULE_PARM(max_scsi_luns, "i"); -MODULE_PARM_DESC(max_scsi_luns, +module_param_named(max_luns, max_scsi_luns, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(max_luns, "last scsi LUN (should be between 1 and 2^32-1)"); -#else - -static int __init scsi_luns_setup(char *str) -{ - unsigned int tmp; - - if (get_option(&str, &tmp) == 1) { - max_scsi_luns = tmp; - return 1; - } else { - printk(KERN_WARNING "scsi_luns_setup: usage max_scsi_luns=n " - "(n should be between 1 and 2^32-1)\n"); - return 0; - } -} - -__setup("max_scsi_luns=", scsi_luns_setup); - -#endif #ifdef CONFIG_SCSI_REPORT_LUNS /* @@ -106,29 +87,10 @@ */ static unsigned int max_scsi_report_luns = 128; -#ifdef MODULE -MODULE_PARM(max_scsi_report_luns, "i"); -MODULE_PARM_DESC(max_scsi_report_luns, +module_param_named(max_report_luns, max_scsi_report_luns, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(max_report_luns, "REPORT LUNS maximum number of LUNS received (should be" " between 1 and 16384)"); -#else -static int __init scsi_report_luns_setup(char *str) -{ - unsigned int tmp; - - if (get_option(&str, &tmp) == 1) { - max_scsi_report_luns = tmp; - return 1; - } else { - printk(KERN_WARNING "scsi_report_luns_setup: usage" - " max_scsi_report_luns=n (n should be between 1" - " and 16384)\n"); - return 0; - } -} - -__setup("max_scsi_report_luns=", scsi_report_luns_setup); -#endif #endif /** @@ -141,7 +103,8 @@ * @sreq to unlock a device, storing the (unused) results into result. * Called for BLIST_KEY devices. **/ -static void scsi_unlock_floptical(Scsi_Request *sreq, unsigned char *result) +static void scsi_unlock_floptical(struct scsi_request *sreq, + unsigned char *result) { unsigned char scsi_cmd[MAX_COMMAND_SIZE]; @@ -154,8 +117,7 @@ scsi_cmd[5] = 0; sreq->sr_cmd_len = 0; sreq->sr_data_direction = SCSI_DATA_READ; - scsi_wait_req(sreq, (void *) scsi_cmd, (void *) result, 0x2a /* size */, - SCSI_TIMEOUT, 3); + scsi_wait_req(sreq, scsi_cmd, result, 0x2a /* size */, SCSI_TIMEOUT, 3); } /** @@ -354,10 +316,10 @@ * are copied to the Scsi_Device at @sreq->sr_device (sdev); * any flags value is stored in *@bflags. **/ -static void scsi_probe_lun(Scsi_Request *sreq, char *inq_result, +static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, int *bflags) { - Scsi_Device *sdev = sreq->sr_device; /* a bit ugly */ + struct scsi_device *sdev = sreq->sr_device; /* a bit ugly */ unsigned char scsi_cmd[MAX_COMMAND_SIZE]; int possible_inq_resp_len; @@ -522,7 +484,7 @@ * SCSI_SCAN_NO_RESPONSE: could not allocate or setup a Scsi_Device * SCSI_SCAN_LUN_PRESENT: a new Scsi_Device was allocated and initialized **/ -static int scsi_add_lun(Scsi_Device *sdev, char *inq_result, int *bflags) +static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) { struct scsi_device *sdev_sibling; struct scsi_target *starget; @@ -578,8 +540,6 @@ default: printk(KERN_INFO "scsi: unknown device type %d\n", sdev->type); } - - sdev->random = (sdev->type == TYPE_TAPE) ? 0 : 1; scsi_set_name(sdev, inq_result); diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c --- a/drivers/scsi/scsi_syms.c Mon May 26 03:03:34 2003 +++ b/drivers/scsi/scsi_syms.c Thu Jun 5 04:26:04 2003 @@ -31,10 +31,12 @@ */ EXPORT_SYMBOL(scsi_register_driver); EXPORT_SYMBOL(scsi_register_interface); -EXPORT_SYMBOL(scsi_register_host); -EXPORT_SYMBOL(scsi_unregister_host); +EXPORT_SYMBOL(scsi_host_alloc); EXPORT_SYMBOL(scsi_add_host); EXPORT_SYMBOL(scsi_remove_host); +EXPORT_SYMBOL(scsi_host_get); +EXPORT_SYMBOL(scsi_host_put); +EXPORT_SYMBOL(scsi_host_lookup); EXPORT_SYMBOL(scsi_register); EXPORT_SYMBOL(scsi_unregister); EXPORT_SYMBOL(scsicam_bios_param); diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c --- a/drivers/scsi/scsi_sysfs.c Mon May 26 08:45:44 2003 +++ b/drivers/scsi/scsi_sysfs.c Thu Jun 5 11:52:51 2003 @@ -487,7 +487,7 @@ } EXPORT_SYMBOL(scsi_sysfs_modify_sdev_attribute); -void scsi_sysfs_release_attributes(struct SHT *hostt) +void scsi_sysfs_release_attributes(struct scsi_host_template *hostt) { if(hostt->sdev_attrs != scsi_sysfs_sdev_attrs) kfree(hostt->sdev_attrs); diff -Nru a/drivers/scsi/scsi_typedefs.h b/drivers/scsi/scsi_typedefs.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/scsi/scsi_typedefs.h Thu Jun 5 11:47:24 2003 @@ -0,0 +1,6 @@ + +typedef struct scsi_host_template Scsi_Host_Template; +typedef struct scsi_device Scsi_Device; +typedef struct scsi_cmnd Scsi_Cmnd; +typedef struct scsi_request Scsi_Request; +typedef struct scsi_pointer Scsi_Pointer; diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c Sun Jun 15 13:38:43 2003 +++ b/drivers/scsi/sd.c Tue Jun 17 02:17:15 2003 @@ -76,6 +76,7 @@ struct scsi_driver *driver; /* always &sd_template */ struct scsi_device *device; struct gendisk *disk; + unsigned int openers; /* protected by BKL for now, yuck */ sector_t capacity; /* size in 512-byte sectors */ u32 index; u8 media_present; @@ -87,7 +88,7 @@ static unsigned long sd_index_bits[SD_DISKS / BITS_PER_LONG]; static spinlock_t sd_index_lock = SPIN_LOCK_UNLOCKED; -static void sd_init_onedisk(struct scsi_disk * sdkp, struct gendisk *disk); +static int sd_revalidate_disk(struct gendisk *disk); static void sd_rw_intr(struct scsi_cmnd * SCpnt); static int sd_probe(struct device *); @@ -95,7 +96,6 @@ static void sd_shutdown(struct device *dev); static void sd_rescan(struct device *); static int sd_init_command(struct scsi_cmnd *); -static int sd_synchronize_cache(struct scsi_disk *, int); static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, struct scsi_request *SRpnt, unsigned char *buffer); @@ -396,9 +396,10 @@ if (!sdev->online) goto error_out; - if (sdev->removable && sdev->access_count == 1) + if (!sdkp->openers++ && sdev->removable) { if (scsi_block_when_processing_errors(sdev)) scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); + } return 0; @@ -421,13 +422,15 @@ static int sd_release(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; - struct scsi_device *sdev = scsi_disk(disk)->device; + struct scsi_disk *sdkp = scsi_disk(disk); + struct scsi_device *sdev = sdkp->device; SCSI_LOG_HLQUEUE(3, printk("sd_release: disk=%s\n", disk->disk_name)); - if (sdev->removable && sdev->access_count == 1) + if (!--sdkp->openers && sdev->removable) { if (scsi_block_when_processing_errors(sdev)) scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); + } /* * XXX and what if there are packets in flight and this close() @@ -566,7 +569,7 @@ * UNIT ATTENTION, or with same cartridge - GOOD STATUS. * * Drives that auto spin down. eg iomega jaz 1G, will be started - * by sd_spinup_disk() from sd_init_onedisk(), which happens whenever + * by sd_spinup_disk() from sd_revalidate_disk(), which happens whenever * sd_revalidate() is called. */ retval = -ENODEV; @@ -632,15 +635,6 @@ kfree(buffer); } -static int sd_revalidate_disk(struct gendisk *disk) -{ - struct scsi_disk *sdkp = scsi_disk(disk); - - sd_init_onedisk(sdkp, disk); - set_capacity(disk, sdkp->capacity); - return 0; -} - static struct block_device_operations sd_fops = { .owner = THIS_MODULE, .open = sd_open, @@ -772,7 +766,7 @@ } /* - * spinup disk - called only in sd_init_onedisk() + * spinup disk - called only in sd_revalidate_disk() */ static void sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, @@ -856,7 +850,7 @@ SRpnt->sr_sense_buffer[0] = 0; SRpnt->sr_sense_buffer[2] = 0; - SRpnt->sr_data_direction = SCSI_DATA_READ; + SRpnt->sr_data_direction = SCSI_DATA_NONE; scsi_wait_req(SRpnt, (void *)cmd, (void *) buffer, 0/*512*/, SD_TIMEOUT, SD_MAX_RETRIES); @@ -892,7 +886,7 @@ } /* - * read disk capacity - called only in sd_init_onedisk() + * read disk capacity */ static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, @@ -1105,7 +1099,7 @@ } /* - * read write protect setting, if possible - called only in sd_init_onedisk() + * read write protect setting, if possible - called only in sd_revalidate_disk() * called with buffer of length 512 */ static void @@ -1147,7 +1141,7 @@ } /* - * sd_read_cache_type - called only from sd_init_onedisk() + * sd_read_cache_type - called only from sd_revalidate_disk() * called with buffer of length 512 */ static void @@ -1206,71 +1200,69 @@ } /** - * sd_init_onedisk - called the first time a new disk is seen, + * sd_revalidate_disk - called the first time a new disk is seen, * performs disk spin up, read_capacity, etc. - * @sdkp: pointer to associated struct scsi_disk object - * @dsk_nr: disk number within this driver (e.g. 0->/dev/sda, - * 1->/dev/sdb, etc) - * - * Note: this function is local to this driver. + * @disk: struct gendisk we care about **/ -static void -sd_init_onedisk(struct scsi_disk * sdkp, struct gendisk *disk) +static int sd_revalidate_disk(struct gendisk *disk) { + struct scsi_disk *sdkp = scsi_disk(disk); + struct scsi_device *sdp = sdkp->device; + struct scsi_request *sreq; unsigned char *buffer; - struct scsi_device *sdp; - struct scsi_request *SRpnt; - SCSI_LOG_HLQUEUE(3, printk("sd_init_onedisk: disk=%s\n", disk->disk_name)); + SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name)); /* * If the device is offline, don't try and read capacity or any * of the other niceties. */ - sdp = sdkp->device; - if (sdp->online == FALSE) - return; + if (!sdp->online) + goto out; - SRpnt = scsi_allocate_request(sdp); - if (!SRpnt) { - printk(KERN_WARNING "(sd_init_onedisk:) Request allocation " + sreq = scsi_allocate_request(sdp); + if (!sreq) { + printk(KERN_WARNING "(sd_revalidate_disk:) Request allocation " "failure.\n"); - return; + goto out; } - buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); + buffer = kmalloc(512, GFP_KERNEL | __GFP_DMA); if (!buffer) { - printk(KERN_WARNING "(sd_init_onedisk:) Memory allocation " + printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation " "failure.\n"); - goto leave; + goto out_release_request; } /* defaults, until the device tells us otherwise */ + sdp->sector_size = 512; sdkp->capacity = 0; - sdkp->device->sector_size = 512; sdkp->media_present = 1; sdkp->write_prot = 0; sdkp->WCE = 0; sdkp->RCD = 0; - sd_spinup_disk(sdkp, disk->disk_name, SRpnt, buffer); + sd_spinup_disk(sdkp, disk->disk_name, sreq, buffer); - if (sdkp->media_present) - sd_read_capacity(sdkp, disk->disk_name, SRpnt, buffer); - - if (sdp->removable && sdkp->media_present) - sd_read_write_protect_flag(sdkp, disk->disk_name, SRpnt, buffer); - /* without media there is no reason to ask; - moreover, some devices react badly if we do */ - if (sdkp->media_present) - sd_read_cache_type(sdkp, disk->disk_name, SRpnt, buffer); + /* + * Without media there is no reason to ask; moreover, some devices + * react badly if we do. + */ + if (sdkp->media_present) { + sd_read_capacity(sdkp, disk->disk_name, sreq, buffer); + if (sdp->removable) + sd_read_write_protect_flag(sdkp, disk->disk_name, + sreq, buffer); + sd_read_cache_type(sdkp, disk->disk_name, sreq, buffer); + } - SRpnt->sr_device->remap = 1; - - leave: - scsi_release_request(SRpnt); - + set_capacity(disk, sdkp->capacity); kfree(buffer); + + out_release_request: + scsi_release_request(sreq); + out: + return 0; } /** @@ -1329,6 +1321,7 @@ sdkp->driver = &sd_template; sdkp->disk = gd; sdkp->index = index; + sdkp->openers = 0; gd->major = sd_major(index >> 4); gd->first_minor = (index & 15) << 4; @@ -1344,16 +1337,16 @@ strcpy(gd->devfs_name, sdp->devfs_name); - sd_init_onedisk(sdkp, gd); + gd->private_data = &sdkp->driver; + + sd_revalidate_disk(gd); gd->driverfs_dev = &sdp->sdev_driverfs_dev; gd->flags = GENHD_FL_DRIVERFS; if (sdp->removable) gd->flags |= GENHD_FL_REMOVABLE; - gd->private_data = &sdkp->driver; gd->queue = sdkp->device->request_queue; - set_capacity(gd, sdkp->capacity); dev_set_drvdata(dev, sdkp); add_disk(gd); @@ -1400,16 +1393,57 @@ return 0; } +/* + * Send a SYNCHRONIZE CACHE instruction down to the device through + * the normal SCSI command structure. Wait for the command to + * complete. + */ static void sd_shutdown(struct device *dev) { + struct scsi_device *sdp = to_scsi_device(dev); struct scsi_disk *sdkp = dev_get_drvdata(dev); + struct scsi_request *sreq; + int retries, res; - if (sdkp->WCE) { - printk(KERN_NOTICE "Synchronizing SCSI cache: "); - sd_synchronize_cache(sdkp, 1); - printk("\n"); + if (!sdp->online || !sdkp->WCE) + return; + + printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: ", + sdkp->disk->disk_name); + + sreq = scsi_allocate_request(sdp); + if (!sreq) { + printk("FAILED\n No memory for request\n"); + return; } -} + + sreq->sr_data_direction = SCSI_DATA_NONE; + for (retries = 3; retries > 0; --retries) { + unsigned char cmd[10] = { 0 }; + + cmd[0] = SYNCHRONIZE_CACHE; + /* + * Leave the rest of the command zero to indicate + * flush everything. + */ + scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES); + if (sreq->sr_result == 0) + break; + } + + res = sreq->sr_result; + if (res) { + printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " + "host = %d, driver = %02x\n ", + status_byte(res), msg_byte(res), + host_byte(res), driver_byte(res)); + if (driver_byte(res) & DRIVER_SENSE) + print_req_sense("sd", sreq); + } + + scsi_release_request(sreq); + printk("\n"); +} /** * init_sd - entry point for this driver (both when built in or when @@ -1447,60 +1481,6 @@ scsi_unregister_driver(&sd_template.gendrv); for (i = 0; i < SD_MAJORS; i++) unregister_blkdev(sd_major(i), "sd"); -} - -/* send a SYNCHRONIZE CACHE instruction down to the device through the - * normal SCSI command structure. Wait for the command to complete (must - * have user context) */ -static int sd_synchronize_cache(struct scsi_disk *sdkp, int verbose) -{ - struct scsi_request *SRpnt; - struct scsi_device *SDpnt = sdkp->device; - int retries, the_result; - - if (!SDpnt->online) - return 0; - - if (verbose) - printk("%s ", sdkp->disk->disk_name); - - SRpnt = scsi_allocate_request(SDpnt); - if(!SRpnt) { - if(verbose) - printk("FAILED\n No memory for request\n"); - return 0; - } - - SRpnt->sr_data_direction = SCSI_DATA_NONE; - - for(retries = 3; retries > 0; --retries) { - unsigned char cmd[10] = { 0 }; - - cmd[0] = SYNCHRONIZE_CACHE; - /* leave the rest of the command zero to indicate - * flush everything */ - scsi_wait_req(SRpnt, (void *)cmd, NULL, 0, - SD_TIMEOUT, SD_MAX_RETRIES); - - if(SRpnt->sr_result == 0) - break; - } - - the_result = SRpnt->sr_result; - if(verbose) { - if(the_result != 0) { - printk("FAILED\n status = %x, message = %02x, host = %d, driver = %02x\n ", - status_byte(the_result), - msg_byte(the_result), - host_byte(the_result), - driver_byte(the_result)); - if (driver_byte(the_result) & DRIVER_SENSE) - print_req_sense("sd", SRpnt); - - } - } - scsi_release_request(SRpnt); - return (the_result == 0); } MODULE_LICENSE("GPL"); diff -Nru a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c --- a/drivers/scsi/seagate.c Sun May 4 02:56:46 2003 +++ b/drivers/scsi/seagate.c Sun Jun 8 12:18:41 2003 @@ -729,13 +729,6 @@ return 0; } -static int seagate_st0x_command(Scsi_Cmnd * SCpnt) -{ - return internal_command (SCpnt->device->id, SCpnt->device->lun, SCpnt->cmnd, - SCpnt->request_buffer, SCpnt->request_bufflen, - (int) NO_RECONNECT); -} - static int internal_command (unsigned char target, unsigned char lun, const void *cmnd, void *buff, int bufflen, int reselect) { @@ -1704,7 +1697,6 @@ .detect = seagate_st0x_detect, .release = seagate_st0x_release, .info = seagate_st0x_info, - .command = seagate_st0x_command, .queuecommand = seagate_st0x_queue_command, .eh_abort_handler = seagate_st0x_abort, .eh_bus_reset_handler = seagate_st0x_bus_reset, diff -Nru a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c --- a/drivers/scsi/sim710.c Sun May 25 17:00:00 2003 +++ b/drivers/scsi/sim710.c Tue Jun 17 13:27:45 2003 @@ -121,6 +121,7 @@ hostdata->differential = differential; hostdata->clock = clock; hostdata->chip710 = 1; + NCR_700_set_io_mapped(hostdata); /* and register the chip */ if((host = NCR_700_detect(&sim710_driver_template, hostdata)) == NULL) { @@ -143,7 +144,7 @@ return 0; out_unregister: - scsi_unregister(host); + scsi_host_put(host); out_release: release_region(host->base, 64); out_free: @@ -294,12 +295,17 @@ unsigned char irq, differential = 0, scsi_id = 7; if(strcmp(edev->id.sig, "HWP0C80") == 0) { + __u8 val; eisa_irqs = eisa_hwp_irqs; irq_index = (inb(io_addr + 0xc85) & 0x7) - 1; -#if 0 - /* this doesn't seem to work at the moment */ - scsi_id = ffs(inb(io_addr + 0x4)); -#endif + + val = inb(io_addr + 0x4); + scsi_id = ffs(val) - 1; + + if(scsi_id > 7 || (val & ~(1<name); + scsi_id = 7; + } } else { eisa_irqs = eisa_cpq_irqs; irq_index = inb(io_addr + 0xc88) & 0x07; diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c --- a/drivers/scsi/sr.c Sun Jun 15 13:38:43 2003 +++ b/drivers/scsi/sr.c Mon Jun 16 17:22:18 2003 @@ -524,7 +524,6 @@ sprintf(cd->cdi.name, "sr%d", minor); sdev->sector_size = 2048; /* A guess, just in case */ - sdev->remap = 1; /* FIXME: need to handle a get_capabilities failure properly ?? */ get_capabilities(cd); diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c Mon May 26 04:18:14 2003 +++ b/drivers/scsi/st.c Thu Jun 5 11:39:47 2003 @@ -3674,22 +3674,6 @@ #endif -/* Driverfs file support */ -static ssize_t st_device_kdev_read(struct device *dev, char *page) -{ - kdev_t kdev; - kdev.value=(unsigned long)dev->driver_data; - return sprintf(page, "%x\n",kdev.value); -} -static DEVICE_ATTR(kdev,S_IRUGO,st_device_kdev_read,NULL); - -static ssize_t st_device_type_read(struct device *ev, char * page) -{ - return sprintf (page, "CHR\n"); -} -static DEVICE_ATTR(type,S_IRUGO,st_device_type_read,NULL); - - static struct file_operations st_fops = { .owner = THIS_MODULE, diff -Nru a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c --- a/drivers/scsi/sun3x_esp.c Fri Feb 7 14:02:17 2003 +++ b/drivers/scsi/sun3x_esp.c Sun Jun 8 12:18:41 2003 @@ -413,7 +413,6 @@ .slave_alloc = esp_slave_alloc, .slave_destroy = esp_slave_destroy, .info = esp_info, - .command = esp_command, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, .eh_bus_reset_handler = esp_reset, diff -Nru a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c --- a/drivers/scsi/sym53c416.c Sun May 4 02:56:46 2003 +++ b/drivers/scsi/sym53c416.c Sun Jun 8 12:18:41 2003 @@ -787,20 +787,6 @@ return 0; } -static void internal_done(Scsi_Cmnd *SCpnt) -{ - SCpnt->SCp.Status++; -} - -static int sym53c416_command(Scsi_Cmnd *SCpnt) -{ - sym53c416_queuecommand(SCpnt, internal_done); - SCpnt->SCp.Status = 0; - while(!SCpnt->SCp.Status) - barrier(); - return SCpnt->result; -} - static int sym53c416_abort(Scsi_Cmnd *SCpnt) { return FAILED; @@ -880,7 +866,6 @@ .name = "Symbios Logic 53c416", .detect = sym53c416_detect, .info = sym53c416_info, - .command = sym53c416_command, .queuecommand = sym53c416_queuecommand, .eh_abort_handler = sym53c416_abort, .eh_host_reset_handler =sym53c416_host_reset, diff -Nru a/drivers/scsi/t128.c b/drivers/scsi/t128.c --- a/drivers/scsi/t128.c Sun May 4 02:56:46 2003 +++ b/drivers/scsi/t128.c Mon Jun 2 17:27:45 2003 @@ -280,6 +280,16 @@ return count; } +static int t128_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + /* * Function : int t128_biosparam(Disk * disk, struct block_device *dev, int *ip) * @@ -403,6 +413,7 @@ static Scsi_Host_Template driver_template = { .name = "Trantor T128/T128F/T228", .detect = t128_detect, + .release = t128_release, .queuecommand = t128_queue_command, .eh_abort_handler = t128_abort, .eh_bus_reset_handler = t128_bus_reset, diff -Nru a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c --- a/drivers/scsi/u14-34f.c Thu May 8 11:24:15 2003 +++ b/drivers/scsi/u14-34f.c Tue Jun 3 10:54:37 2003 @@ -1,6 +1,36 @@ /* * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. * + * 03 Jun 2003 Rev. 8.10 for linux-2.5.70 + * + Update for new IRQ API. + * + Use "goto" when appropriate. + * + Drop u14-34f.h. + * + Update for new module_param API. + * + Module parameters can now be specified only in the + * same format as the kernel boot options. + * + * boot option old module param + * ----------- ------------------ + * addr,... io_port=addr,... + * lc:[y|n] linked_comm=[1|0] + * mq:xx max_queue_depth=xx + * tm:[0|1|2] tag_mode=[0|1|2] + * et:[y|n] ext_tran=[1|0] + * of:[y|n] have_old_firmware=[1|0] + * + * A valid example using the new parameter format is: + * modprobe u14-34f "u14-34f=0x340,0x330,lc:y,tm:0,mq:4" + * + * which is equivalent to the old format: + * modprobe u14-34f io_port=0x340,0x330 linked_comm=1 tag_mode=0 \ + * max_queue_depth=4 + * + * With actual module code, u14-34f and u14_34f are equivalent + * as module parameter names. + * + * 12 Feb 2003 Rev. 8.04 for linux 2.5.60 + * + Release irq before calling scsi_register. + * * 12 Nov 2002 Rev. 8.02 for linux 2.5.47 * + Release driver_lock before calling scsi_register. * @@ -221,7 +251,7 @@ * * Multiple U14F and/or U34F host adapters are supported. * - * Copyright (C) 1994-2002 Dario Ballabio (ballabio_dario@emc.com) + * Copyright (C) 1994-2003 Dario Ballabio (ballabio_dario@emc.com) * * Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it * @@ -375,31 +405,8 @@ * the driver sets host->wish_block = TRUE for all ISA boards. */ -#include - -#ifndef LinuxVersionCode -#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) -#endif - -#define MAX_INT_PARAM 10 - -#if defined(MODULE) -#include - -MODULE_PARM(boot_options, "s"); -MODULE_PARM(io_port, "1-" __MODULE_STRING(MAX_INT_PARAM) "i"); -MODULE_PARM(linked_comm, "i"); -MODULE_PARM(have_old_firmware, "i"); -MODULE_PARM(link_statistics, "i"); -MODULE_PARM(max_queue_depth, "i"); -MODULE_PARM(tag_mode, "i"); -MODULE_PARM(ext_tran, "i"); -MODULE_AUTHOR("Dario Ballabio"); - -#endif - +#include #include -#include #include #include #include @@ -408,20 +415,42 @@ #include #include #include +#include #include -#include #include #include #include #include #include - +#include "scsi.h" +#include "hosts.h" #include #include -#include "scsi.h" -#include "hosts.h" -#include "u14-34f.h" +static int u14_34f_detect(Scsi_Host_Template *); +static int u14_34f_release(struct Scsi_Host *); +static int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +static int u14_34f_eh_abort(Scsi_Cmnd *); +static int u14_34f_eh_host_reset(Scsi_Cmnd *); +static int u14_34f_bios_param(struct scsi_device *, struct block_device *, + sector_t, int *); +static int u14_34f_slave_configure(Scsi_Device *); + +static Scsi_Host_Template driver_template = { + .name = "UltraStor 14F/34F rev. 8.10.00 ", + .detect = u14_34f_detect, + .release = u14_34f_release, + .queuecommand = u14_34f_queuecommand, + .eh_abort_handler = u14_34f_eh_abort, + .eh_device_reset_handler = NULL, + .eh_bus_reset_handler = NULL, + .eh_host_reset_handler = u14_34f_eh_host_reset, + .bios_param = u14_34f_bios_param, + .slave_configure = u14_34f_slave_configure, + .this_id = 7, + .unchecked_isa_dma = 1, + .use_clustering = ENABLE_CLUSTERING + }; #if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD) #error "Adjust your defines" @@ -610,7 +639,6 @@ static int setup_done = FALSE; static int link_statistics; static int ext_tran = FALSE; -static char *boot_options; #if defined(HAVE_OLD_UX4F_FIRMWARE) static int have_old_firmware = TRUE; @@ -636,6 +664,24 @@ static int max_queue_depth = MAX_CMD_PER_LUN; #endif +#define MAX_INT_PARAM 10 +#define MAX_BOOT_OPTIONS_SIZE 256 +static char boot_options[MAX_BOOT_OPTIONS_SIZE]; + +#if defined(MODULE) +#include +#include + +module_param_string(u14_34f, boot_options, MAX_BOOT_OPTIONS_SIZE, 0); +MODULE_PARM_DESC(u14_34f, " equivalent to the \"u14-34f=...\" kernel boot " \ +"option." \ +" Example: modprobe u14-34f \"u14_34f=0x340,0x330,lc:y,tm:0,mq:4\""); +MODULE_AUTHOR("Dario Ballabio"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("UltraStor 14F/34F SCSI Driver"); + +#endif + static int u14_34f_slave_configure(Scsi_Device *dev) { int j, tqd, utqd; char *tag_suffix, *link_suffix; @@ -802,24 +848,20 @@ sprintf(name, "%s%d", driver_name, j); - if(!request_region(port_base, REGION_SIZE, driver_name)) { + if (!request_region(port_base, REGION_SIZE, driver_name)) { #if defined(DEBUG_DETECT) printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base); #endif - return FALSE; + goto fail; } - if (inb(port_base + REG_PRODUCT_ID1) != PRODUCT_ID1) { - release_region(port_base, REGION_SIZE); - return FALSE; - } + spin_lock_irq(&driver_lock); + + if (inb(port_base + REG_PRODUCT_ID1) != PRODUCT_ID1) goto freelock; in_byte = inb(port_base + REG_PRODUCT_ID2); - if ((in_byte & 0xf0) != PRODUCT_ID2) { - release_region(port_base, REGION_SIZE); - return FALSE; - } + if ((in_byte & 0xf0) != PRODUCT_ID2) goto freelock; *(char *)&config_1 = inb(port_base + REG_CONFIG1); *(char *)&config_2 = inb(port_base + REG_CONFIG2); @@ -833,16 +875,13 @@ SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0), driver_name, (void *) &sha[j])) { printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); - release_region(port_base, REGION_SIZE); - return FALSE; + goto freelock; } if (subversion == ISA && request_dma(dma_channel, driver_name)) { printk("%s: unable to allocate DMA channel %u, detaching.\n", name, dma_channel); - free_irq(irq, &sha[j]); - release_region(port_base, REGION_SIZE); - return FALSE; + goto freeirq; } if (have_old_firmware) tpnt->use_clustering = DISABLE_CLUSTERING; @@ -853,13 +892,7 @@ if (sh[j] == NULL) { printk("%s: unable to register host, detaching.\n", name); - - free_irq(irq, &sha[j]); - - if (subversion == ISA) free_dma(dma_channel); - - release_region(port_base, REGION_SIZE); - return FALSE; + goto freedma; } sh[j]->io_port = port_base; @@ -938,6 +971,8 @@ if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "BMST"); else sprintf(dma_name, "DMA %u", dma_channel); + spin_unlock_irq(&driver_lock); + for (i = 0; i < sh[j]->can_queue; i++) HD(j)->cp[i].cp_dma_addr = pci_map_single(HD(j)->pdev, &HD(j)->cp[i], sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL); @@ -947,8 +982,7 @@ sh[j]->sg_tablesize * sizeof(struct sg_list), (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) { printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i); - u14_34f_release(sh[j]); - return FALSE; + goto release; } if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN) @@ -960,7 +994,7 @@ tag_mode = TAG_ORDERED; if (j == 0) { - printk("UltraStor 14F/34F: Copyright (C) 1994-2002 Dario Ballabio.\n"); + printk("UltraStor 14F/34F: Copyright (C) 1994-2003 Dario Ballabio.\n"); printk("%s config options -> of:%c, tm:%d, lc:%c, mq:%d, et:%c.\n", driver_name, YESNO(have_old_firmware), tag_mode, YESNO(linked_comm), max_queue_depth, YESNO(ext_tran)); @@ -979,6 +1013,20 @@ BN(j), i, sh[j]->this_id); return TRUE; + +freedma: + if (subversion == ISA) free_dma(dma_channel); +freeirq: + free_irq(irq, &sha[j]); +freelock: + spin_unlock_irq(&driver_lock); + release_region(port_base, REGION_SIZE); +fail: + return FALSE; + +release: + u14_34f_release(sh[j]); + return FALSE; } static void internal_setup(char *str, int *ints) { @@ -1034,13 +1082,10 @@ static int u14_34f_detect(Scsi_Host_Template *tpnt) { unsigned int j = 0, k; - unsigned long spin_flags; - - spin_lock_irqsave(&driver_lock, spin_flags); tpnt->proc_name = "u14-34f"; - if(boot_options) option_setup(boot_options); + if(strlen(boot_options)) option_setup(boot_options); #if defined(MODULE) /* io_port could have been modified when loading as a module */ @@ -1060,7 +1105,6 @@ } num_boards = j; - spin_unlock_irqrestore(&driver_lock, spin_flags); return j; } @@ -1680,7 +1724,7 @@ } -static void ihdlr(int irq, unsigned int j) { +static irqreturn_t ihdlr(int irq, unsigned int j) { Scsi_Cmnd *SCpnt; unsigned int i, k, c, status, tstatus, reg, ret; struct mscp *spp, *cpp; @@ -1689,7 +1733,7 @@ panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq); /* Check if this board need to be serviced */ - if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) return; + if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) goto none; HD(j)->iocount++; @@ -1701,7 +1745,7 @@ outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR); printk("%s: ihdlr, busy timeout error, irq %d, reg 0x%x, count %d.\n", BN(j), irq, reg, HD(j)->iocount); - return; + goto none; } ret = inl(sh[j]->io_port + REG_ICM); @@ -1721,23 +1765,23 @@ spp = cpp; #if defined(DEBUG_GENERATE_ABORTS) - if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) return; + if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) goto handled; #endif if (HD(j)->cp_stat[i] == IGNORE) { HD(j)->cp_stat[i] = FREE; - return; + goto handled; } else if (HD(j)->cp_stat[i] == LOCKED) { HD(j)->cp_stat[i] = FREE; printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i, HD(j)->iocount); - return; + goto handled; } else if (HD(j)->cp_stat[i] == FREE) { printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i, HD(j)->iocount); - return; + goto handled; } else if (HD(j)->cp_stat[i] == IN_RESET) printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i); @@ -1887,23 +1931,25 @@ if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq, HD(j)->iocount); - return; +handled: + return IRQ_HANDLED; +none: + return IRQ_NONE; } static irqreturn_t do_interrupt_handler(int irq, void *shap, - struct pt_regs *regs) -{ + struct pt_regs *regs) { unsigned int j; unsigned long spin_flags; + irqreturn_t ret; /* Check if the interrupt must be processed by this handler */ - if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) - return IRQ_NONE; + if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return IRQ_NONE; spin_lock_irqsave(sh[j]->host_lock, spin_flags); - ihdlr(irq, j); + ret = ihdlr(irq, j); spin_unlock_irqrestore(sh[j]->host_lock, spin_flags); - return IRQ_HANDLED; + return ret; } static int u14_34f_release(struct Scsi_Host *shpnt) { @@ -1930,22 +1976,8 @@ return FALSE; } -static Scsi_Host_Template driver_template = { - .name = "UltraStor 14F/34F rev. " U14_34F_VERSION " ", - .detect = u14_34f_detect, - .release = u14_34f_release, - .queuecommand = u14_34f_queuecommand, - .eh_abort_handler = u14_34f_eh_abort, - .eh_host_reset_handler = u14_34f_eh_host_reset, - .bios_param = u14_34f_bios_param, - .slave_configure = u14_34f_slave_configure, - .this_id = 7, - .unchecked_isa_dma = 1, - .use_clustering = ENABLE_CLUSTERING, -}; #include "scsi_module.c" #ifndef MODULE __setup("u14-34f=", option_setup); #endif /* end MODULE */ -MODULE_LICENSE("GPL"); diff -Nru a/drivers/scsi/u14-34f.h b/drivers/scsi/u14-34f.h --- a/drivers/scsi/u14-34f.h Sun May 4 02:56:46 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,14 +0,0 @@ -/* - * u14-34f.h - used by the low-level driver for UltraStor 14F/34F - */ - -static int u14_34f_detect(Scsi_Host_Template *); -static int u14_34f_release(struct Scsi_Host *); -static int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -static int u14_34f_eh_abort(Scsi_Cmnd *); -static int u14_34f_eh_host_reset(Scsi_Cmnd *); -static int u14_34f_bios_param(struct scsi_device *, struct block_device *, - sector_t, int *); -static int u14_34f_slave_configure(Scsi_Device *); - -#define U14_34F_VERSION "8.03.00" diff -Nru a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c --- a/drivers/scsi/ultrastor.c Thu May 8 11:24:15 2003 +++ b/drivers/scsi/ultrastor.c Mon Jun 2 17:27:44 2003 @@ -643,6 +643,18 @@ return ultrastor_14f_detect(tpnt) || ultrastor_24f_detect(tpnt); } +static int ultrastor_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->dma_channel != 0xff) + free_dma(shost->dma_channel); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} + static const char *ultrastor_info(struct Scsi_Host * shpnt) { static char buf[64]; @@ -1177,6 +1189,7 @@ static Scsi_Host_Template driver_template = { .name = "UltraStor 14F/24F/34F", .detect = ultrastor_detect, + .release = ultrastor_release, .info = ultrastor_info, .queuecommand = ultrastor_queuecommand, .eh_abort_handler = ultrastor_abort, diff -Nru a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c --- a/drivers/scsi/wd7000.c Mon May 12 08:12:55 2003 +++ b/drivers/scsi/wd7000.c Sun Jun 8 12:18:41 2003 @@ -1031,14 +1031,6 @@ return (scsierr | (hosterr << 16)); } - -static void wd7000_scsi_done(Scsi_Cmnd * SCpnt) -{ - dprintk("wd7000_scsi_done: 0x%06lx\n", (long) SCpnt); - SCpnt->SCp.phase = 0; -} - - #define wd7000_intr_ack(host) outb (0, host->iobase + ASC_INTR_ACK) static void wd7000_intr_handle(int irq, void *dev_id, struct pt_regs *regs) @@ -1188,20 +1180,6 @@ return 0; } - -static int wd7000_command(Scsi_Cmnd * SCpnt) -{ - wd7000_queuecommand(SCpnt, wd7000_scsi_done); - - while (SCpnt->SCp.phase > 0) { - cpu_relax(); - barrier(); /* phase counts scbs down to 0 */ - } - - return (SCpnt->result); -} - - static int wd7000_diagnostics(Adapter * host, int code) { static IcbDiag icb = { ICB_OP_DIAGNOSTICS }; @@ -1616,6 +1594,15 @@ return (present); } +static int wd7000_release(struct Scsi_Host *shost) +{ + if (shost->irq) + free_irq(shost->irq, NULL); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + scsi_unregister(shost); + return 0; +} /* * I have absolutely NO idea how to do an abort with the WD7000... @@ -1722,7 +1709,7 @@ .proc_info = wd7000_proc_info, .name = "Western Digital WD-7000", .detect = wd7000_detect, - .command = wd7000_command, + .release = wd7000_release, .queuecommand = wd7000_queuecommand, .eh_bus_reset_handler = wd7000_bus_reset, .eh_device_reset_handler = wd7000_device_reset, diff -Nru a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c --- a/drivers/usb/image/hpusbscsi.c Fri Jun 6 12:51:40 2003 +++ b/drivers/usb/image/hpusbscsi.c Wed Jun 11 20:06:31 2003 @@ -104,7 +104,7 @@ goto out_free_controlurb; /* In host->hostdata we store a pointer to desc */ - new->host = scsi_register(&hpusbscsi_scsi_host_template, sizeof(new)); + new->host = scsi_host_alloc(&hpusbscsi_scsi_host_template, sizeof(new)); if (!new->host) goto out_unlink_controlurb; @@ -137,7 +137,7 @@ scsi_remove_host(desc->host); usb_unlink_urb(desc->controlurb); - scsi_unregister(desc->host); + scsi_host_put(desc->host); usb_free_urb(desc->controlurb); usb_free_urb(desc->dataurb); diff -Nru a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c --- a/drivers/usb/image/microtek.c Thu May 29 21:51:27 2003 +++ b/drivers/usb/image/microtek.c Thu Jun 5 11:39:39 2003 @@ -811,7 +811,7 @@ MTS_WARNING( "will this work? Image data EP is not usually %d\n", (int)new_desc->ep_image ); - new_desc->host = scsi_register(&mts_scsi_host_template, + new_desc->host = scsi_host_alloc(&mts_scsi_host_template, sizeof(new_desc)); if (!new_desc->host) goto out_free_urb; @@ -838,7 +838,7 @@ scsi_remove_host(desc->host); usb_unlink_urb(desc->urb); - scsi_unregister(desc->host); + scsi_host_put(desc->host); usb_free_urb(desc->urb); kfree(desc); diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c --- a/drivers/usb/storage/scsiglue.c Sun Jun 1 12:09:08 2003 +++ b/drivers/usb/storage/scsiglue.c Sun Jun 8 13:31:57 2003 @@ -360,29 +360,20 @@ * this defines our host template, with which we'll allocate hosts */ -struct SHT usb_stor_host_template = { +struct scsi_host_template usb_stor_host_template = { /* basic userland interface stuff */ .name = "usb-storage", .proc_name = "usb-storage", .proc_info = usb_storage_proc_info, - .proc_dir = NULL, .info = usb_storage_info, - .ioctl = NULL, - - /* old-style detect and release */ - .detect = NULL, - .release = NULL, /* command interface -- queued only */ - .command = NULL, .queuecommand = usb_storage_queuecommand, /* error and abort handlers */ .eh_abort_handler = usb_storage_command_abort, .eh_device_reset_handler = usb_storage_device_reset, .eh_bus_reset_handler = usb_storage_bus_reset, - .eh_host_reset_handler = NULL, - .eh_strategy_handler = NULL, /* queue commands only, only one command per LUN */ .can_queue = 1, @@ -391,21 +382,9 @@ /* unknown initiator id */ .this_id = -1, - /* no limit on commands */ - .max_sectors = 0, - - /* pre- and post- device scan functions */ - .slave_alloc = NULL, - .slave_configure = NULL, - .slave_destroy = NULL, - /* lots of sg segments can be handled */ .sg_tablesize = SG_ALL, - /* use 32-bit address space for DMA */ - .unchecked_isa_dma = FALSE, - .highmem_io = FALSE, - /* merge commands... this seems to help performance, but * periodically someone should test to see which setting is more * optimal. @@ -414,9 +393,6 @@ /* emulated HBA */ .emulated = TRUE, - - /* sorry, no BIOS to help us */ - .bios_param = NULL, /* module management */ .module = THIS_MODULE diff -Nru a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h --- a/drivers/usb/storage/scsiglue.h Sun Jan 19 06:10:31 2003 +++ b/drivers/usb/storage/scsiglue.h Thu Jun 5 11:52:51 2003 @@ -47,7 +47,7 @@ extern unsigned char usb_stor_sense_notready[18]; extern unsigned char usb_stor_sense_invalidCDB[18]; -extern struct SHT usb_stor_host_template; +extern struct scsi_host_template usb_stor_host_template; extern int usb_stor_scsiSense10to6(Scsi_Cmnd*); extern int usb_stor_scsiSense6to10(Scsi_Cmnd*); diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c --- a/drivers/usb/storage/usb.c Sun Jun 8 07:15:45 2003 +++ b/drivers/usb/storage/usb.c Wed Jun 11 20:19:46 2003 @@ -736,7 +736,7 @@ * Since this is a new device, we need to register a SCSI * host definition with the higher SCSI layers. */ - us->host = scsi_register(&usb_stor_host_template, sizeof(us)); + us->host = scsi_host_alloc(&usb_stor_host_template, sizeof(us)); if (!us->host) { printk(KERN_WARNING USB_STORAGE "Unable to register the scsi host\n"); @@ -772,7 +772,7 @@ /* Finish the SCSI host removal sequence */ if (us->host) { (struct us_data *) us->host->hostdata[0] = NULL; - scsi_unregister(us->host); + scsi_host_put(us->host); } /* Kill the control thread diff -Nru a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/Kconfig.binfmt Sun Jun 15 09:07:21 2003 @@ -0,0 +1,116 @@ +config BINFMT_ELF + tristate "Kernel support for ELF binaries" + depends on MMU + default y + ---help--- + ELF (Executable and Linkable Format) is a format for libraries and + executables used across different architectures and operating + systems. Saying Y here will enable your kernel to run ELF binaries + and enlarge it by about 13 KB. ELF support under Linux has now all + but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) + because it is portable (this does *not* mean that you will be able + to run executables from different architectures or operating systems + however) and makes building run-time libraries very easy. Many new + executables are distributed solely in ELF format. You definitely + want to say Y here. + + Information about ELF is contained in the ELF HOWTO available from + . + + If you find that after upgrading from Linux kernel 1.2 and saying Y + here, you still can't run any ELF binaries (they just crash), then + you'll have to install the newest ELF runtime libraries, including + ld.so (check the file for location and + latest version). + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read . The module + will be called binfmt_elf. Saying M or N here is dangerous because + some crucial programs on your system might be in ELF format. + +config BINFMT_FLAT + tristate "Kernel support for flat binaries" + depends on !MMU || SUPERH + help + Support uClinux FLAT format binaries. + +config BINFMT_ZFLAT + bool "Enable ZFLAT support" + depends on BINFMT_FLAT + help + Support FLAT format compressed binaries + +config BINFMT_AOUT + tristate "Kernel support for a.out and ECOFF binaries" + depends on X86 || ALPHA || ARM || M68K || MIPS || SPARC + ---help--- + A.out (Assembler.OUTput) is a set of formats for libraries and + executables used in the earliest versions of UNIX. Linux used + the a.out formats QMAGIC and ZMAGIC until they were replaced + with the ELF format. + + The conversion to ELF started in 1995. This option is primarily + provided for historical interest and for the benefit of those + who need to run binaries from that era. + + Most people should answer N here. If you think you may have + occasional use for this format, enable module support above + and answer M here to compile this support as a module called + binfmt_aout. + + If any crucial components of your system (such as /sbin/init + or /lib/ld.so) are still in a.out format, you will have to + say Y here. + +config OSF4_COMPAT + bool "OSF/1 v4 readv/writev compatibility" + depends on ALPHA && BINFMT_AOUT + help + Say Y if you are using OSF/1 binaries (like Netscape and Acrobat) + with v4 shared libraries freely available from Compaq. If you're + going to use shared libraries from Tru64 version 5.0 or later, say N. + +config BINFMT_EM86 + tristate "Kernel support for Linux/Intel ELF binaries" + depends on ALPHA + ---help--- + Say Y here if you want to be able to execute Linux/Intel ELF + binaries just like native Alpha binaries on your Alpha machine. For + this to work, you need to have the emulator /usr/bin/em86 in place. + + You can get the same functionality by saying N here and saying Y to + "Kernel support for MISC binaries". + + You may answer M to compile the emulation support as a module and + later load the module when you want to use a Linux/Intel binary. The + module will be called binfmt_em86. If unsure, say Y. + +config BINFMT_SOM + tristate "Kernel support for SOM binaries" + depends on PARISC && HPUX + help + SOM is a binary executable format inherited from HP/UX. Say + Y here to be able to load and execute SOM binaries directly. + +config BINFMT_MISC + tristate "Kernel support for MISC binaries" + ---help--- + If you say Y here, it will be possible to plug wrapper-driven binary + formats into the kernel. You will like this especially when you use + programs that need an interpreter to run like Java, Python or + Emacs-Lisp. It's also useful if you often run DOS executables under + the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from + ). Once you have + registered such a binary class with the kernel, you can start one of + those programs simply by typing in its name at a shell prompt; Linux + will automatically feed it to the correct interpreter. + + You can do other nice things, too. Read the file + to learn how to use this + feature, and for information about how + to include Java support. + + You may say M here for module support and later load the module when + you have use for it; the module is called binfmt_misc. If you + don't know what to answer at this point, say Y. diff -Nru a/fs/namei.c b/fs/namei.c --- a/fs/namei.c Thu Jun 12 15:51:27 2003 +++ b/fs/namei.c Mon Jun 16 22:09:04 2003 @@ -985,6 +985,8 @@ * 7. If we were asked to remove a directory and victim isn't one - ENOTDIR. * 8. If we were asked to remove a non-directory and victim isn't one - EISDIR. * 9. We can't remove a root or mountpoint. + * 10. We don't allow removal of NFS sillyrenamed files; it's handled by + * nfs_async_unlink(). */ static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir) { @@ -1008,6 +1010,8 @@ return -EISDIR; if (IS_DEADDIR(dir)) return -ENOENT; + if (victim->d_flags & DCACHE_NFSFS_RENAMED) + return -EBUSY; return 0; } diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c --- a/fs/nfs/inode.c Sun May 25 19:14:31 2003 +++ b/fs/nfs/inode.c Mon Jun 16 22:03:19 2003 @@ -715,7 +715,6 @@ if (fattr->valid & NFS_ATTR_FATTR_V4) nfsi->change_attr = fattr->change_attr; inode->i_size = nfs_size_to_loff_t(fattr->size); - inode->i_mode = fattr->mode; inode->i_nlink = fattr->nlink; inode->i_uid = fattr->uid; inode->i_gid = fattr->gid; diff -Nru a/fs/nfsd/auth.c b/fs/nfsd/auth.c --- a/fs/nfsd/auth.c Tue Feb 5 09:39:38 2002 +++ b/fs/nfsd/auth.c Tue Jun 17 16:31:29 2003 @@ -17,9 +17,6 @@ struct svc_cred *cred = &rqstp->rq_cred; int i; - if (rqstp->rq_userset) - return; - if (exp->ex_flags & NFSEXP_ALLSQUASH) { cred->cr_uid = exp->ex_anon_uid; cred->cr_gid = exp->ex_anon_gid; @@ -57,5 +54,4 @@ current->cap_permitted); } - rqstp->rq_userset = 1; } diff -Nru a/fs/nfsd/export.c b/fs/nfsd/export.c --- a/fs/nfsd/export.c Mon May 19 23:34:38 2003 +++ b/fs/nfsd/export.c Tue Jun 17 16:18:16 2003 @@ -153,9 +153,13 @@ goto out; dprintk("Path seems to be <%s>\n", buf); err = 0; - if (len == 0) + if (len == 0) { + struct svc_expkey *ek; set_bit(CACHE_NEGATIVE, &key.h.flags); - else { + ek = svc_expkey_lookup(&key, 2); + if (ek) + expkey_put(&ek->h, &svc_expkey_cache); + } else { struct nameidata nd; struct svc_expkey *ek; struct svc_export *exp; diff -Nru a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c --- a/fs/nfsd/nfs4proc.c Mon May 19 23:34:38 2003 +++ b/fs/nfsd/nfs4proc.c Tue Jun 17 16:30:53 2003 @@ -147,12 +147,6 @@ return 0; } -static inline int -nfsd4_renew(clientid_t *clientid) -{ - return nfs_ok; -} - /* * filehandle-manipulating ops. */ diff -Nru a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c --- a/fs/nfsd/nfs4state.c Mon May 19 23:34:37 2003 +++ b/fs/nfsd/nfs4state.c Tue Jun 17 16:31:07 2003 @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,7 @@ static u32 current_clientid = 1; static u32 current_ownerid = 0; static u32 current_fileid = 0; +static u32 nfs4_init = 0; /* debug counters */ u32 list_add_perfile = 0; @@ -105,11 +107,28 @@ * * unconf_str_hastbl[] and unconf_id_hashtbl[] hold unconfirmed * setclientid info. + * + * client_lru holds client queue ordered by nfs4_client.cl_time + * for lease renewal. */ static struct list_head conf_id_hashtbl[CLIENT_HASH_SIZE]; static struct list_head conf_str_hashtbl[CLIENT_HASH_SIZE]; static struct list_head unconf_str_hashtbl[CLIENT_HASH_SIZE]; static struct list_head unconf_id_hashtbl[CLIENT_HASH_SIZE]; +static struct list_head client_lru; + +static inline void +renew_client(struct nfs4_client *clp) +{ + /* + * Move client to the end to the LRU list. + */ + dprintk("renewing client (clientid %08x/%08x)\n", + clp->cl_clientid.cl_boot, + clp->cl_clientid.cl_id); + list_move_tail(&clp->cl_lru, &client_lru); + clp->cl_time = get_seconds(); +} /* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */ static int @@ -160,6 +179,7 @@ dprintk("NFSD: expire_client\n"); list_del(&clp->cl_idhash); list_del(&clp->cl_strhash); + list_del(&clp->cl_lru); while (!list_empty(&clp->cl_perclient)) { sop = list_entry(clp->cl_perclient.next, struct nfs4_stateowner, so_perclient); release_stateowner(sop); @@ -176,6 +196,7 @@ INIT_LIST_HEAD(&clp->cl_idhash); INIT_LIST_HEAD(&clp->cl_strhash); INIT_LIST_HEAD(&clp->cl_perclient); + INIT_LIST_HEAD(&clp->cl_lru); out: return clp; } @@ -264,6 +285,8 @@ list_add(&clp->cl_strhash, &unconf_str_hashtbl[strhashval]); idhashval = clientid_hashval(clp->cl_clientid.cl_id); list_add(&clp->cl_idhash, &unconf_id_hashtbl[idhashval]); + list_add_tail(&clp->cl_lru, &client_lru); + clp->cl_time = get_seconds(); } void @@ -271,13 +294,13 @@ { unsigned int strhashval; - printk("ANDROS: move_to_confirm nfs4_client %p\n", clp); list_del_init(&clp->cl_strhash); list_del_init(&clp->cl_idhash); list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]); strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len); list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]); + renew_client(clp); } /* @@ -940,9 +963,7 @@ open->op_stateowner = sop; status = nfs_ok; renew: - /* XXX implement LRU and state recovery thread - * renew will place nfs4_client at end of LRU - */ + renew_client(sop->so_client); out: up(&client_sema); /*XXX need finer grained locking */ return status; @@ -1048,13 +1069,98 @@ kfree(stp); goto out; } +static struct work_struct laundromat_work; +static void laundromat_main(void *); +static DECLARE_WORK(laundromat_work, laundromat_main, NULL); + +int +nfsd4_renew(clientid_t *clid) +{ + struct nfs4_client *clp; + struct list_head *pos, *next; + unsigned int idhashval; + int status; + + down(&client_sema); + printk("process_renew(%08x/%08x): starting\n", + clid->cl_boot, clid->cl_id); + status = nfserr_stale_clientid; + if (STALE_CLIENTID(clid)) + goto out; + status = nfs_ok; + idhashval = clientid_hashval(clid->cl_id); + list_for_each_safe(pos, next, &conf_id_hashtbl[idhashval]) { + clp = list_entry(pos, struct nfs4_client, cl_idhash); + if (!cmp_clid(&clp->cl_clientid, clid)) + continue; + renew_client(clp); + goto out; + } + list_for_each_safe(pos, next, &unconf_id_hashtbl[idhashval]) { + clp = list_entry(pos, struct nfs4_client, cl_idhash); + if (!cmp_clid(&clp->cl_clientid, clid)) + continue; + renew_client(clp); + goto out; + } + /* + * Couldn't find an nfs4_client for this clientid. + * Presumably this is because the client took too long to + * RENEW, so return NFS4ERR_EXPIRED. + */ + printk("nfsd4_renew: clientid not found!\n"); + status = nfserr_expired; +out: + up(&client_sema); + return status; +} + +time_t +nfs4_laundromat(void) +{ + struct nfs4_client *clp; + struct list_head *pos, *next; + time_t cutoff = get_seconds() - NFSD_LEASE_TIME; + time_t t, return_val = NFSD_LEASE_TIME; + + down(&client_sema); + + dprintk("NFSD: laundromat service - starting, examining clients\n"); + list_for_each_safe(pos, next, &client_lru) { + clp = list_entry(pos, struct nfs4_client, cl_lru); + if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) { + t = clp->cl_time - cutoff; + if (return_val > t) + return_val = t; + break; + } + dprintk("NFSD: purging unused client (clientid %08x)\n", + clp->cl_clientid.cl_id); + expire_client(clp); + } + if (return_val < NFSD_LAUNDROMAT_MINTIMEOUT) + return_val = NFSD_LAUNDROMAT_MINTIMEOUT; + up(&client_sema); + return return_val; +} + +void +laundromat_main(void *not_used) +{ + time_t t; + + t = nfs4_laundromat(); + dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t); + schedule_delayed_work(&laundromat_work, t*HZ); +} void nfs4_state_init(void) { - struct timespec tv; int i; + if (nfs4_init) + return; for (i = 0; i < CLIENT_HASH_SIZE; i++) { INIT_LIST_HEAD(&conf_id_hashtbl[i]); INIT_LIST_HEAD(&conf_str_hashtbl[i]); @@ -1067,9 +1173,13 @@ for (i = 0; i < OWNER_HASH_SIZE; i++) { INIT_LIST_HEAD(&ownerstr_hashtbl[i]); } + INIT_LIST_HEAD(&client_lru); init_MUTEX(&client_sema); - tv = CURRENT_TIME; - boot_time = tv.tv_sec; + boot_time = get_seconds(); + INIT_WORK(&laundromat_work,laundromat_main, NULL); + schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ); + nfs4_init = 1; + } static void @@ -1089,6 +1199,9 @@ } } release_all_files(); + cancel_delayed_work(&laundromat_work); + flush_scheduled_work(); + nfs4_init = 0; dprintk("NFSD: list_add_perfile %d list_del_perfile %d\n", list_add_perfile, list_del_perfile); dprintk("NFSD: add_perclient %d del_perclient %d\n", diff -Nru a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c --- a/fs/nfsd/nfs4xdr.c Mon May 19 23:34:36 2003 +++ b/fs/nfsd/nfs4xdr.c Tue Jun 17 16:30:43 2003 @@ -1039,6 +1039,7 @@ *p++ = htonl((u32)(n)); \ } while (0) #define WRITEMEM(ptr,nbytes) do { \ + *(p + XDR_QUADLEN(nbytes) -1) = 0; \ memcpy(p, ptr, nbytes); \ p += XDR_QUADLEN(nbytes); \ } while (0) @@ -1425,6 +1426,7 @@ u32 *p = cd->buffer; u32 *attrlenp; struct dentry *dentry; + struct svc_export *exp = cd->rd_fhp->fh_export; u32 bmval0, bmval1; int nfserr = 0; @@ -1454,9 +1456,7 @@ if ((bmval0 & ~(FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_FILEID)) || bmval1) { /* * "Heavyweight" case: we have no choice except to - * call nfsd4_encode_fattr(). As far as I know, - * only Windows clients will trigger this code - * path. + * call nfsd4_encode_fattr(). */ dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen); if (IS_ERR(dentry)) { @@ -1464,10 +1464,25 @@ goto error; } - nfserr = nfsd4_encode_fattr(NULL, cd->rd_fhp->fh_export, - dentry, p, &buflen, cd->rd_bmval); - dput(dentry); + if (d_mountpoint(dentry)) { + if ((nfserr = nfsd_cross_mnt(cd->rd_rqstp, &dentry, + &exp))) { + /* + * -EAGAIN is the only error returned from + * nfsd_cross_mnt() and it indicates that an + * up-call has been initiated to fill in the export + * options on exp. When the answer comes back, + * this call will be retried. + */ + dput(dentry); + nfserr = nfserr_dropit; + goto error; + } + } + + nfserr = nfsd4_encode_fattr(NULL, exp, + dentry, p, &buflen, cd->rd_bmval); if (!nfserr) { p += buflen; goto out; diff -Nru a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c --- a/fs/nfsd/nfsctl.c Sun May 25 18:48:17 2003 +++ b/fs/nfsd/nfsctl.c Tue Jun 17 16:31:07 2003 @@ -453,7 +453,6 @@ nfsd_cache_init(); /* RPC reply cache */ nfsd_export_init(); /* Exports table */ nfsd_lockd_init(); /* lockd->nfsd callbacks */ - nfs4_state_init(); /* NFSv4 State */ if (proc_mkdir("fs/nfs", 0)) { struct proc_dir_entry *entry; entry = create_proc_entry("fs/nfs/exports", 0, NULL); diff -Nru a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c --- a/fs/nfsd/nfsfh.c Wed Apr 2 22:51:32 2003 +++ b/fs/nfsd/nfsfh.c Tue Jun 17 16:31:29 2003 @@ -161,9 +161,6 @@ goto out; } - /* Set user creds if we haven't done so already. */ - nfsd_setuser(rqstp, exp); - /* * Look up the dentry using the NFS file handle. */ @@ -222,6 +219,10 @@ cache_get(&exp->h); inode = dentry->d_inode; + + + /* Set user creds for this exportpoint */ + nfsd_setuser(rqstp, exp); /* Type check. The correct error return for type mismatches * does not seem to be generally agreed upon. SunOS seems to diff -Nru a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c --- a/fs/nfsd/nfsproc.c Mon Jan 13 04:39:46 2003 +++ b/fs/nfsd/nfsproc.c Tue Jun 17 16:18:16 2003 @@ -591,6 +591,7 @@ { nfserr_dquot, -EDQUOT }, #endif { nfserr_stale, -ESTALE }, + { nfserr_dropit, -EAGAIN }, { nfserr_dropit, -ENOMEM }, { -1, -EIO } }; diff -Nru a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c --- a/fs/nfsd/nfssvc.c Tue Jun 10 23:33:23 2003 +++ b/fs/nfsd/nfssvc.c Tue Jun 17 16:31:07 2003 @@ -91,6 +91,7 @@ /* Readahead param cache - will no-op if it already exists */ error = nfsd_racache_init(2*nrservs); + nfs4_state_init(); if (error<0) goto out; if (!nfsd_serv) { diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c --- a/fs/nfsd/vfs.c Sun May 4 22:49:54 2003 +++ b/fs/nfsd/vfs.c Tue Jun 17 16:24:29 2003 @@ -74,6 +74,46 @@ static struct raparms * raparml; static struct raparms * raparm_cache; +/* + * Called from nfsd_lookup and encode_dirent. Check if we have crossed + * a mount point. + * Returns -EAGAIN leaving *dpp and *expp unchanged, + * or nfs_ok having possibly changed *dpp and *expp + */ +int +nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, + struct svc_export **expp) +{ + struct svc_export *exp = *expp, *exp2 = NULL; + struct dentry *dentry = *dpp; + struct vfsmount *mnt = mntget(exp->ex_mnt); + struct dentry *mounts = dget(dentry); + int err = nfs_ok; + + while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts)); + + exp2 = exp_get_by_name(exp->ex_client, mnt, mounts, &rqstp->rq_chandle); + if (IS_ERR(exp2)) { + err = PTR_ERR(exp2); + dput(mounts); + mntput(mnt); + goto out; + } + if (exp2 && ((exp->ex_flags & NFSEXP_CROSSMNT) || EX_NOHIDE(exp2))) { + /* successfully crossed mount point */ + exp_put(exp); + *expp = exp2; + dput(dentry); + *dpp = mounts; + } else { + if (exp2) exp_put(exp2); + dput(mounts); + } + mntput(mnt); +out: + return err; +} + /* * Look up one component of a pathname. * N.B. After this call _both_ fhp and resfh need an fh_put @@ -154,34 +194,10 @@ * check if we have crossed a mount point ... */ if (d_mountpoint(dentry)) { - struct svc_export *exp2 = NULL; - struct vfsmount *mnt = mntget(exp->ex_mnt); - struct dentry *mounts = dget(dentry); - while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts)) - ; - - exp2 = exp_get_by_name(exp->ex_client, mnt, - mounts, &rqstp->rq_chandle); - if (IS_ERR(exp2)) { - err = PTR_ERR(exp2); - dput(mounts); - dput(dentry); - mntput(mnt); - goto out; - } - if (exp2 && - ((exp->ex_flags & NFSEXP_CROSSMNT) - || EX_NOHIDE(exp2))) { - /* successfully crossed mount point */ - exp_put(exp); - exp = exp2; + if ((err = nfsd_cross_mnt(rqstp, &dentry, &exp))) { dput(dentry); - dentry = mounts; - } else { - if (exp2) exp_put(exp2); - dput(mounts); + goto out_nfserr; } - mntput(mnt); } } /* diff -Nru a/include/asm-i386/apic.h b/include/asm-i386/apic.h --- a/include/asm-i386/apic.h Sat Jun 14 17:17:28 2003 +++ b/include/asm-i386/apic.h Sun Jun 15 11:00:08 2003 @@ -81,6 +81,8 @@ extern void setup_apic_nmi_watchdog (void); extern void disable_lapic_nmi_watchdog(void); extern void enable_lapic_nmi_watchdog(void); +extern void disable_timer_nmi_watchdog(void); +extern void enable_timer_nmi_watchdog(void); extern inline void nmi_watchdog_tick (struct pt_regs * regs); extern int APIC_init_uniprocessor (void); extern void disable_APIC_timer(void); diff -Nru a/include/asm-sparc/xor.h b/include/asm-sparc/xor.h --- a/include/asm-sparc/xor.h Mon Feb 4 23:53:56 2002 +++ b/include/asm-sparc/xor.h Mon Jun 16 18:31:20 2003 @@ -250,11 +250,11 @@ } static struct xor_block_template xor_block_SPARC = { - name: "SPARC", - do_2: sparc_2, - do_3: sparc_3, - do_4: sparc_4, - do_5: sparc_5, + .name = "SPARC", + .do_2 = sparc_2, + .do_3 = sparc_3, + .do_4 = sparc_4, + .do_5 = sparc_5, }; /* For grins, also test the generic routines. */ diff -Nru a/include/asm-sparc64/xor.h b/include/asm-sparc64/xor.h --- a/include/asm-sparc64/xor.h Mon Feb 4 23:54:46 2002 +++ b/include/asm-sparc64/xor.h Mon Jun 16 18:31:20 2003 @@ -388,11 +388,11 @@ "); static struct xor_block_template xor_block_VIS = { - name: "VIS", - do_2: xor_vis_2, - do_3: xor_vis_3, - do_4: xor_vis_4, - do_5: xor_vis_5, + .name = "VIS", + .do_2 = xor_vis_2, + .do_3 = xor_vis_3, + .do_4 = xor_vis_4, + .do_5 = xor_vis_5, }; #define XOR_TRY_TEMPLATES xor_speed(&xor_block_VIS) diff -Nru a/include/asm-v850/hardirq.h b/include/asm-v850/hardirq.h --- a/include/asm-v850/hardirq.h Mon May 12 18:59:24 2003 +++ b/include/asm-v850/hardirq.h Mon Jun 16 22:23:12 2003 @@ -80,12 +80,12 @@ # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET #endif -#define irq_exit() \ -do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && softirq_pending(smp_processor_id())) \ - do_softirq(); \ - preempt_enable_no_resched(); \ +#define irq_exit() \ +do { \ + preempt_count() -= IRQ_EXIT_OFFSET; \ + if (!in_interrupt() && softirq_pending(smp_processor_id())) \ + do_softirq(); \ + preempt_enable_no_resched(); \ } while (0) #ifndef CONFIG_SMP diff -Nru a/include/asm-v850/io.h b/include/asm-v850/io.h --- a/include/asm-v850/io.h Fri Nov 1 08:38:12 2002 +++ b/include/asm-v850/io.h Mon Jun 16 22:23:12 2003 @@ -1,8 +1,8 @@ /* * include/asm-v850/io.h -- Misc I/O operations * - * Copyright (C) 2001,02 NEC Corporation - * Copyright (C) 2001,02 Miles Bader + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this @@ -29,6 +29,13 @@ (void)((*(volatile unsigned short *) (addr)) = (b)) #define writel(b, addr) \ (void)((*(volatile unsigned int *) (addr)) = (b)) + +#define __raw_readb readb +#define __raw_readw readw +#define __raw_readl readl +#define __raw_writeb writeb +#define __raw_writew writew +#define __raw_writel writel #define inb(addr) readb (addr) #define inw(addr) readw (addr) diff -Nru a/include/linux/atmdev.h b/include/linux/atmdev.h --- a/include/linux/atmdev.h Wed Jun 4 17:57:06 2003 +++ b/include/linux/atmdev.h Tue Jun 17 11:00:05 2003 @@ -452,7 +452,7 @@ int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci); int atm_pcr_goal(struct atm_trafprm *tp); -void atm_async_release_vcc(struct atm_vcc *vcc,int reply); +void vcc_release_async(struct atm_vcc *vcc, int reply); #endif /* __KERNEL__ */ diff -Nru a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h --- a/include/linux/nfsd/nfsd.h Mon May 19 23:34:37 2003 +++ b/include/linux/nfsd/nfsd.h Tue Jun 17 16:30:53 2003 @@ -69,6 +69,8 @@ int fh_lock_parent(struct svc_fh *, struct dentry *); int nfsd_racache_init(int); void nfsd_racache_shutdown(void); +int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, + struct svc_export **expp); int nfsd_lookup(struct svc_rqst *, struct svc_fh *, const char *, int, struct svc_fh *); int nfsd_setattr(struct svc_rqst *, struct svc_fh *, @@ -226,6 +228,7 @@ #define COMPOUND_ERR_SLACK_SPACE 12 /* OP_SETATTR */ #define NFSD_LEASE_TIME 60 /* seconds */ +#define NFSD_LAUNDROMAT_MINTIMEOUT 10 /* seconds */ /* * The following attributes are currently not supported by the NFSv4 server: diff -Nru a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h --- a/include/linux/nfsd/state.h Mon May 19 23:34:37 2003 +++ b/include/linux/nfsd/state.h Tue Jun 17 16:30:53 2003 @@ -73,13 +73,18 @@ struct list_head cl_idhash; /* hash by cl_clientid.id */ struct list_head cl_strhash; /* hash by cl_name */ struct list_head cl_perclient; /* list: stateowners */ + struct list_head cl_lru; /* tail queue */ struct xdr_netobj cl_name; /* id generated by client */ nfs4_verifier cl_verifier; /* generated by client */ + time_t cl_time; /* time of last lease renewal */ u32 cl_addr; /* client ipaddress */ struct svc_cred cl_cred; /* setclientid principal */ clientid_t cl_clientid; /* generated by server */ nfs4_verifier cl_confirm; /* generated by server */ }; + +extern time_t nfs4_laundromat(void); +int nfsd4_renew(clientid_t *clid); static inline void update_stateid(stateid_t *stateid) diff -Nru a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h --- a/include/linux/sunrpc/cache.h Tue Mar 11 20:03:48 2003 +++ b/include/linux/sunrpc/cache.h Tue Jun 17 16:18:16 2003 @@ -115,6 +115,8 @@ struct list_head recent; /* on fifo */ struct cache_head *item; /* cache item we wait on */ time_t recv_time; + void *owner; /* we might need to discard all defered requests + * owned by someone */ void (*revisit)(struct cache_deferred_req *req, int too_many); }; @@ -168,12 +170,14 @@ tmp = container_of(*hp, RTN, MEMBER); \ if (TEST) { /* found a match */ \ \ + if (set == 1 && test_bit(CACHE_VALID, &tmp->MEMBER.flags) && !new) \ + break; \ + \ atomic_inc(&tmp->MEMBER.refcnt); \ if (set) { \ - if (set!= 2 && test_bit(CACHE_VALID, &tmp->MEMBER.flags))\ + if (set == 1 && test_bit(CACHE_VALID, &tmp->MEMBER.flags))\ { /* need to swap in new */ \ RTN *t2; \ - if (!new) break; \ \ new->MEMBER.next = tmp->MEMBER.next; \ *hp = &new->MEMBER; \ @@ -242,6 +246,7 @@ extern void cache_defer_req(struct cache_req *req, struct cache_head *item); extern void cache_revisit_request(struct cache_head *item); +extern void cache_clean_deferred(void *owner); static inline struct cache_head *cache_get(struct cache_head *h) { diff -Nru a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h --- a/include/linux/sunrpc/svc.h Tue May 6 07:20:53 2003 +++ b/include/linux/sunrpc/svc.h Tue Jun 17 16:31:29 2003 @@ -125,7 +125,6 @@ u32 rq_proc; /* procedure number */ u32 rq_prot; /* IP protocol */ unsigned short - rq_userset : 1, /* auth->setuser OK */ rq_secure : 1; /* secure port */ @@ -196,14 +195,14 @@ static inline void svc_pushback_unused_pages(struct svc_rqst *rqstp) { - while (rqstp->rq_resused) { + while (rqstp->rq_resused && + rqstp->rq_res.pages != &rqstp->rq_respages[rqstp->rq_resused]) { + if (rqstp->rq_respages[--rqstp->rq_resused] != NULL) { rqstp->rq_argpages[rqstp->rq_arghi++] = rqstp->rq_respages[rqstp->rq_resused]; rqstp->rq_respages[rqstp->rq_resused] = NULL; } - if (rqstp->rq_res.pages == &rqstp->rq_respages[rqstp->rq_resused]) - break; } } @@ -218,7 +217,6 @@ } struct svc_deferred_req { - struct svc_serv *serv; u32 prot; /* protocol (UDP or TCP) */ struct sockaddr_in addr; struct svc_sock *svsk; /* where reply must go */ diff -Nru a/include/linux/tcp.h b/include/linux/tcp.h --- a/include/linux/tcp.h Fri Jun 6 07:22:29 2003 +++ b/include/linux/tcp.h Tue Jun 17 09:35:27 2003 @@ -219,7 +219,7 @@ __u32 snd_sml; /* Last byte of the most recently transmitted small packet */ __u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */ __u32 lsndtime; /* timestamp of last sent data packet (for restart window) */ - + struct tcp_bind_bucket *bind_hash; /* Delayed ACK control data */ struct { __u8 pending; /* ACK is pending */ diff -Nru a/include/net/sctp/structs.h b/include/net/sctp/structs.h --- a/include/net/sctp/structs.h Mon Jun 16 08:11:36 2003 +++ b/include/net/sctp/structs.h Tue Jun 17 09:35:27 2003 @@ -313,6 +313,7 @@ /* What is our base endpointer? */ struct sctp_endpoint *ep; + struct sctp_bind_bucket *bind_hash; /* Various Socket Options. */ __u16 default_stream; __u32 default_ppid; diff -Nru a/include/net/sock.h b/include/net/sock.h --- a/include/net/sock.h Mon Jun 16 08:11:36 2003 +++ b/include/net/sock.h Tue Jun 17 09:35:27 2003 @@ -133,7 +133,6 @@ * @sk_forward_alloc - space allocated forward * @sk_allocation - allocation mode * @sk_sndbuf - size of send buffer in bytes - * @sk_prev - pointer to previous sock in the list this sock is in * @sk_flags - %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE settings * @sk_no_check - %SO_NO_CHECK setting, wether or not checkup packets * @sk_debug - %SO_DEBUG setting @@ -206,7 +205,6 @@ int sk_forward_alloc; unsigned int sk_allocation; int sk_sndbuf; - struct sock *sk_prev; unsigned long sk_flags; char sk_no_check; unsigned char sk_debug; diff -Nru a/include/net/syncppp.h b/include/net/syncppp.h --- a/include/net/syncppp.h Mon Feb 4 23:40:24 2002 +++ b/include/net/syncppp.h Fri May 30 12:35:20 2003 @@ -48,6 +48,7 @@ struct timer_list pp_timer; struct net_device *pp_if; char pp_link_state; /* Link status */ + spinlock_t lock; }; struct ppp_device diff -Nru a/include/net/tcp.h b/include/net/tcp.h --- a/include/net/tcp.h Mon Jun 16 11:44:09 2003 +++ b/include/net/tcp.h Tue Jun 17 09:35:27 2003 @@ -1475,7 +1475,8 @@ TCP_INC_STATS(TcpEstabResets); sk->sk_prot->unhash(sk); - if (sk->sk_prev && !(sk->sk_userlocks & SOCK_BINDPORT_LOCK)) + if (tcp_sk(sk)->bind_hash && + !(sk->sk_userlocks & SOCK_BINDPORT_LOCK)) tcp_put_port(sk); /* fall through */ default: diff -Nru a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/scsi/scsi_cmnd.h Sun Jun 8 12:19:25 2003 @@ -0,0 +1,164 @@ +#ifndef _SCSI_SCSI_CMND_H +#define _SCSI_SCSI_CMND_H + +#include +#include + +struct request; +struct scatterlist; +struct scsi_device; +struct scsi_request; + + +/* embedded in scsi_cmnd */ +struct scsi_pointer { + char *ptr; /* data pointer */ + int this_residual; /* left in this buffer */ + struct scatterlist *buffer; /* which buffer */ + int buffers_residual; /* how many buffers left */ + + dma_addr_t dma_handle; + + volatile int Status; + volatile int Message; + volatile int have_data_in; + volatile int sent_command; + volatile int phase; +}; + +struct scsi_cmnd { + int sc_magic; + + struct scsi_device *device; + unsigned short state; + unsigned short owner; + struct scsi_request *sc_request; + + struct list_head list; /* scsi_cmnd participates in queue lists */ + + struct list_head eh_entry; /* entry for the host eh_cmd_q */ + int eh_state; /* Used for state tracking in error handlr */ + int eh_eflags; /* Used by error handlr */ + void (*done) (struct scsi_cmnd *); /* Mid-level done function */ + + /* + * A SCSI Command is assigned a nonzero serial_number when internal_cmnd + * passes it to the driver's queue command function. The serial_number + * is cleared when scsi_done is entered indicating that the command has + * been completed. If a timeout occurs, the serial number at the moment + * of timeout is copied into serial_number_at_timeout. By subsequently + * comparing the serial_number and serial_number_at_timeout fields + * during abort or reset processing, we can detect whether the command + * has already completed. This also detects cases where the command has + * completed and the SCSI Command structure has already being reused + * for another command, so that we can avoid incorrectly aborting or + * resetting the new command. + */ + unsigned long serial_number; + unsigned long serial_number_at_timeout; + + int retries; + int allowed; + int timeout_per_command; + int timeout_total; + int timeout; + + /* + * We handle the timeout differently if it happens when a reset, + * abort, etc are in process. + */ + unsigned volatile char internal_timeout; + + unsigned char cmd_len; + unsigned char old_cmd_len; + unsigned char sc_data_direction; + unsigned char sc_old_data_direction; + + /* These elements define the operation we are about to perform */ +#define MAX_COMMAND_SIZE 16 + unsigned char cmnd[MAX_COMMAND_SIZE]; + unsigned request_bufflen; /* Actual request size */ + + struct timer_list eh_timeout; /* Used to time out the command. */ + void *request_buffer; /* Actual requested buffer */ + + /* These elements define the operation we ultimately want to perform */ + unsigned char data_cmnd[MAX_COMMAND_SIZE]; + unsigned short old_use_sg; /* We save use_sg here when requesting + * sense info */ + unsigned short use_sg; /* Number of pieces of scatter-gather */ + unsigned short sglist_len; /* size of malloc'd scatter-gather list */ + unsigned short abort_reason; /* If the mid-level code requests an + * abort, this is the reason. */ + unsigned bufflen; /* Size of data buffer */ + void *buffer; /* Data buffer */ + + unsigned underflow; /* Return error if less than + this amount is transferred */ + unsigned old_underflow; /* save underflow here when reusing the + * command for error handling */ + + unsigned transfersize; /* How much we are guaranteed to + transfer with each SCSI transfer + (ie, between disconnect / + reconnects. Probably == sector + size */ + + int resid; /* Number of bytes requested to be + transferred less actual number + transferred (0 if not supported) */ + + struct request *request; /* The command we are + working on */ + +#define SCSI_SENSE_BUFFERSIZE 64 + unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE]; /* obtained by REQUEST SENSE + * when CHECK CONDITION is + * received on original command + * (auto-sense) */ + + unsigned flags; + + /* Low-level done function - can be used by low-level driver to point + * to completion function. Not used by mid/upper level code. */ + void (*scsi_done) (struct scsi_cmnd *); + + /* + * The following fields can be written to by the host specific code. + * Everything else should be left alone. + */ + struct scsi_pointer SCp; /* Scratchpad used by some host adapters */ + + unsigned char *host_scribble; /* The host adapter is allowed to + * call scsi_malloc and get some memory + * and hang it here. The host adapter + * is also expected to call scsi_free + * to release this memory. (The memory + * obtained by scsi_malloc is guaranteed + * to be at an address < 16Mb). */ + + int result; /* Status code from lower level driver */ + + unsigned char tag; /* SCSI-II queued command tag */ + unsigned long pid; /* Process ID, starts at 0 */ +}; + +/* + * These are the values that scsi_cmd->state can take. + */ +#define SCSI_STATE_TIMEOUT 0x1000 +#define SCSI_STATE_FINISHED 0x1001 +#define SCSI_STATE_FAILED 0x1002 +#define SCSI_STATE_QUEUED 0x1003 +#define SCSI_STATE_UNUSED 0x1006 +#define SCSI_STATE_DISCONNECTING 0x1008 +#define SCSI_STATE_INITIALIZING 0x1009 +#define SCSI_STATE_BHQUEUE 0x100a +#define SCSI_STATE_MLQUEUE 0x100b + + +extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, int); +extern void scsi_put_command(struct scsi_cmnd *); +extern void scsi_io_completion(struct scsi_cmnd *, int, int); + +#endif /* _SCSI_SCSI_CMND_H */ diff -Nru a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/scsi/scsi_device.h Sun Jun 8 12:19:25 2003 @@ -0,0 +1,106 @@ +#ifndef _SCSI_SCSI_DEVICE_H +#define _SCSI_SCSI_DEVICE_H + +#include +#include +#include + +struct request_queue; +struct scsi_cmnd; + + +struct scsi_device { + struct class_device sdev_classdev; + + struct list_head siblings; /* list of all devices on this host */ + struct list_head same_target_siblings; /* just the devices sharing same target id */ + struct Scsi_Host *host; + struct request_queue *request_queue; + volatile unsigned short device_busy; /* commands actually active on low-level */ + spinlock_t sdev_lock; /* also the request queue_lock */ + spinlock_t list_lock; + struct list_head cmd_list; /* queue of in use SCSI Command structures */ + struct list_head starved_entry; + struct scsi_cmnd *current_cmnd; /* currently active command */ + unsigned short queue_depth; /* How deep of a queue we want */ + unsigned short last_queue_full_depth; /* These two are used by */ + unsigned short last_queue_full_count; /* scsi_track_queue_full() */ + unsigned long last_queue_full_time;/* don't let QUEUE_FULLs on the same + jiffie count on our counter, they + could all be from the same event. */ + + unsigned int id, lun, channel; + + unsigned int manufacturer; /* Manufacturer of device, for using + * vendor-specific cmd's */ + unsigned sector_size; /* size in bytes */ + + int access_count; /* Count of open channels/mounts */ + + void *hostdata; /* available to low-level driver */ + char devfs_name[256]; /* devfs junk */ + char type; + char scsi_level; + unsigned char inquiry_len; /* valid bytes in 'inquiry' */ + unsigned char * inquiry; /* INQUIRY response data */ + char * vendor; /* [back_compat] point into 'inquiry' ... */ + char * model; /* ... after scan; point to static string */ + char * rev; /* ... "nullnullnullnull" before scan */ + unsigned char current_tag; /* current tag */ + struct scsi_target *sdev_target; /* used only for single_lun */ + + unsigned online:1; + + unsigned writeable:1; + unsigned removable:1; + unsigned changed:1; /* Data invalid due to media change */ + unsigned busy:1; /* Used to prevent races */ + unsigned lockable:1; /* Able to prevent media removal */ + unsigned locked:1; /* Media removal disabled */ + unsigned borken:1; /* Tell the Seagate driver to be + * painfully slow on this device */ + unsigned disconnect:1; /* can disconnect */ + unsigned soft_reset:1; /* Uses soft reset option */ + unsigned sdtr:1; /* Device supports SDTR messages */ + unsigned wdtr:1; /* Device supports WDTR messages */ + unsigned ppr:1; /* Device supports PPR messages */ + unsigned tagged_supported:1; /* Supports SCSI-II tagged queuing */ + unsigned tagged_queue:1;/* This is going away!!!! Look at simple_tags + instead!!! Please fix your driver now!! */ + unsigned simple_tags:1; /* simple queue tag messages are enabled */ + unsigned ordered_tags:1;/* ordered queue tag messages are enabled */ + unsigned single_lun:1; /* Indicates we should only allow I/O to + * one of the luns for the device at a + * time. */ + unsigned was_reset:1; /* There was a bus reset on the bus for + * this device */ + unsigned expecting_cc_ua:1; /* Expecting a CHECK_CONDITION/UNIT_ATTN + * because we did a bus reset. */ + unsigned use_10_for_rw:1; /* first try 10-byte read / write */ + unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */ + unsigned no_start_on_add:1; /* do not issue start on add */ + + unsigned int device_blocked; /* Device returned QUEUE_FULL. */ + + unsigned int max_device_blocked; /* what device_blocked counts down from */ +#define SCSI_DEFAULT_DEVICE_BLOCKED 3 + + struct device sdev_driverfs_dev; +}; +#define to_scsi_device(d) \ + container_of(d, struct scsi_device, sdev_driverfs_dev) + +extern struct scsi_device *scsi_add_device(struct Scsi_Host *, + uint, uint, uint); +extern int scsi_remove_device(struct scsi_device *); +extern void scsi_set_device_offline(struct scsi_device *); + +extern int scsi_device_get(struct scsi_device *); +extern void scsi_device_put(struct scsi_device *); + +extern void scsi_adjust_queue_depth(struct scsi_device *, int, int); +extern int scsi_track_queue_full(struct scsi_device *, int); + +extern int scsi_set_medium_removal(struct scsi_device *, char); + +#endif /* _SCSI_SCSI_DEVICE_H */ diff -Nru a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/scsi/scsi_eh.h Sun Jun 8 15:03:00 2003 @@ -0,0 +1,21 @@ +#ifndef _SCSI_SCSI_EH_H +#define _SCSI_SCSI_EH_H + +extern void scsi_add_timer(struct scsi_cmnd *, int, + void (*)(struct scsi_cmnd *)); +extern int scsi_delete_timer(struct scsi_cmnd *); +extern void scsi_report_bus_reset(struct Scsi_Host *, int); +extern void scsi_report_device_reset(struct Scsi_Host *, int, int); +extern int scsi_block_when_processing_errors(struct scsi_device *); +extern void scsi_sleep(int); + +/* + * Reset request from external source + */ +#define SCSI_TRY_RESET_DEVICE 1 +#define SCSI_TRY_RESET_BUS 2 +#define SCSI_TRY_RESET_HOST 3 + +extern int scsi_reset_provider(struct scsi_device *, int); + +#endif /* _SCSI_SCSI_EH_H */ diff -Nru a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/scsi/scsi_host.h Sun Jun 8 13:31:57 2003 @@ -0,0 +1,525 @@ +#ifndef _SCSI_SCSI_HOST_H +#define _SCSI_SCSI_HOST_H + +#include +#include +#include + +struct block_device; +struct module; +struct scsi_cmnd; +struct scsi_device; +struct Scsi_Host; +struct scsi_host_cmd_pool; + + +/* + * The various choices mean: + * NONE: Self evident. Host adapter is not capable of scatter-gather. + * ALL: Means that the host adapter module can do scatter-gather, + * and that there is no limit to the size of the table to which + * we scatter/gather data. + * Anything else: Indicates the maximum number of chains that can be + * used in one scatter-gather request. + */ +#define SG_NONE 0 +#define SG_ALL 0xff + + +#define DISABLE_CLUSTERING 0 +#define ENABLE_CLUSTERING 1 + + +struct scsi_host_template { + struct module *module; + const char *name; + + /* + * Used to initialize old-style drivers. For new-style drivers + * just perform all work in your module initialization function. + * + * Status: OBSOLETE + */ + int (* detect)(struct scsi_host_template *); + + /* + * Used as unload callback for hosts with old-style drivers. + * + * Status: OBSOLETE + */ + int (* release)(struct Scsi_Host *); + + /* + * The info function will return whatever useful information the + * developer sees fit. If not provided, then the name field will + * be used instead. + * + * Status: OPTIONAL + */ + const char *(* info)(struct Scsi_Host *); + + /* + * Ioctl interface + * + * Status: OPTIONAL + */ + int (* ioctl)(struct scsi_device *dev, int cmd, void *arg); + + /* + * The queuecommand function is used to queue up a scsi + * command block to the LLDD. When the driver finished + * processing the command the done callback is invoked. + * + * If queuecommand returns 0, then the HBA has accepted the + * command. The done() function must be called on the command + * when the driver has finished with it. (you may call done on the + * command before queuecommand returns, but in this case you + * *must* return 0 from queuecommand). + * + * Queuecommand may also reject the command, in which case it may + * not touch the command and must not call done() for it. + * + * There are two possible rejection returns: + * + * SCSI_MLQUEUE_DEVICE_BUSY: Block this device temporarily, but + * allow commands to other devices serviced by this host. + * + * SCSI_MLQUEUE_HOST_BUSY: Block all devices served by this + * host temporarily. + * + * For compatibility, any other non-zero return is treated the + * same as SCSI_MLQUEUE_HOST_BUSY. + * + * NOTE: "temporarily" means either until the next command for# + * this device/host completes, or a period of time determined by + * I/O pressure in the system if there are no other outstanding + * commands. + * + * STATUS: REQUIRED + */ + int (* queuecommand)(struct scsi_cmnd *, + void (*done)(struct scsi_cmnd *)); + + /* + * This is an error handling strategy routine. You don't need to + * define one of these if you don't want to - there is a default + * routine that is present that should work in most cases. For those + * driver authors that have the inclination and ability to write their + * own strategy routine, this is where it is specified. Note - the + * strategy routine is *ALWAYS* run in the context of the kernel eh + * thread. Thus you are guaranteed to *NOT* be in an interrupt + * handler when you execute this, and you are also guaranteed to + * *NOT* have any other commands being queued while you are in the + * strategy routine. When you return from this function, operations + * return to normal. + * + * See scsi_error.c scsi_unjam_host for additional comments about + * what this function should and should not be attempting to do. + * + * Status: REQUIRED (at least one of them) + */ + int (* eh_strategy_handler)(struct Scsi_Host *); + int (* eh_abort_handler)(struct scsi_cmnd *); + int (* eh_device_reset_handler)(struct scsi_cmnd *); + int (* eh_bus_reset_handler)(struct scsi_cmnd *); + int (* eh_host_reset_handler)(struct scsi_cmnd *); + + /* + * Old EH handlers, no longer used. Make them warn the user of old + * drivers by using a wrong type + * + * Status: MORE THAN OBSOLETE + */ + int (* abort)(int); + int (* reset)(int, int); + + /* + * Before the mid layer attempts to scan for a new device where none + * currently exists, it will call this entry in your driver. Should + * your driver need to allocate any structs or perform any other init + * items in order to send commands to a currently unused target/lun + * combo, then this is where you can perform those allocations. This + * is specifically so that drivers won't have to perform any kind of + * "is this a new device" checks in their queuecommand routine, + * thereby making the hot path a bit quicker. + * + * Return values: 0 on success, non-0 on failure + * + * Deallocation: If we didn't find any devices at this ID, you will + * get an immediate call to slave_destroy(). If we find something + * here then you will get a call to slave_configure(), then the + * device will be used for however long it is kept around, then when + * the device is removed from the system (or * possibly at reboot + * time), you will then get a call to slave_detach(). This is + * assuming you implement slave_configure and slave_destroy. + * However, if you allocate memory and hang it off the device struct, + * then you must implement the slave_destroy() routine at a minimum + * in order to avoid leaking memory + * each time a device is tore down. + * + * Status: OPTIONAL + */ + int (* slave_alloc)(struct scsi_device *); + + /* + * Once the device has responded to an INQUIRY and we know the + * device is online, we call into the low level driver with the + * struct scsi_device *. If the low level device driver implements + * this function, it *must* perform the task of setting the queue + * depth on the device. All other tasks are optional and depend + * on what the driver supports and various implementation details. + * + * Things currently recommended to be handled at this time include: + * + * 1. Setting the device queue depth. Proper setting of this is + * described in the comments for scsi_adjust_queue_depth. + * 2. Determining if the device supports the various synchronous + * negotiation protocols. The device struct will already have + * responded to INQUIRY and the results of the standard items + * will have been shoved into the various device flag bits, eg. + * device->sdtr will be true if the device supports SDTR messages. + * 3. Allocating command structs that the device will need. + * 4. Setting the default timeout on this device (if needed). + * 5. Anything else the low level driver might want to do on a device + * specific setup basis... + * 6. Return 0 on success, non-0 on error. The device will be marked + * as offline on error so that no access will occur. If you return + * non-0, your slave_detach routine will never get called for this + * device, so don't leave any loose memory hanging around, clean + * up after yourself before returning non-0 + * + * Status: OPTIONAL + */ + int (* slave_configure)(struct scsi_device *); + + /* + * Immediately prior to deallocating the device and after all activity + * has ceased the mid layer calls this point so that the low level + * driver may completely detach itself from the scsi device and vice + * versa. The low level driver is responsible for freeing any memory + * it allocated in the slave_alloc or slave_configure calls. + * + * Status: OPTIONAL + */ + void (* slave_destroy)(struct scsi_device *); + + /* + * This function determines the bios parameters for a given + * harddisk. These tend to be numbers that are made up by + * the host adapter. Parameters: + * size, device, list (heads, sectors, cylinders) + * + * Status: OPTIONAL + */ + int (* bios_param)(struct scsi_device *, struct block_device *, + sector_t, int []); + + /* + * Can be used to export driver statistics and other infos to the + * world outside the kernel ie. userspace and it also provides an + * interface to feed the driver with information. + * + * Status: OBSOLETE + */ + int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int); + + /* + * Name of proc directory + */ + char *proc_name; + + /* + * Used to store the procfs directory if a driver implements the + * proc_info method. + */ + struct proc_dir_entry *proc_dir; + + /* + * This determines if we will use a non-interrupt driven + * or an interrupt driven scheme, It is set to the maximum number + * of simultaneous commands a given host adapter will accept. + */ + int can_queue; + + /* + * In many instances, especially where disconnect / reconnect are + * supported, our host also has an ID on the SCSI bus. If this is + * the case, then it must be reserved. Please set this_id to -1 if + * your setup is in single initiator mode, and the host lacks an + * ID. + */ + int this_id; + + /* + * This determines the degree to which the host adapter is capable + * of scatter-gather. + */ + unsigned short sg_tablesize; + + /* + * If the host adapter has limitations beside segment count + */ + unsigned short max_sectors; + + /* + * This specifies "machine infinity" for host templates which don't + * limit the transfer size. Note this limit represents an absolute + * maximum, and may be over the transfer limits allowed for + * individual devices (e.g. 256 for SCSI-1) + */ +#define SCSI_DEFAULT_MAX_SECTORS 1024 + + /* + * True if this host adapter can make good use of linked commands. + * This will allow more than one command to be queued to a given + * unit on a given host. Set this to the maximum number of command + * blocks to be provided for each device. Set this to 1 for one + * command block per lun, 2 for two, etc. Do not set this to 0. + * You should make sure that the host adapter will do the right thing + * before you try setting this above 1. + */ + short cmd_per_lun; + + /* + * present contains counter indicating how many boards of this + * type were found when we did the scan. + */ + unsigned char present; + + /* + * true if this host adapter uses unchecked DMA onto an ISA bus. + */ + unsigned unchecked_isa_dma:1; + + /* + * true if this host adapter can make good use of clustering. + * I originally thought that if the tablesize was large that it + * was a waste of CPU cycles to prepare a cluster list, but + * it works out that the Buslogic is faster if you use a smaller + * number of segments (i.e. use clustering). I guess it is + * inefficient. + */ + unsigned use_clustering:1; + + /* + * True for emulated SCSI host adapters (e.g. ATAPI) + */ + unsigned emulated:1; + + unsigned highmem_io:1; + + /* + * True if the driver wishes to use the generic block layer + * tag queueing functions + */ + unsigned use_blk_tcq:1; + + /* + * Countdown for host blocking with no commands outstanding + */ + unsigned int max_host_blocked; + + /* + * Default value for the blocking. If the queue is empty, + * host_blocked counts down in the request_fn until it restarts + * host operations as zero is reached. + * + * FIXME: This should probably be a value in the template + */ +#define SCSI_DEFAULT_HOST_BLOCKED 7 + + /* + * Pointer to the sysfs class properties for this host + */ + struct class_device_attribute **shost_attrs; + + /* + * Pointer to the SCSI device properties for this host + */ + struct device_attribute **sdev_attrs; + + /* + * List of hosts per template. + * + * This is only for use by scsi_module.c for legacy templates. + * For these access to it is synchronized implicitly by + * module_init/module_exit. + */ + struct list_head legacy_hosts; +}; + +struct Scsi_Host { + struct list_head my_devices; + struct scsi_host_cmd_pool *cmd_pool; + spinlock_t free_list_lock; + struct list_head free_list; /* backup store of cmd structs */ + struct list_head starved_list; + + spinlock_t default_lock; + spinlock_t *host_lock; + + struct list_head eh_cmd_q; + struct task_struct * ehandler; /* Error recovery thread. */ + struct semaphore * eh_wait; /* The error recovery thread waits on + this. */ + struct completion * eh_notify; /* wait for eh to begin or end */ + struct semaphore * eh_action; /* Wait for specific actions on the + host. */ + unsigned int eh_active:1; /* Indicates the eh thread is awake and active if + this is true. */ + unsigned int eh_kill:1; /* set when killing the eh thread */ + wait_queue_head_t host_wait; + struct scsi_host_template *hostt; + volatile unsigned short host_busy; /* commands actually active on low-level */ + volatile unsigned short host_failed; /* commands that failed. */ + + unsigned short host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ + int resetting; /* if set, it means that last_reset is a valid value */ + unsigned long last_reset; + + /* + * These three parameters can be used to allow for wide scsi, + * and for host adapters that support multiple busses + * The first two should be set to 1 more than the actual max id + * or lun (i.e. 8 for normal systems). + */ + unsigned int max_id; + unsigned int max_lun; + unsigned int max_channel; + + /* + * This is a unique identifier that must be assigned so that we + * have some way of identifying each detected host adapter properly + * and uniquely. For hosts that do not support more than one card + * in the system at one time, this does not need to be set. It is + * initialized to 0 in scsi_register. + */ + unsigned int unique_id; + + /* + * The maximum length of SCSI commands that this host can accept. + * Probably 12 for most host adapters, but could be 16 for others. + * For drivers that don't set this field, a value of 12 is + * assumed. I am leaving this as a number rather than a bit + * because you never know what subsequent SCSI standards might do + * (i.e. could there be a 20 byte or a 24-byte command a few years + * down the road?). + */ + unsigned char max_cmd_len; + + int this_id; + int can_queue; + short cmd_per_lun; + short unsigned int sg_tablesize; + short unsigned int max_sectors; + + unsigned in_recovery:1; + unsigned unchecked_isa_dma:1; + unsigned use_clustering:1; + unsigned highmem_io:1; + unsigned use_blk_tcq:1; + + /* + * Host has requested that no further requests come through for the + * time being. + */ + unsigned host_self_blocked:1; + + /* + * Host uses correct SCSI ordering not PC ordering. The bit is + * set for the minority of drivers whose authors actually read + * the spec ;) + */ + unsigned reverse_ordering:1; + + /* + * Host has rejected a command because it was busy. + */ + unsigned int host_blocked; + + /* + * Value host_blocked counts down from + */ + unsigned int max_host_blocked; + + /* + * Support for sysfs + */ + struct device host_gendev; + struct class_device class_dev; + + /* legacy crap */ + unsigned long base; + unsigned long io_port; + unsigned char n_io_port; + unsigned char dma_channel; + unsigned int irq; + + + /* + * List of hosts per template. + * + * This is only for use by scsi_module.c for legacy templates. + * For these access to it is synchronized implicitly by + * module_init/module_exit. + */ + struct list_head sht_legacy_list; + + /* + * We should ensure that this is aligned, both for better performance + * and also because some compilers (m68k) don't automatically force + * alignment to a long boundary. + */ + unsigned long hostdata[0] /* Used for storage of host specific stuff */ + __attribute__ ((aligned (sizeof(unsigned long)))); +}; +#define dev_to_shost(d) \ + container_of(d, struct Scsi_Host, host_gendev) +#define class_to_shost(d) \ + container_of(d, struct Scsi_Host, class_dev) + +extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int); +extern int scsi_add_host(struct Scsi_Host *, struct device *); +extern int scsi_remove_host(struct Scsi_Host *); +extern void scsi_host_get(struct Scsi_Host *); +extern void scsi_host_put(struct Scsi_Host *t); +extern struct Scsi_Host *scsi_host_lookup(unsigned short); + +extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *); + +static inline void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock) +{ + shost->host_lock = lock; +} + +static inline void scsi_set_device(struct Scsi_Host *shost, + struct device *dev) +{ + shost->host_gendev.parent = dev; +} + +static inline struct device *scsi_get_device(struct Scsi_Host *shost) +{ + return shost->host_gendev.parent; +} + +extern void scsi_sysfs_release_attributes(struct scsi_host_template *); + +extern void scsi_unblock_requests(struct Scsi_Host *); +extern void scsi_block_requests(struct Scsi_Host *); + +/* + * These two functions are used to allocate and free a pseudo device + * which will connect to the host adapter itself rather than any + * physical device. You must deallocate when you are done with the + * thing. This physical pseudo-device isn't real and won't be available + * from any high-level drivers. + */ +extern void scsi_free_host_dev(struct scsi_device *); +extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *); + +/* legacy interfaces */ +extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int); +extern void scsi_unregister(struct Scsi_Host *); + +#endif /* _SCSI_SCSI_HOST_H */ diff -Nru a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/scsi/scsi_request.h Sun Jun 8 15:03:00 2003 @@ -0,0 +1,58 @@ +#ifndef _SCSI_SCSI_REQUEST_H +#define _SCSI_SCSI_REQUEST_H + +#include + +struct request; +struct scsi_cmnd; +struct scsi_device; +struct Scsi_Host; + + +/* + * This is essentially a slimmed down version of Scsi_Cmnd. The point of + * having this is that requests that are injected into the queue as result + * of things like ioctls and character devices shouldn't be using a + * Scsi_Cmnd until such a time that the command is actually at the head + * of the queue and being sent to the driver. + */ +struct scsi_request { + int sr_magic; + int sr_result; /* Status code from lower level driver */ + unsigned char sr_sense_buffer[SCSI_SENSE_BUFFERSIZE]; /* obtained by REQUEST SENSE + * when CHECK CONDITION is + * received on original command + * (auto-sense) */ + + struct Scsi_Host *sr_host; + struct scsi_device *sr_device; + struct scsi_cmnd *sr_command; + struct request *sr_request; /* A copy of the command we are + working on */ + unsigned sr_bufflen; /* Size of data buffer */ + void *sr_buffer; /* Data buffer */ + int sr_allowed; + unsigned char sr_data_direction; + unsigned char sr_cmd_len; + unsigned char sr_cmnd[MAX_COMMAND_SIZE]; + void (*sr_done) (struct scsi_cmnd *); /* Mid-level done function */ + int sr_timeout_per_command; + unsigned short sr_use_sg; /* Number of pieces of scatter-gather */ + unsigned short sr_sglist_len; /* size of malloc'd scatter-gather list */ + unsigned sr_underflow; /* Return error if less than + this amount is transferred */ + void *upper_private_data; /* reserved for owner (usually upper + level driver) of this request */ +}; + +extern struct scsi_request *scsi_allocate_request(struct scsi_device *); +extern void scsi_release_request(struct scsi_request *); +extern void scsi_wait_req(struct scsi_request *, const void *cmnd, + void *buffer, unsigned bufflen, + int timeout, int retries); +extern void scsi_do_req(struct scsi_request *, const void *cmnd, + void *buffer, unsigned bufflen, + void (*done) (struct scsi_cmnd *), + int timeout, int retries); + +#endif /* _SCSI_SCSI_REQUEST_H */ diff -Nru a/include/scsi/scsi_tcq.h b/include/scsi/scsi_tcq.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/scsi/scsi_tcq.h Sun Jun 8 15:03:00 2003 @@ -0,0 +1,94 @@ +#ifndef _SCSI_SCSI_TCQ_H +#define _SCSI_SCSI_TCQ_H + +#include +#include +#include + + +#define MSG_SIMPLE_TAG 0x20 +#define MSG_HEAD_TAG 0x21 +#define MSG_ORDERED_TAG 0x22 + +#define SCSI_NO_TAG (-1) /* identify no tag in use */ + + +/** + * scsi_activate_tcq - turn on tag command queueing + * @SDpnt: device to turn on TCQ for + * @depth: queue depth + * + * Notes: + * Eventually, I hope depth would be the maximum depth + * the device could cope with and the real queue depth + * would be adjustable from 0 to depth. + **/ +static inline void scsi_activate_tcq(struct scsi_device *sdev, int depth) +{ + if (sdev->tagged_supported) { + if (!blk_queue_tagged(sdev->request_queue)) + blk_queue_init_tags(sdev->request_queue, depth); + scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth); + } +} + +/** + * scsi_deactivate_tcq - turn off tag command queueing + * @SDpnt: device to turn off TCQ for + **/ +static inline void scsi_deactivate_tcq(struct scsi_device *sdev, int depth) +{ + if (blk_queue_tagged(sdev->request_queue)) + blk_queue_free_tags(sdev->request_queue); + scsi_adjust_queue_depth(sdev, 0, depth); +} + +/** + * scsi_populate_tag_msg - place a tag message in a buffer + * @SCpnt: pointer to the Scsi_Cmnd for the tag + * @msg: pointer to the area to place the tag + * + * Notes: + * designed to create the correct type of tag message for the + * particular request. Returns the size of the tag message. + * May return 0 if TCQ is disabled for this device. + **/ +static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg) +{ + struct request *req = cmd->request; + + if (blk_rq_tagged(req)) { + if (req->flags & REQ_HARDBARRIER) + *msg++ = MSG_ORDERED_TAG; + else + *msg++ = MSG_SIMPLE_TAG; + *msg++ = req->tag; + return 2; + } + + return 0; +} + +/** + * scsi_find_tag - find a tagged command by device + * @SDpnt: pointer to the ScSI device + * @tag: the tag number + * + * Notes: + * Only works with tags allocated by the generic blk layer. + **/ +static inline struct scsi_cmnd *scsi_find_tag(struct scsi_device *sdev, int tag) +{ + + struct request *req; + + if (tag != SCSI_NO_TAG) { + req = blk_queue_find_tag(sdev->request_queue, tag); + return req ? (struct scsi_cmnd *)req->special : NULL; + } + + /* single command, look in space */ + return sdev->current_cmnd; +} + +#endif /* _SCSI_SCSI_TCQ_H */ diff -Nru a/kernel/compat.c b/kernel/compat.c --- a/kernel/compat.c Sun Jun 15 05:27:20 2003 +++ b/kernel/compat.c Tue Jun 17 05:37:03 2003 @@ -354,6 +354,8 @@ if (put_compat_rusage(ru, &r)) return -EFAULT; + + return 0; } asmlinkage long diff -Nru a/net/atm/clip.c b/net/atm/clip.c --- a/net/atm/clip.c Wed Jun 4 17:57:07 2003 +++ b/net/atm/clip.c Tue Jun 17 11:00:05 2003 @@ -140,8 +140,8 @@ DPRINTK("releasing vcc %p->%p of " "entry %p\n",clip_vcc,clip_vcc->vcc, entry); - atm_async_release_vcc(clip_vcc->vcc, - -ETIMEDOUT); + vcc_release_async(clip_vcc->vcc, + -ETIMEDOUT); } if (entry->vccs || time_before(jiffies, entry->expires)) { diff -Nru a/net/atm/common.c b/net/atm/common.c --- a/net/atm/common.c Wed Jun 4 17:57:07 2003 +++ b/net/atm/common.c Tue Jun 17 11:00:05 2003 @@ -239,15 +239,16 @@ } -void atm_async_release_vcc(struct atm_vcc *vcc,int reply) +void vcc_release_async(struct atm_vcc *vcc, int reply) { - set_bit(ATM_VF_CLOSE,&vcc->flags); + set_bit(ATM_VF_CLOSE, &vcc->flags); vcc->reply = reply; + vcc->sk->sk_err = -reply; wake_up(&vcc->sleep); } -EXPORT_SYMBOL(atm_async_release_vcc); +EXPORT_SYMBOL(vcc_release_async); static int adjust_tp(struct atm_trafprm *tp,unsigned char aal) @@ -276,8 +277,8 @@ } -static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi, - int vci) +static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, int vpi, + int vci) { int error; @@ -334,29 +335,26 @@ } -static int atm_do_connect(struct atm_vcc *vcc,int itf,int vpi,int vci) +int vcc_connect(struct socket *sock, int itf, short vpi, int vci) { struct atm_dev *dev; - int return_val; - - dev = atm_dev_lookup(itf); - if (!dev) - return_val = -ENODEV; - else { - return_val = atm_do_connect_dev(vcc,dev,vpi,vci); - if (return_val) atm_dev_release(dev); - } - - return return_val; -} + struct atm_vcc *vcc = ATM_SD(sock); + int error; + DPRINTK("vcc_connect (vpi %d, vci %d)\n",vpi,vci); + if (sock->state == SS_CONNECTED) + return -EISCONN; + if (sock->state != SS_UNCONNECTED) + return -EINVAL; + if (!(vpi || vci)) + return -EINVAL; -int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci) -{ if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC) clear_bit(ATM_VF_PARTIAL,&vcc->flags); - else if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) return -EINVAL; - DPRINTK("atm_connect (TX: cl %d,bw %d-%d,sdu %d; " + else + if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) + return -EINVAL; + DPRINTK("vcc_connect (TX: cl %d,bw %d-%d,sdu %d; " "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n", vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr, vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu, @@ -364,141 +362,135 @@ vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu, vcc->qos.aal == ATM_AAL5 ? "" : vcc->qos.aal == ATM_AAL0 ? "" : " ??? code ",vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal); - if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) return -EBADFD; + if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) + return -EBADFD; if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) return -EINVAL; if (itf != ATM_ITF_ANY) { - int error; - - error = atm_do_connect(vcc,itf,vpi,vci); - if (error) return error; - } - else { - struct atm_dev *dev = NULL; + dev = atm_dev_lookup(itf); + error = __vcc_connect(vcc, dev, vpi, vci); + if (error) { + atm_dev_release(dev); + return error; + } + } else { struct list_head *p, *next; + dev = NULL; spin_lock(&atm_dev_lock); list_for_each_safe(p, next, &atm_devs) { dev = list_entry(p, struct atm_dev, dev_list); atm_dev_hold(dev); spin_unlock(&atm_dev_lock); - if (!atm_do_connect_dev(vcc,dev,vpi,vci)) + if (!__vcc_connect(vcc, dev, vpi, vci)) break; atm_dev_release(dev); dev = NULL; spin_lock(&atm_dev_lock); } spin_unlock(&atm_dev_lock); - if (!dev) return -ENODEV; + if (!dev) + return -ENODEV; } if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) set_bit(ATM_VF_PARTIAL,&vcc->flags); - return 0; -} - - -int atm_connect(struct socket *sock,int itf,short vpi,int vci) -{ - int error; - - DPRINTK("atm_connect (vpi %d, vci %d)\n",vpi,vci); - if (sock->state == SS_CONNECTED) return -EISCONN; - if (sock->state != SS_UNCONNECTED) return -EINVAL; - if (!(vpi || vci)) return -EINVAL; - error = atm_connect_vcc(ATM_SD(sock),itf,vpi,vci); - if (error) return error; if (test_bit(ATM_VF_READY,&ATM_SD(sock)->flags)) sock->state = SS_CONNECTED; return 0; } -int atm_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, - int total_len, int flags) +int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + int size, int flags) { - DECLARE_WAITQUEUE(wait,current); + struct sock *sk = sock->sk; struct atm_vcc *vcc; struct sk_buff *skb; - int eff_len,error; - void *buff; - int size; + int copied, error = -EINVAL; - if (sock->state != SS_CONNECTED) return -ENOTCONN; - if (flags & ~MSG_DONTWAIT) return -EOPNOTSUPP; - if (m->msg_iovlen != 1) return -ENOSYS; /* fix this later @@@ */ - buff = m->msg_iov->iov_base; - size = m->msg_iov->iov_len; + if (sock->state != SS_CONNECTED) + return -ENOTCONN; + if (flags & ~MSG_DONTWAIT) /* only handle MSG_DONTWAIT */ + return -EOPNOTSUPP; vcc = ATM_SD(sock); - add_wait_queue(&vcc->sleep,&wait); - set_current_state(TASK_INTERRUPTIBLE); - error = 1; /* <= 0 is error */ - while (!(skb = skb_dequeue(&vcc->sk->sk_receive_queue))) { - if (test_bit(ATM_VF_RELEASED,&vcc->flags) || - test_bit(ATM_VF_CLOSE,&vcc->flags)) { - error = vcc->reply; - break; - } - if (!test_bit(ATM_VF_READY,&vcc->flags)) { - error = 0; - break; - } - if (flags & MSG_DONTWAIT) { - error = -EAGAIN; - break; - } - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - if (signal_pending(current)) { - error = -ERESTARTSYS; - break; - } - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&vcc->sleep,&wait); - if (error <= 0) return error; - sock_recv_timestamp(m, vcc->sk, skb); - eff_len = skb->len > size ? size : skb->len; - if (skb->len > size) /* Not fit ? Report it... */ - m->msg_flags |= MSG_TRUNC; - if (vcc->dev->ops->feedback) - vcc->dev->ops->feedback(vcc,skb,(unsigned long) skb->data, - (unsigned long) buff,eff_len); - DPRINTK("RcvM %d -= %d\n", atomic_read(&vcc->sk->sk_rmem_alloc), - skb->truesize); - atm_return(vcc,skb->truesize); - error = copy_to_user(buff,skb->data,eff_len) ? -EFAULT : 0; - kfree_skb(skb); - return error ? error : eff_len; + if (test_bit(ATM_VF_RELEASED,&vcc->flags) || + test_bit(ATM_VF_CLOSE,&vcc->flags)) + return vcc->reply; + if (!test_bit(ATM_VF_READY, &vcc->flags)) + return 0; + + skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &error); + if (!skb) + return error; + + copied = skb->len; + if (copied > size) { + copied = size; + msg->msg_flags |= MSG_TRUNC; + } + + error = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + if (error) + return error; + sock_recv_timestamp(msg, sk, skb); + if (vcc->dev->ops->feedback) + vcc->dev->ops->feedback(vcc, skb, (unsigned long) skb->data, + (unsigned long) msg->msg_iov->iov_base, copied); + DPRINTK("RcvM %d -= %d\n", atomic_read(&vcc->sk->rmem_alloc), skb->truesize); + atm_return(vcc, skb->truesize); + skb_free_datagram(sk, skb); + return copied; } -int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, +int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, int total_len) { - DECLARE_WAITQUEUE(wait,current); + struct sock *sk = sock->sk; + DEFINE_WAIT(wait); struct atm_vcc *vcc; struct sk_buff *skb; int eff,error; const void *buff; int size; - if (sock->state != SS_CONNECTED) return -ENOTCONN; - if (m->msg_name) return -EISCONN; - if (m->msg_iovlen != 1) return -ENOSYS; /* fix this later @@@ */ + lock_sock(sk); + if (sock->state != SS_CONNECTED) { + error = -ENOTCONN; + goto out; + } + if (m->msg_name) { + error = -EISCONN; + goto out; + } + if (m->msg_iovlen != 1) { + error = -ENOSYS; /* fix this later @@@ */ + goto out; + } buff = m->msg_iov->iov_base; size = m->msg_iov->iov_len; vcc = ATM_SD(sock); - if (test_bit(ATM_VF_RELEASED,&vcc->flags) || - test_bit(ATM_VF_CLOSE,&vcc->flags)) - return vcc->reply; - if (!test_bit(ATM_VF_READY,&vcc->flags)) return -EPIPE; - if (!size) return 0; - if (size < 0 || size > vcc->qos.txtp.max_sdu) return -EMSGSIZE; + if (test_bit(ATM_VF_RELEASED, &vcc->flags) || + test_bit(ATM_VF_CLOSE, &vcc->flags)) { + error = vcc->reply; + goto out; + } + if (!test_bit(ATM_VF_READY, &vcc->flags)) { + error = -EPIPE; + goto out; + } + if (!size) { + error = 0; + goto out; + } + if (size < 0 || size > vcc->qos.txtp.max_sdu) { + error = -EMSGSIZE; + goto out; + } /* verify_area is done by net/socket.c */ eff = (size+3) & ~3; /* align to word boundary */ - add_wait_queue(&vcc->sleep,&wait); - set_current_state(TASK_INTERRUPTIBLE); + prepare_to_wait(&vcc->sleep, &wait, TASK_INTERRUPTIBLE); error = 0; while (!(skb = alloc_tx(vcc,eff))) { if (m->msg_flags & MSG_DONTWAIT) { @@ -506,7 +498,6 @@ break; } schedule(); - set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { error = -ERESTARTSYS; break; @@ -520,19 +511,24 @@ error = -EPIPE; break; } + prepare_to_wait(&vcc->sleep, &wait, TASK_INTERRUPTIBLE); } - set_current_state(TASK_RUNNING); - remove_wait_queue(&vcc->sleep,&wait); - if (error) return error; + finish_wait(&vcc->sleep, &wait); + if (error) + goto out; skb->dev = NULL; /* for paths shared with net_device interfaces */ ATM_SKB(skb)->atm_options = vcc->atm_options; if (copy_from_user(skb_put(skb,size),buff,size)) { kfree_skb(skb); - return -EFAULT; + error = -EFAULT; + goto out; } if (eff != size) memset(skb->data+size,0,eff-size); error = vcc->dev->ops->send(vcc,skb); - return error ? error : size; + error = error ? error : size; +out: + release_sock(sk); + return error; } @@ -563,129 +559,51 @@ } -static void copy_aal_stats(struct k_atm_aal_stats *from, - struct atm_aal_stats *to) -{ -#define __HANDLE_ITEM(i) to->i = atomic_read(&from->i) - __AAL_STAT_ITEMS -#undef __HANDLE_ITEM -} - - -static void subtract_aal_stats(struct k_atm_aal_stats *from, - struct atm_aal_stats *to) -{ -#define __HANDLE_ITEM(i) atomic_sub(to->i,&from->i) - __AAL_STAT_ITEMS -#undef __HANDLE_ITEM -} - - -static int fetch_stats(struct atm_dev *dev,struct atm_dev_stats *arg,int zero) +int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { - struct atm_dev_stats tmp; - int error = 0; - - copy_aal_stats(&dev->stats.aal0,&tmp.aal0); - copy_aal_stats(&dev->stats.aal34,&tmp.aal34); - copy_aal_stats(&dev->stats.aal5,&tmp.aal5); - if (arg) error = copy_to_user(arg,&tmp,sizeof(tmp)); - if (zero && !error) { - subtract_aal_stats(&dev->stats.aal0,&tmp.aal0); - subtract_aal_stats(&dev->stats.aal34,&tmp.aal34); - subtract_aal_stats(&dev->stats.aal5,&tmp.aal5); - } - return error ? -EFAULT : 0; -} - - -int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg) -{ - struct atm_dev *dev; - struct list_head *p; struct atm_vcc *vcc; - int *tmp_buf, *tmp_p; - void *buf; - int error,len,size,number, ret_val; + int error; - ret_val = 0; vcc = ATM_SD(sock); switch (cmd) { case SIOCOUTQ: if (sock->state != SS_CONNECTED || - !test_bit(ATM_VF_READY,&vcc->flags)) { - ret_val = -EINVAL; + !test_bit(ATM_VF_READY, &vcc->flags)) { + error = -EINVAL; goto done; } - ret_val = put_user(vcc->sk->sk_sndbuf - - atomic_read(&vcc->sk->sk_wmem_alloc), - (int *) arg) ? -EFAULT : 0; + error = put_user(vcc->sk->sk_sndbuf - + atomic_read(&vcc->sk->sk_wmem_alloc), + (int *) arg) ? -EFAULT : 0; goto done; case SIOCINQ: { struct sk_buff *skb; if (sock->state != SS_CONNECTED) { - ret_val = -EINVAL; + error = -EINVAL; goto done; } skb = skb_peek(&vcc->sk->sk_receive_queue); - ret_val = put_user(skb ? skb->len : 0,(int *) arg) - ? -EFAULT : 0; + error = put_user(skb ? skb->len : 0, + (int *) arg) ? -EFAULT : 0; goto done; } - case ATM_GETNAMES: - if (get_user(buf, - &((struct atm_iobuf *) arg)->buffer)) { - ret_val = -EFAULT; - goto done; - } - if (get_user(len, - &((struct atm_iobuf *) arg)->length)) { - ret_val = -EFAULT; - goto done; - } - size = 0; - spin_lock(&atm_dev_lock); - list_for_each(p, &atm_devs) - size += sizeof(int); - if (size > len) { - spin_unlock(&atm_dev_lock); - ret_val = -E2BIG; - goto done; - } - tmp_buf = kmalloc(size, GFP_ATOMIC); - if (!tmp_buf) { - spin_unlock(&atm_dev_lock); - ret_val = -ENOMEM; - goto done; - } - tmp_p = tmp_buf; - list_for_each(p, &atm_devs) { - dev = list_entry(p, struct atm_dev, dev_list); - *tmp_p++ = dev->number; - } - spin_unlock(&atm_dev_lock); - ret_val = ((copy_to_user(buf, tmp_buf, size)) || - put_user(size, &((struct atm_iobuf *) arg)->length) - ) ? -EFAULT : 0; - kfree(tmp_buf); - goto done; case SIOCGSTAMP: /* borrowed from IP */ if (!vcc->sk->sk_stamp.tv_sec) { - ret_val = -ENOENT; + error = -ENOENT; goto done; } - ret_val = copy_to_user((void *)arg, &vcc->sk->sk_stamp, - sizeof(struct timeval)) ? -EFAULT : 0; + error = copy_to_user((void *)arg, &vcc->sk->sk_stamp, + sizeof(struct timeval)) ? -EFAULT : 0; goto done; case ATM_SETSC: printk(KERN_WARNING "ATM_SETSC is obsolete\n"); - ret_val = 0; + error = 0; goto done; case ATMSIGD_CTRL: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } /* @@ -696,28 +614,28 @@ * have the same privledges that /proc/kcore needs */ if (!capable(CAP_SYS_RAWIO)) { - ret_val = -EPERM; + error = -EPERM; goto done; } error = sigd_attach(vcc); - if (!error) sock->state = SS_CONNECTED; - ret_val = error; + if (!error) + sock->state = SS_CONNECTED; goto done; #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) case SIOCMKCLIP: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } if (try_atm_clip_ops()) { - ret_val = atm_clip_ops->clip_create(arg); + error = atm_clip_ops->clip_create(arg); module_put(atm_clip_ops->owner); } else - ret_val = -ENOSYS; + error = -ENOSYS; goto done; case ATMARPD_CTRL: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } #if defined(CONFIG_ATM_CLIP_MODULE) @@ -728,48 +646,47 @@ error = atm_clip_ops->atm_init_atmarp(vcc); if (!error) sock->state = SS_CONNECTED; - ret_val = error; } else - ret_val = -ENOSYS; + error = -ENOSYS; goto done; case ATMARP_MKIP: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } if (try_atm_clip_ops()) { - ret_val = atm_clip_ops->clip_mkip(vcc, arg); + error = atm_clip_ops->clip_mkip(vcc, arg); module_put(atm_clip_ops->owner); } else - ret_val = -ENOSYS; + error = -ENOSYS; goto done; case ATMARP_SETENTRY: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } if (try_atm_clip_ops()) { - ret_val = atm_clip_ops->clip_setentry(vcc, arg); + error = atm_clip_ops->clip_setentry(vcc, arg); module_put(atm_clip_ops->owner); } else - ret_val = -ENOSYS; + error = -ENOSYS; goto done; case ATMARP_ENCAP: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } if (try_atm_clip_ops()) { - ret_val = atm_clip_ops->clip_encap(vcc, arg); + error = atm_clip_ops->clip_encap(vcc, arg); module_put(atm_clip_ops->owner); } else - ret_val = -ENOSYS; + error = -ENOSYS; goto done; #endif #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) case ATMLEC_CTRL: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } #if defined(CONFIG_ATM_LANE_MODULE) @@ -781,37 +698,36 @@ module_put(atm_lane_ops->owner); if (error >= 0) sock->state = SS_CONNECTED; - ret_val = error; } else - ret_val = -ENOSYS; + error = -ENOSYS; goto done; case ATMLEC_MCAST: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } if (try_atm_lane_ops()) { - ret_val = atm_lane_ops->mcast_attach(vcc, (int) arg); + error = atm_lane_ops->mcast_attach(vcc, (int) arg); module_put(atm_lane_ops->owner); } else - ret_val = -ENOSYS; + error = -ENOSYS; goto done; case ATMLEC_DATA: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } if (try_atm_lane_ops()) { - ret_val = atm_lane_ops->vcc_attach(vcc, (void *) arg); + error = atm_lane_ops->vcc_attach(vcc, (void *) arg); module_put(atm_lane_ops->owner); } else - ret_val = -ENOSYS; + error = -ENOSYS; goto done; #endif #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE) case ATMMPC_CTRL: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } #if defined(CONFIG_ATM_MPOA_MODULE) @@ -823,63 +739,62 @@ module_put(atm_mpoa_ops->owner); if (error >= 0) sock->state = SS_CONNECTED; - ret_val = error; } else - ret_val = -ENOSYS; + error = -ENOSYS; goto done; case ATMMPC_DATA: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } if (try_atm_mpoa_ops()) { - ret_val = atm_mpoa_ops->vcc_attach(vcc, arg); + error = atm_mpoa_ops->vcc_attach(vcc, arg); module_put(atm_mpoa_ops->owner); } else - ret_val = -ENOSYS; + error = -ENOSYS; goto done; #endif #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE) case SIOCSIFATMTCP: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } if (!atm_tcp_ops.attach) { - ret_val = -ENOPKG; + error = -ENOPKG; goto done; } - fops_get (&atm_tcp_ops); - error = atm_tcp_ops.attach(vcc,(int) arg); - if (error >= 0) sock->state = SS_CONNECTED; - else fops_put (&atm_tcp_ops); - ret_val = error; + fops_get(&atm_tcp_ops); + error = atm_tcp_ops.attach(vcc, (int) arg); + if (error >= 0) + sock->state = SS_CONNECTED; + else + fops_put (&atm_tcp_ops); goto done; case ATMTCP_CREATE: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } if (!atm_tcp_ops.create_persistent) { - ret_val = -ENOPKG; + error = -ENOPKG; goto done; } error = atm_tcp_ops.create_persistent((int) arg); - if (error < 0) fops_put (&atm_tcp_ops); - ret_val = error; + if (error < 0) + fops_put (&atm_tcp_ops); goto done; case ATMTCP_REMOVE: if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; + error = -EPERM; goto done; } if (!atm_tcp_ops.remove_persistent) { - ret_val = -ENOPKG; + error = -ENOPKG; goto done; } error = atm_tcp_ops.remove_persistent((int) arg); - fops_put (&atm_tcp_ops); - ret_val = error; + fops_put(&atm_tcp_ops); goto done; #endif default: @@ -887,182 +802,23 @@ } #if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE) if (pppoatm_ioctl_hook) { - ret_val = pppoatm_ioctl_hook(vcc, cmd, arg); - if (ret_val != -ENOIOCTLCMD) + error = pppoatm_ioctl_hook(vcc, cmd, arg); + if (error != -ENOIOCTLCMD) goto done; } #endif #if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE) if (br2684_ioctl_hook) { - ret_val = br2684_ioctl_hook(vcc, cmd, arg); - if (ret_val != -ENOIOCTLCMD) + error = br2684_ioctl_hook(vcc, cmd, arg); + if (error != -ENOIOCTLCMD) goto done; } #endif - if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) { - ret_val = -EFAULT; - goto done; - } - if (get_user(len,&((struct atmif_sioc *) arg)->length)) { - ret_val = -EFAULT; - goto done; - } - if (get_user(number,&((struct atmif_sioc *) arg)->number)) { - ret_val = -EFAULT; - goto done; - } - if (!(dev = atm_dev_lookup(number))) { - ret_val = -ENODEV; - goto done; - } - - size = 0; - switch (cmd) { - case ATM_GETTYPE: - size = strlen(dev->type)+1; - if (copy_to_user(buf,dev->type,size)) { - ret_val = -EFAULT; - goto done_release; - } - break; - case ATM_GETESI: - size = ESI_LEN; - if (copy_to_user(buf,dev->esi,size)) { - ret_val = -EFAULT; - goto done_release; - } - break; - case ATM_SETESI: - { - int i; - for (i = 0; i < ESI_LEN; i++) - if (dev->esi[i]) { - ret_val = -EEXIST; - goto done_release; - } - } - /* fall through */ - case ATM_SETESIF: - { - unsigned char esi[ESI_LEN]; - - if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; - goto done_release; - } - if (copy_from_user(esi,buf,ESI_LEN)) { - ret_val = -EFAULT; - goto done_release; - } - memcpy(dev->esi,esi,ESI_LEN); - ret_val = ESI_LEN; - goto done_release; - } - case ATM_GETSTATZ: - if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; - goto done_release; - } - /* fall through */ - case ATM_GETSTAT: - size = sizeof(struct atm_dev_stats); - error = fetch_stats(dev,buf,cmd == ATM_GETSTATZ); - if (error) { - ret_val = error; - goto done_release; - } - break; - case ATM_GETCIRANGE: - size = sizeof(struct atm_cirange); - if (copy_to_user(buf,&dev->ci_range,size)) { - ret_val = -EFAULT; - goto done_release; - } - break; - case ATM_GETLINKRATE: - size = sizeof(int); - if (copy_to_user(buf,&dev->link_rate,size)) { - ret_val = -EFAULT; - goto done_release; - } - break; - case ATM_RSTADDR: - if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; - goto done_release; - } - atm_reset_addr(dev); - break; - case ATM_ADDADDR: - case ATM_DELADDR: - if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; - goto done_release; - } - { - struct sockaddr_atmsvc addr; - - if (copy_from_user(&addr,buf,sizeof(addr))) { - ret_val = -EFAULT; - goto done_release; - } - if (cmd == ATM_ADDADDR) - ret_val = atm_add_addr(dev,&addr); - else - ret_val = atm_del_addr(dev,&addr); - goto done_release; - } - case ATM_GETADDR: - size = atm_get_addr(dev,buf,len); - if (size < 0) - ret_val = size; - else - /* may return 0, but later on size == 0 means "don't - write the length" */ - ret_val = put_user(size, - &((struct atmif_sioc *) arg)->length) ? -EFAULT : 0; - goto done_release; - case ATM_SETLOOP: - if (__ATM_LM_XTRMT((int) (long) buf) && - __ATM_LM_XTLOC((int) (long) buf) > - __ATM_LM_XTRMT((int) (long) buf)) { - ret_val = -EINVAL; - goto done_release; - } - /* fall through */ - case ATM_SETCIRANGE: - case SONET_GETSTATZ: - case SONET_SETDIAG: - case SONET_CLRDIAG: - case SONET_SETFRAMING: - if (!capable(CAP_NET_ADMIN)) { - ret_val = -EPERM; - goto done_release; - } - /* fall through */ - default: - if (!dev->ops->ioctl) { - ret_val = -EINVAL; - goto done_release; - } - size = dev->ops->ioctl(dev,cmd,buf); - if (size < 0) { - ret_val = (size == -ENOIOCTLCMD ? -EINVAL : size); - goto done_release; - } - } - - if (size) - ret_val = put_user(size,&((struct atmif_sioc *) arg)->length) ? - -EFAULT : 0; - else - ret_val = 0; -done_release: - atm_dev_release(dev); + error = atm_dev_ioctl(cmd, arg); done: - return ret_val; + return error; } @@ -1120,14 +876,16 @@ return check_tp(&qos->rxtp); } - -static int atm_do_setsockopt(struct socket *sock,int level,int optname, - void *optval,int optlen) +int vcc_setsockopt(struct socket *sock, int level, int optname, + char *optval, int optlen) { struct atm_vcc *vcc; unsigned long value; int error; + if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname)) + return -EINVAL; + vcc = ATM_SD(sock); switch (optname) { case SO_ATMQOS: @@ -1161,10 +919,16 @@ } -static int atm_do_getsockopt(struct socket *sock,int level,int optname, - void *optval,int optlen) +int vcc_getsockopt(struct socket *sock, int level, int optname, + char *optval, int *optlen) { struct atm_vcc *vcc; + int len; + + if (get_user(len, optlen)) + return -EFAULT; + if (__SO_LEVEL_MATCH(optname, level) && len != __SO_SIZE(optname)) + return -EINVAL; vcc = ATM_SD(sock); switch (optname) { @@ -1195,28 +959,7 @@ break; } if (!vcc->dev || !vcc->dev->ops->getsockopt) return -EINVAL; - return vcc->dev->ops->getsockopt(vcc,level,optname,optval,optlen); -} - - -int atm_setsockopt(struct socket *sock,int level,int optname,char *optval, - int optlen) -{ - if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname)) - return -EINVAL; - return atm_do_setsockopt(sock,level,optname,optval,optlen); -} - - -int atm_getsockopt(struct socket *sock,int level,int optname, - char *optval,int *optlen) -{ - int len; - - if (get_user(len,optlen)) return -EFAULT; - if (__SO_LEVEL_MATCH(optname, level) && len != __SO_SIZE(optname)) - return -EINVAL; - return atm_do_getsockopt(sock,level,optname,optval,len); + return vcc->dev->ops->getsockopt(vcc, level, optname, optval, len); } diff -Nru a/net/atm/common.h b/net/atm/common.h --- a/net/atm/common.h Thu May 15 21:12:28 2003 +++ b/net/atm/common.h Tue Jun 17 11:00:05 2003 @@ -12,19 +12,18 @@ int atm_create(struct socket *sock,int protocol,int family); int atm_release(struct socket *sock); -int atm_connect(struct socket *sock,int itf,short vpi,int vci); -int atm_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, - int total_len, int flags); -int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, +int vcc_connect(struct socket *sock, int itf, short vpi, int vci); +int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + int size, int flags); +int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, int total_len); unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait); -int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg); -int atm_setsockopt(struct socket *sock,int level,int optname,char *optval, - int optlen); -int atm_getsockopt(struct socket *sock,int level,int optname,char *optval, - int *optlen); +int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); +int vcc_setsockopt(struct socket *sock, int level, int optname, char *optval, + int optlen); +int vcc_getsockopt(struct socket *sock, int level, int optname, char *optval, + int *optlen); -int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci); void atm_release_vcc_sk(struct sock *sk,int free_sk); void atm_shutdown_dev(struct atm_dev *dev); diff -Nru a/net/atm/lec.c b/net/atm/lec.c --- a/net/atm/lec.c Wed Jun 4 17:57:07 2003 +++ b/net/atm/lec.c Tue Jun 17 11:00:06 2003 @@ -1079,7 +1079,7 @@ clear_bit(ATM_VF_READY,&entry->vcc->flags); entry->vcc->push(entry->vcc, NULL); #endif - atm_async_release_vcc(entry->vcc, -EPIPE); + vcc_release_async(entry->vcc, -EPIPE); entry->vcc = NULL; } if (entry->recv_vcc) { @@ -1089,7 +1089,7 @@ clear_bit(ATM_VF_READY,&entry->recv_vcc->flags); entry->recv_vcc->push(entry->recv_vcc, NULL); #endif - atm_async_release_vcc(entry->recv_vcc, -EPIPE); + vcc_release_async(entry->recv_vcc, -EPIPE); entry->recv_vcc = NULL; } } diff -Nru a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c --- a/net/atm/mpoa_caches.c Tue Feb 5 09:40:00 2002 +++ b/net/atm/mpoa_caches.c Tue Jun 17 10:32:43 2003 @@ -212,7 +212,7 @@ client->eg_ops->put(eg_entry); return; } - atm_async_release_vcc(vcc, -EPIPE); + vcc_release_async(vcc, -EPIPE); } return; @@ -447,7 +447,7 @@ client->in_ops->put(in_entry); return; } - atm_async_release_vcc(vcc, -EPIPE); + vcc_release_async(vcc, -EPIPE); } return; diff -Nru a/net/atm/pvc.c b/net/atm/pvc.c --- a/net/atm/pvc.c Thu May 15 21:54:16 2003 +++ b/net/atm/pvc.c Tue Jun 17 11:00:06 2003 @@ -31,20 +31,29 @@ static int pvc_bind(struct socket *sock,struct sockaddr *sockaddr, int sockaddr_len) { + struct sock *sk = sock->sk; struct sockaddr_atmpvc *addr; struct atm_vcc *vcc; + int error; if (sockaddr_len != sizeof(struct sockaddr_atmpvc)) return -EINVAL; addr = (struct sockaddr_atmpvc *) sockaddr; if (addr->sap_family != AF_ATMPVC) return -EAFNOSUPPORT; + lock_sock(sk); vcc = ATM_SD(sock); - if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) return -EBADFD; + if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) { + error = -EBADFD; + goto out; + } if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) { if (vcc->vpi != ATM_VPI_UNSPEC) addr->sap_addr.vpi = vcc->vpi; if (vcc->vci != ATM_VCI_UNSPEC) addr->sap_addr.vci = vcc->vci; } - return atm_connect(sock,addr->sap_addr.itf,addr->sap_addr.vpi, - addr->sap_addr.vci); + error = vcc_connect(sock, addr->sap_addr.itf, addr->sap_addr.vpi, + addr->sap_addr.vci); +out: + release_sock(sk); + return error; } @@ -54,6 +63,31 @@ return pvc_bind(sock,sockaddr,sockaddr_len); } +static int pvc_setsockopt(struct socket *sock, int level, int optname, + char *optval, int optlen) +{ + struct sock *sk = sock->sk; + int error; + + lock_sock(sk); + error = vcc_setsockopt(sock, level, optname, optval, optlen); + release_sock(sk); + return error; +} + + +static int pvc_getsockopt(struct socket *sock, int level, int optname, + char *optval, int *optlen) +{ + struct sock *sk = sock->sk; + int error; + + lock_sock(sk); + error = vcc_getsockopt(sock, level, optname, optval, optlen); + release_sock(sk); + return error; +} + static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr, int *sockaddr_len,int peer) @@ -72,7 +106,7 @@ } -static struct proto_ops SOCKOPS_WRAPPED(pvc_proto_ops) = { +static struct proto_ops pvc_proto_ops = { .family = PF_ATMPVC, .release = atm_release, @@ -82,20 +116,16 @@ .accept = sock_no_accept, .getname = pvc_getname, .poll = atm_poll, - .ioctl = atm_ioctl, + .ioctl = vcc_ioctl, .listen = sock_no_listen, .shutdown = pvc_shutdown, - .setsockopt = atm_setsockopt, - .getsockopt = atm_getsockopt, - .sendmsg = atm_sendmsg, - .recvmsg = atm_recvmsg, + .setsockopt = pvc_setsockopt, + .getsockopt = pvc_getsockopt, + .sendmsg = vcc_sendmsg, + .recvmsg = vcc_recvmsg, .mmap = sock_no_mmap, .sendpage = sock_no_sendpage, }; - - -#include -SOCKOPS_WRAP(pvc_proto, PF_ATMPVC); static int pvc_create(struct socket *sock,int protocol) diff -Nru a/net/atm/resources.c b/net/atm/resources.c --- a/net/atm/resources.c Thu May 15 17:20:17 2003 +++ b/net/atm/resources.c Tue Jun 17 11:00:06 2003 @@ -12,6 +12,7 @@ #include #include #include +#include #include /* for barrier */ #include #include @@ -19,6 +20,7 @@ #include "common.h" #include "resources.h" +#include "addr.h" #ifndef NULL @@ -170,6 +172,240 @@ dev->ops->dev_close(dev); atm_dev_deregister(dev); } + + +static void copy_aal_stats(struct k_atm_aal_stats *from, + struct atm_aal_stats *to) +{ +#define __HANDLE_ITEM(i) to->i = atomic_read(&from->i) + __AAL_STAT_ITEMS +#undef __HANDLE_ITEM +} + + +static void subtract_aal_stats(struct k_atm_aal_stats *from, + struct atm_aal_stats *to) +{ +#define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i) + __AAL_STAT_ITEMS +#undef __HANDLE_ITEM +} + + +static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats *arg, int zero) +{ + struct atm_dev_stats tmp; + int error = 0; + + copy_aal_stats(&dev->stats.aal0, &tmp.aal0); + copy_aal_stats(&dev->stats.aal34, &tmp.aal34); + copy_aal_stats(&dev->stats.aal5, &tmp.aal5); + if (arg) + error = copy_to_user(arg, &tmp, sizeof(tmp)); + if (zero && !error) { + subtract_aal_stats(&dev->stats.aal0, &tmp.aal0); + subtract_aal_stats(&dev->stats.aal34, &tmp.aal34); + subtract_aal_stats(&dev->stats.aal5, &tmp.aal5); + } + return error ? -EFAULT : 0; +} + + +int atm_dev_ioctl(unsigned int cmd, unsigned long arg) +{ + void *buf; + int error, len, number, size = 0; + struct atm_dev *dev; + struct list_head *p; + int *tmp_buf, *tmp_p; + + switch (cmd) { + case ATM_GETNAMES: + if (get_user(buf, &((struct atm_iobuf *) arg)->buffer)) + return -EFAULT; + if (get_user(len, &((struct atm_iobuf *) arg)->length)) + return -EFAULT; + spin_lock(&atm_dev_lock); + list_for_each(p, &atm_devs) + size += sizeof(int); + if (size > len) { + spin_unlock(&atm_dev_lock); + return -E2BIG; + } + tmp_buf = kmalloc(size, GFP_ATOMIC); + if (!tmp_buf) { + spin_unlock(&atm_dev_lock); + return -ENOMEM; + } + tmp_p = tmp_buf; + list_for_each(p, &atm_devs) { + dev = list_entry(p, struct atm_dev, dev_list); + *tmp_p++ = dev->number; + } + spin_unlock(&atm_dev_lock); + error = ((copy_to_user(buf, tmp_buf, size)) || + put_user(size, &((struct atm_iobuf *) arg)->length)) + ? -EFAULT : 0; + kfree(tmp_buf); + return error; + default: + break; + } + + if (get_user(buf, &((struct atmif_sioc *) arg)->arg)) + return -EFAULT; + if (get_user(len, &((struct atmif_sioc *) arg)->length)) + return -EFAULT; + if (get_user(number, &((struct atmif_sioc *) arg)->number)) + return -EFAULT; + + if (!(dev = atm_dev_lookup(number))) + return -ENODEV; + + switch (cmd) { + case ATM_GETTYPE: + size = strlen(dev->type) + 1; + if (copy_to_user(buf, dev->type, size)) { + error = -EFAULT; + goto done; + } + break; + case ATM_GETESI: + size = ESI_LEN; + if (copy_to_user(buf, dev->esi, size)) { + error = -EFAULT; + goto done; + } + break; + case ATM_SETESI: + { + int i; + + for (i = 0; i < ESI_LEN; i++) + if (dev->esi[i]) { + error = -EEXIST; + goto done; + } + } + /* fall through */ + case ATM_SETESIF: + { + unsigned char esi[ESI_LEN]; + + if (!capable(CAP_NET_ADMIN)) { + error = -EPERM; + goto done; + } + if (copy_from_user(esi, buf, ESI_LEN)) { + error = -EFAULT; + goto done; + } + memcpy(dev->esi, esi, ESI_LEN); + error = ESI_LEN; + goto done; + } + case ATM_GETSTATZ: + if (!capable(CAP_NET_ADMIN)) { + error = -EPERM; + goto done; + } + /* fall through */ + case ATM_GETSTAT: + size = sizeof(struct atm_dev_stats); + error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ); + if (error) + goto done; + break; + case ATM_GETCIRANGE: + size = sizeof(struct atm_cirange); + if (copy_to_user(buf, &dev->ci_range, size)) { + error = -EFAULT; + goto done; + } + break; + case ATM_GETLINKRATE: + size = sizeof(int); + if (copy_to_user(buf, &dev->link_rate, size)) { + error = -EFAULT; + goto done; + } + break; + case ATM_RSTADDR: + if (!capable(CAP_NET_ADMIN)) { + error = -EPERM; + goto done; + } + atm_reset_addr(dev); + break; + case ATM_ADDADDR: + case ATM_DELADDR: + if (!capable(CAP_NET_ADMIN)) { + error = -EPERM; + goto done; + } + { + struct sockaddr_atmsvc addr; + + if (copy_from_user(&addr, buf, sizeof(addr))) { + error = -EFAULT; + goto done; + } + if (cmd == ATM_ADDADDR) + error = atm_add_addr(dev, &addr); + else + error = atm_del_addr(dev, &addr); + goto done; + } + case ATM_GETADDR: + error = atm_get_addr(dev, buf, len); + if (error < 0) + goto done; + size = error; + /* may return 0, but later on size == 0 means "don't + write the length" */ + error = put_user(size, &((struct atmif_sioc *) arg)->length) + ? -EFAULT : 0; + goto done; + case ATM_SETLOOP: + if (__ATM_LM_XTRMT((int) (long) buf) && + __ATM_LM_XTLOC((int) (long) buf) > + __ATM_LM_XTRMT((int) (long) buf)) { + error = -EINVAL; + goto done; + } + /* fall through */ + case ATM_SETCIRANGE: + case SONET_GETSTATZ: + case SONET_SETDIAG: + case SONET_CLRDIAG: + case SONET_SETFRAMING: + if (!capable(CAP_NET_ADMIN)) { + error = -EPERM; + goto done; + } + /* fall through */ + default: + if (!dev->ops->ioctl) { + error = -EINVAL; + goto done; + } + size = dev->ops->ioctl(dev, cmd, buf); + if (size < 0) { + error = (size == -ENOIOCTLCMD ? -EINVAL : size); + goto done; + } + } + + if (size) + error = put_user(size, &((struct atmif_sioc *) arg)->length) + ? -EFAULT : 0; + else + error = 0; +done: + atm_dev_release(dev); + return error; +} + struct sock *alloc_atm_vcc_sk(int family) { diff -Nru a/net/atm/resources.h b/net/atm/resources.h --- a/net/atm/resources.h Thu May 15 17:20:17 2003 +++ b/net/atm/resources.h Tue Jun 17 11:00:06 2003 @@ -16,6 +16,7 @@ struct sock *alloc_atm_vcc_sk(int family); void free_atm_vcc_sk(struct sock *sk); +int atm_dev_ioctl(unsigned int cmd, unsigned long arg); #ifdef CONFIG_PROC_FS diff -Nru a/net/atm/signaling.c b/net/atm/signaling.c --- a/net/atm/signaling.c Wed Jun 4 17:57:07 2003 +++ b/net/atm/signaling.c Tue Jun 17 11:00:06 2003 @@ -124,14 +124,16 @@ clear_bit(ATM_VF_REGIS,&vcc->flags); clear_bit(ATM_VF_READY,&vcc->flags); vcc->reply = msg->reply; + vcc->sk->sk_err = -msg->reply; break; case as_indicate: vcc = *(struct atm_vcc **) &msg->listen_vcc; DPRINTK("as_indicate!!!\n"); + lock_sock(vcc->sk); if (vcc->sk->sk_ack_backlog == vcc->sk->sk_max_ack_backlog) { sigd_enq(0,as_reject,vcc,NULL,NULL); - return 0; + goto as_indicate_complete; } vcc->sk->sk_ack_backlog++; skb_queue_tail(&vcc->sk->sk_receive_queue, skb); @@ -140,11 +142,14 @@ &vcc->sleep); vcc->callback(vcc); } +as_indicate_complete: + release_sock(vcc->sk); return 0; case as_close: set_bit(ATM_VF_RELEASED,&vcc->flags); clear_bit(ATM_VF_READY,&vcc->flags); vcc->reply = msg->reply; + vcc->sk->sk_err = -msg->reply; break; case as_modify: modify_qos(vcc,msg); @@ -202,6 +207,7 @@ !test_bit(ATM_VF_META,&vcc->flags)) { set_bit(ATM_VF_RELEASED,&vcc->flags); vcc->reply = -EUNATCH; + vcc->sk->sk_err = EUNATCH; wake_up(&vcc->sleep); } vcc = vcc->next; diff -Nru a/net/atm/svc.c b/net/atm/svc.c --- a/net/atm/svc.c Wed Jun 4 17:57:07 2003 +++ b/net/atm/svc.c Tue Jun 17 11:00:06 2003 @@ -59,18 +59,18 @@ static void svc_disconnect(struct atm_vcc *vcc) { - DECLARE_WAITQUEUE(wait,current); + DEFINE_WAIT(wait); struct sk_buff *skb; DPRINTK("svc_disconnect %p\n",vcc); if (test_bit(ATM_VF_REGIS,&vcc->flags)) { - add_wait_queue(&vcc->sleep,&wait); + prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE); sigd_enq(vcc,as_close,NULL,NULL,NULL); while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) { - set_current_state(TASK_UNINTERRUPTIBLE); schedule(); + prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE); } - remove_wait_queue(&vcc->sleep,&wait); + finish_wait(&vcc->sleep, &wait); } /* beware - socket is still in use by atmsigd until the last as_indicate has been answered */ @@ -107,80 +107,138 @@ static int svc_bind(struct socket *sock,struct sockaddr *sockaddr, int sockaddr_len) { - DECLARE_WAITQUEUE(wait,current); + DEFINE_WAIT(wait); + struct sock *sk = sock->sk; struct sockaddr_atmsvc *addr; struct atm_vcc *vcc; + int error; - if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) return -EINVAL; - if (sock->state == SS_CONNECTED) return -EISCONN; - if (sock->state != SS_UNCONNECTED) return -EINVAL; + if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) + return -EINVAL; + lock_sock(sk); + if (sock->state == SS_CONNECTED) { + error = -EISCONN; + goto out; + } + if (sock->state != SS_UNCONNECTED) { + error = -EINVAL; + goto out; + } vcc = ATM_SD(sock); - if (test_bit(ATM_VF_SESSION,&vcc->flags)) return -EINVAL; + if (test_bit(ATM_VF_SESSION, &vcc->flags)) { + error = -EINVAL; + goto out; + } addr = (struct sockaddr_atmsvc *) sockaddr; - if (addr->sas_family != AF_ATMSVC) return -EAFNOSUPPORT; + if (addr->sas_family != AF_ATMSVC) { + error = -EAFNOSUPPORT; + goto out; + } clear_bit(ATM_VF_BOUND,&vcc->flags); /* failing rebind will kill old binding */ /* @@@ check memory (de)allocation on rebind */ - if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) return -EBADFD; + if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) { + error = -EBADFD; + goto out; + } vcc->local = *addr; vcc->reply = WAITING; - add_wait_queue(&vcc->sleep,&wait); + prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE); sigd_enq(vcc,as_bind,NULL,NULL,&vcc->local); while (vcc->reply == WAITING && sigd) { - set_current_state(TASK_UNINTERRUPTIBLE); schedule(); + prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE); } - remove_wait_queue(&vcc->sleep,&wait); + finish_wait(&vcc->sleep, &wait); clear_bit(ATM_VF_REGIS,&vcc->flags); /* doesn't count */ - if (!sigd) return -EUNATCH; - if (!vcc->reply) set_bit(ATM_VF_BOUND,&vcc->flags); - return vcc->reply; + if (!sigd) { + error = -EUNATCH; + goto out; + } + if (!vcc->reply) + set_bit(ATM_VF_BOUND,&vcc->flags); + error = vcc->reply; +out: + release_sock(sk); + return error; } static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, int sockaddr_len,int flags) { - DECLARE_WAITQUEUE(wait,current); + DEFINE_WAIT(wait); + struct sock *sk = sock->sk; struct sockaddr_atmsvc *addr; struct atm_vcc *vcc = ATM_SD(sock); int error; DPRINTK("svc_connect %p\n",vcc); - if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) return -EINVAL; - if (sock->state == SS_CONNECTED) return -EISCONN; - if (sock->state == SS_CONNECTING) { - if (vcc->reply == WAITING) return -EALREADY; - sock->state = SS_UNCONNECTED; - if (vcc->reply) return vcc->reply; + lock_sock(sk); + if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) { + error = -EINVAL; + goto out; } - else { - int error; - if (sock->state != SS_UNCONNECTED) return -EINVAL; - if (test_bit(ATM_VF_SESSION,&vcc->flags)) return -EINVAL; + switch (sock->state) { + default: + error = -EINVAL; + goto out; + case SS_CONNECTED: + error = -EISCONN; + goto out; + case SS_CONNECTING: + if (vcc->reply == WAITING) { + error = -EALREADY; + goto out; + } + sock->state = SS_UNCONNECTED; + if (vcc->reply) { + error = vcc->reply; + goto out; + } + break; + case SS_UNCONNECTED: + if (test_bit(ATM_VF_SESSION, &vcc->flags)) { + error = -EINVAL; + goto out; + } addr = (struct sockaddr_atmsvc *) sockaddr; - if (addr->sas_family != AF_ATMSVC) return -EAFNOSUPPORT; - if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) return -EBADFD; + if (addr->sas_family != AF_ATMSVC) { + error = -EAFNOSUPPORT; + goto out; + } + if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) { + error = -EBADFD; + goto out; + } if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || - vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) - return -EINVAL; + vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) { + error = -EINVAL; + goto out; + } if (!vcc->qos.txtp.traffic_class && - !vcc->qos.rxtp.traffic_class) return -EINVAL; + !vcc->qos.rxtp.traffic_class) { + error = -EINVAL; + goto out; + } vcc->remote = *addr; vcc->reply = WAITING; - add_wait_queue(&vcc->sleep,&wait); + prepare_to_wait(&vcc->sleep, &wait, TASK_INTERRUPTIBLE); sigd_enq(vcc,as_connect,NULL,NULL,&vcc->remote); if (flags & O_NONBLOCK) { - remove_wait_queue(&vcc->sleep,&wait); + finish_wait(&vcc->sleep, &wait); sock->state = SS_CONNECTING; - return -EINPROGRESS; + error = -EINPROGRESS; + goto out; } error = 0; while (vcc->reply == WAITING && sigd) { - set_current_state(TASK_INTERRUPTIBLE); schedule(); - if (!signal_pending(current)) continue; + if (!signal_pending(current)) { + prepare_to_wait(&vcc->sleep, &wait, TASK_INTERRUPTIBLE); + continue; + } DPRINTK("*ABORT*\n"); /* * This is tricky: @@ -196,13 +254,13 @@ */ sigd_enq(vcc,as_close,NULL,NULL,NULL); while (vcc->reply == WAITING && sigd) { - set_current_state(TASK_UNINTERRUPTIBLE); + prepare_to_wait(&vcc->sleep, &wait, TASK_INTERRUPTIBLE); schedule(); } if (!vcc->reply) while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) { - set_current_state(TASK_UNINTERRUPTIBLE); + prepare_to_wait(&vcc->sleep, &wait, TASK_INTERRUPTIBLE); schedule(); } clear_bit(ATM_VF_REGIS,&vcc->flags); @@ -212,10 +270,17 @@ error = -EINTR; break; } - remove_wait_queue(&vcc->sleep,&wait); - if (error) return error; - if (!sigd) return -EUNATCH; - if (vcc->reply) return vcc->reply; + finish_wait(&vcc->sleep, &wait); + if (error) + goto out; + if (!sigd) { + error = -EUNATCH; + goto out; + } + if (vcc->reply) { + error = vcc->reply; + goto out; + } } /* * Not supported yet @@ -228,56 +293,73 @@ /* * #endif */ - if (!(error = atm_connect(sock,vcc->itf,vcc->vpi,vcc->vci))) + if (!(error = vcc_connect(sock, vcc->itf, vcc->vpi, vcc->vci))) sock->state = SS_CONNECTED; else (void) svc_disconnect(vcc); +out: + release_sock(sk); return error; } static int svc_listen(struct socket *sock,int backlog) { - DECLARE_WAITQUEUE(wait,current); + DEFINE_WAIT(wait); + struct sock *sk = sock->sk; struct atm_vcc *vcc = ATM_SD(sock); + int error; DPRINTK("svc_listen %p\n",vcc); + lock_sock(sk); /* let server handle listen on unbound sockets */ - if (test_bit(ATM_VF_SESSION,&vcc->flags)) return -EINVAL; + if (test_bit(ATM_VF_SESSION,&vcc->flags)) { + error = -EINVAL; + goto out; + } vcc->reply = WAITING; - add_wait_queue(&vcc->sleep,&wait); + prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE); sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local); while (vcc->reply == WAITING && sigd) { - set_current_state(TASK_UNINTERRUPTIBLE); schedule(); + prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE); + } + finish_wait(&vcc->sleep, &wait); + if (!sigd) { + error = -EUNATCH; + goto out; } - remove_wait_queue(&vcc->sleep,&wait); - if (!sigd) return -EUNATCH; set_bit(ATM_VF_LISTEN,&vcc->flags); vcc->sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT; - return vcc->reply; + error = vcc->reply; +out: + release_sock(sk); + return error; } static int svc_accept(struct socket *sock,struct socket *newsock,int flags) { + struct sock *sk = sock->sk; struct sk_buff *skb; struct atmsvc_msg *msg; struct atm_vcc *old_vcc = ATM_SD(sock); struct atm_vcc *new_vcc; int error; + lock_sock(sk); + error = svc_create(newsock,0); if (error) - return error; + goto out; new_vcc = ATM_SD(newsock); DPRINTK("svc_accept %p -> %p\n",old_vcc,new_vcc); while (1) { - DECLARE_WAITQUEUE(wait,current); + DEFINE_WAIT(wait); - add_wait_queue(&old_vcc->sleep,&wait); + prepare_to_wait(&old_vcc->sleep, &wait, TASK_INTERRUPTIBLE); while (!(skb = skb_dequeue(&old_vcc->sk->sk_receive_queue)) && sigd) { if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break; @@ -289,46 +371,63 @@ error = -EAGAIN; break; } - set_current_state(TASK_INTERRUPTIBLE); + release_sock(sk); schedule(); + lock_sock(sk); if (signal_pending(current)) { error = -ERESTARTSYS; break; } + prepare_to_wait(&old_vcc->sleep, &wait, TASK_INTERRUPTIBLE); + } + finish_wait(&old_vcc->sleep, &wait); + if (error) + goto out; + if (!skb) { + error = -EUNATCH; + goto out; } - remove_wait_queue(&old_vcc->sleep,&wait); - if (error) return error; - if (!skb) return -EUNATCH; msg = (struct atmsvc_msg *) skb->data; new_vcc->qos = msg->qos; set_bit(ATM_VF_HASQOS,&new_vcc->flags); new_vcc->remote = msg->svc; new_vcc->local = msg->local; new_vcc->sap = msg->sap; - error = atm_connect(newsock,msg->pvc.sap_addr.itf, - msg->pvc.sap_addr.vpi,msg->pvc.sap_addr.vci); + error = vcc_connect(newsock, msg->pvc.sap_addr.itf, + msg->pvc.sap_addr.vpi, msg->pvc.sap_addr.vci); dev_kfree_skb(skb); old_vcc->sk->sk_ack_backlog--; if (error) { sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL, &old_vcc->qos,error); - return error == -EAGAIN ? -EBUSY : error; + error = error == -EAGAIN ? -EBUSY : error; + goto out; } /* wait should be short, so we ignore the non-blocking flag */ new_vcc->reply = WAITING; - add_wait_queue(&new_vcc->sleep,&wait); + prepare_to_wait(&new_vcc->sleep, &wait, TASK_UNINTERRUPTIBLE); sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL); while (new_vcc->reply == WAITING && sigd) { - set_current_state(TASK_UNINTERRUPTIBLE); + release_sock(sk); schedule(); + lock_sock(sk); + prepare_to_wait(&new_vcc->sleep, &wait, TASK_UNINTERRUPTIBLE); + } + finish_wait(&new_vcc->sleep, &wait); + if (!sigd) { + error = -EUNATCH; + goto out; } - remove_wait_queue(&new_vcc->sleep,&wait); - if (!sigd) return -EUNATCH; if (!new_vcc->reply) break; - if (new_vcc->reply != -ERESTARTSYS) return new_vcc->reply; + if (new_vcc->reply != -ERESTARTSYS) { + error = new_vcc->reply; + goto out; + } } newsock->state = SS_CONNECTED; - return 0; +out: + release_sock(sk); + return error; } @@ -347,17 +446,17 @@ int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos) { - DECLARE_WAITQUEUE(wait,current); + DEFINE_WAIT(wait); vcc->reply = WAITING; - add_wait_queue(&vcc->sleep,&wait); + prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE); sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0); while (vcc->reply == WAITING && !test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) { - set_current_state(TASK_UNINTERRUPTIBLE); schedule(); + prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE); } - remove_wait_queue(&vcc->sleep,&wait); + finish_wait(&vcc->sleep, &wait); if (!sigd) return -EUNATCH; return vcc->reply; } @@ -366,33 +465,57 @@ static int svc_setsockopt(struct socket *sock,int level,int optname, char *optval,int optlen) { + struct sock *sk = sock->sk; struct atm_vcc *vcc; + int error = 0; if (!__SO_LEVEL_MATCH(optname, level) || optname != SO_ATMSAP || - optlen != sizeof(struct atm_sap)) - return atm_setsockopt(sock,level,optname,optval,optlen); + optlen != sizeof(struct atm_sap)) { + error = vcc_setsockopt(sock, level, optname, optval, optlen); + goto out; + } vcc = ATM_SD(sock); - if (copy_from_user(&vcc->sap,optval,optlen)) return -EFAULT; - set_bit(ATM_VF_HASSAP,&vcc->flags); - return 0; + if (copy_from_user(&vcc->sap, optval, optlen)) { + error = -EFAULT; + goto out; + } + set_bit(ATM_VF_HASSAP, &vcc->flags); +out: + release_sock(sk); + return error; } static int svc_getsockopt(struct socket *sock,int level,int optname, char *optval,int *optlen) { - int len; + struct sock *sk = sock->sk; + int error = 0, len; - if (!__SO_LEVEL_MATCH(optname, level) || optname != SO_ATMSAP) - return atm_getsockopt(sock,level,optname,optval,optlen); - if (get_user(len,optlen)) return -EFAULT; - if (len != sizeof(struct atm_sap)) return -EINVAL; - return copy_to_user(optval,&ATM_SD(sock)->sap,sizeof(struct atm_sap)) ? - -EFAULT : 0; + lock_sock(sk); + if (!__SO_LEVEL_MATCH(optname, level) || optname != SO_ATMSAP) { + error = vcc_getsockopt(sock, level, optname, optval, optlen); + goto out; + } + if (get_user(len, optlen)) { + error = -EFAULT; + goto out; + } + if (len != sizeof(struct atm_sap)) { + error = -EINVAL; + goto out; + } + if (copy_to_user(optval, &ATM_SD(sock)->sap, sizeof(struct atm_sap))) { + error = -EFAULT; + goto out; + } +out: + release_sock(sk); + return error; } -static struct proto_ops SOCKOPS_WRAPPED(svc_proto_ops) = { +static struct proto_ops svc_proto_ops = { .family = PF_ATMSVC, .release = svc_release, @@ -402,20 +525,17 @@ .accept = svc_accept, .getname = svc_getname, .poll = atm_poll, - .ioctl = atm_ioctl, + .ioctl = vcc_ioctl, .listen = svc_listen, .shutdown = svc_shutdown, .setsockopt = svc_setsockopt, .getsockopt = svc_getsockopt, - .sendmsg = atm_sendmsg, - .recvmsg = atm_recvmsg, + .sendmsg = vcc_sendmsg, + .recvmsg = vcc_recvmsg, .mmap = sock_no_mmap, .sendpage = sock_no_sendpage, }; - -#include -SOCKOPS_WRAP(svc_proto, PF_ATMSVC); static int svc_create(struct socket *sock,int protocol) { diff -Nru a/net/ipv4/igmp.c b/net/ipv4/igmp.c --- a/net/ipv4/igmp.c Mon May 19 23:22:52 2003 +++ b/net/ipv4/igmp.c Tue Jun 17 09:44:51 2003 @@ -387,8 +387,17 @@ if (type == IGMPV3_ALLOW_NEW_SOURCES || type == IGMPV3_BLOCK_OLD_SOURCES) return skb; - if (pmc->crcount || isquery) + if (pmc->crcount || isquery) { + /* make sure we have room for group header and at + * least one source. + */ + if (skb && AVAILABLE(skb) < sizeof(struct igmpv3_grec)+ + sizeof(__u32)) { + igmpv3_sendpack(skb); + skb = 0; /* add_grhead will get a new one */ + } skb = add_grhead(skb, pmc, type, &pgr); + } return skb; } pih = skb ? (struct igmpv3_report *)skb->h.igmph : 0; diff -Nru a/net/ipv4/tcp.c b/net/ipv4/tcp.c --- a/net/ipv4/tcp.c Mon Jun 16 09:53:26 2003 +++ b/net/ipv4/tcp.c Tue Jun 17 09:35:27 2003 @@ -1909,7 +1909,7 @@ BUG_TRAP(sk_unhashed(sk)); /* If it has not 0 inet_sk(sk)->num, it must be bound */ - BUG_TRAP(!inet_sk(sk)->num || sk->sk_prev); + BUG_TRAP(!inet_sk(sk)->num || tcp_sk(sk)->bind_hash); #ifdef TCP_DEBUG if (sk->sk_zapped) { @@ -2164,7 +2164,7 @@ tcp_sack_reset(tp); __sk_dst_reset(sk); - BUG_TRAP(!inet->num || sk->sk_prev); + BUG_TRAP(!inet->num || tp->bind_hash); sk->sk_error_report(sk); return err; diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c --- a/net/ipv4/tcp_ipv4.c Mon Jun 16 09:53:26 2003 +++ b/net/ipv4/tcp_ipv4.c Tue Jun 17 09:35:27 2003 @@ -156,9 +156,9 @@ struct tcp_bind_bucket *tb; spin_lock(&head->lock); - tb = (struct tcp_bind_bucket *)sk->sk_prev; + tb = tcp_sk(sk)->bind_hash; sk_add_bind_node(child, &tb->owners); - child->sk_prev = (struct sock *)tb; + tcp_sk(child)->bind_hash = tb; spin_unlock(&head->lock); } @@ -174,7 +174,7 @@ { inet_sk(sk)->num = snum; sk_add_bind_node(sk, &tb->owners); - sk->sk_prev = (struct sock *)tb; + tcp_sk(sk)->bind_hash = tb; } static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb) @@ -279,9 +279,9 @@ (!sk->sk_reuse || sk->sk_state == TCP_LISTEN)) tb->fastreuse = 0; success: - if (!sk->sk_prev) + if (!tcp_sk(sk)->bind_hash) tcp_bind_hash(sk, tb, snum); - BUG_TRAP(sk->sk_prev == (struct sock *)tb); + BUG_TRAP(tcp_sk(sk)->bind_hash == tb); ret = 0; fail_unlock: @@ -301,9 +301,9 @@ struct tcp_bind_bucket *tb; spin_lock(&head->lock); - tb = (struct tcp_bind_bucket *)sk->sk_prev; + tb = tcp_sk(sk)->bind_hash; __hlist_del(&sk->sk_bind_node); - sk->sk_prev = NULL; + tcp_sk(sk)->bind_hash = NULL; inet->num = 0; tcp_bucket_destroy(tb); spin_unlock(&head->lock); @@ -730,7 +730,7 @@ } head = &tcp_bhash[tcp_bhashfn(snum)]; - tb = (struct tcp_bind_bucket *)sk->sk_prev; + tb = tcp_sk(sk)->bind_hash; spin_lock_bh(&head->lock); if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { __tcp_v4_hash(sk, 0); @@ -2101,7 +2101,7 @@ __skb_queue_purge(&tp->ucopy.prequeue); /* Clean up a referenced TCP bind bucket. */ - if (sk->sk_prev) + if (tp->bind_hash) tcp_put_port(sk); /* If sendmsg cached page exists, toss it. */ diff -Nru a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c --- a/net/ipv4/tcp_minisocks.c Mon Jun 16 11:44:09 2003 +++ b/net/ipv4/tcp_minisocks.c Tue Jun 17 09:35:28 2003 @@ -301,8 +301,8 @@ */ bhead = &tcp_bhash[tcp_bhashfn(inet_sk(sk)->num)]; spin_lock(&bhead->lock); - tw->tw_tb = (struct tcp_bind_bucket *)sk->sk_prev; - BUG_TRAP(sk->sk_prev); + tw->tw_tb = tcp_sk(sk)->bind_hash; + BUG_TRAP(tcp_sk(sk)->bind_hash); tw_add_bind_node(tw, &tw->tw_tb->owners); spin_unlock(&bhead->lock); @@ -620,7 +620,7 @@ /* SANITY */ sk_node_init(&newsk->sk_node); - newsk->sk_prev = NULL; + tcp_sk(newsk)->bind_hash = NULL; /* Clone the TCP header template */ inet_sk(newsk)->dport = req->rmt_port; diff -Nru a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c --- a/net/ipv6/ip6_tunnel.c Mon Jun 9 07:56:44 2003 +++ b/net/ipv6/ip6_tunnel.c Tue Jun 17 11:17:42 2003 @@ -230,8 +230,6 @@ dev->init = ip6ip6_tnl_dev_init; memcpy(&t->parms, p, sizeof (*p)); t->parms.name[IFNAMSIZ - 1] = '\0'; - if (t->parms.hop_limit > 255) - t->parms.hop_limit = -1; strcpy(dev->name, t->parms.name); if (!dev->name[0]) { int i = 0; @@ -952,7 +950,7 @@ ipv6_addr_copy(&t->parms.laddr, &p->laddr); ipv6_addr_copy(&t->parms.raddr, &p->raddr); t->parms.flags = p->flags; - t->parms.hop_limit = (p->hop_limit <= 255 ? p->hop_limit : -1); + t->parms.hop_limit = p->hop_limit; t->parms.encap_limit = p->encap_limit; t->parms.flowinfo = p->flowinfo; ip6ip6_tnl_link_config(t); diff -Nru a/net/ipv6/mcast.c b/net/ipv6/mcast.c --- a/net/ipv6/mcast.c Thu Jun 12 00:04:26 2003 +++ b/net/ipv6/mcast.c Tue Jun 17 09:44:51 2003 @@ -1321,8 +1321,17 @@ if (type == MLD2_ALLOW_NEW_SOURCES || type == MLD2_BLOCK_OLD_SOURCES) return skb; - if (pmc->mca_crcount || isquery) + if (pmc->mca_crcount || isquery) { + /* make sure we have room for group header and at + * least one source. + */ + if (skb && AVAILABLE(skb) < sizeof(struct mld2_grec)+ + sizeof(struct in6_addr)) { + mld_sendpack(skb); + skb = 0; /* add_grhead will get a new one */ + } skb = add_grhead(skb, pmc, type, &pgr); + } return skb; } pmr = skb ? (struct mld2_report *)skb->h.raw : 0; diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c --- a/net/ipv6/tcp_ipv6.c Mon Jun 16 09:53:26 2003 +++ b/net/ipv6/tcp_ipv6.c Tue Jun 17 09:35:28 2003 @@ -225,9 +225,9 @@ tb->fastreuse = 0; success: - if (!sk->sk_prev) + if (!tcp_sk(sk)->bind_hash) tcp_bind_hash(sk, tb, snum); - BUG_TRAP(sk->sk_prev == (struct sock *)tb); + BUG_TRAP(tcp_sk(sk)->bind_hash == tb); ret = 0; fail_unlock: @@ -1947,7 +1947,7 @@ __skb_queue_purge(&tp->ucopy.prequeue); /* Clean up a referenced TCP bind bucket. */ - if (sk->sk_prev) + if (tcp_sk(sk)->bind_hash) tcp_put_port(sk); /* If sendmsg cached page exists, toss it. */ diff -Nru a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c --- a/net/ipx/af_ipx.c Mon Jun 16 08:11:36 2003 +++ b/net/ipx/af_ipx.c Tue Jun 17 10:11:58 2003 @@ -269,7 +269,7 @@ #ifdef CONFIG_IPX_INTERN static struct sock *ipxitf_find_internal_socket(struct ipx_interface *intrfc, - unsigned char *node, + unsigned char *ipx_node, unsigned short port) { struct sock *s; @@ -282,7 +282,7 @@ struct ipx_opt *ipxs = ipx_sk(s); if (ipxs->port == port && - !memcmp(node, ipxs->node, IPX_NODE_LEN)) + !memcmp(ipx_node, ipxs->node, IPX_NODE_LEN)) goto found; } s = NULL; diff -Nru a/net/sctp/endpointola.c b/net/sctp/endpointola.c --- a/net/sctp/endpointola.c Sat Jun 21 07:36:01 2003 +++ b/net/sctp/endpointola.c Tue Jun 17 09:35:28 2003 @@ -209,7 +209,7 @@ sctp_bind_addr_free(&ep->base.bind_addr); /* Remove and free the port */ - if (ep->base.sk->sk_prev) + if (sctp_sk(ep->base.sk)->bind_hash) sctp_put_port(ep->base.sk); /* Give up our hold on the sock. */ diff -Nru a/net/sctp/socket.c b/net/sctp/socket.c --- a/net/sctp/socket.c Mon Jun 16 08:11:36 2003 +++ b/net/sctp/socket.c Tue Jun 17 09:35:28 2003 @@ -3078,9 +3078,9 @@ */ success: inet_sk(sk)->num = snum; - if (!sk->sk_prev) { + if (!sctp_sk(sk)->bind_hash) { sk_add_bind_node(sk, &pp->sk_list); - sk->sk_prev = (struct sock *) pp; + sctp_sk(sk)->bind_hash = pp; } ret = 0; @@ -3345,9 +3345,9 @@ struct sctp_bind_bucket *pp; sctp_spin_lock(&head->lock); - pp = (struct sctp_bind_bucket *)sk->sk_prev; + pp = sctp_sk(sk)->bind_hash; hlist_del(&sk->sk_bind_node); - sk->sk_prev = NULL; + sctp_sk(sk)->bind_hash = NULL; inet_sk(sk)->num = 0; sctp_bucket_destroy(pp); sctp_spin_unlock(&head->lock); diff -Nru a/net/sunrpc/cache.c b/net/sunrpc/cache.c --- a/net/sunrpc/cache.c Sat May 10 11:46:35 2003 +++ b/net/sunrpc/cache.c Tue Jun 17 16:18:16 2003 @@ -310,14 +310,17 @@ cp = & current_detail->hash_table[current_index]; ch = *cp; for (; ch; cp= & ch->next, ch= *cp) { - if (atomic_read(&ch->refcnt)) - continue; - if (ch->expiry_time < get_seconds() - || ch->last_refresh < current_detail->flush_time - ) - break; if (current_detail->nextcheck > ch->expiry_time) current_detail->nextcheck = ch->expiry_time+1; + if (ch->expiry_time >= get_seconds() + && ch->last_refresh >= current_detail->flush_time + ) + continue; + if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) + queue_loose(current_detail, ch); + + if (atomic_read(&ch->refcnt)) + continue; } if (ch) { cache_get(ch); @@ -464,6 +467,31 @@ dreq = list_entry(pending.next, struct cache_deferred_req, recent); list_del_init(&dreq->recent); dreq->revisit(dreq, 0); + } +} + +void cache_clean_deferred(void *owner) +{ + struct cache_deferred_req *dreq, *tmp; + struct list_head pending; + + + INIT_LIST_HEAD(&pending); + spin_lock(&cache_defer_lock); + + list_for_each_entry_safe(dreq, tmp, &cache_defer_list, recent) { + if (dreq->owner == owner) { + list_del(&dreq->hash); + list_move(&dreq->recent, &pending); + cache_defer_cnt--; + } + } + spin_unlock(&cache_defer_lock); + + while (!list_empty(&pending)) { + dreq = list_entry(pending.next, struct cache_deferred_req, recent); + list_del_init(&dreq->recent); + dreq->revisit(dreq, 1); } } diff -Nru a/net/sunrpc/svc.c b/net/sunrpc/svc.c --- a/net/sunrpc/svc.c Fri Feb 7 12:25:20 2003 +++ b/net/sunrpc/svc.c Tue Jun 17 16:18:16 2003 @@ -98,6 +98,8 @@ sk_list); svc_delete_socket(svsk); } + + cache_clean_deferred(serv); /* Unregister service with the portmapper */ svc_register(serv, 0, 0); diff -Nru a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c --- a/net/sunrpc/svcauth_unix.c Tue Mar 11 20:03:48 2003 +++ b/net/sunrpc/svcauth_unix.c Tue Jun 17 16:18:16 2003 @@ -195,12 +195,12 @@ ipm.m_addr.s_addr = htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4); ipm.h.flags = 0; - if (dom) + if (dom) { ipm.m_client = container_of(dom, struct unix_domain, h); - else + ipm.m_add_change = ipm.m_client->addr_changes; + } else set_bit(CACHE_NEGATIVE, &ipm.h.flags); ipm.h.expiry_time = expiry; - ipm.m_add_change = ipm.m_client->addr_changes; ipmp = ip_map_lookup(&ipm, 1); if (ipmp) diff -Nru a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c --- a/net/sunrpc/svcsock.c Wed Jun 4 17:57:09 2003 +++ b/net/sunrpc/svcsock.c Tue Jun 17 16:31:29 2003 @@ -681,8 +681,17 @@ dprintk("svc: socket %p TCP (listen) state change %d\n", sk, sk->sk_state); - if (sk->sk_state != TCP_ESTABLISHED) { - /* Aborted connection, SYN_RECV or whatever... */ + if (sk->sk_state != TCP_LISTEN) { + /* + * This callback may called twice when a new connection + * is established as a child socket inherits everything + * from a parent LISTEN socket. + * 1) data_ready method of the parent socket will be called + * when one of child sockets become ESTABLISHED. + * 2) data_ready method of the child socket may be called + * when it receives data before the socket is accepted. + * In case of 2, we should ignore it silently. + */ goto out; } if (!(svsk = (struct svc_sock *) sk->sk_user_data)) { @@ -1060,6 +1069,8 @@ set_bit(SK_CHNGBUF, &svsk->sk_flags); set_bit(SK_DATA, &svsk->sk_flags); + if (sk->sk_state != TCP_ESTABLISHED) + set_bit(SK_CLOSE, &svsk->sk_flags); } } @@ -1211,7 +1222,6 @@ } rqstp->rq_secure = ntohs(rqstp->rq_addr.sin_port) < 1024; - rqstp->rq_userset = 0; rqstp->rq_chandle.defer = svc_defer; if (serv->sv_stats) @@ -1443,7 +1453,7 @@ static void svc_revisit(struct cache_deferred_req *dreq, int too_many) { struct svc_deferred_req *dr = container_of(dreq, struct svc_deferred_req, handle); - struct svc_serv *serv = dr->serv; + struct svc_serv *serv = dreq->owner; struct svc_sock *svsk; if (too_many) { @@ -1481,7 +1491,7 @@ if (dr == NULL) return NULL; - dr->serv = rqstp->rq_server; + dr->handle.owner = rqstp->rq_server; dr->prot = rqstp->rq_prot; dr->addr = rqstp->rq_addr; dr->argslen = rqstp->rq_arg.len >> 2;