]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.2 2.1.2
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:12:33 +0000 (15:12 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:12:33 +0000 (15:12 -0500)
109 files changed:
CREDITS
Documentation/Configure.help
Documentation/ioctl-number.txt
Makefile
arch/alpha/kernel/apecs.c
arch/alpha/kernel/cia.c
arch/alpha/kernel/entry.S
arch/alpha/kernel/head.S
arch/alpha/kernel/lca.c
arch/alpha/lib/memcpy.c
arch/alpha/mm/fault.c
arch/alpha/mm/init.c
arch/i386/kernel/entry.S
arch/i386/kernel/ioport.c
arch/i386/kernel/irq.c
arch/i386/kernel/process.c
arch/i386/kernel/ptrace.c
arch/i386/kernel/signal.c
arch/i386/kernel/sys_i386.c
arch/i386/kernel/traps.c
arch/i386/mm/fault.c
arch/i386/mm/init.c
arch/m68k/atari/ataints.c
arch/m68k/mm/init.c
arch/mips/mm/init.c
arch/ppc/mm/init.c
arch/sparc/mm/init.c
drivers/char/console.c
drivers/char/cyclades.c
drivers/char/ftape/fdc-io.c
drivers/char/keyboard.c
drivers/char/n_tty.c
drivers/char/pcxx.c
drivers/char/pty.c
drivers/char/tty_io.c
drivers/char/vga.c
drivers/net/at1700.c
drivers/net/eepro.c
drivers/net/eth16i.c
drivers/net/fmv18x.c
drivers/net/hp-plus.c
drivers/net/hp100.c
drivers/net/ibmtr.c
drivers/net/lance32.c
drivers/net/ne.c
drivers/net/ni65.h
drivers/net/seeq8005.c
drivers/net/sk_g16.c
drivers/net/skeleton.c
drivers/net/smc9194.c
drivers/scsi/53c7,8xx.c
drivers/scsi/NCR5380.c
drivers/scsi/advansys.c
drivers/scsi/atari_NCR5380.c
drivers/scsi/scsi.c
drivers/scsi/sg.c
drivers/sound/audio.c
drivers/sound/sb_common.c
fs/dquot.c
fs/ext/truncate.c
fs/ext2/file.c
fs/noquot.c
fs/open.c
fs/pipe.c
fs/read_write.c
fs/select.c
include/asm-alpha/cia.h
include/asm-alpha/io.h
include/asm-alpha/lca.h
include/asm-alpha/mman.h
include/asm-alpha/mmu_context.h
include/asm-alpha/processor.h
include/asm-alpha/shmparam.h
include/asm-i386/bugs.h
include/asm-i386/io.h
include/asm-i386/ipc.h [new file with mode: 0644]
include/asm-i386/irq.h
include/asm-i386/mman.h
include/asm-i386/pgtable.h
include/asm-i386/processor.h
include/asm-i386/ptrace.h
include/asm-i386/user.h
include/asm-m68k/mman.h
include/asm-mips/io.h
include/asm-mips/mman.h
include/asm-ppc/mman.h
include/asm-ppc/pgtable.h
include/asm-sparc/mman.h
include/linux/config.h
include/linux/ipc.h
include/linux/mm.h
include/linux/msg.h
include/linux/posix_types.h
include/linux/proc_fs.h
include/linux/sem.h
include/linux/shm.h
include/linux/soundcard.h
include/linux/timex.h
include/linux/types.h
include/net/tcp.h
init/main.c
kernel/ksyms.c
mm/filemap.c
mm/memory.c
mm/mmap.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/unix/af_unix.c

diff --git a/CREDITS b/CREDITS
index f5c2532683e182d14a95bbd8c81aadf7c66e0433..bf5d5539de16ecd134a2ebba3cca4dca5768dfd9 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1088,13 +1088,12 @@ E: snprobst@immd4.informatik.uni-erlangen.de
 D: The Linux Support Team Erlangen
 
 N: Daniel Quinlan
-E: Daniel.Quinlan@linux.org
-W: http://www.bucknell.edu/~quinlan
+E: quinlan@pathname.com
+W: http://www.pathname.com/~quinlan/
 D: FSSTND coordinator; FHS editor
 D: random Linux documentation, patches, and hacks
-S: Box C-5083
-S: Bucknell University
-S: Lewisburg, Pennsylvania 17837
+S: 4390 Albany Dr. #41A
+S: San Jose, California 95129
 S: USA
 
 N: Eric S. Raymond
index 53a77a5b26c8ba4563f9e5bb7412f2837e696195..bda2615581dbf51446d525e5143bd2a3e6c01cac 100644 (file)
@@ -3,13 +3,12 @@
 # This version of the Linux kernel configuration help texts
 # corresponds to the kernel versions 2.0.x.
 #
-# International versions available on the WWW:
-#   - http://www.eis.or.jp/muse/kikutani/Configure.help-1.2.x.euc 
-# is a Japanese translation of a previous version of this file,
-# written by kikutani@eis.or.jp.
+# International versions of this file available on the WWW:
+#   - http://jf.gee.kyoto-u.ac.jp/JF/JF-ftp/euc/Configure.help.euc
+# is a Japanese translation, maintained by Tetsuyasu YAMADA
+# (tetsu@cauchy.nslab.ntt.jp). 
 #   - http://nevod.perm.su/service/linux/doc/kernel/Configure.help 
-# is a Russian translation of this file, maintained by
-# kaf@linux.nevod.perm.su.
+# is a Russian translation, maintained by kaf@linux.nevod.perm.su.
 #
 # Information about what a kernel is, what it does, how to patch and
 # compile it and much more is contained in the Kernel-HOWTO, available
@@ -115,18 +114,15 @@ CONFIG_BLK_DEV_INITRD
 
 Loop device support
 CONFIG_BLK_DEV_LOOP
-  Enabling this option will allow you to mount a file as a file system.
-  This is useful if you want to check an ISO9660 file system before
-  burning the CD, or want to use floppy images without first writing
-  them to floppy.
-  This option also allows one to mount a filesystem with encryption.
-  To use these features, you need a recent version of mount, such as
-  the one found at ftp.win.tue.nl:/pub/linux/util/mount-2.5X.tar.gz.
-  If you want to use encryption, you might also be interested in the
-  (old) DES package ftp.funet.fi:/pub/OS/Linux/BETA/loop/des.1.tar.gz.
-  Note that this loop device has nothing to do with the loopback
-  device used for network connections from the machine to itself.
-  Most users will answer N here.
+  Enabling this option will allow you to mount a file as a file
+  system.  This is useful if you want to check an ISO9660 file system
+  before burning the CD, or want to use floppy images without first
+  writing them to floppy.  This option also allows one to mount a
+  filesystem with encryption.  To use these features, you need a
+  recent version of mount (check the file Documentation/Changes for
+  location and latest version).  Note that this loop device has
+  nothing to do with the loopback device used for network connections
+  from the machine to itself.  Most users will answer N here.
 
 Enhanced IDE/MFM/RLL disk/cdrom/tape support
 CONFIG_BLK_DEV_IDE 
@@ -566,10 +562,9 @@ CONFIG_BLK_DEV_TRITON
   If your PCI system uses an IDE harddrive (as opposed to SCSI, say)
   and includes the Intel 430FX PCI Triton chipset, you will want to
   enable this option to allow use of bus-mastering DMA data transfers.
-  Read the comments at the beginning of drivers/block/triton.c.  The
-  hdparm utility can be obtained via ftp (user: anonymous) from
-  sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/.  It is safe
-  to say Y.
+  Read the comments at the beginning of drivers/block/triton.c.  Check
+  the file Documentation/Changes for location and latest version of
+  the hdparm utility. It is safe to say Y to this question.
 
 System V IPC
 CONFIG_SYSVIPC
@@ -593,56 +588,55 @@ CONFIG_BINFMT_ELF
   executables used across different architectures and operating
   systems. This option will enable your kernel to run ELF binaries and
   enlarge it by about 2kB. ELF support under Linux is quickly
-  replacing the traditional Linux a.out format because it is portable
-  (this does *not* mean that you will be able to run executables from
-  different architectures or operating systems!) 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 on the WWW at
+  replacing 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!) 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 on the WWW at
   http://www.sjc.ox.ac.uk/users/barlow/elf-howto.html (To browse the
   WWW, you need to have access to a machine on the Internet that has
   one of the programs lynx, netscape or Mosaic).  If you find that
   after upgrading to Linux kernel 1.3 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 (available
-  via ftp (user: anonymous) from
-  tsx-11.mit.edu:/pub/linux/packages/GCC). Also note that ELF binary
-  support was broken in kernel versions 1.3.0 - 1.3.2. Either use a
-  newer 1.3 kernel or one of the stable 1.2 versions. 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 Documentation/modules.txt. Saying M or N here is dangerous
-  because some crucial programs on your system might be in ELF
-  format. 
+  install the newest ELF runtime libraries, including ld.so (check the
+  file Documentation/Changes 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 Documentation/modules.txt. Saying M or N here is dangerous
+  because some crucial programs on your system might be in ELF format.
 
 Compile kernel as ELF - if your GCC is ELF-GCC
 CONFIG_KERNEL_ELF
   The gcc version 2.7.0 and newer produces the new ELF binary format
-  as default. If you have such a compiler (try "gcc -v"), say Y
-  here, otherwise N.
+  as default. If you have such a compiler (try "gcc -v"), say Y here,
+  otherwise N.  
   It is possible, albeit almost pointless, to compile the kernel in
-  a.out format even if your compiler produces ELF as default. For
-  that, you would have to say N here and change the variables LD and
-  CC in the toplevel Makefile. Similarly, if your compiler produces
-  a.out by default but is able to produce ELF, you can compile the
-  kernel in ELF by saying Y here and editing the variables CC
-  and LD in the toplevel Makefile.
+  a.out (i.e. QMAGIC) format even if your compiler produces ELF as
+  default. For that, you would have to say N here and change the
+  variables LD and CC in the toplevel Makefile. Similarly, if your
+  compiler produces a.out by default but is able to produce ELF, you
+  can compile the kernel in ELF by saying Y here and editing the
+  variables CC and LD in the toplevel Makefile.
 
 Kernel support for A.OUT binaries
 CONFIG_BINFMT_AOUT
-  A.OUT (Assembler.OUTput) format is a format for libraries and
-  executables used in the earliest versions of UNIX. Linux used this
-  format until it was replaced with the ELF format.
-  As more and more programs are converted to ELF, the use for A.OUT
+  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 when
-  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. You may answer M for module support and
-  later load the module when you find a program which needs a.out
-  format. Saying M or N here is dangerous, because some crucial
-  programs on your system might be in A.OUT format.
+  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. Saying M or N
+  here is dangerous though, because some crucial programs on your
+  system might still be in A.OUT format.
 
 Kernel support for JAVA binaries
 CONFIG_BINFMT_JAVA
@@ -664,7 +658,7 @@ CONFIG_BINFMT_JAVA
   warrant removing support. However its removal is a good idea if you
   do not have the JDK installed. If you don't know what to answer at
   this point then answer Y. You may answer M for module support and
-  later load the module when you install the JDK or find a interesting
+  later load the module when you install the JDK or find an interesting
   Java program that you can't live without.
 
 Processor type
@@ -699,7 +693,7 @@ CONFIG_CPU_LITTLE_ENDIAN
   opposed to mips-linux-gcc or mips-linuxelf-gcc), say Y here,
   otherwise N. Most MIPS machines use little-endian code, but it might
   be necessary to run older Mips systems, such as the Sony News and
-  MIPS RC3xxx in big endian mode.
+  MIPS RC3xxx, in big endian mode.
 
 Enable loadable module support
 CONFIG_MODULES
@@ -717,14 +711,13 @@ CONFIG_MODVERSIONS
   kernel. Enabling this option makes it possible, and safe, to use the
   same modules even after compiling a new kernel; this requires the
   program modprobe. All the software needed for module support is in
-  the modules package in sunsite.unc.edu:/pub/Linux/kernel, available
-  via ftp (user: anonymous) to be extracted with "tar xzvf filename".
-  NOTE: if you say Y here but don't have the program genksyms (which
-  is also contained in the above mentioned modules package), then the
-  building of your kernel will fail.
-  If you are going to use modules that are generated from non-kernel
-  sources, you would benefit from this option. Otherwise it's not that
-  important. So, N ought to be a safe bet.
+  the modules package (check the file Documentation/Changes for
+  location and latest version).  NOTE: if you say Y here but don't
+  have the program genksyms (which is also contained in the above
+  mentioned modules package), then the building of your kernel will
+  fail.  If you are going to use modules that are generated from
+  non-kernel sources, you would benefit from this option. Otherwise
+  it's not that important. So, N ought to be a safe bet.
 
 Kernel daemon support
 CONFIG_KERNELD
@@ -840,19 +833,20 @@ CONFIG_IP_FIREWALL
   about 2kB. You may need to read the FIREWALL-HOWTO, available via
   ftp (user: anonymous) in
   sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also, you will need the
-  ipfwadm tool (available via ftp (user: anonymous) from ftp.xos.nl) 
-  to allow selective blocking of internet traffic based
-  on type, origin and destination.  You need to enable IP firewalling
-  in order to be able to use IP masquerading (i.e. local computers can
-  chat with an outside host, but that outside host is made to think
-  that it is talking to the firewall box. Makes the local network
-  completely invisible and avoids the need to allocate valid IP host
-  addresses for the machines on the local net) or to use the IP packet
-  accounting to see what is using all your network bandwidth.
-  This option is also needed when you want to enable the transparent
-  proxying support (makes the computers on the local network think
-  they're talking to a remote computer, while in reality the traffic
-  is redirected by your Linux firewall to a local proxy server).
+  ipfwadm tool (check the file Documentation/Changes for location and
+  latest version) to allow selective blocking of internet traffic
+  based on type, origin and destination.  You need to enable IP
+  firewalling in order to be able to use IP masquerading (i.e. local
+  computers can chat with an outside host, but that outside host is
+  made to think that it is talking to the firewall box. Makes the
+  local network completely invisible and avoids the need to allocate
+  valid IP host addresses for the machines on the local net) or to use
+  the IP packet accounting to see what is using all your network
+  bandwidth.  This option is also needed when you want to enable the
+  transparent proxying support (makes the computers on the local
+  network think they're talking to a remote computer, while in reality
+  the traffic is redirected by your Linux firewall to a local proxy
+  server).
 
 IP: accounting
 CONFIG_IP_ACCT
@@ -863,7 +857,8 @@ CONFIG_IP_ACCT
   firewalling. The data is accessible with "cat /proc/net/ip_acct", so
   you want to say Y to the /proc filesystem below, if you say Y
   here. To specify what exactly should be recorded, you need the tool
-  ipfwadm (available from ftp.xos.nl if you don't have a copy already).
+  ipfwadm (check the file Documentation/Changes for location and
+  latest version).
 
 IP: tunneling
 CONFIG_NET_IPIP
@@ -977,17 +972,25 @@ CONFIG_INET_PCTCP
 
 Reverse ARP
 CONFIG_INET_RARP
-  Since you asked: if there's a diskless machine on your local network
-  that know its hardware ethernet address but doesn't know its IP
-  address upon startup, it can send out a Reverse Address Resolution
-  Protocol request to find out its own IP address. If you want your
-  Linux box to be able to *answer* such requests, say Y here; you'd
-  have to run the program rarp ("man rarp") on your box.  Superior
-  solutions to the same problem are given by the protocols BOOTP and
-  DHCP. If you want to compile RARP support as a module ( = code which
-  can be inserted in and removed from the running kernel whenever you
-  want), say M here and read Documentation/modules.txt.  If you don't
-  understand a word, say N and rest in peace.
+  Since you asked: if there are (usually diskless or portable)
+  machines on your local network that know their hardware ethernet
+  addresses but don't know their IP addresses upon startup, they can
+  send out a Reverse Address Resolution Protocol (RARP) request to
+  find out their own IP addresses. Diskless Sun 3 machines use this
+  procedure at boot time. If you want your Linux box to be able to
+  *answer* such requests, say Y here; you'd have to run the program
+  rarp ("man rarp") on your box. If you actually want to use a
+  diskless Sun 3 machine as an Xterminal to Linux, say Y here and
+  fetch Linux-Xkernel from
+  ftp://sunsite.unc.edu/pub/Linux/system/Network/boot.net/.  Superior
+  solutions to the problem of booting and configuring machines over a
+  net connection are given by the protocol BOOTP and its successor
+  DHCP. See the DHCP FAQ
+  http://web.syr.edu/~jmwobus/comfaqs/dhcp.faq.html for details.  If
+  you want to compile RARP support as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt.  If you don't
+  understand a word of the above, say N and rest in peace.
 
 Assume subnets are local
 CONFIG_INET_SNARL
@@ -1734,7 +1737,8 @@ CONFIG_DUMMY
   module ( = code which can be inserted in and removed from the
   running kernel whenever you want), say M here and read
   Documentation/modules.txt. If you want to use more than one dummy
-  device at a time, you need to compile it as a module.
+  device at a time, you need to compile it as a module. Instead of
+  'dummy', it will they will then be called 'dummy0', 'dummy1' etc.
   
 SLIP (serial line) support
 CONFIG_SLIP
@@ -1974,7 +1978,7 @@ CONFIG_DLCI_MAX
 
 Sangoma S502A FRAD support
 CONFIG_SDLA
-  Say Y here if you need a driver for the Sangoma S502A, S502E and
+  Say Y here if you need a driver for the Sangoma S502A, S502E, and
   S508 Frame Relay Access Devices. These are multi-protocol
   cards, but only frame relay is supported by the driver at this
   time. Please read Documentation/framerelay.txt. This driver is also
@@ -2978,25 +2982,25 @@ CONFIG_ROOT_NFS
 BOOTP support
 CONFIG_RNFS_BOOTP
   If you want your Linux box to mount its whole root filesystem from
-  some other computer over the net via NFS and you want the address
-  of your computer to be discovered automatically using the BOOTP
-  protocol (a special protocol designed for doing this job), say Y
-  here. In case the boot ROM of your network card was designed for
-  booting Linux and does BOOTP itself, providing all necessary
-  information on the kernel command line, you can say N here.
-  If unsure, say Y. Note that in case you want to use BOOTP, a BOOTP
+  some other computer over the net via NFS and you want the IP address
+  of your computer to be discovered automatically at boot time using
+  the BOOTP protocol (a special protocol designed for doing this job),
+  say Y here. In case the boot ROM of your network card was designed
+  for booting Linux and does BOOTP itself, providing all necessary
+  information on the kernel command line, you can say N here.  If
+  unsure, say Y. Note that in case you want to use BOOTP, a BOOTP
   server must be operating on your network. Read
   Documentation/nfsroot.txt for details.
 
 RARP support
 CONFIG_RNFS_RARP
   If you want your Linux box to mount its whole root filesystem from
-  some other computer over the net via NFS and you want the address
-  of your computer to be discovered automatically using the RARP
-  protocol (an older protocol which is being obsoleted by BOOTP), say
-  Y here. Note that in case you want to use RARP, a RARP server must be
-  operating on your network. Read Documentation/nfsroot.txt for
-  details. 
+  some other computer over the net via NFS and you want the IP address
+  of your computer to be discovered automatically at boot time using
+  the RARP protocol (an older protocol which is being obsoleted by
+  BOOTP), say Y here. Note that in case you want to use RARP, a RARP
+  server must be operating on your network. Read
+  Documentation/nfsroot.txt for details.
 
 ISO9660 cdrom filesystem support
 CONFIG_ISO9660_FS
index 771f44166d68223d6208726e44e91a0b6365b9d9..73ba54c38e701d7ca944f1ad06f9f9b952fd08c7 100644 (file)
@@ -1,5 +1,5 @@
 Ioctl Numbers
-6 Aug 1996
+5 Oct 1996
 Michael Chastain
 <mec@duracef.shout.net>
 
@@ -51,7 +51,7 @@ Following the convention is good because:
     code to call verify_area to validate parameters.
 
 This table lists ioctls visible from user land for Linux/i386.  It is
-current to Linux 2.0.11.
+current to Linux 2.1.1
 
 Code   Seq#    Include File            Comments
 ========================================================
@@ -104,3 +104,5 @@ Code        Seq#    Include File            Comments
 0x89   00-0F   asm-i386/sockios.h
 0x89   10-FF   linux/sockios.h
 0x90   00      linux/sbpcd.h
+0x99   00-0F   537-Addinboard driver (in development, e-mail contact:
+                                       b.kohl@ipn-b.comlink.apc.org)
index 647adfae673537017f7927fd672d5ec122aec042..8a45dad1f69392ca956c6a2917b5e0b9ac8361ff 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 1
+SUBLEVEL = 2
 
 ARCH = i386
 
index f4554bcc13a78371307f9f55e3969adaef01c3e4..124c5b58e3424c1a459d96aa56318188902e605a 100644 (file)
@@ -526,8 +526,8 @@ void apecs_machine_check(unsigned long vector, unsigned long la_ptr,
 #define MCHK_NO_DEVSEL 0x205L
 #define MCHK_NO_TABT 0x204L
        if (apecs_mcheck_expected &&
-           (((unsigned int)mchk_procdata->paltemp[0] == MCHK_NO_DEVSEL) ||
-            ((unsigned int)mchk_procdata->paltemp[0] == MCHK_NO_TABT))
+           (((unsigned int)mchk_header->code == MCHK_NO_DEVSEL) ||
+            ((unsigned int)mchk_header->code == MCHK_NO_TABT))
            )
        {
 #else
@@ -550,19 +550,21 @@ void apecs_machine_check(unsigned long vector, unsigned long la_ptr,
                printk("apecs_machine_check: HW correctable (0x%lx)\n", vector);
        }
        else {
-               printk("APECS machine check:\n");
-               printk("  vector=0x%lx la_ptr=0x%lx\n",
+               printk(KERN_CRIT "APECS machine check:\n");
+               printk(KERN_CRIT "  vector=0x%lx la_ptr=0x%lx\n",
                       vector, la_ptr);
-               printk("  pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+               printk(KERN_CRIT
+                      "  pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
                       regs->pc, mchk_header->size, mchk_header->proc_offset,
                       mchk_header->sys_offset);
-               printk("  expected %d DCSR 0x%lx PEAR 0x%lx\n",
+               printk(KERN_CRIT "  expected %d DCSR 0x%lx PEAR 0x%lx\n",
                       apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
                       mchk_sysdata->epic_pear);
 
                ptr = (unsigned long *)la_ptr;
                for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
-                   printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
+                   printk(KERN_CRIT " +%lx %lx %lx\n",
+                          i*sizeof(long), ptr[i], ptr[i+1]);
                }
 #if 0
                /* doesn't work with MILO */
index ea59808e43295f9f4b0d462106639c1b82384d14..98bc94227204e41f36b4101ffc9a992220826dc5 100644 (file)
 extern struct hwrpb_struct *hwrpb;
 extern asmlinkage void wrmces(unsigned long mces);
 extern int alpha_sys_type;
+
+/*
+ * Machine check reasons.  Defined according to PALcode sources
+ * (osf.h and platform.h).
+ */
+#define MCHK_K_TPERR           0x0080
+#define MCHK_K_TCPERR          0x0082
+#define MCHK_K_HERR            0x0084
+#define MCHK_K_ECC_C           0x0086
+#define MCHK_K_ECC_NC          0x0088
+#define MCHK_K_OS_BUGCHECK     0x008A
+#define MCHK_K_PAL_BUGCHECK    0x0090
+
 /*
  * BIOS32-style PCI interface:
  */
@@ -38,7 +51,7 @@ extern int alpha_sys_type;
 
 static volatile unsigned int CIA_mcheck_expected = 0;
 static volatile unsigned int CIA_mcheck_taken = 0;
-static unsigned long CIA_jd, CIA_jd1, CIA_jd2;
+static unsigned long CIA_jd;
 
 
 /*
@@ -438,16 +451,19 @@ int cia_pci_clr_err(void)
 }
 
 void cia_machine_check(unsigned long vector, unsigned long la_ptr,
-                        struct pt_regs * regs)
+                      struct pt_regs * regs)
 {
-#if 0
-        printk("CIA machine check ignored\n") ;
-#else
        struct el_common *mchk_header;
+       struct el_procdata *mchk_procdata;
        struct el_CIA_sysdata_mcheck *mchk_sysdata;
+       unsigned long * ptr;
+       const char * reason;
+       char buf[128];
+       long i;
 
        mchk_header = (struct el_common *)la_ptr;
-
+       mchk_procdata =
+               (struct el_procdata *)(la_ptr + mchk_header->proc_offset);
        mchk_sysdata = 
          (struct el_CIA_sysdata_mcheck *)(la_ptr + mchk_header->sys_offset);
 
@@ -458,13 +474,14 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr,
             CIA_mcheck_expected, mchk_sysdata->epic_dcsr, mchk_sysdata->epic_pear));
 #ifdef DEBUG
        {
-           unsigned long *ptr;
-           int i;
+               unsigned long *ptr;
+               int i;
 
-           ptr = (unsigned long *)la_ptr;
-           for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
-               printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
-           }
+               ptr = (unsigned long *)la_ptr;
+               for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+                       printk(" +%lx %lx %lx\n", i*sizeof(long),
+                              ptr[i], ptr[i+1]);
+               }
        }
 #endif /* DEBUG */
        /*
@@ -483,12 +500,56 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr,
                cia_pci_clr_err();
                wrmces(0x7);
                mb();
+               return;
+       }
+
+       switch ((unsigned int) mchk_header->code) {
+             case MCHK_K_TPERR:        reason = "tag parity error"; break;
+             case MCHK_K_TCPERR:       reason = "tag control parity error"; break;
+             case MCHK_K_HERR:         reason = "generic hard error"; break;
+             case MCHK_K_ECC_C:        reason = "correctable ECC error"; break;
+             case MCHK_K_ECC_NC:       reason = "uncorrectable ECC error"; break;
+             case MCHK_K_OS_BUGCHECK:  reason = "OS-specific PAL bugcheck"; break;
+             case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break;
+             case 0x96: reason = "i-cache read retryable error"; break;
+             case 0x98: reason = "processor detected hard error"; break;
+
+               /* system specific (these are for Alcor, at least): */
+             case 0x203: reason = "system detected uncorrectable ECC error"; break;
+             case 0x205: reason = "parity error detected by CIA"; break;
+             case 0x207: reason = "non-existent memory error"; break;
+             case 0x209: reason = "PCI SERR detected"; break;
+             case 0x20b: reason = "PCI data parity error detected"; break;
+             case 0x20d: reason = "PCI address parity error detected"; break;
+             case 0x20f: reason = "PCI master abort error"; break;
+             case 0x211: reason = "PCI target abort error"; break;
+             case 0x213: reason = "scatter/gather PTE invalid error"; break;
+             case 0x215: reason = "flash ROM write error"; break;
+             case 0x217: reason = "IOA timeout detected"; break;
+             case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
+             case 0x21b: reason = "EISA fail-safe timer timeout"; break;
+             case 0x21d: reason = "EISA bus time-out"; break;
+             case 0x21f: reason = "EISA software generated NMI"; break;
+             case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
+             default:
+               sprintf(buf, "reason for machine-check unknown (0x%x)",
+                       (unsigned int) mchk_header->code);
+               reason = buf;
+               break;
+       }
+       wrmces(rdmces());       /* reset machine check pending flag */
+       mb();
+
+       printk(KERN_CRIT "  CIA machine check: %s%s\n",
+              reason, mchk_header->retry ? " (retryable)" : "");
+
+       /* dump the the logout area to give all info: */
+
+       ptr = (unsigned long *)la_ptr;
+       for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+           printk(KERN_CRIT " +%8lx %016lx %016lx\n",
+                  i*sizeof(long), ptr[i], ptr[i+1]);
        }
-#if 1
-       else
-         printk("CIA machine check NOT expected\n") ;
-#endif
-#endif
 }
 
 #endif /* CONFIG_ALPHA_CIA */
index 0ff8ff726463f1280a1c96d2eb8f5d4ef8d02776..99efc69339418a68d7327053994c22fb6b383016 100644 (file)
@@ -55,6 +55,7 @@
        stq     $2,16($30);             \
        stq     $3,24($30);             \
        stq     $4,32($30);             \
+       lda     $2,hae;                 \
        stq     $5,40($30);             \
        stq     $6,48($30);             \
        stq     $7,56($30);             \
@@ -62,6 +63,7 @@
        stq     $19,72($30);            \
        stq     $20,80($30);            \
        stq     $21,88($30);            \
+       ldq     $2,HAE_CACHE($2);       \
        stq     $22,96($30);            \
        stq     $23,104($30);           \
        stq     $24,112($30);           \
        stq     $26,128($30);           \
        stq     $27,136($30);           \
        stq     $28,144($30);           \
-       lda     $2,hae;                 \
-       ldq     $2,HAE_CACHE($2);       \
        stq     $2,152($30)
 
 #define RESTORE_ALL                    \
-       lda     $8,hae;                 \
-       ldq     $7,HAE_CACHE($8);       \
-       ldq     $6,152($30);            \
-       subq    $7,$6,$5;               \
-       beq     $5,99f;                 \
-       ldq     $7,HAE_REG($8);         \
-       addq    $31,7,$16;              \
-       call_pal PAL_swpipl;            \
-       stq     $6,HAE_CACHE($8);       \
-       stq     $6,0($7);               \
-       mb;                             \
-       bis     $0,$0,$16;              \
-       call_pal PAL_swpipl;            \
-99:;                                   \
+       lda     $19,hae;                \
        ldq     $0,0($30);              \
        ldq     $1,8($30);              \
        ldq     $2,16($30);             \
        ldq     $3,24($30);             \
+       ldq     $20,152($30);           \
+       ldq     $21,HAE_CACHE($19);     \
        ldq     $4,32($30);             \
        ldq     $5,40($30);             \
        ldq     $6,48($30);             \
        ldq     $7,56($30);             \
+       subq    $20,$21,$20;            \
        ldq     $8,64($30);             \
+       beq     $20,99f;                \
+       ldq     $20,HAE_REG($19);       \
+       addq    $31,7,$16;              \
+       call_pal PAL_swpipl;            \
+       stq     $21,HAE_CACHE($19);     \
+       stq     $21,0($20);             \
+       bis     $0,$0,$16;              \
+       call_pal PAL_swpipl;            \
+       ldq     $0,0($30);              \
+       ldq     $1,8($30);              \
+99:;                                   \
        ldq     $19,72($30);            \
        ldq     $20,80($30);            \
        ldq     $21,88($30);            \
 
 .text
 .set noat
-#ifdef __linux__
+#if defined(__linux__) && !defined(__ELF__)
   .set singlegp
 #endif
 
@@ -473,24 +474,22 @@ alpha_switch_to:
 .globl ret_from_sys_call
 .ent   entSys
 entSys:
-       stq     $16,24($30)
-       stq     $17,32($30)
-       stq     $18,40($30)
        SAVE_ALL
-       /* FIXME: optimize */
        lda     $1,current_set
+       lda     $4,NR_SYSCALLS($31)
+       stq     $16,SP_OFF+24($30)
+       lda     $5,sys_call_table
        ldq     $2,0($1)
+       lda     $27,do_entSys
+       cmpult  $0,$4,$4
        ldq     $3,TASK_FLAGS($2)
+       stq     $17,SP_OFF+32($30)
+       s8addq  $0,$5,$5
        and     $3,PF_PTRACED,$3
+       stq     $18,SP_OFF+40($30)
        bne     $3,strace
-       /* end of strace */     
-       lda     $1,NR_SYSCALLS($31)
-       lda     $2,sys_call_table
-       lda     $27,do_entSys
-       cmpult  $0,$1,$1
-       s8addq  $0,$2,$2
-       beq     $1,1f
-       ldq     $27,0($2)
+       beq     $4,1f
+       ldq     $27,0($5)
 1:     jsr     $26,($27),do_entSys
        blt     $0,syscall_error        /* the call failed */
        stq     $0,0($30)
index 0c1fc8681ecca1c5e6299e203f6be657531d2cf7..9038efae8af4a8dad240d1628a03a7780789db72 100644 (file)
@@ -125,3 +125,52 @@ wrfpcr:
        lda     $30,0x10($30)
        ret     ($26)
        .end    wrfpcr
+
+#define ex_count 0($16)
+#define ex_r9   8($16)
+#define ex_r10 16($16)
+#define ex_r11 24($16)
+#define ex_r12 32($16)
+#define ex_r13 40($16)
+#define ex_r14 48($16)
+#define ex_r15 56($16)
+#define ex_r26 64($16)
+#define ex_r30 72($16)
+
+       .align 3
+       .globl  __exception
+       .ent    __exception
+__exception:
+       ldq     $1,ex_count
+       bis     $31,$31,$0      /* return 0 */
+       addq    $1,1,$2
+       bne     $1,1f           /* don't save state if orig_count != 0 */
+       stq     $9,ex_r9
+       stq     $10,ex_r10
+       stq     $11,ex_r11
+       stq     $12,ex_r12
+       stq     $13,ex_r13
+       stq     $14,ex_r14
+       stq     $15,ex_r15
+       stq     $26,ex_r26
+       stq     $30,ex_r30
+1:     stq     $2,ex_count
+       ret     ($26)
+       .end    __exception
+
+       .align 3
+       .globl  __handle_exception
+       .ent    __handle_exception
+__handle_exception:
+       ldq     $9,ex_r9
+       ldq     $10,ex_r10
+       ldq     $11,ex_r11
+       ldq     $12,ex_r12
+       ldq     $13,ex_r13
+       ldq     $14,ex_r14
+       ldq     $15,ex_r15
+       ldq     $26,ex_r26
+       ldq     $30,ex_r30
+       bis     $31,1,$0        /* return 1 */
+       ret     ($26)
+       .end    __handle_exception
index f153f5be1a05dad33f5ad5185f1046ece5a097c4..2030efc4c4b0e3dd6eb864296cfb5ddd55a94c18 100644 (file)
@@ -386,11 +386,14 @@ void ioc_error (__u32 stat0, __u32 stat1)
 
 void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *regs)
 {
+       unsigned long * ptr;
        const char * reason;
        union el_lca el;
        char buf[128];
+       long i;
 
-       printk("lca: machine check (la=0x%lx,pc=0x%lx)\n", la, regs->pc);
+       printk(KERN_CRIT "lca: machine check (la=0x%lx,pc=0x%lx)\n",
+              la, regs->pc);
        el.c = (struct el_common *) la;
        /*
         * The first quadword after the common header always seems to
@@ -399,9 +402,9 @@ void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *
         * logout frame, the upper 32 bits is the machine check
         * revision level, which we ignore for now.
         */
-       switch (el.s->reason & 0xffffffff) {
+       switch (el.c->code & 0xffffffff) {
              case MCHK_K_TPERR:        reason = "tag parity error"; break;
-             case MCHK_K_TCPERR:       reason = "tag something parity error"; break;
+             case MCHK_K_TCPERR:       reason = "tag control parity error"; break;
              case MCHK_K_HERR:         reason = "access to non-existent memory"; break;
              case MCHK_K_ECC_C:        reason = "correctable ECC error"; break;
              case MCHK_K_ECC_NC:       reason = "non-correctable ECC error"; break;
@@ -416,7 +419,7 @@ void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *
              case MCHK_K_UNKNOWN:
              default:
                sprintf(buf, "reason for machine-check unknown (0x%lx)",
-                       el.s->reason & 0xffffffff);
+                       el.c->code & 0xffffffff);
                reason = buf;
                break;
        }
@@ -425,7 +428,8 @@ void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *
 
        switch (el.c->size) {
              case sizeof(struct el_lca_mcheck_short):
-               printk("  Reason: %s (short frame%s, dc_stat=%lx):\n",
+               printk(KERN_CRIT
+                      "  Reason: %s (short frame%s, dc_stat=%lx):\pn",
                       reason, el.c->retry ? ", retryable" : "", el.s->dc_stat);
                if (el.s->esr & ESR_EAV) {
                    mem_error(el.s->esr, el.s->ear);
@@ -436,11 +440,12 @@ void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *
                break;
 
              case sizeof(struct el_lca_mcheck_long):
-               printk("  Reason: %s (long frame%s):\n",
+               printk(KERN_CRIT "  Reason: %s (long frame%s):\n",
                       reason, el.c->retry ? ", retryable" : "");
-               printk("    reason: %lx  exc_addr: %lx  dc_stat: %lx\n", 
+               printk(KERN_CRIT
+                      "    reason: %lx  exc_addr: %lx  dc_stat: %lx\n", 
                       el.l->pt[0], el.l->exc_addr, el.l->dc_stat);
-               printk("    car: %lx\n", el.l->car);
+               printk(KERN_CRIT "    car: %lx\n", el.l->car);
                if (el.l->esr & ESR_EAV) {
                    mem_error(el.l->esr, el.l->ear);
                }
@@ -450,7 +455,15 @@ void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *
                break;
 
              default:
-               printk("  Unknown errorlog size %d\n", el.c->size);
+               printk(KERN_CRIT "  Unknown errorlog size %d\n", el.c->size);
+       }
+
+       /* dump the the logout area to give all info: */
+
+       ptr = (unsigned long *) la;
+       for (i = 0; i < el.c->size / sizeof(long); i += 2) {
+           printk(KERN_CRIT " +%8lx %016lx %016lx\n",
+                  i*sizeof(long), ptr[i], ptr[i+1]);
        }
 }
 
index 78fa4177d8850ed9632c69c2dcea7582d8d9a5d0..bcfac1020825c4af65ba499dfcd3144e534257b4 100644 (file)
@@ -81,7 +81,7 @@ static inline void __memcpy_unaligned(unsigned long d, unsigned long s, long n)
 }
 
 /*
- * Hmm.. Strange. The __asm__ here is there to make gcc use a integer register
+ * Hmm.. Strange. The __asm__ here is there to make gcc use an integer register
  * for the load-store. I don't know why, but it would seem that using a floating
  * point register for the move seems to slow things down (very small difference,
  * though).
index bf619b1c148a184eb0de5ccb47439f112169658d..df5f8c2522d4d80b131b94a153f2c94a1ce9bcb1 100644 (file)
@@ -97,6 +97,11 @@ good_area:
  */
 bad_area:
        up(&mm->mmap_sem);
+       /* Did we have an exception handler installed? */
+       if (current->tss.ex.count == 1) {
+               current->tss.ex.count = 0;
+               __handle_exception(&current->tss.ex);
+       }
        if (user_mode(&regs)) {
                printk("%s: memory violation at pc=%08lx rp=%08lx (bad address = %08lx)\n",
                        tsk->comm, regs.pc, regs.r26, address);
index 362651117defebc9c7e76c6b794e888e645e83ad..a6457543639e126329872382f3a880e93908838e 100644 (file)
@@ -30,7 +30,7 @@ extern void show_net_buffers(void);
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
  * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving a inode
+ * for a process dying in kernel mode, possibly leaving an inode
  * unused etc..
  *
  * BAD_PAGETABLE is the accompanying page-table: it is initialized
index 020f29d0098a19a07733d0d3cf96bec577a21ad2..39f0d03bd571b0286d8e2d23a432438dc8cf6944 100644 (file)
  *     18(%esp) - %eax
  *     1C(%esp) - %ds
  *     20(%esp) - %es
- *      24(%esp) - %fs
- *     28(%esp) - %gs
- *     2C(%esp) - orig_eax
- *     30(%esp) - %eip
- *     34(%esp) - %cs
- *     38(%esp) - %eflags
- *     3C(%esp) - %oldesp
- *     40(%esp) - %oldss
+ *     24(%esp) - orig_eax
+ *     28(%esp) - %eip
+ *     2C(%esp) - %cs
+ *     30(%esp) - %eflags
+ *     34(%esp) - %oldesp
+ *     38(%esp) - %oldss
  *
  * "current" is in register %ebx during any slow entries.
  */
@@ -57,14 +55,12 @@ EBP         = 0x14
 EAX            = 0x18
 DS             = 0x1C
 ES             = 0x20
-FS             = 0x24
-GS             = 0x28
-ORIG_EAX       = 0x2C
-EIP            = 0x30
-CS             = 0x34
-EFLAGS         = 0x38
-OLDESP         = 0x3C
-OLDSS          = 0x40
+ORIG_EAX       = 0x24
+EIP            = 0x28
+CS             = 0x2C
+EFLAGS         = 0x30
+OLDESP         = 0x34
+OLDSS          = 0x38
 
 CF_MASK                = 0x00000001
 IF_MASK                = 0x00000200
@@ -88,8 +84,6 @@ ENOSYS = 38
 
 #define SAVE_ALL \
        cld; \
-       push %gs; \
-       push %fs; \
        push %es; \
        push %ds; \
        pushl %eax; \
@@ -204,8 +198,6 @@ ENOSYS = 38
        popl %eax; \
        pop %ds; \
        pop %es; \
-       pop %fs; \
-       pop %gs; \
        addl $4,%esp; \
        iret
 
@@ -228,8 +220,6 @@ ENOSYS = 38
        popl %eax; \
        pop %ds; \
        pop %es; \
-       pop %fs; \
-       pop %gs; \
        addl $4,%esp; \
        iret
 #endif
@@ -287,7 +277,6 @@ ENTRY(system_call)
        movl SYMBOL_NAME(sys_call_table)(,%eax,4),%eax
        testl %eax,%eax
        je ret_from_sys_call
-       andl $~CF_MASK,EFLAGS(%esp)     # clear carry - assume no errors
        testb $0x20,flags(%ebx)         # PF_TRACESYS
        jne tracesys
        call *%eax
@@ -296,51 +285,39 @@ ENTRY(system_call)
        .globl ret_from_sys_call
 ret_from_sys_call:
        cmpl $0,SYMBOL_NAME(intr_count)
-       jne 2f
+       jne 1f
 9:     movl SYMBOL_NAME(bh_mask),%eax
        andl SYMBOL_NAME(bh_active),%eax
        jne handle_bottom_half
-       movl EFLAGS(%esp),%eax          # check VM86 flag: CS/SS are
-       testl $(VM_MASK),%eax           # different then
-       jne 1f
-       cmpw $(KERNEL_CS),CS(%esp)      # was old code segment supervisor ?
-       je 2f
-1:     sti
-       orl $(IF_MASK),%eax             # these just try to make sure
-       andl $~NT_MASK,%eax             # the program doesn't do anything
-       movl %eax,EFLAGS(%esp)          # stupid
+       movl EFLAGS(%esp),%eax          # mix EFLAGS and CS
+       movb CS(%esp),%al
+       testl $(VM_MASK | 3),%eax       # return to VM86 mode or non-supervisor?
+       je 1f
        cmpl $0,SYMBOL_NAME(need_resched)
        jne reschedule
-       cmpl SYMBOL_NAME(task),%ebx     # task[0] cannot have signals
-       je 2f
-       movl blocked(%ebx),%ecx
-       movl %ecx,%eax                  # save blocked in %eax for signal handling
-       notl %ecx
-       andl signal(%ebx),%ecx
+       movl blocked(%ebx),%eax
+       movl %eax,%esi                  # save blocked in %esi for signal handling
+       notl %eax
+       andl signal(%ebx),%eax
        jne signal_return
-2:     RESTORE_ALL
+1:     RESTORE_ALL
        ALIGN
 signal_return:
-       movl %esp,%ecx
-       pushl %ecx
-       testl $(VM_MASK),EFLAGS(%ecx)
+       testl $(VM_MASK),EFLAGS(%esp)
+       pushl %esp
        jne v86_signal_return
-       pushl %eax
+       pushl %esi
        call SYMBOL_NAME(do_signal)
-       popl %eax
-       popl %eax
+       addl $8,%esp
        RESTORE_ALL
        ALIGN
 v86_signal_return:
-       pushl %eax
        call SYMBOL_NAME(save_v86_state)
-       popl %edx
        movl %eax,%esp
        pushl %eax
-       pushl %edx
+       pushl %esi
        call SYMBOL_NAME(do_signal)
-       popl %edx
-       popl %edx
+       addl $8,%esp
        RESTORE_ALL
        ALIGN
 tracesys:
@@ -357,8 +334,6 @@ ENTRY(divide_error)
        pushl $ SYMBOL_NAME(do_divide_error)
        ALIGN
 error_code:
-       push %fs
-       push %es
        push %ds
        pushl %eax
        xorl %eax,%eax
@@ -369,12 +344,12 @@ error_code:
        decl %eax                       # eax = -1
        pushl %ecx
        pushl %ebx
-       cld
        xorl %ecx,%ecx                  # zero ecx
+       cld
+       mov %es,%cx                     # get the lower order bits of es
        xchgl %eax, ORIG_EAX(%esp)      # orig_eax (get the error code. )
-       mov %gs,%bx                     # get the lower order bits of gs
        movl %esp,%edx
-       xchgl %ecx, GS(%esp)            # get the address and save gs.
+       xchgl %ecx, ES(%esp)            # get the address and save es.
        pushl %eax                      # push the error code
        pushl %edx
        movl $(KERNEL_DS),%edx
index c949f70cd9f3d27f8a551ab2482318a3ba391de9..bcefeef9b8acaad9dfceb456f0c3510007f87379 100644 (file)
@@ -75,8 +75,8 @@ unsigned int *stack;
  */
 asmlinkage int sys_iopl(long ebx,long ecx,long edx,
             long esi, long edi, long ebp, long eax, long ds,
-            long es, long fs, long gs, long orig_eax,
-            long eip,long cs,long eflags,long esp,long ss)
+            long es, long orig_eax, long eip, long cs,
+            long eflags, long esp, long ss)
 {
        unsigned int level = ebx;
 
index 44c7dff962ef7459466583dbcbd0a3ede8609a69..0903c624ecc82026a42eb04867e856d66b14db92 100644 (file)
@@ -187,7 +187,7 @@ static struct irqaction irq13 = { smp_message_irq, SA_INTERRUPT, 0, "IPI", NULL,
 #else
 
 /*
- * Note that on a 486, we don't want to do a SIGFPE on a irq13
+ * Note that on a 486, we don't want to do a SIGFPE on an irq13
  * as the irq is unreliable, and exception 16 works correctly
  * (ie as explained in the intel literature). On a 386, you
  * can't use exception 16 due to bad IBM design, so we have to
index bf0e6a2ef456ded93f76d2e9cf626326ec6bc579..c3d67a93603fb2bbe9732c15fb8eb756635fe5b8 100644 (file)
@@ -225,17 +225,16 @@ void hard_reset_now(void)
 void show_regs(struct pt_regs * regs)
 {
        printk("\n");
-       printk("EIP: %04x:[<%08lx>]",0xffff & regs->cs,regs->eip);
-       if (regs->cs & 3)
-               printk(" ESP: %04x:%08lx",0xffff & regs->ss,regs->esp);
+       printk("EIP: %04x:[<%08lx>]",0xffff & regs->xcs,regs->eip);
+       if (regs->xcs & 3)
+               printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
        printk(" EFLAGS: %08lx\n",regs->eflags);
        printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
                regs->eax,regs->ebx,regs->ecx,regs->edx);
        printk("ESI: %08lx EDI: %08lx EBP: %08lx",
                regs->esi, regs->edi, regs->ebp);
-       printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
-               0xffff & regs->ds,0xffff & regs->es,
-               0xffff & regs->fs,0xffff & regs->gs);
+       printk(" DS: %04x ES: %04x\n",
+               0xffff & regs->xds,0xffff & regs->xes);
 }
 
 /*
@@ -387,7 +386,23 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
        if (dump->start_stack < TASK_SIZE)
                dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
 
-       dump->regs = *regs;
+       dump->regs.ebx = regs->ebx;
+       dump->regs.ecx = regs->ecx;
+       dump->regs.edx = regs->edx;
+       dump->regs.esi = regs->esi;
+       dump->regs.edi = regs->edi;
+       dump->regs.ebp = regs->ebp;
+       dump->regs.eax = regs->eax;
+       dump->regs.ds = regs->xds;
+       dump->regs.es = regs->xes;
+       __asm__("mov %%fs,%0":"=r" (dump->regs.fs));
+       __asm__("mov %%gs,%0":"=r" (dump->regs.gs));
+       dump->regs.orig_eax = regs->orig_eax;
+       dump->regs.eip = regs->eip;
+       dump->regs.cs = regs->xcs;
+       dump->regs.eflags = regs->eflags;
+       dump->regs.esp = regs->esp;
+       dump->regs.ss = regs->xss;
 
        dump->u_fpvalid = dump_fpu (regs, &dump->i387);
 }
index f6461105f0ed552bb383acde83c420e96fabcbf3..20eaa2372add81269d9940f7589d62bc059287dd 100644 (file)
 #define TRAP_FLAG 0x100
 
 /*
- * this is the number to subtract from the top of the stack. To find
- * the local frame.
+ * Offset of eflags on child stack..
  */
-#define MAGICNUMBER 68
+#define EFL_OFFSET ((EFL-2)*4-sizeof(struct pt_regs))
 
 /* change a pid into a task struct. */
 static inline struct task_struct * get_task(int pid)
@@ -295,6 +294,71 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
        return 0;
 }
 
+static int putreg(struct task_struct *child,
+       unsigned long regno, unsigned long value)
+{
+       switch (regno >> 2) {
+               case ORIG_EAX:
+                       return -EIO;
+               case FS:
+                       if (value && (value & 3) != 3)
+                               return -EIO;
+                       child->tss.fs = value;
+                       return 0;
+               case GS:
+                       if (value && (value & 3) != 3)
+                               return -EIO;
+                       child->tss.gs = value;
+                       return 0;
+               case DS:
+               case ES:
+                       if (value && (value & 3) != 3)
+                               return -EIO;
+                       value &= 0xffff;
+                       break;
+               case SS:
+               case CS:
+                       if ((value & 3) != 3)
+                               return -EIO;
+                       value &= 0xffff;
+                       break;
+               case EFL:
+                       value &= FLAG_MASK;
+                       value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;
+       }
+       if (regno > GS*4)
+               regno -= 2*4;
+       put_stack_long(child, regno - sizeof(struct pt_regs), value);
+       return 0;
+}
+
+static unsigned long getreg(struct task_struct *child,
+       unsigned long regno)
+{
+       unsigned long retval = ~0UL;
+
+       switch (regno >> 2) {
+               case FS:
+                       retval = child->tss.fs;
+                       break;
+               case GS:
+                       retval = child->tss.gs;
+                       break;
+               case DS:
+               case ES:
+               case SS:
+               case CS:
+                       retval = 0xffff;
+                       /* fall through */
+               default:
+                       if (regno > GS*4)
+                               regno -= 2*4;
+                       regno = regno - sizeof(struct pt_regs);
+                       retval &= get_stack_long(child, regno);
+       }
+       return retval;
+}
+
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
        struct task_struct *child;
@@ -376,15 +440,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        if (res)
                                return res;
                        tmp = 0;  /* Default return condition */
-                       if(addr < 17*sizeof(long)) {
-                         addr = addr >> 2; /* temporary hack. */
-
-                         tmp = get_stack_long(child, sizeof(long)*addr - MAGICNUMBER);
-                         if (addr == DS || addr == ES ||
-                             addr == FS || addr == GS ||
-                             addr == CS || addr == SS)
-                           tmp &= 0xffff;
-                       };
+                       if(addr < 17*sizeof(long))
+                               tmp = getreg(child, addr);
                        if(addr >= (long) &dummy->u_debugreg[0] &&
                           addr <= (long) &dummy->u_debugreg[7]){
                                addr -= (long) &dummy->u_debugreg[0];
@@ -405,35 +462,14 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                            addr > sizeof(struct user) - 3)
                                return -EIO;
 
-                       addr = addr >> 2; /* temporary hack. */
-
-                       if (addr == ORIG_EAX)
-                               return -EIO;
-                       if (addr == DS || addr == ES ||
-                           addr == FS || addr == GS ||
-                           addr == CS || addr == SS) {
-                               data &= 0xffff;
-                               if (data && (data & 3) != 3)
-                                       return -EIO;
-                       }
-                       if (addr == EFL) {   /* flags. */
-                               data &= FLAG_MASK;
-                               data |= get_stack_long(child, EFL*sizeof(long)-MAGICNUMBER)  & ~FLAG_MASK;
-                       }
-                 /* Do not allow the user to set the debug register for kernel
-                    address space */
-                 if(addr < 17){
-                         if (put_stack_long(child, sizeof(long)*addr-MAGICNUMBER, data))
-                               return -EIO;
-                       return 0;
-                       };
+                       if (addr < 17*sizeof(long))
+                               return putreg(child, addr, data);
 
                  /* We need to be very careful here.  We implicitly
                     want to modify a portion of the task_struct, and we
                     have to be selective about what portions we allow someone
                     to modify. */
 
-                 addr = addr << 2;  /* Convert back again */
                  if(addr >= (long) &dummy->u_debugreg[0] &&
                     addr <= (long) &dummy->u_debugreg[7]){
 
@@ -469,8 +505,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        child->exit_code = data;
                        wake_up_process(child);
        /* make sure the single step bit is not set. */
-                       tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
-                       put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
+                       tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
+                       put_stack_long(child, EFL_OFFSET,tmp);
                        return 0;
                }
 
@@ -487,8 +523,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        wake_up_process(child);
                        child->exit_code = SIGKILL;
        /* make sure the single step bit is not set. */
-                       tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
-                       put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
+                       tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
+                       put_stack_long(child, EFL_OFFSET, tmp);
                        return 0;
                }
 
@@ -498,8 +534,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        if ((unsigned long) data > NSIG)
                                return -EIO;
                        child->flags &= ~PF_TRACESYS;
-                       tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) | TRAP_FLAG;
-                       put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
+                       tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
+                       put_stack_long(child, EFL_OFFSET, tmp);
                        wake_up_process(child);
                        child->exit_code = data;
        /* give it a chance to run. */
@@ -518,8 +554,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        child->p_pptr = child->p_opptr;
                        SET_LINKS(child);
                        /* make sure the single step bit is not set. */
-                       tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
-                       put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
+                       tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
+                       put_stack_long(child, EFL_OFFSET, tmp);
                        return 0;
                }
 
index 5fd7bebd3432c022519e8416483bc1651e4fc379..9b750a63145bb8368f468bf796b9b6e3fc68f066 100644 (file)
@@ -79,23 +79,31 @@ static void restore_i387(struct _fpstate *buf)
  */
 asmlinkage int sys_sigreturn(unsigned long __unused)
 {
-#define COPY(x) regs->x = context.x
-#define COPY_SEG(x) \
-if ((context.x & 0xfffc) && (context.x & 3) != 3) goto badframe; COPY(x);
-#define COPY_SEG_STRICT(x) \
-if (!(context.x & 0xfffc) || (context.x & 3) != 3) goto badframe; COPY(x);
-       struct sigcontext context;
+#define COPY(x) regs->x = context->x
+#define COPY_SEG(seg) \
+{ unsigned int tmp = context->seg; \
+if ((tmp & 0xfffc) && (tmp & 3) != 3) goto badframe; \
+regs->x##seg = tmp; }
+#define COPY_SEG_STRICT(seg) \
+{ unsigned int tmp = context->seg; \
+if ((tmp & 0xfffc) && (tmp & 3) != 3) goto badframe; \
+regs->x##seg = tmp; }
+#define GET_SEG(seg) \
+{ unsigned int tmp = context->seg; \
+if ((tmp & 0xfffc) && (tmp & 3) != 3) goto badframe; \
+__asm__("mov %w0,%%" #seg: :"r" (tmp)); }
+       struct sigcontext * context;
        struct pt_regs * regs;
 
        regs = (struct pt_regs *) &__unused;
-       if (verify_area(VERIFY_READ, (void *) regs->esp, sizeof(context)))
+       context = (struct sigcontext *) regs->esp;
+       if (verify_area(VERIFY_READ, context, sizeof(*context)))
                goto badframe;
-       memcpy_fromfs(&context,(void *) regs->esp, sizeof(context));
-       current->blocked = context.oldmask & _BLOCKABLE;
+       current->blocked = context->oldmask & _BLOCKABLE;
        COPY_SEG(ds);
        COPY_SEG(es);
-       COPY_SEG(fs);
-       COPY_SEG(gs);
+       GET_SEG(fs);
+       GET_SEG(gs);
        COPY_SEG_STRICT(ss);
        COPY_SEG_STRICT(cs);
        COPY(eip);
@@ -104,15 +112,15 @@ if (!(context.x & 0xfffc) || (context.x & 3) != 3) goto badframe; COPY(x);
        COPY(esp); COPY(ebp);
        COPY(edi); COPY(esi);
        regs->eflags &= ~0x40DD5;
-       regs->eflags |= context.eflags & 0x40DD5;
+       regs->eflags |= context->eflags & 0x40DD5;
        regs->orig_eax = -1;            /* disable syscall checks */
-       if (context.fpstate) {
-               struct _fpstate * buf = context.fpstate;
+       if (context->fpstate) {
+               struct _fpstate * buf = context->fpstate;
                if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
                        goto badframe;
                restore_i387(buf);
        }
-       return context.eax;
+       return context->eax;
 badframe:
        do_exit(SIGSEGV);
 }
@@ -164,7 +172,7 @@ static void setup_frame(struct sigaction * sa,
        unsigned long * frame;
 
        frame = (unsigned long *) regs->esp;
-       if (regs->ss != USER_DS && sa->sa_restorer)
+       if ((regs->xss & 0xffff) != USER_DS && sa->sa_restorer)
                frame = (unsigned long *) sa->sa_restorer;
        frame -= 64;
        if (verify_area(VERIFY_WRITE,frame,64*4))
@@ -178,10 +186,15 @@ static void setup_frame(struct sigaction * sa,
                put_user(current->exec_domain->signal_invmap[signr], frame+1);
        else
                put_user(signr, frame+1);
-       put_user(regs->gs, frame+2);
-       put_user(regs->fs, frame+3);
-       put_user(regs->es, frame+4);
-       put_user(regs->ds, frame+5);
+       {
+               unsigned int tmp = 0;
+#define PUT_SEG(seg, mem) \
+__asm__("mov %%" #seg",%w0":"=r" (tmp):"0" (tmp)); *(mem) = tmp;
+               PUT_SEG(gs, frame+2);
+               PUT_SEG(fs, frame+3);
+       }
+       put_user(regs->xes, frame+4);
+       put_user(regs->xds, frame+5);
        put_user(regs->edi, frame+6);
        put_user(regs->esi, frame+7);
        put_user(regs->ebp, frame+8);
@@ -193,10 +206,10 @@ static void setup_frame(struct sigaction * sa,
        put_user(current->tss.trap_no, frame+14);
        put_user(current->tss.error_code, frame+15);
        put_user(regs->eip, frame+16);
-       put_user(regs->cs, frame+17);
+       put_user(regs->xcs, frame+17);
        put_user(regs->eflags, frame+18);
        put_user(regs->esp, frame+19);
-       put_user(regs->ss, frame+20);
+       put_user(regs->xss, frame+20);
        put_user((unsigned long) save_i387((struct _fpstate *)(frame+32)),frame+21);
 /* non-iBCS2 extensions.. */
        put_user(oldmask, frame+22);
@@ -211,9 +224,15 @@ static void setup_frame(struct sigaction * sa,
        /* Set up registers for signal handler */
        regs->esp = (unsigned long) frame;
        regs->eip = (unsigned long) sa->sa_handler;
-       regs->cs = USER_CS; regs->ss = USER_DS;
-       regs->ds = USER_DS; regs->es = USER_DS;
-       regs->gs = USER_DS; regs->fs = USER_DS;
+       {
+               unsigned long seg = USER_DS;
+               __asm__("mov %w0,%%fs ; mov %w0,%%gs":"=r" (seg) :"0" (seg));
+               set_fs(seg);
+               regs->xds = seg;
+               regs->xes = seg;
+               regs->xss = seg;
+               regs->xcs = USER_CS;
+       }
        regs->eflags &= ~TF_MASK;
 }
 
@@ -273,7 +292,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
                 *      including volatiles for the inline function to get
                 *      current combined with this gets it confused.
                 */
-               struct task_struct *t=current;
+               struct task_struct *t=current;
                __asm__("bsf %3,%1\n\t"
                        "btrl %1,%0"
                        :"=m" (t->signal),"=r" (signr)
index 0368d81b40fa86c4253cf1d74fff04e3f11bb80d..b26996738cb32802d46d50bd7224294c6db0abd1 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/mman.h>
 
 #include <asm/segment.h>
+#include <asm/ipc.h>
 
 /*
  * sys_pipe() is the normal C calling standard for creating
index 858bb901f2112a5e10992fa2727546334d2134d0..7d4f875be5825fb71f264dd2c46b10765b0aceac 100644 (file)
@@ -102,22 +102,22 @@ int kstack_depth_to_print = 24;
 
        esp = (unsigned long) &regs->esp;
        ss = KERNEL_DS;
-       if ((regs->eflags & VM_MASK) || (3 & regs->cs) == 3)
+       if ((regs->eflags & VM_MASK) || (3 & regs->xcs) == 3)
                return;
-       if (regs->cs & 3) {
+       if (regs->xcs & 3) {
                esp = regs->esp;
-               ss = regs->ss;
+               ss = regs->xss & 0xffff;
        }
        console_verbose();
        printk("%s: %04lx\n", str, err & 0xffff);
        printk("CPU:    %d\n", smp_processor_id());
-       printk("EIP:    %04x:[<%08lx>]\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags);
+       printk("EIP:    %04x:[<%08lx>]\nEFLAGS: %08lx\n", 0xffff & regs->xcs,regs->eip,regs->eflags);
        printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
                regs->eax, regs->ebx, regs->ecx, regs->edx);
        printk("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
                regs->esi, regs->edi, regs->ebp, esp);
-       printk("ds: %04x   es: %04x   fs: %04x   gs: %04x   ss: %04x\n",
-               regs->ds, regs->es, regs->fs, regs->gs, ss);
+       printk("ds: %04x   es: %04x   ss: %04x\n",
+               regs->xds & 0xffff, regs->xes & 0xffff, ss);
        store_TR(i);
        if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page)
                printk("Corrupted stack page\n");
@@ -158,7 +158,7 @@ int kstack_depth_to_print = 24;
        }
        printk("\nCode: ");
        for(i=0;i<20;i++)
-               printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip)));
+               printk("%02x ",0xff & get_seg_byte(regs->xcs & 0xffff,(i+(char *)regs->eip)));
        printk("\n");
        do_exit(SIGSEGV);
 }
@@ -174,13 +174,9 @@ DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun
 DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current)
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present, current)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment, current)
+DO_ERROR(15, SIGSEGV, "reserved", reserved, current)
 DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current)
 
-asmlinkage void do_reserved(struct pt_regs * regs, long error_code)
-{
-       printk("Uhhuh.. Reserved trap code, whazzup? (%ld)\n", error_code);
-}
-
 asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
 {
        if (regs->eflags & VM_MASK) {
@@ -215,7 +211,7 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
        force_sig(SIGTRAP, current);
        current->tss.trap_no = 1;
        current->tss.error_code = error_code;
-       if ((regs->cs & 3) == 0) {
+       if ((regs->xcs & 3) == 0) {
                /* If this is a kernel mode trap, then reset db7 and allow us to continue */
                __asm__("movl %0,%%db7"
                        : /* no output */
@@ -330,7 +326,7 @@ void trap_init(void)
                return;
        }
        smptrap++;
-       if (strncmp((char*)phys_to_virt(0x0FFFD9), "EISA", 4) == 0)
+       if (readl(0x0FFFD9) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
                EISA_bus = 1;
        set_call_gate(&default_ldt,lcall7);
        set_trap_gate(0,&divide_error);
index 92d4f195d92f1100c9da053a2a859283ad668747..34cb13c2ae05278f224aef0d8accf003f11d5d56 100644 (file)
@@ -110,6 +110,7 @@ good_area:
  */
 bad_area:
        up(&mm->mmap_sem);
+       handle_exception(&tsk->tss.ex);
        if (error_code & 4) {
                tsk->tss.cr2 = address;
                tsk->tss.error_code = error_code;
index a2c54d98ced79d17e10bd898d1cc9c1aff4ac2d0..b52c0b2ee2f244a8b88a5893f895e6552f1348a7 100644 (file)
@@ -40,7 +40,7 @@ extern void show_net_buffers(void);
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
  * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving a inode
+ * for a process dying in kernel mode, possibly leaving an inode
  * unused etc..
  *
  * BAD_PAGETABLE is the accompanying page-table: it is initialized
index 4a7fe4500149447ab511775e8bf84c05e24afa05..a5c685ef3c8036c98ca84ac202ba246c4f00bf3a 100644 (file)
@@ -393,7 +393,7 @@ void atari_init_IRQ(void)
        if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) {
                /* Initialize the LM1992 Sound Controller to enable
                   the PSG sound.  This is misplaced here, it should
-                  be in a atasound_init(), that doesn't exist yet. */
+                  be in an atasound_init(), that doesn't exist yet. */
                atari_microwire_cmd(MW_LM1992_PSG_HIGH);
        }
        
index c08fddc0888ac882207c09837f5916de03d404de..f4f6c4c3e169df74b7c0e24edce85a91c4b25fdc 100644 (file)
@@ -31,7 +31,7 @@ extern void show_net_buffers(void);
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
  * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving a inode
+ * for a process dying in kernel mode, possibly leaving an inode
  * unused etc..
  *
  * BAD_PAGETABLE is the accompanying page-table: it is initialized
index 52feb57eb0bffc4580ccd7900e58cd21c4a43324..cabaae009c7917189f784e084515926ad3c95700 100644 (file)
@@ -34,7 +34,7 @@ extern char empty_zero_page[PAGE_SIZE];
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
  * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving a inode
+ * for a process dying in kernel mode, possibly leaving an inode
  * unused etc..
  *
  * BAD_PAGETABLE is the accompanying page-table: it is initialized
index 81b8ab947cd225bd4563de12599dfcd5cb48b8d4..f0fe249d69a884c2d074e0ef248556d6bf316db1 100644 (file)
@@ -35,7 +35,7 @@ extern void show_net_buffers(void);
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
  * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving a inode
+ * for a process dying in kernel mode, possibly leaving an inode
  * unused etc..
  *
  * BAD_PAGETABLE is the accompanying page-table: it is initialized
index cc9cffa79a01ee965fe8c5419fd64f2165662f9d..df3e24f3b8a2b8df51fd8d2a024740d3623abcd2 100644 (file)
@@ -32,7 +32,7 @@ struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
  * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving a inode
+ * for a process dying in kernel mode, possibly leaving an inode
  * unused etc..
  *
  * BAD_PAGETABLE is the accompanying page-table: it is initialized
index 5c5fdba8475d9577091b910f12eaaca8f81791b5..2f6933f73b02ce0d1884a51025dbc41b48f2ec73 100644 (file)
@@ -1391,7 +1391,12 @@ static int con_write(struct tty_struct * tty, int from_user,
        disable_bh(CONSOLE_BH);
        while (!tty->stopped && count) {
                enable_bh(CONSOLE_BH);
+               if (exception()) {
+                       n = -EFAULT;
+                       break;
+               }
                c = from_user ? get_user(buf) : *buf;
+               end_exception();
                buf++; n++; count--;
                disable_bh(CONSOLE_BH);
 
index 4d1358d942531093c3409c047ca63a0ed912f834..de67dfb6f8198d248193cd888af9f1ff15c5d2b7 100644 (file)
@@ -1,5 +1,5 @@
 static char rcsid[] =
-"$Revision: 1.36.3.7A $$Date: 1996/07/27 10:25:50 $";
+"$Revision: 1.36.3.9 $$Date: 1996/10/07 19:47:13 $";
 /*
  *  linux/drivers/char/cyclades.c
  *
@@ -24,6 +24,14 @@ static char rcsid[] =
  *   int cy_open(struct tty_struct *tty, struct file *filp);
  *
  * $Log: cyclades.c,v $
+ * Revision 1.36.3.9  1996/10/07 19:47:13  bentson
+ * add MOD_DEC_USE_COUNT in one return from cy_close (as
+ * noted by Jon Lewis <jlewis@INORGANIC5.FDT.NET>)
+ *
+ * Revision 1.36.3.8  1996/06/07 16:29:00  bentson
+ * starting minor number at zero; added missing verify_area
+ * as noted by Heiko Eissfeldt <heiko@colossus.escape.de>
+ *
  * Revision 1.36.3.7  1996/04/19 21:06:18  bentson
  * remove unneeded boot message & fix CLOCAL hardware flow
  * control (Miquel van Smoorenburg <miquels@Q.cistron.nl>);
@@ -2355,6 +2363,7 @@ cy_close(struct tty_struct * tty, struct file * filp)
 
     /* If the TTY is being hung up, nothing to do */
     if (tty_hung_up_p(filp)) {
+       MOD_DEC_USE_COUNT;
        restore_flags(flags);
        return;
     }
index fc756e58d5dd93d29f695e7e0a27b2dcf0d4a9a4..51fc128d8b93945de7198b79f35ab909836f62f6 100644 (file)
@@ -418,7 +418,7 @@ void fdc_set_write_precomp(int precomp)
        fdc_update_dsr();
 }
 
-/* Read back the Drive Specification regs on a i82078, so that we
+/* Read back the Drive Specification regs on an i82078, so that we
  * are able to restore them later
  */
 void fdc_save_drive_specs(void)
@@ -1011,11 +1011,11 @@ int fdc_probe(void)
                                                result = fdc_issue_command(cmd, 1, stat, 1);
                                                TRACE(2, "FDC is already locked");
                                        }
-                                       /* Test for a i82078 FDC */
+                                       /* Test for an i82078 FDC */
                                        cmd[0] = FDC_PARTID;
                                        result = fdc_issue_command(cmd, 1, stat, 1);
                                        if (result < 0 || stat[0] == 0x80) {
-                                               /* invalid command: not a i82078xx type FDC */
+                                               /* invalid command: not an i82078xx type FDC */
                                                result = no_fdc;
                                                for (i = 0; i < 4; ++i) {
                                                        outb_p(i, fdc.tdr);
@@ -1045,12 +1045,12 @@ int fdc_probe(void)
                                                        result = fdc_issue_command(cmd, 1, stat, 16);
                                                        if (result < 0) {
                                                                TRACE(1, "FDC_SAVE failed. Dunno why");
-                                                               /* guess we better claim the fdc to be a i82078 */
+                                                               /* guess we better claim the fdc to be an i82078 */
                                                                result = i82078;
                                                                TRACE(2, "Type i82078 FDC (i suppose) found");
                                                        } else {
                                                                if ((stat[0] & FDC_SEL3V_BIT)) {
-                                                                       /* fdc running off 5Volts; Pray that it's a i82078-1
+                                                                       /* fdc running off 5Volts; Pray that it's an i82078-1
                                                                         */
                                                                        TRACE(2, "Type i82078-1 or 5Volt i82078SL FDC found");
                                                                        TRACE(2, "Treating it as an i82078-1 (2Mbps) FDC");
index 0737c500a9e2b163f80b6063c7b7b4675dc891f5..3fee4013d615395b8a255b77f109607ea5c30f9b 100644 (file)
@@ -1062,7 +1062,7 @@ static void do_slock(unsigned char value, char up_flag)
 
 /*
  * send_data sends a character to the keyboard and waits
- * for a acknowledge, possibly retrying if asked to. Returns
+ * for an acknowledge, possibly retrying if asked to. Returns
  * the success status.
  */
 static int send_data(unsigned char data)
index 23f1e1524c39ef6ab23693cc2b54244cb8b19a72..181a6b21da3cfd4afa88185b0c9b36fb6b54670c 100644 (file)
@@ -809,6 +809,11 @@ do_it_again:
        }
 
        add_wait_queue(&tty->read_wait, &wait);
+
+       if (exception())
+               goto user_fault;
+
+       disable_bh(TQUEUE_BH);
        while (1) {
                /* First test for status change. */
                if (tty->packet && tty->link->ctrl_status) {
@@ -844,7 +849,9 @@ do_it_again:
                                retval = -ERESTARTSYS;
                                break;
                        }
+                       enable_bh(TQUEUE_BH);
                        schedule();
+                       disable_bh(TQUEUE_BH);
                        continue;
                }
                current->state = TASK_RUNNING;
@@ -859,9 +866,7 @@ do_it_again:
                        while (1) {
                                int eol;
 
-                               disable_bh(TQUEUE_BH);
                                if (!tty->read_cnt) {
-                                       enable_bh(TQUEUE_BH);
                                        break;
                                }
                                eol = clear_bit(tty->read_tail,
@@ -870,7 +875,6 @@ do_it_again:
                                tty->read_tail = ((tty->read_tail+1) &
                                                  (N_TTY_BUF_SIZE-1));
                                tty->read_cnt--;
-                               enable_bh(TQUEUE_BH);
                                if (!eol) {
                                        put_user(c, b++);
                                        if (--nr)
@@ -887,10 +891,8 @@ do_it_again:
                                break;
                        }
                } else {
-                       disable_bh(TQUEUE_BH);
                        copy_from_read_buf(tty, &b, &nr);
                        copy_from_read_buf(tty, &b, &nr);
-                       enable_bh(TQUEUE_BH);
                }
 
                /* If there is enough space in the read buffer now, let the
@@ -905,6 +907,8 @@ do_it_again:
                if (time)
                        current->timeout = time + jiffies;
        }
+       enable_bh(TQUEUE_BH);
+       end_exception();
        remove_wait_queue(&tty->read_wait, &wait);
 
        if (!waitqueue_active(&tty->read_wait))
@@ -919,7 +923,13 @@ do_it_again:
                 goto do_it_again;
        if (!size && !retval)
                clear_bit(TTY_PUSH, &tty->flags);
-        return (size ? size : retval);
+       return (size ? size : retval);
+
+user_fault:
+       enable_bh(TQUEUE_BH);
+       remove_wait_queue(&tty->read_wait, &wait);
+       current->timeout = 0;
+       return -EFAULT;
 }
 
 static int write_chan(struct tty_struct * tty, struct file * file,
@@ -949,12 +959,17 @@ static int write_chan(struct tty_struct * tty, struct file * file,
                        break;
                }
                if (O_OPOST(tty)) {
+                       if (exception()) {
+                               retval = -EFAULT;
+                               break;
+                       }
                        while (nr > 0) {
                                c = get_user(b);
                                if (opost(c, tty) < 0)
                                        break;
                                b++; nr--;
                        }
+                       end_exception();
                        if (tty->driver.flush_chars)
                                tty->driver.flush_chars(tty);
                } else {
index b839d1cddff9ac49937d9edd1b5d91bbb10d3c69..b2c5f9abb0bfcd796942a53f0ae6e25abb9d1f1e 100644 (file)
@@ -1120,10 +1120,12 @@ int pcxe_init(void)
        pcxe_termios = kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL);
        if (!pcxe_termios)
                panic("Unable to allocate pcxe_termios struct");
+       memset(pcxe_termios,0,sizeof(struct termios *)*nbdevs);
 
        pcxe_termios_locked = kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL);
        if (!pcxe_termios_locked)
                panic("Unable to allocate pcxe_termios_locked struct");
+       memset(pcxe_termios_locked,0,sizeof(struct termios *)*nbdevs);
 
        init_bh(DIGI_BH,do_pcxe_bh);
        enable_bh(DIGI_BH);
index 53968b33c54464536c0ec44d9c66a4b5e00b7349..24fe88336be21ecaa8e3808b5d511f966e48adb7 100644 (file)
@@ -123,6 +123,10 @@ static int pty_write(struct tty_struct * tty, int from_user,
                down(&tmp_buf_sem);
                temp_buffer = tmp_buf +
                        ((tty->driver.subtype-1) * PTY_BUF_SIZE);
+               if (exception()) {
+                       up(&tmp_buf_sem);
+                       return -EFAULT;
+               }
                while (count > 0) {
                        n = MIN(count, PTY_BUF_SIZE);
                        memcpy_fromfs(temp_buffer, buf, n);
@@ -134,6 +138,7 @@ static int pty_write(struct tty_struct * tty, int from_user,
                        buf += n;  c+= n;
                        count -= n;
                }
+               end_exception();
                up(&tmp_buf_sem);
        } else {
                c = MIN(count, to->ldisc.receive_room(to));
index 7b6bad9203fea3923cf75b4b2ca844b7201eca9c..7d9a864ad1ec3cebdcb1375fe86837008c4c8c84 100644 (file)
@@ -11,7 +11,7 @@
  * Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
  *
  * Modified by Theodore Ts'o, 9/14/92, to dynamically allocate the
- * tty_struct and tty_queue structures.  Previously there was a array
+ * tty_struct and tty_queue structures.  Previously there was an array
  * of 256 tty_struct's which was statically allocated, and the
  * tty_queue structures were allocated at boot time.  Both are now
  * dynamically allocated only when the tty is open.
@@ -1441,16 +1441,22 @@ static int tty_ioctl(struct inode * inode, struct file * file,
                                             sizeof (struct winsize));
                        if (retval)
                                return retval;
+                       if (exception())
+                               return -EFAULT;
                        memcpy_tofs((struct winsize *) arg, &tty->winsize,
                                    sizeof (struct winsize));
+                       end_exception();
                        return 0;
                case TIOCSWINSZ:
                        retval = verify_area(VERIFY_READ, (void *) arg,
                                             sizeof (struct winsize));
                        if (retval)
-                               return retval;                  
+                               return retval;
+                       if (exception())
+                               return -EFAULT;
                        memcpy_fromfs(&tmp_ws, (struct winsize *) arg,
                                      sizeof (struct winsize));
+                       end_exception();
                        if (memcmp(&tmp_ws, &tty->winsize,
                                   sizeof(struct winsize))) {
                                if (tty->pgrp > 0)
@@ -1477,7 +1483,10 @@ static int tty_ioctl(struct inode * inode, struct file * file,
                        retval = verify_area(VERIFY_READ, (void *) arg, sizeof(int));
                        if (retval)
                                return retval;
+                       if (exception())
+                               return -EFAULT;
                        arg = get_user((unsigned int *) arg);
+                       end_exception();
                        if (arg)
                                file->f_flags |= O_NONBLOCK;
                        else
@@ -1539,7 +1548,10 @@ static int tty_ioctl(struct inode * inode, struct file * file,
                                             sizeof (pid_t));
                        if (retval)
                                return retval;
+                       if (exception())
+                               return -EFAULT;
                        put_user(real_tty->pgrp, (pid_t *) arg);
+                       end_exception();
                        return 0;
                case TIOCSPGRP:
                        retval = tty_check_change(real_tty);
@@ -1563,7 +1575,10 @@ static int tty_ioctl(struct inode * inode, struct file * file,
                                             sizeof (int));
                        if (retval)
                                return retval;
+                       if (exception())
+                               return -EFAULT;
                        put_user(tty->ldisc.num, (int *) arg);
+                       end_exception();
                        return 0;
                case TIOCSETD:
                        retval = tty_check_change(tty);
@@ -1573,7 +1588,10 @@ static int tty_ioctl(struct inode * inode, struct file * file,
                                             sizeof (int));
                        if (retval)
                                return retval;
+                       if (exception())
+                               return -EFAULT;
                        arg = get_user((int *) arg);
+                       end_exception();
                        return tty_set_ldisc(tty, arg);
                case TIOCLINUX:
                        if (tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
@@ -1583,7 +1601,11 @@ static int tty_ioctl(struct inode * inode, struct file * file,
                        retval = verify_area(VERIFY_READ, (void *) arg, 1);
                        if (retval)
                                return retval;
-                       switch (retval = get_user((char *)arg))
+                       if (exception())
+                               return -EFAULT;
+                       retval = get_user((char *)arg);
+                       end_exception();
+                       switch (retval)
                        {
                                case 0:
                                case 8:
index 0fe5305efe1c43f2bf32868d09d63a71f8ccf657..5ac4bf1c18129ec0593026373efa0432e54b41d4 100644 (file)
@@ -409,10 +409,10 @@ set_get_font(char * arg, int set, int ch512)
                arg += cmapsz;
                if (set)
                  for (i=0; i<cmapsz ; i++)
-                   *(charmap+i) = get_user(arg+i);
+                   scr_writeb(get_user(arg+i), charmap+i);
                else
                  for (i=0; i<cmapsz ; i++)
-                   put_user(*(charmap+i), arg+i);
+                   put_user(scr_readb(charmap+i), arg+i);
              }
          }
        
index 78a1068f4f9a96d07cc72d054b82954d86bfeea1..73efdfd5945e2a18dd45d732aa8c893aa9c9815b 100644 (file)
@@ -131,7 +131,7 @@ static void set_multicast_list(struct device *dev);
    (detachable devices only).
    */
 #ifdef HAVE_DEVLIST
-/* Support for a alternate probe manager, which will eliminate the
+/* Support for an alternate probe manager, which will eliminate the
    boilerplate below. */
 struct netdev_entry at1700_drv =
 {"at1700", at1700_probe1, AT1700_IO_EXTENT, at1700_probe_list};
index 582b7cb5ba4e21e22c0eb2bc11b3e4009b9c5990..c4b07413a0ba5755733b289807f906fdd09f03a0 100644 (file)
@@ -300,7 +300,7 @@ buffer (transmit-buffer = 32K - receive-buffer).
    (detachable devices only).
    */
 #ifdef HAVE_DEVLIST
-/* Support for a alternate probe manager, which will eliminate the
+/* Support for an alternate probe manager, which will eliminate the
    boilerplate below. */
 struct netdev_entry netcard_drv =
 {"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist};
index ee484c387e50b51ac00f9cb1174f8ededb0d8055..b079be80316d024d19fc08e67e97df19384cb0c4 100644 (file)
@@ -398,7 +398,7 @@ static int eth16i_probe1(struct device *dev, short ioaddr)
     return -ENODEV;
   
   /* 
-     Now it seems that we have found a ethernet chip in this particular
+     Now it seems that we have found an ethernet chip in this particular
      ioaddr. The MB86985 chip has this feature, that when you read a 
      certain register it will increase its io base address to next
      configurable slot. Now when we have found the chip, first thing is
index 121dd0bb8cc5a42a82ac9f4c9fa01e1b9f9ff653..d9e69da69b3c824b256b1a15c8c5a9d8e9f5d4a7 100644 (file)
@@ -124,7 +124,7 @@ static void set_multicast_list(struct device *dev);
    (detachable devices only).
    */
 #ifdef HAVE_DEVLIST
-/* Support for a alternate probe manager, which will eliminate the
+/* Support for an alternate probe manager, which will eliminate the
    boilerplate below. */
 struct netdev_entry fmv18x_drv =
 {"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list};
index b2074435822b6c789accf463b848b585aa86719f..7441fd7ed7f35f0b80fa4eb38696c14175d8d15b 100644 (file)
@@ -115,7 +115,7 @@ static void hpp_io_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
 /*     Probe a list of addresses for an HP LAN+ adaptor.
        This routine is almost boilerplate. */
 #ifdef HAVE_DEVLIST
-/* Support for a alternate probe manager, which will eliminate the
+/* Support for an alternate probe manager, which will eliminate the
    boilerplate below. */
 struct netdev_entry hpplus_drv =
 {"hpplus", hpp_probe1, HP_IO_EXTENT, hpplus_portlist};
index 21997a8338ca20219b942a6f9317fa4e0d4610a7..acd8ee1379a9d69113f3423a81085654c49b71d9 100644 (file)
@@ -1030,7 +1030,7 @@ static int hp100_down_vg_link( struct device *dev )
   if ( i <= 0 )                                /* not signal - not logout */
     return 0;
   hp100_andw( ~HP100_LINK_CMD, LAN_CFG_VG );
-  time = jiffies + 10; 
+  time = jiffies + 10*HZ/100
   while ( time > jiffies )
     if ( !( hp100_inw( LAN_CFG_VG ) & ( HP100_LINK_UP_ST | 
                                         HP100_LINK_CABLE_ST | 
index 73cba43f20d97f291051d913408c6514846dd4fe..1b51ecf3b7e4f703b307b70daddbfeaff2c82f1c 100644 (file)
@@ -1488,7 +1488,7 @@ void tr_readlog(struct device *dev) {
 
 /* tok_get_stats():  Basically a scaffold routine which will return
    the address of the tr_statistics structure associated with
-   this device -- the tr.... structure is a ethnet look-alike
+   this device -- the tr.... structure is an ethnet look-alike
    so at least for this iteration may suffice.   */
 
 static struct enet_statistics * tok_get_stats(struct device *dev) {
index 2e8fd20078609ba16a5a938491d53175a51fbc85..82e3ec09fb7a1db75164d928a2c6c499535163db 100644 (file)
@@ -55,7 +55,7 @@ int lance32_debug = 1;
  *         only tested on Alpha Noname Board
  * v0.02:  changed IRQ handling for new interrupt scheme (dev_id)
  *         tested on a ASUS SP3G
- * v0.10:  fixed a odd problem with the 79C794 in a Compaq Deskpro XL
+ * v0.10:  fixed an odd problem with the 79C794 in a Compaq Deskpro XL
  *         looks like the 974 doesn't like stopping and restarting in a
  *         short period of time; now we do a reinit of the lance; the
  *         bug was triggered by doing ifconfig eth0 <ip> broadcast <addr>
index 6ac4c2aa6dcef7a0f1bdd9048540d2145ef85a47..76ee26a4f9aea4e55addaa62bd46a754a4b16f37 100644 (file)
@@ -299,14 +299,21 @@ static int ne_probe1(struct device *dev, int ioaddr)
            wordlength = 1;
     }
 
+    /* At this point, wordlength *only* tells us if the SA_prom is doubled
+       up or not because some broken PCI cards don't respect the byte-wide
+       request in program_seq above, and hence don't have doubled up values. 
+       These broken cards would otherwise be detected as an ne1000.  */
+
+    if (wordlength == 2)
+       for (i = 0; i < 16; i++)
+               SA_prom[i] = SA_prom[i+i];
+    
+    if (pci_irq_line)
+       wordlength = 2;         /* Catch broken cards mentioned above. */
+
     if (wordlength == 2) {
        /* We must set the 8390 for word mode. */
        outb_p(0x49, ioaddr + EN0_DCFG);
-       /* We used to reset the ethercard here, but it doesn't seem
-          to be necessary. */
-       /* Un-double the SA_prom values. */
-       for (i = 0; i < 16; i++)
-           SA_prom[i] = SA_prom[i+i];
        start_page = NESM_START_PG;
        stop_page = NESM_STOP_PG;
     } else {
index eaddbf28fb3c85ba5528f3ce6ea44012857bccd0..37e2fe0167b4e7314789685e2d4f9035510af19c 100644 (file)
@@ -1,6 +1,6 @@
 /* am7990 (lance) definitions
  * 
- * This is a extension to the Linux operating system, and is covered by
+ * This is an extension to the Linux operating system, and is covered by
  * same Gnu Public License that covers that work.
  * 
  * Michael Hipp
index c4d48521d267a3d35b1ff0cb2fd15f0331b0c6d0..ce2f978b9173badba8fc70ad78ed941d04ccb463 100644 (file)
@@ -101,7 +101,7 @@ inline void wait_for_buffer(struct device *dev);
    (detachable devices only).
    */
 #ifdef HAVE_DEVLIST
-/* Support for a alternate probe manager, which will eliminate the
+/* Support for an alternate probe manager, which will eliminate the
    boilerplate below. */
 struct netdev_entry seeq8005_drv =
 {"seeq8005", seeq8005_probe1, SEEQ8005_IO_EXTENT, seeq8005_portlist};
index 696acafefc3022fcb7f67f2ca7ff1bb19dc70312..161370f25caf271152f3512fbf5b371465a33472 100644 (file)
@@ -390,7 +390,7 @@ static const char *rcsid = "$Id: sk_g16.c,v 1.1 1994/06/30 16:25:15 root Exp $";
  *
  * PROM: The PROM obtains the ETHERNET-MAC-Address. It is realised as a
  *       8-Bit PROM, this means only the 16 even addresses are used of the
- *       32 Byte Address region. Access to a odd address results in invalid
+ *       32 Byte Address region. Access to an odd address results in invalid
  *       data.
  * 
  * LANCE I/O Reg: The I/O Reg is build of 4 single Registers, Low-Byte Write,
index bfb9cf746dcee24e6ceb9da25320f3b7232bb2eb..b6f1919826e6ad9498ab15840e5bb07142307b7f 100644 (file)
@@ -120,7 +120,7 @@ extern void chipset_init(struct device *dev, int startp);
  */
 #ifdef HAVE_DEVLIST
 /*
- * Support for a alternate probe manager,
+ * Support for an alternate probe manager,
  * which will eliminate the boilerplate below.
  */
 struct netdev_entry netcard_drv =
index e3d648d014b266abdfc471c23aa30a4e884c4e40..dac1b98313245c98c0592af3099c1386ebd7d972 100644 (file)
@@ -1454,7 +1454,7 @@ static void smc_rcv(struct device *dev)
        PRINTK2(("RCV: STATUS %4x LENGTH %4x\n", status, packet_length ));
        /* 
         . the packet length contains 3 extra words : 
-        . status, length, and a extra word with an odd byte .
+        . status, length, and an extra word with an odd byte .
        */
        packet_length -= 6; 
        
index 15153c18c2e99b36ac8311f05efb2346bcf08925..025bd7e5b13a1f1dfb95adfca8635f4fd4246cd4 100644 (file)
  *             in the host code.
  *
  *     On the NCR53c710, interrupts are generated as on the NCR53c8x0,
- *             only the lack of a interrupt-on-the-fly facility complicates
+ *             only the lack of an interrupt-on-the-fly facility complicates
  *             things.   Also, SCSI ID registers and commands are 
  *             bit fielded rather than binary encoded.
  *             
@@ -248,7 +248,7 @@ typedef unsigned int  u32;
 #include <linux/proc_fs.h>
 #include <linux/string.h>
 #include <linux/malloc.h>
-#include <linuxv/malloc.h>
+#include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/time.h>
index 3c4bda01a0c86f1cf849af0d6e5a0876d91851ed..5a5a5a20d9ec5d78530398a4307702e3570d3822 100644 (file)
 /*
  * Using this file :
  * This file a skeleton Linux SCSI driver for the NCR 5380 series
- * of chips.  To use it, you write a architecture specific functions 
+ * of chips.  To use it, you write an architecture specific functions 
  * and macros and include this file in your driver.
  *
  * These macros control options : 
index c7f037b8d36211e8abce7dbe979325ce8c10e174..6c9b7e072a080451332b3093c6100c71c8b4b472 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: advansys.c,v 1.20 1996/09/26 00:47:54 bobf Exp bobf $ */
+/* $Id: advansys.c,v 1.24 1996/10/05 00:58:14 bobf Exp bobf $ */
 /*
  * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
  * 
  */
 
 /*
- * The driver has been run with the v1.2.13, v1.3.57, and v2.0.21 kernels.
+ * The driver has been used in the following kernels:
+ * v1.2.13, v1.3.57, v2.0.21, v2.1.0
  */
-#define ASC_VERSION "1.7"    /* AdvanSys Driver Version */
+#define ASC_VERSION "1.8"    /* AdvanSys Driver Version */
 
 /*
 
          5. Remove the request timeout issue form the driver issues list.
          6. Miscellaneous documentation additions and changes.
 
+     1.8 (10/4/96):
+         1. Make changes to handle the new v2.1.0 kernel memory mapping
+            in which a kernel virtual address may not be equivalent to its
+            bus or DMA memory address.
+         2. Change abort and reset request handling to make it yet even
+            more robust.
+         3. Try to mitigate request starvation by sending ordered requests
+            to heavily loaded, tag queuing enabled devices.
+         4. Maintain statistics on request response time.
+         5. Add request response time statistics and other information to
+            the adapter /proc file: /proc/scsi/advansys[0...].
+
   I. Known Problems or Issues
 
-         None
+         1. If a large "Device Queue Size" is set in the adapter
+            BIOS and a device supports the queue depth and the device
+            is heavily loaded, requests may be sent to the device
+            faster than they can be executed causing the requests to
+            queue up in the low-level driver on a wait queue. This may
+            lead to time-out abort requests by the mid-level driver.
+            
+            The short term solution is to set a smaller "Device Queue
+            Size" in the adapter BIOS. Response times can be monitored
+            per device by reading the /proc/scsi/advansys/[0...] file.
+            
+            The long term solution is to modify the mid-level driver to
+            institute a flow control mechanism between the two levels.
+            The low-level driver would notify the mid-level driver when
+            a device is falling behind on executing requests. This would
+            prevent the mid-level driver from sending more requests until
+            the low-level driver has notified it that the device has caught
+            up on request execution.
 
   J. Credits
 
@@ -2137,15 +2167,52 @@ int                 AscRestoreNewMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SA
 #define DRIVER_BYTE(byte)      ((byte) << 24)
 
 /*
- * REQ and REQP are the generic name for a SCSI request block and pointer.
- * REQPTID(reqp) returns reqp's target id.
- * REQPNEXT(reqp) returns reqp's next pointer.
- * REQPNEXTP(reqp) returns a pointer to reqp's next pointer.
+ * The following definitions and macros are OS independent interfaces to
+ * the queue functions:
+ *  REQ - SCSI request structure
+ *  REQP - pointer to SCSI request structure
+ *  REQPTID(reqp) - reqp's target id
+ *  REQPNEXT(reqp) - reqp's next pointer
+ *  REQPNEXTP(reqp) - pointer to reqp's next pointer
+ *  REQPTIME(reqp) - reqp's time stamp value
+ *  REQTIMESTAMP() - system time stamp value
  */
 typedef Scsi_Cmnd                      REQ, *REQP;
 #define REQPNEXT(reqp)         ((REQP) ((reqp)->host_scribble))
 #define REQPNEXTP(reqp)                ((REQP *) &((reqp)->host_scribble))
 #define REQPTID(reqp)          ((reqp)->target)
+#define REQPTIME(reqp)         ((reqp)->SCp.this_residual)
+#define REQTIMESTAMP()         (jiffies)
+
+#define REQTIMESTAT(function, ascq, reqp, tid) \
+{ \
+       /*
+        * If the request time stamp is less than the system time stamp, then \
+        * maybe the system time stamp wrapped. Set the request time to zero.\
+        */ \
+       if (REQPTIME(reqp) <= REQTIMESTAMP()) { \
+               REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \
+       } else { \
+               /* Indicate an error occurred with the assertion. */ \
+               ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \
+               REQPTIME(reqp) = 0; \
+       } \
+       /* Handle first minimum time case without external initialization. */ \
+       if (((ascq)->q_tot_cnt[tid] == 1) ||  \
+               (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \
+                       (ascq)->q_min_tim[tid] = REQPTIME(reqp); \
+                       ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \
+                               (function), (tid), (ascq)->q_min_tim[tid]); \
+               } \
+       if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \
+               (ascq)->q_max_tim[tid] = REQPTIME(reqp); \
+               ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \
+                       (function), tid, (ascq)->q_max_tim[tid]); \
+       } \
+       (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \
+       /* Reset the time stamp field. */ \
+       REQPTIME(reqp) = 0; \
+}
 
 /* asc_enqueue() flags */
 #define ASC_FRONT              1
@@ -2287,8 +2354,7 @@ typedef Scsi_Cmnd                 REQ, *REQP;
 #define        ASC_DBG3(lvl, s, a1, a2, a3)
 #define        ASC_DBG4(lvl, s, a1, a2, a3, a4)
 #define        ASC_DBG_PRT_SCSI_HOST(lvl, s)
-#define        ASC_DBG_PRT_DVC_VAR(lvl, v)
-#define        ASC_DBG_PRT_DVC_CFG(lvl, c)
+#define        ASC_DBG_PRT_SCSI_CMND(lvl, s)
 #define        ASC_DBG_PRT_SCSI_Q(lvl, scsiqp)
 #define        ASC_DBG_PRT_QDONE_INFO(lvl, qdone)
 #define        ASC_DBG_PRT_HEX(lvl, name, start, length)
@@ -2348,17 +2414,10 @@ typedef Scsi_Cmnd                       REQ, *REQP;
                } \
        }
 
-#define        ASC_DBG_PRT_DVC_VAR(lvl, v) \
-       { \
-               if (asc_dbglvl >= (lvl)) { \
-                       asc_prt_dvc_var(v); \
-               } \
-       }
-
-#define        ASC_DBG_PRT_DVC_CFG(lvl, c) \
+#define        ASC_DBG_PRT_SCSI_CMND(lvl, s) \
        { \
                if (asc_dbglvl >= (lvl)) { \
-                       asc_prt_dvc_cfg(c); \
+                       asc_prt_scsi_cmnd(s); \
                } \
        }
 
@@ -2447,6 +2506,10 @@ typedef struct asc_queue {
 #ifdef ADVANSYS_STATS
        short                                   q_cur_cnt[ASC_MAX_TID+1]; /* current queue count */
        short                                   q_max_cnt[ASC_MAX_TID+1]; /* maximum queue count */
+       ulong                                   q_tot_cnt[ASC_MAX_TID+1]; /* total enqueue count */
+       ulong                                   q_tot_tim[ASC_MAX_TID+1]; /* total time queued */
+       ushort                                  q_max_tim[ASC_MAX_TID+1]; /* maximum time queued */
+       ushort                                  q_min_tim[ASC_MAX_TID+1]; /* minimum time queued */
 #endif /* ADVANSYS_STATS */
 } asc_queue_t;
 
@@ -2464,10 +2527,11 @@ typedef struct asc_board {
        ASC_DVC_CFG                      asc_dvc_cfg;           /* Device configuration */
        asc_queue_t                      active;                        /* Active command queue */
        asc_queue_t                      waiting;                       /* Waiting command queue */
+       asc_queue_t                      done;                          /* Done command queue */
        ASC_SCSI_BIT_ID_TYPE init_tidmask;              /* Target initialized mask */
        ASCEEP_CONFIG            eep_config;            /* EEPROM configuration */
-       asc_queue_t                      scsi_done_q;           /* Completion command queue */
-       ulong                            reset_jiffies;         /* Saved time of last reset */
+       ulong                            last_reset;            /* Saved time of last reset */
+       ushort                           rcnt[ASC_MAX_TID+1]; /* Starvation Request Count */
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
        /* /proc/scsi/advansys/[0...] */
        char                             *prtbuf;                       /* Statistics Print Buffer */
@@ -2646,6 +2710,7 @@ STATIC int                        asc_prt_board_stats(struct Scsi_Host *, char *, int);
 #endif /* ADVANSYS_STATS */
 #ifdef ADVANSYS_DEBUG
 STATIC void            asc_prt_scsi_host(struct Scsi_Host *);
+STATIC void            asc_prt_scsi_cmnd(Scsi_Cmnd *);
 STATIC void            asc_prt_dvc_cfg(ASC_DVC_CFG *);
 STATIC void            asc_prt_dvc_var(ASC_DVC_VAR *);
 STATIC void            asc_prt_scsi_q(ASC_SCSI_Q *);
@@ -3512,7 +3577,9 @@ advansys_info(struct Scsi_Host *shp)
  * Polled-I/O. Apparently host drivers shouldn't return until
  * command is finished.
  *
- * XXX - Can host drivers block here instead of spinning on command status?
+ * Note: This is an old interface that is no longer used by the SCSI
+ * mid-level driver. The new interface, advansys_queuecommand(),
+ * currently handles all requests.
  */
 int
 advansys_command(Scsi_Cmnd *scp)
@@ -3521,6 +3588,10 @@ advansys_command(Scsi_Cmnd *scp)
        ASC_STATS(scp->host, command);
        scp->SCp.Status = 0; /* Set to a known state */
        advansys_queuecommand(scp, advansys_command_done);
+       /*
+        * XXX - Can host drivers block here instead of spinning on
+        * command status?
+        */
        while (scp->SCp.Status == 0) {
                continue;
        }
@@ -3571,11 +3642,11 @@ advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
                }
 
                /*
-                * Add blocked requests to the board's 'scsi_done_q'. The queued
+                * Add blocked requests to the board's 'done' queue. The queued
                 * requests will be completed at the end of the abort or reset
                 * handling.
                 */
-               asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK);
+               asc_enqueue(&boardp->done, scp, ASC_BACK);
                restore_flags(flags);
                return 0;
        }
@@ -3601,7 +3672,7 @@ advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
         * target waiting list.
         * 
         * If an error occurred, the request will have been placed on the
-        * board's 'scsi_done_q' and must be completed before returning.
+        * board's 'done' queue and must be completed before returning.
         */
        scp->scsi_done = done;
        switch (asc_execute_scsi_cmnd(scp)) {
@@ -3612,7 +3683,7 @@ advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
                break;
        case ASC_ERROR:
        default:
-               done_scp = asc_dequeue_list(&boardp->scsi_done_q, NULL, ASC_TID_ALL);
+               done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
                /* Interrupts could be enabled here. */
                asc_scsi_done_list(done_scp);
                break;
@@ -3634,42 +3705,63 @@ advansys_abort(Scsi_Cmnd *scp)
        asc_board_t                     *boardp;
        ASC_DVC_VAR                     *asc_dvc_varp;
        int                                     flags;
-       int                                     status = ASC_FALSE;
-       int                                     abort_do_done = ASC_FALSE;
-       Scsi_Cmnd                       *done_scp;
-       int                                     ret = ASC_ERROR;
-
-       ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
+       int                                     do_scsi_done;
+       int                                     scp_found;
+       Scsi_Cmnd                       *done_scp = NULL;
+       int                                     ret;
 
        /* Save current flags and disable interrupts. */
        save_flags(flags);
        cli();
 
+       ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
+
 #ifdef ADVANSYS_STATS
        if (scp->host != NULL) {
                ASC_STATS(scp->host, abort);
        }       
 #endif /* ADVANSYS_STATS */
 
+#ifdef ADVVANSYS_DEBUG
+       do_scsi_done = ASC_ERROR;
+       scp_found = ASC_ERROR;
+       ret = ASC_ERROR;
+#endif /* ADVANSYS_DEBUG */
+
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
        if (scp->serial_number != scp->serial_number_at_timeout) {
+               ASC_PRINT1(
+"advansys_abort: timeout serial number changed for request %x\n",
+                       (unsigned) scp);
+               do_scsi_done = ASC_FALSE;
+               scp_found = ASC_FALSE;
                ret = SCSI_ABORT_NOT_RUNNING;
        } else
 #endif /* version >= v1.3.89 */
        if ((shp = scp->host) == NULL) {
                scp->result = HOST_BYTE(DID_ERROR);
+               do_scsi_done = ASC_TRUE;
+               scp_found = ASC_FALSE;
                ret = SCSI_ABORT_ERROR;
        } else if ((boardp = ASC_BOARDP(shp))->flags & 
                                (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
                ASC_PRINT2(
 "advansys_abort: board %d: Nested host reset or abort, flags 0x%x\n",
                        boardp->id, boardp->flags);
+               do_scsi_done = ASC_TRUE;
+               if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
+                   (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
+                       scp_found = ASC_TRUE;
+               } else {
+                       scp_found = ASC_FALSE;
+               }
                scp->result = HOST_BYTE(DID_ERROR);
                ret = SCSI_ABORT_ERROR;
        } else {
                /* Set abort flag to avoid nested reset or abort requests. */
                boardp->flags |= ASC_HOST_IN_ABORT;
 
+               do_scsi_done = ASC_TRUE;
                if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
                        /*
                         * If asc_rmqueue() found the command on the waiting
@@ -3678,6 +3770,7 @@ advansys_abort(Scsi_Cmnd *scp)
                         */
                        ASC_DBG1(1, "advansys_abort: scp %x found on waiting queue\n",
                                (unsigned) scp);
+                       scp_found = ASC_TRUE;
                        scp->result = HOST_BYTE(DID_ABORT);
                        ret = SCSI_ABORT_SUCCESS;
                } else if (asc_isqueued(&boardp->active, scp) == ASC_TRUE) {
@@ -3693,7 +3786,7 @@ advansys_abort(Scsi_Cmnd *scp)
                        sti(); /* Enable interrupts for AscAbortSRB(). */
                        ASC_DBG1(1, "advansys_abort: before AscAbortSRB(), scp %x\n",
                                (unsigned) scp);
-                       switch (status = AscAbortSRB(asc_dvc_varp, (ulong) scp)) {
+                       switch (AscAbortSRB(asc_dvc_varp, (ulong) scp)) {
                        case ASC_TRUE:
                                /* asc_isr_callback() will be called */
                                ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n");
@@ -3713,20 +3806,23 @@ advansys_abort(Scsi_Cmnd *scp)
                        cli();
 
                        /*
-                        * If the abort failed, remove the request from the
-                        * active list and complete it.
+                        * The request will either still be on the active queue
+                        * or have been added to the board's done queue.
                         */
-                       if (status != ASC_TRUE) {
-                               if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
-                                       scp->result = HOST_BYTE(DID_ABORT);
-                                       abort_do_done = ASC_TRUE;
-                               }
+                       if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
+                               scp->result = HOST_BYTE(DID_ABORT);
+                               scp_found = ASC_TRUE;
+                       } else {
+                               scp_found = asc_rmqueue(&boardp->done, scp);
+                               ASC_ASSERT(scp_found == ASC_TRUE);
                        }
 
                } else {
                        /*
                         * The command was not found on the active or waiting queues.
                         */
+                       do_scsi_done = ASC_TRUE;
+                       scp_found = ASC_FALSE;
                        ret = SCSI_ABORT_NOT_RUNNING;
                }
 
@@ -3736,11 +3832,11 @@ advansys_abort(Scsi_Cmnd *scp)
                /*
                 * Because the ASC_HOST_IN_ABORT flag causes both
                 * 'advansys_interrupt' and 'asc_isr_callback' to
-                * queue requests to the board's 'scsi_done_q' and
+                * queue requests to the board's 'done' queue and
                 * prevents waiting commands from being executed,
                 * these queued requests must be handled here.
                 */
-               done_scp = asc_dequeue_list(&boardp->scsi_done_q, NULL, ASC_TID_ALL);
+               done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
 
                /*
                 * Start any waiting commands for the board.
@@ -3749,22 +3845,39 @@ advansys_abort(Scsi_Cmnd *scp)
                        ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
                        asc_execute_queue(&boardp->waiting);
                }
+       }
 
-               /* Interrupts could be enabled here. */
+       /* Interrupts could be enabled here. */
 
-               /*
-                * If needed, complete the aborted request.
-                */
-               if (abort_do_done == ASC_TRUE) {
+       /*
+        * Complete the request to be aborted, unless it has been
+        * restarted as detected above, even if it was not found on
+        * the device active or waiting queues.
+        */
+       ASC_ASSERT(do_scsi_done != ASC_ERROR);
+       ASC_ASSERT(scp_found != ASC_ERROR);
+       if (do_scsi_done == ASC_TRUE) {
+               if (scp->scsi_done == NULL) {
+                       ASC_PRINT1(
+"advansys_abort: aborted request scsi_done() is NULL, %x\n",
+                               (unsigned) scp);
+               } else {
+                       if (scp_found == ASC_FALSE) {
+                               ASC_PRINT1(
+"advansys_abort: abort request not active or waiting, completing anyway %x\n",
+                                       (unsigned) scp);
+                       }
                        ASC_STATS(scp->host, done);
                        scp->scsi_done(scp);
                }
+       }
 
-               /*
-                * It is possible for the request done function to re-enable
-                * interrupts without confusing the driver. But here interrupts
-                * aren't enabled until all requests have been completed.
-                */
+       /*
+        * It is possible for the request done function to re-enable
+        * interrupts without confusing the driver. But here interrupts
+        * aren't enabled until all requests have been completed.
+        */
+       if (done_scp != NULL) {
                asc_scsi_done_list(done_scp);
        }
 
@@ -3795,18 +3908,18 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
        int                                     flags;
        Scsi_Cmnd                       *done_scp = NULL, *last_scp = NULL;
        Scsi_Cmnd                       *tscp, *new_last_scp;
-       int                                     scp_found = ASC_FALSE;
-       int                             device_reset = ASC_FALSE;
+       int                                     do_scsi_done;
+       int                                     scp_found;
        int                                     status;
        int                                     target;
-       int                                     ret = ASC_ERROR;
-
-       ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
+       int                                     ret;
 
        /* Save current flags and disable interrupts. */
        save_flags(flags);
        cli();
 
+       ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
+
 #ifdef ADVANSYS_STATS
        if (scp->host != NULL) {
                ASC_STATS(scp->host, reset);
@@ -3815,21 +3928,35 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
 
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
        if (scp->serial_number != scp->serial_number_at_timeout) {
+               ASC_PRINT1(
+"advansys_reset: timeout serial number changed for request %x\n",
+                       (unsigned) scp);
+               do_scsi_done = ASC_FALSE;
+               scp_found = ASC_FALSE;
                ret = SCSI_RESET_NOT_RUNNING;
        } else
 #endif /* version >= v1.3.89 */
        if ((shp = scp->host) == NULL) {
                scp->result = HOST_BYTE(DID_ERROR);
+               do_scsi_done = ASC_TRUE;
+               scp_found = ASC_FALSE;
                ret = SCSI_RESET_ERROR;
        } else if ((boardp = ASC_BOARDP(shp))->flags & 
                                (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
                ASC_PRINT2(
 "advansys_reset: board %d: Nested host reset or abort, flags 0x%x\n",
                        boardp->id, boardp->flags);
+               do_scsi_done = ASC_TRUE;
+               if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
+                   (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
+                       scp_found = ASC_TRUE;
+               } else {
+                       scp_found = ASC_FALSE;
+               }
                scp->result = HOST_BYTE(DID_ERROR);
                ret = SCSI_RESET_ERROR;
-       } else if (jiffies >= boardp->reset_jiffies &&
-                          jiffies < (boardp->reset_jiffies + (10 * HZ))) {
+       } else if (jiffies >= boardp->last_reset &&
+                          jiffies < (boardp->last_reset + (10 * HZ))) {
                /*
                 * Don't allow a reset to be attempted within 10 seconds
                 * of the last reset.
@@ -3840,15 +3967,27 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
                 */
                ASC_DBG(1,
                        "advansys_reset: reset within 10 sec of last reset ignored\n");
+               do_scsi_done = ASC_TRUE;
+               if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
+                   (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
+                       scp_found = ASC_TRUE;
+               } else {
+                       scp_found = ASC_FALSE;
+               }
                scp->result = HOST_BYTE(DID_ERROR);
                ret = SCSI_RESET_ERROR;
        } else {
+               int device_reset = ASC_FALSE;
+
+               do_scsi_done = ASC_TRUE;
+
                /* Set reset flag to avoid nested reset or abort requests. */
                boardp->flags |= ASC_HOST_IN_RESET;
 
                /*
-                * If the request is on the target waiting or active queue,
-                * note that it was found and remove it from its queue.
+                * If the request is on the target waiting or active queue
+                * or the board done queue, then remove it and note that it
+                * was found.
                 */
                if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
                        ASC_DBG(1, "advansys_reset: active scp_found = TRUE\n");
@@ -3856,6 +3995,10 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
                } else if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
                        ASC_DBG(1, "advansys_reset: waiting scp_found = TRUE\n");
                        scp_found = ASC_TRUE;
+               } else if (asc_rmqueue(&boardp->done, scp) == ASC_TRUE) {
+                       scp_found = ASC_TRUE;
+               } else {
+                       scp_found = ASC_FALSE;
                }
 
                /*
@@ -3939,11 +4082,11 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
                /*
                 * Because the ASC_HOST_IN_RESET flag causes both
                 * 'advansys_interrupt' and 'asc_isr_callback' to
-                * queue requests to the board's 'scsi_done_q' and
+                * queue requests to the board's 'done' queue and
                 * prevents waiting commands from being executed,
                 * these queued requests must be handled here.
                 */
-               done_scp = asc_dequeue_list(&boardp->scsi_done_q, &last_scp,
+               done_scp = asc_dequeue_list(&boardp->done, &last_scp,
                                                                        ASC_TID_ALL);
 
                /*
@@ -4006,7 +4149,7 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
                }
 
                /* Save the time of the most recently completed reset. */
-               boardp->reset_jiffies = jiffies;
+               boardp->last_reset = jiffies;
 
                /* Clear reset flag. */
                boardp->flags &= ~ASC_HOST_IN_RESET;
@@ -4018,34 +4161,35 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
                        ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
                        asc_execute_queue(&boardp->waiting);
                }
+               ret = SCSI_RESET_SUCCESS;
+       }
 
-               /* Interrupts could be enabled here. */
+       /* Interrupts could be enabled here. */
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-               /*
-                * If the command was found on the active or waiting request
-                * queues or if the the SCSI_RESET_SYNCHRONOUS flag is set,
-                * then done the command now.
-                */
-               if (scp_found == ASC_TRUE || (reset_flags & SCSI_RESET_SYNCHRONOUS)) {
-                       scp->result = HOST_BYTE(DID_RESET);
-                       ASC_STATS(scp->host, done);
-                       scp->scsi_done(scp);
-               }
-#else /* version >= v1.3.89 */
-               if (scp_found == ASC_TRUE) {
-                       scp->result = HOST_BYTE(DID_RESET);
+       ASC_ASSERT(do_scsi_done != ASC_ERROR);
+       ASC_ASSERT(scp_found != ASC_ERROR);
+       if (do_scsi_done == ASC_TRUE) {
+               if (scp->scsi_done == NULL) {
+                       ASC_PRINT1(
+"advansys_reset: reset request scsi_done() is NULL, %x\n",
+                               (unsigned) scp);
+               } else {
+                       if (scp_found == ASC_FALSE) {
+                               ASC_PRINT1(
+"advansys_reset: reset request not active or waiting, completing anyway %x\n",
+                                       (unsigned) scp);
+                       }
                        ASC_STATS(scp->host, done);
                        scp->scsi_done(scp);
                }
-#endif /* version >= v1.3.89 */
-               ret = SCSI_RESET_SUCCESS;
+       }
 
-               /*
-                * It is possible for the request done function to re-enable
-                * interrupts without confusing the driver. But here interrupts
-                * aren't enabled until requests have been completed.
-                */
+       /*
+        * It is possible for the request done function to re-enable
+        * interrupts without confusing the driver. But here interrupts
+        * aren't enabled until requests have been completed.
+        */
+       if (done_scp != NULL) {
                asc_scsi_done_list(done_scp);
        }
 
@@ -4239,11 +4383,11 @@ advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                         * Add to the list of requests that must be completed.
                         */
                        if (done_scp == NULL) {
-                               done_scp = asc_dequeue_list(&boardp->scsi_done_q, &last_scp,
+                               done_scp = asc_dequeue_list(&boardp->done, &last_scp,
                                        ASC_TID_ALL);
                        } else {
                                ASC_ASSERT(last_scp != NULL);
-                               REQPNEXT(last_scp) = asc_dequeue_list(&boardp->scsi_done_q,
+                               REQPNEXT(last_scp) = asc_dequeue_list(&boardp->done,
                                        &new_last_scp, ASC_TID_ALL);
                                if (new_last_scp != NULL) {
                                        ASC_ASSERT(REQPNEXT(last_scp) != NULL);
@@ -4318,6 +4462,7 @@ asc_scsi_done_list(Scsi_Cmnd *scp)
                tscp = REQPNEXT(scp);
                REQPNEXT(scp) = NULL;
                ASC_STATS(scp->host, done);
+               ASC_ASSERT(scp->scsi_done != NULL);
                scp->scsi_done(scp);
                scp = tscp;
        }
@@ -4360,7 +4505,7 @@ asc_scsi_done_list(Scsi_Cmnd *scp)
  *     host_scribble - used for pointer to another Scsi_Cmnd
  *
  * If this function returns ASC_NOERROR or ASC_ERROR the request
- * has been enqueued on the board's 'scsi_done_q' and must be
+ * has been enqueued on the board's 'done' queue and must be
  * completed by the caller.
  *
  * If ASC_BUSY is returned the request must be enqueued by the
@@ -4387,7 +4532,7 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
        if ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(scp->target)) == 0) {
                if (asc_init_dev(asc_dvc_varp, scp) == ASC_FALSE) {
                        scp->result = HOST_BYTE(DID_BAD_TARGET);
-                       asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK);
+                       asc_enqueue(&boardp->done, scp, ASC_BACK);
                        return ASC_ERROR;
                }
                boardp->init_tidmask |= ASC_TIX_TO_TARGET_ID(scp->target);
@@ -4412,9 +4557,29 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
        asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
        asc_scsi_q.q1.target_lun = scp->lun;
        asc_scsi_q.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun);
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
        asc_scsi_q.q1.sense_addr = (ulong) &scp->sense_buffer[0];
+#else /* version >= v2.1.0 */
+       asc_scsi_q.q1.sense_addr = virt_to_bus(&scp->sense_buffer[0]);
+#endif /* version >= v2.1.0 */
        asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
-       asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE;
+
+       /*
+        * If there are more than five outstanding commands for the
+        * current target, then every tenth command send an ORDERED
+        * request. This heuristic tries to retain the benefit of
+        * request sorting while preventing request starvation.
+        *
+        * The request count is incremented below for every successfully
+        * started request.
+        * 
+        */
+       if ((asc_dvc_varp->cur_dvc_qng[scp->target] > 5) &&
+           (boardp->rcnt[scp->target] % 10) == 0) {
+               asc_scsi_q.q2.tag_code = M2_QTAG_MSG_ORDERED;
+       } else {
+               asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE;
+       }
 
        /*
         * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
@@ -4425,8 +4590,11 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
                 * CDB request of single contiguous buffer.
                 */
                ASC_STATS(scp->host, cont_cnt);
-               /* request_buffer is already a real address. */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
                asc_scsi_q.q1.data_addr = (ulong) scp->request_buffer;
+#else /* version >= v2.1.0 */
+               asc_scsi_q.q1.data_addr = virt_to_bus(scp->request_buffer);
+#endif /* version >= v2.1.0 */
                asc_scsi_q.q1.data_cnt = scp->request_bufflen;
                ASC_STATS_ADD(scp->host, cont_xfer,
                                          ASC_CEILING(scp->request_bufflen, 512));
@@ -4444,7 +4612,7 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
 "asc_execute_scsi_cmnd: board %d: use_sg %d > sg_tablesize %d\n",
                                boardp->id, scp->use_sg, scp->host->sg_tablesize);
                        scp->result = HOST_BYTE(DID_ERROR);
-                       asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK);
+                       asc_enqueue(&boardp->done, scp, ASC_BACK);
                        return ASC_ERROR;
                }
 
@@ -4468,7 +4636,11 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
                 */
                slp = (struct scatterlist *) scp->request_buffer;
                for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
                        asc_sg_head.sg_list[sgcnt].addr = (ulong) slp->address;
+#else /* version >= v2.1.0 */
+                       asc_sg_head.sg_list[sgcnt].addr = virt_to_bus(slp->address);
+#endif /* version >= v2.1.0 */
                        asc_sg_head.sg_list[sgcnt].bytes = slp->length;
                        ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
                }
@@ -4484,6 +4656,11 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
        switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
        case ASC_NOERROR:
                ASC_STATS(scp->host, asc_noerror);
+               /*
+                * Increment monotonically increasing per device successful
+                * request count. Wrapping of 'rcnt' doesn't matter.
+                */
+               boardp->rcnt[scp->target]++;
                asc_enqueue(&boardp->active, scp, ASC_BACK);
                ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n");
                break;
@@ -4497,7 +4674,7 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
                        boardp->id, asc_dvc_varp->err_code);
                ASC_STATS(scp->host, asc_error);
                scp->result = HOST_BYTE(DID_ERROR);
-               asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK);
+               asc_enqueue(&boardp->done, scp, ASC_BACK);
                break;
        default:
                ASC_PRINT2(
@@ -4505,7 +4682,7 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
                        boardp->id, asc_dvc_varp->err_code);
                ASC_STATS(scp->host, asc_unknown);
                scp->result = HOST_BYTE(DID_ERROR);
-               asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK);
+               asc_enqueue(&boardp->done, scp, ASC_BACK);
                break;
        }
 
@@ -4645,7 +4822,7 @@ asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
         * The done function for the command will be called from
         * advansys_interrupt().
         */
-       asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK);
+       asc_enqueue(&boardp->done, scp, ASC_BACK);
 
        return;
 }
@@ -5188,12 +5365,14 @@ asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
        ascq->q_tidmask |= ASC_TIX_TO_TARGET_ID(tid);
 #ifdef ADVANSYS_STATS
        /* Maintain request queue statistics. */
+       ascq->q_tot_cnt[tid]++;
        ascq->q_cur_cnt[tid]++;
        if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
                ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
                ASC_DBG2(1, "asc_enqueue: new q_max_cnt[%d] %d\n",
                        tid, ascq->q_max_cnt[tid]);
        }
+       REQPTIME(reqp) = REQTIMESTAMP();
 #endif /* ADVANSYS_STATS */
        ASC_DBG1(1, "asc_enqueue: reqp %x\n", (unsigned) reqp);
        return;
@@ -5227,6 +5406,7 @@ asc_dequeue(asc_queue_t *ascq, int tid)
                /* Maintain request queue statistics. */
                ascq->q_cur_cnt[tid]--;
                ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
+               REQTIMESTAT("asc_dequeue", ascq, reqp, tid);
 #endif /* ADVANSYS_STATS */
        }
        ASC_DBG1(1, "asc_dequeue: reqp %x\n", (unsigned) reqp);
@@ -5249,6 +5429,9 @@ asc_dequeue(asc_queue_t *ascq, int tid)
  * (or the function return value) is not NULL, i.e. use a temporary
  * variable for 'lastpp' and check its value after the function return
  * before assigning it to the list last pointer.
+ *
+ * Unfortunately collecting queuing time statistics adds overhead to
+ * the function that isn't inherent to the function's algorithm.
  */
 REQP
 asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
@@ -5268,7 +5451,7 @@ asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
        if (tid != ASC_TID_ALL) {
                /* Return all requests for the specified 'tid'. */
                if ((ascq->q_tidmask & ASC_TIX_TO_TARGET_ID(tid)) == 0) {
-                       /* List is empty set first and last return pointers to NULL. */
+                       /* List is empty; Set first and last return pointers to NULL. */
                        firstp = lastp = NULL;
                } else {
                        firstp = ascq->q_first[tid];
@@ -5276,7 +5459,13 @@ asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
                        ascq->q_first[tid] = ascq->q_last[tid] = NULL;
                        ascq->q_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid);
 #ifdef ADVANSYS_STATS
-                       ascq->q_cur_cnt[tid] = 0;
+                       {
+                               REQP reqp;
+                               ascq->q_cur_cnt[tid] = 0;
+                               for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
+                                       REQTIMESTAT("asc_dequeue_list", ascq, reqp, tid);
+                               }
+                       }
 #endif /* ADVANSYS_STATS */
                }
        } else {
@@ -5299,6 +5488,14 @@ asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
 #endif /* ADVANSYS_STATS */
                        }
                }
+#ifdef ADVANSYS_STATS
+               {
+                       REQP reqp;
+                       for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
+                               REQTIMESTAT("asc_dequeue_list", ascq, reqp, reqp->target);
+                       }
+               }
+#endif /* ADVANSYS_STATS */
        }
        if (lastpp) {
                *lastpp = lastp;
@@ -5324,7 +5521,7 @@ asc_rmqueue(asc_queue_t *ascq, REQP reqp)
        int                     tid;
        int                     ret = ASC_FALSE;
 
-       ASC_DBG2(1, "asc_rmqueue: ascq %x, reqp %d\n",
+       ASC_DBG2(1, "asc_rmqueue: ascq %x, reqp %x\n",
                (unsigned) ascq, (unsigned) reqp);
        ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
        ASC_ASSERT(reqp != NULL);
@@ -5373,6 +5570,7 @@ asc_rmqueue(asc_queue_t *ascq, REQP reqp)
        /* Maintain request queue statistics. */
        if (ret == ASC_TRUE) {
                ascq->q_cur_cnt[tid]--;
+               REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
        }
        ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
 #endif /* ADVANSYS_STATS */
@@ -5406,6 +5604,7 @@ asc_isqueued(asc_queue_t *ascq, REQP reqp)
                        break;
                }
        }
+       ASC_DBG1(1, "asc_isqueued: ret %x\n", ret);
        return ret;
 }
 
@@ -5608,40 +5807,40 @@ asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
 
        len = asc_prt_line(cp, leftlen,
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
+" host_busy %u, last_reset %u, max_id %u, max_lun %u\n",
+               shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun);
+#else /* version >= v1.3.89 */
 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
                shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun,
                shp->max_channel);
-#else /* version >= v1.3.89 */
-" host_busy %u, last_reset %u, max_id %u, max_lun %u\n",
-               shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun);
 #endif /* version >= v1.3.89 */
        ASC_PRT_NEXT();
        
        len = asc_prt_line(cp, leftlen,
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,57)
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
+" can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
+               shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun);
+#else /* version >= v1.3.57 */
 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
                shp->unique_id, shp->can_queue, shp->this_id, shp->sg_tablesize,
                shp->cmd_per_lun);
-#else /* version >= v1.3.57 */
-" can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
-               shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun);
 #endif /* version >= v1.3.57 */
        ASC_PRT_NEXT();
 
        len = asc_prt_line(cp, leftlen,
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,57)
-" unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n",
-               shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module);
-#else /* version >= v1.3.57 */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
 " unchecked_isa_dma %d, loaded_as_module %d\n",
                shp->unchecked_isa_dma, shp->loaded_as_module);
+#else /* version >= v1.3.57 */
+" unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n",
+               shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module);
 #endif /* version >= v1.3.57 */
        ASC_PRT_NEXT();
 
        len = asc_prt_line(cp, leftlen,
-" flags %x, reset_jiffies %x, jiffies %x\n",
-               ASC_BOARDP(shp)->flags, ASC_BOARDP(shp)->reset_jiffies, jiffies);
+" flags %x, last_reset %x, jiffies %x\n",
+               ASC_BOARDP(shp)->flags, ASC_BOARDP(shp)->last_reset, jiffies);
        ASC_PRT_NEXT();
 
        return totlen;
@@ -5897,18 +6096,19 @@ DvcLeaveCritical(int flags)
 }
 
 /*
- * Convert a virtual address to a virtual address.
- *
- * Apparently Linux is loaded V=R (virtual equals real). Just return
- * the virtual address.
+ * Convert a virtual address to a bus address.
  */
 ulong
 DvcGetPhyAddr(uchar *buf_addr, ulong buf_len)
 {
-       ulong phys_addr;
+       ulong bus_addr;
 
-       phys_addr = (ulong) buf_addr;
-       return phys_addr;
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
+       bus_addr = (ulong) buf_addr;
+#else /* version >= v2.1.0 */
+       bus_addr = virt_to_bus(buf_addr);
+#endif /* version >= v2.1.0 */
+       return bus_addr;
 }
 
 ulong
@@ -5919,7 +6119,11 @@ DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len,
 
        buf_size = buf_len;
        asc_sg_head_ptr->entry_cnt = 1;
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
        asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr;
+#else /* version >= v2.1.0 */
+       asc_sg_head_ptr->sg_list[0].addr = virt_to_bus(buf_addr);
+#endif /* version >= v2.1.0 */
        asc_sg_head_ptr->sg_list[0].bytes = buf_size;
        return buf_size;
 }
@@ -6169,25 +6373,6 @@ asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen)
                s->asc_noerror, s->asc_busy, s->asc_error, s->asc_unknown);
        ASC_PRT_NEXT();
 
-       /*
-        * Display request queuing statistics.
-        */
-       len = asc_prt_line(cp, leftlen,
-" Active and Pending Request Queues:\n");
-       ASC_PRT_NEXT();
-
-       active = &ASC_BOARDP(shp)->active;
-       waiting = &ASC_BOARDP(shp)->waiting;
-       for (i = 0; i < ASC_MAX_TID + 1; i++) {
-               if (active->q_max_cnt[i] > 0 || waiting->q_max_cnt[i] > 0) {
-                       len = asc_prt_line(cp, leftlen,
-"  target %d: active [cur %d, max %d], waiting [cur %d, max %d]\n",
-                               i, active->q_cur_cnt[i], active->q_max_cnt[i],
-                               waiting->q_cur_cnt[i], waiting->q_max_cnt[i]);
-                       ASC_PRT_NEXT();
-               }
-       }
-
        /*
         * Display data transfer statistics.
         */
@@ -6235,6 +6420,44 @@ asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen)
                ASC_PRT_NEXT();
        }
 
+       /*
+        * Display request queuing statistics.
+        */
+       len = asc_prt_line(cp, leftlen,
+" Active and Waiting Request Queues (time unit: %d HZ):\n", HZ);
+       ASC_PRT_NEXT();
+
+       active = &ASC_BOARDP(shp)->active;
+       waiting = &ASC_BOARDP(shp)->waiting;
+       for (i = 0; i < ASC_MAX_TID + 1; i++) {
+               if (active->q_tot_cnt[i] > 0 || waiting->q_tot_cnt[i] > 0) {
+                       len = asc_prt_line(cp, leftlen, " target %d\n", i);
+                       ASC_PRT_NEXT();
+
+                       len = asc_prt_line(cp, leftlen,
+"   active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
+                               active->q_cur_cnt[i], active->q_max_cnt[i],
+                               active->q_tot_cnt[i],
+                               active->q_min_tim[i], active->q_max_tim[i],
+                               (active->q_tot_cnt[i] == 0) ? 0 :
+                               (active->q_tot_tim[i]/active->q_tot_cnt[i]),
+                               (active->q_tot_cnt[i] == 0) ? 0 :
+                               ASC_TENTHS(active->q_tot_tim[i], active->q_tot_cnt[i]));
+                       ASC_PRT_NEXT();
+
+                       len = asc_prt_line(cp, leftlen,
+"   waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n",
+                               waiting->q_cur_cnt[i], waiting->q_max_cnt[i],
+                               waiting->q_tot_cnt[i],
+                               waiting->q_min_tim[i], waiting->q_max_tim[i],
+                               (waiting->q_tot_cnt[i] == 0) ? 0 :
+                               (waiting->q_tot_tim[i]/waiting->q_tot_cnt[i]),
+                               (waiting->q_tot_cnt[i] == 0) ? 0 :
+                               ASC_TENTHS(waiting->q_tot_tim[i], waiting->q_tot_cnt[i]));
+                       ASC_PRT_NEXT();
+               }
+       }
+
        return totlen;
 }
 #endif /* ADVANSYS_STATS */
@@ -6274,6 +6497,60 @@ asc_prt_scsi_host(struct Scsi_Host *s)
        asc_prt_dvc_cfg(&ASC_BOARDP(s)->asc_dvc_cfg);
 }
 
+/*
+ * asc_prt_scsi_cmnd()
+ */
+STATIC void 
+asc_prt_scsi_cmnd(Scsi_Cmnd *s)
+{
+       printk("Scsi_Cmnd at addr %x\n", (unsigned) s);
+
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
+       printk(
+" host %x, device %x, target %u, lun %u\n",
+               (unsigned) s->host, (unsigned) s->device, s->target, s->lun);
+#else /* version >= v1.3.0 */
+       printk(
+" host %x, device %x, target %u, lun %u, channel %u,\n",
+               (unsigned) s->host, (unsigned) s->device, s->target, s->lun,
+               s->channel);
+#endif /* version >= v1.3.0 */
+
+       asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
+
+       printk(
+" use_sg %u, sglist_len %u, abort_reason %x\n",
+               s->use_sg, s->sglist_len, s->abort_reason);
+
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
+       printk(
+" retries %d, allowed %d\n",
+                s->retries, s->allowed);
+#else /* version >= v1.3.89 */
+       printk(
+" serial_number %x, serial_number_at_timeout %x, retries %d, allowed %d\n",
+               (unsigned) s->serial_number, (unsigned) s->serial_number_at_timeout,
+                s->retries, s->allowed);
+#endif /* version >= v1.3.89 */
+
+       printk(
+" timeout_per_command %d, timeout_total %d, timeout %d\n",
+               s->timeout_per_command, s->timeout_total, s->timeout);
+
+       printk(
+" internal_timeout %u, flags %u, this_count %d\n",
+               s->internal_timeout, s->flags, s->this_count);
+
+       printk(
+" scsi_done %x, done %x, host_scribble %x, result %x\n",
+               (unsigned) s->scsi_done, (unsigned) s->done,
+               (unsigned) s->host_scribble, s->result);
+
+       printk(
+" tag %u, pid %u\n",
+               (unsigned) s->tag, (unsigned) s->pid);
+}
+
 /*
  * asc_prt_dvc_var()
  */
index 80e55aa6dceacc3507e58387414537ed99c53238..310b6b911bb705131294f349bce9d1ad14de6f25 100644 (file)
 /*
  * Using this file :
  * This file a skeleton Linux SCSI driver for the NCR 5380 series
- * of chips.  To use it, you write a architecture specific functions 
+ * of chips.  To use it, you write an architecture specific functions 
  * and macros and include this file in your driver.
  *
  * These macros control options : 
index 401ced5a72c8aed7c2fd07a5d80d820d9d626ba3..24c1df4a542232de96009815f83254e43cc8cd2d 100644 (file)
@@ -282,6 +282,7 @@ static struct dev_info device_list[] =
 {"PIONEER","CD-ROM DRM-604X","*", BLIST_FORCELUN | BLIST_SINGLELUN},
 {"EMULEX","MD21/S2     ESDI","*", BLIST_SINGLELUN},
 {"CANON","IPUBJD","*", BLIST_SPARSELUN},
+{"MATSHITA","PD","*", BLIST_FORCELUN | BLIST_SINGLELUN},
 /*
  * Must be at end of list...
  */
index 6cb8801864e6d4e90f26bb8db244132aa609585c..c162fb5a6278456f84f059daeaaa1268698821a7 100644 (file)
@@ -73,7 +73,7 @@ static int sg_ioctl(struct inode * inode,struct file * file,
     switch(cmd_in)
     {
     case SG_SET_TIMEOUT:
-        result = verify_area(VERIFY_READ, (const void *)arg, sizeof(long));
+        result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
         if (result) return result;
 
        scsi_generics[dev].timeout=get_user((int *) arg);
@@ -196,7 +196,7 @@ static void sg_free(char *buff,int size)
  * complete semaphores to tell us whether the buffer is available for us
  * and whether the command is actually done.
  */
-static int sg_read(struct inode *inode,struct file *filp,char *buf,int count)
+static long sg_read(struct inode *inode,struct file *filp,char *buf,unsigned long count)
 {
     int dev=MINOR(inode->i_rdev);
     int i;
@@ -318,7 +318,7 @@ static void sg_command_done(Scsi_Cmnd * SCpnt)
     wake_up(&scsi_generics[dev].read_wait);
 }
 
-static int sg_write(struct inode *inode,struct file *filp,const char *buf,int count)
+static long sg_write(struct inode *inode,struct file *filp,const char *buf,unsigned long count)
 {
     int                          bsize,size,amt,i;
     unsigned char        cmnd[MAX_COMMAND_SIZE];
index d6ce3262d89dc9e7d0b5940acd6d41b2c03cac20..62027a4ca65962670b6cd3a122326efc78aebb42 100644 (file)
@@ -403,7 +403,7 @@ audio_ioctl (int dev, struct fileinfo *file,
 
       case SNDCTL_DSP_GETOSPACE:
        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
-         return 0;
+         return -EPERM;
        if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
          return -(EBUSY);
 
@@ -418,7 +418,7 @@ audio_ioctl (int dev, struct fileinfo *file,
            return err;
 
          if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
-           info.bytes += buf_size - buf_ptr;
+           info.bytes -= buf_ptr;
 
          memcpy_tofs (&((char *) arg)[0], (char *) &info, sizeof (info));
          return 0;
index 6df2fddeb7d75160e6ffa1008ceb81c00f7158b4..b5dda6f51181237b011f600a7fa1e937dfbced4a 100644 (file)
@@ -65,7 +65,7 @@ sb_dsp_command (sb_devc * devc, unsigned char val)
   /*
    * Note! the i<500000 is an emergency exit. The sb_dsp_command() is sometimes
    * called while interrupts are disabled. This means that the timer is
-   * disabled also. However the timeout situation is a abnormal condition.
+   * disabled also. However the timeout situation is an abnormal condition.
    * Normally the DSP should be ready to accept commands after just couple of
    * loops.
    */
index 2645e8e935e2eaa3909076dd7964a0bdeacf2761..5dde5776bb287a7644f42624f3610e6bf91e5722 100644 (file)
@@ -675,7 +675,7 @@ static int get_stats(caddr_t addr)
 }
 
 /*
- * Initialize pointer in a inode to the right dquots.
+ * Initialize pointer in an inode to the right dquots.
  */
 void dquot_initialize(struct inode *inode, short type)
 {
@@ -734,7 +734,7 @@ void dquot_drop(struct inode *inode)
 
 /*
  * This is a simple algorithm that calculates the size of a file in blocks.
- * This is only used on filesystems that do not have a i_blocks count.
+ * This is only used on filesystems that do not have an i_blocks count.
  */
 static u_long isize_to_blocks(size_t isize, size_t blksize)
 {
index a2b4858216f7d459e551618938adf1e5c0f8eae0..995fc5506541c117102e07c6a48b394fa7ad2139 100644 (file)
@@ -242,7 +242,7 @@ void ext_truncate(struct inode * inode)
 }
 
 /*
- * Called when a inode is released. Note that this is different
+ * Called when an inode is released. Note that this is different
  * from ext_open: open gets called at every open, but release
  * gets called only when /all/ the files are closed.
  */
index 12081b07ef602c6c03b448edfddf05be3b2f2d57..0abaa12ae2dbaea55d9856f50a442ed31e10bfcd 100644 (file)
@@ -80,6 +80,21 @@ struct inode_operations ext2_file_inode_operations = {
        NULL                    /* smap */
 };
 
+static inline void remove_suid(struct inode *inode)
+{
+       unsigned int mode;
+
+       /* set S_IGID if S_IXGRP is set, and always set S_ISUID */
+       mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
+
+       /* was any of the uid bits set? */
+       mode &= inode->i_mode;
+       if (mode && suser()) {
+               inode->i_mode &= ~mode;
+               inode->i_dirt = 1;
+       }
+}
+
 static long ext2_file_write (struct inode * inode, struct file * filp,
                            const char * buf, unsigned long count)
 {
@@ -111,6 +126,7 @@ static long ext2_file_write (struct inode * inode, struct file * filp,
                              inode->i_mode);
                return -EINVAL;
        }
+       remove_suid(inode);
        if (filp->f_flags & O_APPEND)
                pos = inode->i_size;
        else
@@ -153,7 +169,13 @@ static long ext2_file_write (struct inode * inode, struct file * filp,
                                break;
                        }
                }
+               if (exception()) {
+                       brelse(bh);
+                       written = -EFAULT;
+                       break;
+               }
                memcpy_fromfs (bh->b_data + offset, buf, c);
+               end_exception();
                update_vm_cache(inode, pos, bh->b_data + offset, c);
                pos2 += c;
                pos += c;
@@ -201,7 +223,7 @@ static long ext2_file_write (struct inode * inode, struct file * filp,
 }
 
 /*
- * Called when a inode is released. Note that this is different
+ * Called when an inode is released. Note that this is different
  * from ext2_open: open gets called at every open, but release
  * gets called only when /all/ the files are closed.
  */
index 2e28a2e42e50f36ad0c2a868a1eae5aec045e764..1e4c8e311c53644c5923c0d165877d3e6548396e 100644 (file)
@@ -39,7 +39,7 @@ void invalidate_dquots(kdev_t dev, short type)
 }
 
 /*
- * Initialize pointer in a inode to the right dquots.
+ * Initialize pointer in an inode to the right dquots.
  */
 void dquot_initialize(struct inode *inode, short type)
 {
index 1d1c94fac68d37e4a16ae6d892a1955053da24a8..c69f236014207d0a46a2c88880a34fc249ec94b2 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -550,7 +550,7 @@ cleanup_file:
 }
 
 /*
- * Find a empty file descriptor entry, and mark it busy
+ * Find an empty file descriptor entry, and mark it busy
  */
 int get_unused_fd(void)
 {
index c54b9770150853c04f3af064a3d36658d54c12c4..d9780f85b8389d0c9f729265a5cecaf000da5ecc 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -51,6 +51,10 @@ static long pipe_read(struct inode * inode, struct file * filp,
                interruptible_sleep_on(&PIPE_WAIT(*inode));
        }
        PIPE_LOCK(*inode)++;
+       if (exception()) {
+               PIPE_LOCK(*inode)--;
+               return -EFAULT;
+       }
        while (count>0 && (size = PIPE_SIZE(*inode))) {
                chars = PIPE_MAX_RCHUNK(*inode);
                if (chars > count)
@@ -66,6 +70,7 @@ static long pipe_read(struct inode * inode, struct file * filp,
                memcpy_tofs(buf, pipebuf, chars );
                buf += chars;
        }
+       end_exception();
        PIPE_LOCK(*inode)--;
        wake_up_interruptible(&PIPE_WAIT(*inode));
        if (read) {
@@ -105,6 +110,10 @@ static long pipe_write(struct inode * inode, struct file * filp,
                        interruptible_sleep_on(&PIPE_WAIT(*inode));
                }
                PIPE_LOCK(*inode)++;
+               if (exception()) {
+                       PIPE_LOCK(*inode)--;
+                       return -EFAULT;
+               }
                while (count>0 && (free = PIPE_FREE(*inode))) {
                        chars = PIPE_MAX_WCHUNK(*inode);
                        if (chars > count)
@@ -118,6 +127,7 @@ static long pipe_write(struct inode * inode, struct file * filp,
                        memcpy_fromfs(pipebuf, buf, chars );
                        buf += chars;
                }
+               end_exception();
                PIPE_LOCK(*inode)--;
                wake_up_interruptible(&PIPE_WAIT(*inode));
                free = 1;
index ee78c317c7fe0860c35d97d71fe5fbe619e998a7..5e4a98b5cfbb9c3026c881c49c9059ea7cd39900 100644 (file)
@@ -112,6 +112,7 @@ asmlinkage long sys_read(unsigned int fd, char * buf, unsigned long count)
        int error;
        struct file * file;
        struct inode * inode;
+       long (*read)(struct inode *, struct file *, char *, unsigned long);
 
        error = -EBADF;
        file = fget(fd);
@@ -123,19 +124,16 @@ asmlinkage long sys_read(unsigned int fd, char * buf, unsigned long count)
        error = -EBADF;
        if (!(file->f_mode & 1))
                goto out;
-       error = -EINVAL;
-       if (!file->f_op || !file->f_op->read)
-               goto out;
-       error = 0;
-       if (count <= 0)
-               goto out;
        error = locks_verify_area(FLOCK_VERIFY_READ,inode,file,file->f_pos,count);
        if (error)
                goto out;
        error = verify_area(VERIFY_WRITE,buf,count);
        if (error)
                goto out;
-       error = file->f_op->read(inode,file,buf,count);
+       error = -EINVAL;
+       if (!file->f_op || !(read = file->f_op->read))
+               goto out;
+       error = read(inode,file,buf,count);
 out:
        fput(file, inode);
 bad_file:
@@ -147,6 +145,7 @@ asmlinkage long sys_write(unsigned int fd, const char * buf, unsigned long count
        int error;
        struct file * file;
        struct inode * inode;
+       long (*write)(struct inode *, struct file *, const char *, unsigned long);
 
        error = -EBADF;
        file = fget(fd);
@@ -157,39 +156,17 @@ asmlinkage long sys_write(unsigned int fd, const char * buf, unsigned long count
                goto out;
        if (!(file->f_mode & 2))
                goto out;
-       error = -EINVAL;
-       if (!file->f_op || !file->f_op->write)
-               goto out;
-       error = 0;
-       if (!count)
-               goto out;
        error = locks_verify_area(FLOCK_VERIFY_WRITE,inode,file,file->f_pos,count);
        if (error)
                goto out;
        error = verify_area(VERIFY_READ,buf,count);
        if (error)
                goto out;
-       /*
-        * If data has been written to the file, remove the setuid and
-        * the setgid bits. We do it anyway otherwise there is an
-        * extremely exploitable race - does your OS get it right |->
-        *
-        * Set ATTR_FORCE so it will always be changed.
-        */
-       if (!suser() && (inode->i_mode & (S_ISUID | S_ISGID))) {
-               struct iattr newattrs;
-               /*
-                * Don't turn off setgid if no group execute. This special
-                * case marks candidates for mandatory locking.
-                */
-               newattrs.ia_mode = inode->i_mode &
-                       ~(S_ISUID | ((inode->i_mode & S_IXGRP) ? S_ISGID : 0));
-               newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_FORCE;
-               notify_change(inode, &newattrs);
-       }
-
+       error = -EINVAL;
+       if (!file->f_op || !(write = file->f_op->write))
+               goto out;
        down(&inode->i_sem);
-       error = file->f_op->write(inode,file,buf,count);
+       error = write(inode,file,buf,count);
        up(&inode->i_sem);
 out:
        fput(file, inode);
index 3d39e187bef5a181cc2cd94dedbc8e0771448f8c..242d3ee8b5675c4877f6102293cddc2b96c2dba1 100644 (file)
@@ -35,7 +35,7 @@
  * sleep/wakeup mechanism works.
  *
  * Two very simple procedures, select_wait() and free_wait() make all the work.
- * select_wait() is a inline-function defined in <linux/sched.h>, as all select
+ * select_wait() is an inline-function defined in <linux/sched.h>, as all select
  * functions have to call it to add an entry to the select table.
  */
 
@@ -67,86 +67,143 @@ static void free_wait(select_table * p)
  * and we aren't going to sleep on the select_table.  -- jrs
  */
 
-static int check(int flag, select_table * wait, struct file * file)
+static inline int __check(
+       int (*select) (struct inode *, struct file *, int, select_table *),
+       struct inode *inode,
+       struct file *file,
+       int flag,
+       select_table * wait)
 {
-       struct inode * inode;
-       struct file_operations *fops;
-       int (*select) (struct inode *, struct file *, int, select_table *);
-
-       inode = file->f_inode;
-       if ((fops = file->f_op) && (select = fops->select))
-               return select(inode, file, flag, wait)
-                   || (wait && select(inode, file, flag, NULL));
-       if (flag != SEL_EX)
-               return 1;
-       return 0;
+       return select(inode, file, flag, wait) ||
+               (wait && select(inode, file, flag, NULL));
 }
 
-static int do_select(int n, fd_set *in, fd_set *out, fd_set *ex,
-       fd_set *res_in, fd_set *res_out, fd_set *res_ex)
+#define check(flag,wait,file) \
+(((file)->f_op && (file)->f_op->select) ? \
+ __check((file)->f_op->select,(file)->f_inode,file,flag,wait) \
+ : \
+ (flag != SEL_EX))
+
+/*
+ * Due to kernel stack usage, we use a _limited_ fd_set type here, and once
+ * we really start supporting >256 file descriptors we'll probably have to
+ * allocate the kernel fd_set copies dynamically.. (The kernel select routines
+ * are careful to touch only the defined low bits of any fd_set pointer, this
+ * is important for performance too).
+ */
+typedef unsigned long limited_fd_set[NR_OPEN/(8*(sizeof(unsigned long)))];
+
+typedef struct {
+       limited_fd_set in, out, ex;
+       limited_fd_set res_in, res_out, res_ex;
+} fd_set_buffer;
+
+#define __IN(in)       (in)
+#define __OUT(in)      (in + sizeof(limited_fd_set)/sizeof(unsigned long))
+#define __EX(in)       (in + 2*sizeof(limited_fd_set)/sizeof(unsigned long))
+#define __RES_IN(in)   (in + 3*sizeof(limited_fd_set)/sizeof(unsigned long))
+#define __RES_OUT(in)  (in + 4*sizeof(limited_fd_set)/sizeof(unsigned long))
+#define __RES_EX(in)   (in + 5*sizeof(limited_fd_set)/sizeof(unsigned long))
+
+#define BITS(in)       (*__IN(in)|*__OUT(in)|*__EX(in))
+
+static int max_select_fd(unsigned long n, fd_set_buffer *fds)
 {
-       int count;
-       select_table wait_table, *wait;
-       struct select_table_entry *entry;
+       unsigned long *open_fds, *in;
        unsigned long set;
-       int i,j;
-       int max = -1;
+       int max;
 
-       j = 0;
-       for (;;) {
-               i = j * __NFDBITS;
-               if (i >= n)
-                       break;
-               set = in->fds_bits[j] | out->fds_bits[j] | ex->fds_bits[j];
-               j++;
-               for ( ; set ; i++,set >>= 1) {
-                       if (i >= n)
-                               goto end_check;
-                       if (!(set & 1))
-                               continue;
-                       if (!current->files->fd[i])
-                               return -EBADF;
-                       if (!current->files->fd[i]->f_inode)
-                               return -EBADF;
-                       max = i;
+       /* handle last in-complete long-word first */
+       set = ~(~0UL << (n & (__NFDBITS-1)));
+       n /= __NFDBITS;
+       open_fds = current->files->open_fds.fds_bits+n;
+       in = fds->in+n;
+       max = 0;
+       if (set) {
+               set &= BITS(in);
+               if (set) {
+                       if (!(set & ~*open_fds))
+                               goto get_max;
+                       return -EBADF;
                }
        }
-end_check:
-       n = max + 1;
+       while (n) {
+               in--;
+               open_fds--;
+               n--;
+               set = BITS(in);
+               if (!set)
+                       continue;
+               if (set & ~*open_fds)
+                       return -EBADF;
+               if (max)
+                       continue;
+get_max:
+               do {
+                       max++;
+                       set >>= 1;
+               } while (set);
+               max += n * __NFDBITS;
+       }
+
+       return max;
+}
+
+#define BIT(i)         (1UL << ((i)&(__NFDBITS-1)))
+#define MEM(i,m)       ((m)+(unsigned)(i)/__NFDBITS)
+#define ISSET(i,m)     (((i)&*(m)) != 0)
+#define SET(i,m)       (*(m) |= (i))
+
+static int do_select(int n, fd_set_buffer *fds)
+{
+       int retval;
+       select_table wait_table, *wait;
+       struct select_table_entry *entry;
+       int i;
+
+       retval = max_select_fd(n, fds);
+       if (retval < 0)
+               goto out;
+       n = retval;
+       retval = -ENOMEM;
        if(!(entry = (struct select_table_entry*) __get_free_page(GFP_KERNEL)))
-               return -ENOMEM;
-       count = 0;
+               goto out;
+       retval = 0;
        wait_table.nr = 0;
        wait_table.entry = entry;
        wait = &wait_table;
-repeat:
-       current->state = TASK_INTERRUPTIBLE;
-       for (i = 0 ; i < n ; i++) {
-               if (FD_ISSET(i,in) && check(SEL_IN,wait,current->files->fd[i])) {
-                       FD_SET(i, res_in);
-                       count++;
-                       wait = NULL;
-               }
-               if (FD_ISSET(i,out) && check(SEL_OUT,wait,current->files->fd[i])) {
-                       FD_SET(i, res_out);
-                       count++;
-                       wait = NULL;
-               }
-               if (FD_ISSET(i,ex) && check(SEL_EX,wait,current->files->fd[i])) {
-                       FD_SET(i, res_ex);
-                       count++;
-                       wait = NULL;
+       for (;;) {
+               struct file ** fd = current->files->fd;
+               current->state = TASK_INTERRUPTIBLE;
+               for (i = 0 ; i < n ; i++,fd++) {
+                       unsigned long bit = BIT(i);
+                       unsigned long *in = MEM(i,fds->in);
+                       if (ISSET(bit,__IN(in)) && check(SEL_IN,wait,*fd)) {
+                               SET(bit, __RES_IN(in));
+                               retval++;
+                               wait = NULL;
+                       }
+                       if (ISSET(bit,__OUT(in)) && check(SEL_OUT,wait,*fd)) {
+                               SET(bit, __RES_OUT(in));
+                               retval++;
+                               wait = NULL;
+                       }
+                       if (ISSET(bit,__EX(in)) && check(SEL_EX,wait,*fd)) {
+                               SET(bit, __RES_EX(in));
+                               retval++;
+                               wait = NULL;
+                       }
                }
-       }
-       wait = NULL;
-       if (!count && current->timeout && !(current->signal & ~current->blocked)) {
+               wait = NULL;
+               if (retval || !current->timeout || (current->signal & ~current->blocked))
+                       break;
                schedule();
-               goto repeat;
        }
        free_wait(&wait_table);
        free_page((unsigned long) entry);
        current->state = TASK_RUNNING;
-       return count;
+out:
+       return retval;
 }
 
 /*
@@ -202,20 +259,11 @@ static inline void __zero_fd_set(long nr, unsigned long * fdset)
 }              
 
 /*
- * Due to kernel stack usage, we use a _limited_ fd_set type here, and once
- * we really start supporting >256 file descriptors we'll probably have to
- * allocate the kernel fd_set copies dynamically.. (The kernel select routines
- * are careful to touch only the defined low bits of any fd_set pointer, this
- * is important for performance too).
- *
  * Note a few subtleties: we use "long" for the dummy, not int, and we do a
  * subtract by 1 on the nr of file descriptors. The former is better for
  * machines with long > int, and the latter allows us to test the bit count
  * against "zero or positive", which can mostly be just a sign bit test..
  */
-typedef struct {
-       unsigned long dummy[NR_OPEN/(8*(sizeof(unsigned long)))];
-} limited_fd_set;
 
 #define get_fd_set(nr,fsp,fdp) \
 __get_fd_set(nr, (int *) (fsp), (int *) (fdp))
@@ -237,9 +285,7 @@ __zero_fd_set((nr)-1, (unsigned long *) (fdp))
 asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
 {
        int error;
-       limited_fd_set res_in, in;
-       limited_fd_set res_out, out;
-       limited_fd_set res_ex, ex;
+       fd_set_buffer fds;
        unsigned long timeout;
 
        error = -EINVAL;
@@ -247,9 +293,9 @@ asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct
                goto out;
        if (n > NR_OPEN)
                n = NR_OPEN;
-       if ((error = get_fd_set(n, inp, &in)) ||
-           (error = get_fd_set(n, outp, &out)) ||
-           (error = get_fd_set(n, exp, &ex))) goto out;
+       if ((error = get_fd_set(n, inp, &fds.in)) ||
+           (error = get_fd_set(n, outp, &fds.out)) ||
+           (error = get_fd_set(n, exp, &fds.ex))) goto out;
        timeout = ~0UL;
        if (tvp) {
                error = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp));
@@ -260,17 +306,11 @@ asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct
                if (timeout)
                        timeout += jiffies + 1;
        }
-       zero_fd_set(n, &res_in);
-       zero_fd_set(n, &res_out);
-       zero_fd_set(n, &res_ex);
+       zero_fd_set(n, &fds.res_in);
+       zero_fd_set(n, &fds.res_out);
+       zero_fd_set(n, &fds.res_ex);
        current->timeout = timeout;
-       error = do_select(n,
-               (fd_set *) &in,
-               (fd_set *) &out,
-               (fd_set *) &ex,
-               (fd_set *) &res_in,
-               (fd_set *) &res_out,
-               (fd_set *) &res_ex);
+       error = do_select(n, &fds);
        timeout = current->timeout - jiffies - 1;
        current->timeout = 0;
        if ((long) timeout < 0)
@@ -289,9 +329,9 @@ asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct
                        goto out;
                error = 0;
        }
-       set_fd_set(n, inp, &res_in);
-       set_fd_set(n, outp, &res_out);
-       set_fd_set(n, exp, &res_ex);
+       set_fd_set(n, inp, &fds.res_in);
+       set_fd_set(n, outp, &fds.res_out);
+       set_fd_set(n, exp, &fds.res_ex);
 out:
        return error;
 }
index 3bd5ea3cf9b33b069dd5201618f2ffebdf825cd0..963cfa8c18bf4a438f25fb66b38c1ea375966854 100644 (file)
@@ -379,48 +379,73 @@ extern unsigned long cia_init (unsigned long mem_start,
 /*
  * Data structure for handling CIA machine checks:
  */
+/* ev5-specific info: */
+struct el_procdata {
+       unsigned long shadow[8];        /* PALmode shadow registers */
+       unsigned long paltemp[24];      /* PAL temporary registers */
+       /* EV5-specific fields */
+       unsigned long exc_addr;         /* Address of excepting instruction. */
+       unsigned long exc_sum;          /* Summary of arithmetic traps. */
+       unsigned long exc_mask;         /* Exception mask (from exc_sum). */
+       unsigned long exc_base;         /* PALbase at time of exception. */
+       unsigned long isr;              /* Interrupt summary register. */
+       unsigned long icsr;             /* Ibox control register. */
+       unsigned long ic_perr_stat;
+       unsigned long dc_perr_stat;
+       unsigned long va;               /* Effective VA of fault or miss. */
+       unsigned long mm_stat;
+       unsigned long sc_addr;
+       unsigned long sc_stat;
+       unsigned long bc_tag_addr;
+       unsigned long ei_addr;
+       unsigned long fill_syn;
+       unsigned long ei_stat;
+       unsigned long ld_lock;
+};
+
+/* system-specific info: */
 struct el_CIA_sysdata_mcheck {
-    u_long      coma_gcr;                       
-    u_long      coma_edsr;                      
-    u_long      coma_ter;                       
-    u_long      coma_elar;                      
-    u_long      coma_ehar;                      
-    u_long      coma_ldlr;                      
-    u_long      coma_ldhr;                      
-    u_long      coma_base0;                     
-    u_long      coma_base1;                     
-    u_long      coma_base2;                     
-    u_long      coma_cnfg0;                     
-    u_long      coma_cnfg1;                     
-    u_long      coma_cnfg2;                     
-    u_long      epic_dcsr;                      
-    u_long      epic_pear;                      
-    u_long      epic_sear;                      
-    u_long      epic_tbr1;                      
-    u_long      epic_tbr2;                      
-    u_long      epic_pbr1;                      
-    u_long      epic_pbr2;                      
-    u_long      epic_pmr1;                      
-    u_long      epic_pmr2;                      
-    u_long      epic_harx1;                     
-    u_long      epic_harx2;                     
-    u_long      epic_pmlt;                      
-    u_long      epic_tag0;                      
-    u_long      epic_tag1;                      
-    u_long      epic_tag2;                      
-    u_long      epic_tag3;                      
-    u_long      epic_tag4;                      
-    u_long      epic_tag5;                      
-    u_long      epic_tag6;                      
-    u_long      epic_tag7;                      
-    u_long      epic_data0;                     
-    u_long      epic_data1;                     
-    u_long      epic_data2;                     
-    u_long      epic_data3;                     
-    u_long      epic_data4;                     
-    u_long      epic_data5;                     
-    u_long      epic_data6;                     
-    u_long      epic_data7;                     
+    unsigned long      coma_gcr;                       
+    unsigned long      coma_edsr;                      
+    unsigned long      coma_ter;                       
+    unsigned long      coma_elar;                      
+    unsigned long      coma_ehar;                      
+    unsigned long      coma_ldlr;                      
+    unsigned long      coma_ldhr;                      
+    unsigned long      coma_base0;                     
+    unsigned long      coma_base1;                     
+    unsigned long      coma_base2;                     
+    unsigned long      coma_cnfg0;                     
+    unsigned long      coma_cnfg1;                     
+    unsigned long      coma_cnfg2;                     
+    unsigned long      epic_dcsr;                      
+    unsigned long      epic_pear;                      
+    unsigned long      epic_sear;                      
+    unsigned long      epic_tbr1;                      
+    unsigned long      epic_tbr2;                      
+    unsigned long      epic_pbr1;                      
+    unsigned long      epic_pbr2;                      
+    unsigned long      epic_pmr1;                      
+    unsigned long      epic_pmr2;                      
+    unsigned long      epic_harx1;                     
+    unsigned long      epic_harx2;                     
+    unsigned long      epic_pmlt;                      
+    unsigned long      epic_tag0;                      
+    unsigned long      epic_tag1;                      
+    unsigned long      epic_tag2;                      
+    unsigned long      epic_tag3;                      
+    unsigned long      epic_tag4;                      
+    unsigned long      epic_tag5;                      
+    unsigned long      epic_tag6;                      
+    unsigned long      epic_tag7;                      
+    unsigned long      epic_data0;                     
+    unsigned long      epic_data1;                     
+    unsigned long      epic_data2;                     
+    unsigned long      epic_data3;                     
+    unsigned long      epic_data4;                     
+    unsigned long      epic_data5;                     
+    unsigned long      epic_data6;                     
+    unsigned long      epic_data7;                     
 };
 
 #define RTC_PORT(x)    (0x70 + (x))
index 9cad208ceaa8e8c5bf6bdde7dca1043a96038ce6..ed6cffc1ff36cfc5f5789daf62c14a5687ce49f7 100644 (file)
@@ -150,7 +150,7 @@ extern void         _writel(unsigned int b, unsigned long addr);
 #endif
 
 /*
- * The "address" in IO memory space is not clearly either a integer or a
+ * The "address" in IO memory space is not clearly either an integer or a
  * pointer. We will accept both, thus the casts.
  *
  * On the alpha, we have the whole physical address space mapped at all
index 161e89a6fbc76b8dbc1c5be9462d37084e1ebd3b..43c6e9ecae4c7171badb8ff64d4fac990e97936f 100644 (file)
@@ -317,7 +317,6 @@ extern unsigned long lca_init (unsigned long mem_start, unsigned long mem_end);
  */
 struct el_lca_mcheck_short {
        struct el_common        h;              /* common logout header */
-       unsigned long           reason;         /* reason for machine check */
        unsigned long           esr;            /* error-status register */
        unsigned long           ear;            /* error-address register */
        unsigned long           dc_stat;        /* dcache status register */
@@ -327,7 +326,7 @@ struct el_lca_mcheck_short {
 
 struct el_lca_mcheck_long {
        struct el_common        h;              /* common logout header */
-       unsigned long           pt[32];         /* PAL temps (pt[0] is reason) */
+       unsigned long           pt[31];         /* PAL temps */
        unsigned long           exc_addr;       /* exception address */
        unsigned long           pad1[3];
        unsigned long           pal_base;       /* PALcode base address */
index 99924142be8cd6820ce87edbc426589712cf454b..a08ec81df7fdd12f58d8d8ed370536543ef37ca8 100644 (file)
@@ -20,8 +20,9 @@
 /* These are linux-specific */
 #define MAP_GROWSDOWN  0x1000          /* stack-like segment */
 #define MAP_DENYWRITE  0x2000          /* ETXTBSY */
-#define MAP_EXECUTABLE 0x4000          /* mark it as a executable */
+#define MAP_EXECUTABLE 0x4000          /* mark it as an executable */
 #define MAP_LOCKED     0x8000          /* lock the mapping */
+#define MAP_NORESERVE  0x10000         /* don't check for reservations */
 
 #define MS_ASYNC       1               /* sync memory asynchronously */
 #define MS_SYNC                2               /* synchronous memory sync */
index 02cec0f9722ccb527b85dfaff015387c798e0a06..a94d1b7ea7ffe2e604e53ea42b4ac1e206e44f4d 100644 (file)
@@ -16,7 +16,7 @@
  * EV5 this is 127.
  *
  * On the EV4, the ASNs are more-or-less useless anyway, as they are
- * only used as a icache tag, not for TB entries.  On the EV5 ASN's
+ * only used as an icache tag, not for TB entries.  On the EV5 ASN's
  * also validate the TB entries, and thus make a lot more sense.
  *
  * The EV4 ASN's don't even match the architecture manual, ugh.  And
index 5aff55201b7620b22eebf0918adf94c62389338e..4cc21418ecd316e8d91d847a1188faebb869b2bd 100644 (file)
 #define wp_works_ok 1
 #define wp_works_ok__is_a_macro /* for versions in ksyms.c */
 
+/*
+ * The VM exception save area. We need to save
+ *     return address (r26)
+ *     PC (r30)
+ *     function-call-saved regs (r9-r15)
+ * Count is used to do some basic sanity checking, and
+ * to handle the case where a kernel service itself sets
+ * up exceptions while another exception is active.
+ *
+ * NOTE: Exceptions are not "recursive": in the case above
+ * the oldest exception is the one that is left active, but
+ * the VM fault handler will notice a count != 1 and abort
+ * because exceptions within exceptions are an error.
+ */
+struct exception_struct {
+       unsigned long count;
+       unsigned long r9, r10, r11, r12, r13, r14, r15;
+       unsigned long r26, r30;
+};
+
+extern int __exception(struct exception_struct *);
+extern void __handle_exception(struct exception_struct *) __attribute__((noreturn));
+
+#define exception()    __exception(&current->tss.ex)
+#define end_exception()        (current->tss.ex.count--)
+
 struct thread_struct {
        /* the fields below are used by PALcode and must match struct pcb: */
        unsigned long ksp;
@@ -47,6 +73,7 @@ struct thread_struct {
         * bit 1..5: IEEE_TRAP_ENABLE bits (see fpu.h)
         */
        unsigned long flags;
+       struct exception_struct ex;
 };
 
 #define INIT_MMAP { &init_mm, 0xfffffc0000000000,  0xfffffc0010000000, \
@@ -56,7 +83,8 @@ struct thread_struct {
        0, 0, 0, \
        0, 0, 0, \
        0, 0, 0, \
-       0 \
+       0, \
+       { 0, } \
 }
 
 #define alloc_kernel_stack()    __get_free_page(GFP_KERNEL)
index 22f97fab11ef84b8c353ee5698584f454d859065..a9ce7164b86f0987640baa44690b8d6db1bcd5bd 100644 (file)
@@ -2,14 +2,11 @@
 #define _ASMAXP_SHMPARAM_H
 
 /*
- * Address range for shared memory attaches if no address passed to
- * shmat().  These ought to be changed to something >4GB so 32-bit
- * errors are caught more easily.  However, they don't seem to be used
- * except for ELF stuff, so it's not really critical until we get ELF
- * support for the Alpha.
+ * Address range for shared memory attaches if no address passed to shmat().
  */
-#define SHM_RANGE_START        0x50000000
-#define SHM_RANGE_END  0x60000000
+#define SHM_RANGE_START        0x14000000000
+#define SHM_RANGE_END  0x15000000000
+
 
 /*
  * Format of a swap-entry for shared memory pages currently out in
index 60f2b1f8a6c368a69282e33ddd08667b2c38d670..1f7b339107405357abf7ef443004ffb7a529c59b 100644 (file)
@@ -115,7 +115,7 @@ static void check_tlb(void)
 #ifndef CONFIG_M386
        /*
         * The 386 chips don't support TLB finegrained invalidation.
-        * They will fault when they hit a invlpg instruction.
+        * They will fault when they hit an invlpg instruction.
         */
        if (x86 == 3) {
                printk("CPU is a 386 and this kernel was compiled for 486 or better.\n");
index 0dc907bfe36eea541533f0ce85b5ba03cefee53c..5e75e8ab99d8cab573159fc05ff933b20b54f7ad 100644 (file)
@@ -153,7 +153,7 @@ __OUTS(l)
 
 /*
  * Note that due to the way __builtin_constant_p() works, you
- *  - can't use it inside a inline function (it will never be true)
+ *  - can't use it inside an inline function (it will never be true)
  *  - you don't have to worry about side effects within the __builtin..
  */
 #define outb(val,port) \
diff --git a/include/asm-i386/ipc.h b/include/asm-i386/ipc.h
new file mode 100644 (file)
index 0000000..f368d14
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __i386_IPC_H__
+#define __i386_IPC_H__
+
+/* 
+ * These are used to wrap system calls on x86.
+ *
+ * See arch/i386/kernel/sys_i386.c for ugly details..
+ */
+struct ipc_kludge {
+       struct msgbuf *msgp;
+       long msgtyp;
+};
+
+#define SEMOP           1
+#define SEMGET          2
+#define SEMCTL          3
+#define MSGSND         11
+#define MSGRCV         12
+#define MSGGET         13
+#define MSGCTL         14
+#define SHMAT          21
+#define SHMDT          22
+#define SHMGET         23
+#define SHMCTL         24
+
+#define IPCCALL(version,op)    ((version)<<16 | (op))
+
+#endif
index 69310caa26700428388104df8cf2f76fcadcbbdb..ed2287ebb05cb586fefbd76d1ab54f575d373045 100644 (file)
@@ -27,8 +27,6 @@ extern void enable_irq(unsigned int);
 
 #define SAVE_ALL \
        "cld\n\t" \
-       "push %gs\n\t" \
-       "push %fs\n\t" \
        "push %es\n\t" \
        "push %ds\n\t" \
        "pushl %eax\n\t" \
@@ -40,9 +38,7 @@ extern void enable_irq(unsigned int);
        "pushl %ebx\n\t" \
        "movl $" STR(KERNEL_DS) ",%edx\n\t" \
        "mov %dx,%ds\n\t" \
-       "mov %dx,%es\n\t" \
-       "movl $0,%edx\n\t"  \
-       "movl %edx,%db7\n\t"
+       "mov %dx,%es\n\t"
 
 /*
  * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
index 6b9b957c49ca3f1cdcead101a8a46ae54694b8f4..c5bd25f7360e7e436d930ff47b06af225dde44ac 100644 (file)
@@ -14,8 +14,9 @@
 
 #define MAP_GROWSDOWN  0x0100          /* stack-like segment */
 #define MAP_DENYWRITE  0x0800          /* ETXTBSY */
-#define MAP_EXECUTABLE 0x1000          /* mark it as a executable */
+#define MAP_EXECUTABLE 0x1000          /* mark it as an executable */
 #define MAP_LOCKED     0x2000          /* pages are locked */
+#define MAP_NORESERVE  0x4000          /* don't check for reservations */
 
 #define MS_ASYNC       1               /* sync memory asynchronously */
 #define MS_INVALIDATE  2               /* invalidate the caches */
index b3d793967cd2f0b110ee0e905ef6911d5a5946bd..d4fa45b820465d94c8a885653690b23fb2d9ed89 100644 (file)
@@ -5,7 +5,7 @@
 
 /*
  * Define USE_PENTIUM_MM if you want the 4MB page table optimizations.
- * This works only on a intel Pentium.
+ * This works only on an intel Pentium.
  */
 #define USE_PENTIUM_MM 1
 
@@ -248,8 +248,8 @@ static inline void flush_tlb_range(struct mm_struct *mm,
 #define __S111 PAGE_SHARED
 
 /*
- * Define this if things work differently on a i386 and a i486:
- * it will (on a i486) warn about kernel memory accesses that are
+ * Define this if things work differently on an i386 and an i486:
+ * it will (on an i486) warn about kernel memory accesses that are
  * done without a 'verify_area(VERIFY_WRITE,..)'
  */
 #undef TEST_VERIFY_AREA
index bb53f5ce703880fe7db1e65466cd2fb95cbf61c3..0080c8e529beb51f742408a374033809ae750963 100644 (file)
@@ -41,6 +41,59 @@ extern int EISA_bus;
  */
 #define TASK_SIZE      (0xC0000000UL)
 
+/*
+ * VM exception register save area..
+ *
+ * When no exceptions are active, count = -1.
+ */
+struct exception_struct {
+       unsigned long count;
+       unsigned long ebx;
+       unsigned long esi;
+       unsigned long edi;
+       unsigned long ebp;
+       unsigned long esp;
+       unsigned long eip;
+};
+
+extern inline int __exception(struct exception_struct *ex)
+{
+       int result;
+       __asm__("incl 0(%2)\n\t"
+               "jne 1f\n\t"
+               "movl %%ebx,4(%2)\n\t"
+               "movl %%esi,8(%2)\n\t"
+               "movl %%edi,12(%2)\n\t"
+               "movl %%ebp,16(%2)\n\t"
+               "movl %%esp,20(%2)\n\t"
+               "movl $1f,24(%2)\n"
+               "1:"
+               :"=a" (result)
+               :"0" (0), "d" (ex)
+               :"cx","memory");
+       return result;
+}
+
+extern inline void handle_exception(struct exception_struct *ex)
+{
+       if (!ex->count) {
+               ex->count--;
+               __asm__("movl  4(%0),%%ebx\n\t"
+                       "movl  8(%0),%%esi\n\t"
+                       "movl 12(%0),%%edi\n\t"
+                       "movl 16(%0),%%ebp\n\t"
+                       "movl 20(%0),%%esp\n\t"
+                       "movl 24(%0),%%eax\n\t"
+                       "jmp *%%eax"
+                       : /* no outputs */
+                       :"d" (ex)
+                       :"memory");
+       }
+}
+
+#define exception()    __exception(&current->tss.ex)
+#define end_exception()        (current->tss.ex.count--)
+
 /*
  * Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
  */
@@ -111,6 +164,7 @@ struct thread_struct {
        struct vm86_struct * vm86_info;
        unsigned long screen_bitmap;
        unsigned long v86flags, v86mask, v86mode;
+       struct exception_struct ex;
 };
 
 #define INIT_MMAP { &init_mm, 0xC0000000, 0xFFFFF000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC }
@@ -128,16 +182,21 @@ struct thread_struct {
        {~0, }, /* ioperm */ \
        _TSS(0), 0, 0, 0, KERNEL_DS, \
        { { 0, }, },  /* 387 state */ \
-       NULL, 0, 0, 0, 0 /* vm86_info */ \
+       NULL, 0, 0, 0, 0 /* vm86_info */, \
+       { -1, } \
 }
 
 #define alloc_kernel_stack()    __get_free_page(GFP_KERNEL)
 #define free_kernel_stack(page) free_page((page))
 
 #define start_thread(regs, new_eip, new_esp) do {\
-       set_fs(USER_DS); \
-       regs->cs = USER_CS; \
-       regs->ds = regs->es = regs->ss = regs->fs = regs->gs = USER_DS; \
+       unsigned long seg = USER_DS; \
+       __asm__("mov %w0,%%fs ; mov %w0,%%gs":"=r" (seg) :"0" (seg)); \
+       set_fs(seg); \
+       regs->xds = seg; \
+       regs->xes = seg; \
+       regs->xss = seg; \
+       regs->xcs = USER_CS; \
        regs->eip = new_eip; \
        regs->esp = new_esp; \
 } while (0)
index 8e4aa52f683c99569dfd738e52be8af18b6a228d..90aa9a55e49f53a07304e21e0a37a020d9c26288 100644 (file)
@@ -31,20 +31,18 @@ struct pt_regs {
        long edi;
        long ebp;
        long eax;
-       unsigned short ds, __dsu;
-       unsigned short es, __esu;
-       unsigned short fs, __fsu;
-       unsigned short gs, __gsu;
+       int  xds;
+       int  xes;
        long orig_eax;
        long eip;
-       unsigned short cs, __csu;
+       int  xcs;
        long eflags;
        long esp;
-       unsigned short ss, __ssu;
+       int  xss;
 };
 
 #ifdef __KERNEL__
-#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->cs))
+#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
 #define instruction_pointer(regs) ((regs)->eip)
 extern void show_regs(struct pt_regs *);
 #endif
index ab2711d2a3d58248259dfcb03ecdd651bf809095..f0e1f886b0049510db94a7c83038f5772921ab3a 100644 (file)
@@ -41,13 +41,29 @@ struct user_i387_struct {
        long    st_space[20];   /* 8*10 bytes for each FP-reg = 80 bytes */
 };
 
+/*
+ * This is the old layout of "struct pt_regs", and
+ * is still the layout used by user more (the new
+ * pt_regs doesn't have all registers as the kernel
+ * doesn't use the extra segment registers)
+ */
+struct user_regs_struct {
+       long ebx, ecx, edx, esi, edi, ebp, eax;
+       unsigned short ds, __ds, es, __es;
+       unsigned short fs, __fs, gs, __gs;
+       long orig_eax, eip;
+       unsigned short cs, __cs;
+       long eflags, esp;
+       unsigned short ss, __ss;
+};
+
 /* When the kernel dumps core, it starts by dumping the user struct -
    this will be used by gdb to figure out where the data and stack segments
    are within the file, and what virtual addresses to use. */
 struct user{
 /* We start with the registers, to mimic the way that "memory" is returned
    from the ptrace(3,...) function.  */
-  struct pt_regs regs;         /* Where the registers are actually stored */
+  struct user_regs_struct regs;                /* Where the registers are actually stored */
 /* ptrace does not yet supply these.  Someday.... */
   int u_fpvalid;               /* True if math co-processor being used. */
                                 /* for this mess. Not yet used. */
index dfefb56764cf782d7b9d44b3b509803e1bc8a5e6..c23f48eafe94ead0d77e178f42953da2fcb15be7 100644 (file)
@@ -14,7 +14,7 @@
 
 #define MAP_GROWSDOWN  0x0100          /* stack-like segment */
 #define MAP_DENYWRITE  0x0800          /* ETXTBSY */
-#define MAP_EXECUTABLE 0x1000          /* mark it as a executable */
+#define MAP_EXECUTABLE 0x1000          /* mark it as an executable */
 #define MAP_LOCKED     0x2000          /* pages are locked */
 
 #define MS_ASYNC       1               /* sync memory asynchronously */
index d1c5a340ab2a0f40a8d1006426f5bd732d2fe2b4..222c3676fb0fce4220bd97437a8d14b803bd6be0 100644 (file)
@@ -192,7 +192,7 @@ __OUTS(w,l,4)
 
 /*
  * Note that due to the way __builtin_constant_p() works, you
- *  - can't use it inside a inline function (it will never be true)
+ *  - can't use it inside an inline function (it will never be true)
  *  - you don't have to worry about side effects within the __builtin..
  */
 #define outb(val,port) \
index 292fd7bf47074754813b159a79bfcaea8b8c8098..f37a215c66b80720b5a7f4751727087b30cd9a65 100644 (file)
@@ -39,7 +39,7 @@
 #define MAP_ANONYMOUS  0x0800          /* don't use a file */
 #define MAP_GROWSDOWN  0x1000          /* stack-like segment */
 #define MAP_DENYWRITE  0x2000          /* ETXTBSY */
-#define MAP_EXECUTABLE 0x4000          /* mark it as a executable */
+#define MAP_EXECUTABLE 0x4000          /* mark it as an executable */
 #define MAP_LOCKED     0x8000          /* pages are locked */
 
 /*
index e0d15f04f2c4d67976a155d53fa8b259563d6844..d377dfc627dc4c3c5c5f38f7db334f45e4a203cc 100644 (file)
@@ -15,7 +15,7 @@
 
 #define MAP_GROWSDOWN  0x0100          /* stack-like segment */
 #define MAP_DENYWRITE  0x0800          /* ETXTBSY */
-#define MAP_EXECUTABLE 0x1000          /* mark it as a executable */
+#define MAP_EXECUTABLE 0x1000          /* mark it as an executable */
 
 #define MS_ASYNC       1               /* sync memory asynchronously */
 #define MS_INVALIDATE  2               /* invalidate the caches */
index 9fe0efc7ca64c74e8b12eb2157b732b9bc438b0d..b8425f882001c88266b160a49c95cfc68aa1452b 100644 (file)
@@ -168,8 +168,8 @@ do { if ((mm_struct) == current->mm) invalidate(); else printk("Can't invalidate
 #endif
 
 /*
- * Define this if things work differently on a i386 and a i486:
- * it will (on a i486) warn about kernel memory accesses that are
+ * Define this if things work differently on an i386 and an i486:
+ * it will (on an i486) warn about kernel memory accesses that are
  * done without a 'verify_area(VERIFY_WRITE,..)'
  */
 #undef CONFIG_TEST_VERIFY_AREA
index c69d6771ef8983ebb2579fa8182617f31633e65c..cebf2384d9b4c52d8bf41fce024fe4c8dfd0b8d1 100644 (file)
@@ -22,7 +22,7 @@
 
 #define MAP_GROWSDOWN  0x0100          /* stack-like segment */
 #define MAP_DENYWRITE  0x0800          /* ETXTBSY */
-#define MAP_EXECUTABLE 0x1000          /* mark it as a executable */
+#define MAP_EXECUTABLE 0x1000          /* mark it as an executable */
 
 #define MS_ASYNC       1               /* sync memory asynchronously */
 #define MS_INVALIDATE  2               /* invalidate the caches */
index da47f8c399742ab9897ca2ebe5bd7d7a0bb5e7a9..790cff4488fada2a0a8751a95564261aded5c080 100644 (file)
@@ -27,7 +27,7 @@
  * in linux/version.h, and should only be used by linux/version.c
  */
 
-/* Shouldn't these be defined somewhere in a i386 definition? */
+/* Shouldn't these be defined somewhere in an i386 definition? */
 
 /* Don't touch these, unless you really know what you're doing. */
 #define DEF_INITSEG    0x9000
index 3878e0203d11beea336040f72cb3ecffb689cd99..9349f0f4970ab9698c2b56228c5c2f77d7c20799 100644 (file)
@@ -1,22 +1,21 @@
 #ifndef _LINUX_IPC_H
 #define _LINUX_IPC_H
+
 #include <linux/types.h>
 
-typedef int key_t;             /* should go in <types.h> type for IPC key */
-#define IPC_PRIVATE ((key_t) 0)  
+#define IPC_PRIVATE ((__kernel_key_t) 0)  
 
 struct ipc_perm
 {
-  key_t  key;
-  ushort uid;   /* owner euid and egid */
-  ushort gid;
-  ushort cuid;  /* creator euid and egid */
-  ushort cgid;
-  ushort mode;  /* access modes see mode flags below */
-  ushort seq;   /* sequence number */
+       __kernel_key_t  key;
+       __kernel_uid_t  uid;
+       __kernel_gid_t  gid;
+       __kernel_uid_t  cuid;
+       __kernel_gid_t  cgid;
+       __kernel_mode_t mode; 
+       unsigned short  seq;
 };
 
-
 /* resource get request flags */
 #define IPC_CREAT  00001000   /* create if key is nonexistent */
 #define IPC_EXCL   00002000   /* fail if key exists */
@@ -38,28 +37,6 @@ struct ipc_perm
 #define IPC_UNUSED     ((void *) -1)
 #define IPC_NOID       ((void *) -2)           /* being allocated/destroyed */
 
-/* 
- * These are used to wrap system calls. See ipc/util.c.
- */
-struct ipc_kludge {
-    struct msgbuf *msgp;
-    long msgtyp;
-};
-
-#define SEMOP          1
-#define SEMGET                 2
-#define SEMCTL                 3
-#define MSGSND                 11
-#define MSGRCV                 12
-#define MSGGET                 13
-#define MSGCTL                 14
-#define SHMAT          21
-#define SHMDT          22
-#define SHMGET                 23
-#define SHMCTL                 24
-
-#define IPCCALL(version,op)    ((version)<<16 | (op))
-
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_IPC_H */
index 201fa17312ca9386b9ff7017d751b9a754b15023..4a0f401b00ae7eed6b09d74d9e51f559291eac03 100644 (file)
@@ -14,11 +14,26 @@ extern void * high_memory;
 
 #include <asm/page.h>
 #include <asm/atomic.h>
+#include <asm/segment.h>
 
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
 
-extern int verify_area(int, const void *, unsigned long);
+extern int __verify_write(const void *, unsigned long);
+
+#define verify_write(type,addr,size) \
+(((type) && !wp_works_ok)?__verify_write((addr),(size)):0)
+
+extern inline int verify_area(int type, const void * addr, unsigned long size)
+{
+       int retval = 0;
+       if (get_fs() != KERNEL_DS) {
+               retval = -EFAULT;
+               if (size <= TASK_SIZE && TASK_SIZE-size >= (unsigned long) addr)
+                       retval = verify_write(type,addr,size);
+       }
+       return retval;
+}
 
 /*
  * Linux kernel virtual memory manager primitives.
@@ -333,17 +348,18 @@ static inline struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned l
        struct vm_area_struct * result = NULL;
 
        if (mm) {
-               struct vm_area_struct * tree = mm->mmap_avl;
+               struct vm_area_struct ** next = &mm->mmap_avl;
                for (;;) {
+                       struct vm_area_struct *tree = *next;
                        if (tree == avl_empty)
                                break;
-                       if (tree->vm_end > addr) {
-                               result = tree;
-                               if (tree->vm_start <= addr)
-                                       break;
-                               tree = tree->vm_avl_left;
-                       } else
-                               tree = tree->vm_avl_right;
+                       next = &tree->vm_avl_right;
+                       if (tree->vm_end <= addr)
+                               continue;
+                       next = &tree->vm_avl_left;
+                       result = tree;
+                       if (tree->vm_start <= addr)
+                               break;
                }
        }
        return result;
index ff20f49e95a4b9dc4423eec49ab90fc19a28392e..fc26e11207a5c4f4cadc2aefeb47c7241c995c89 100644 (file)
@@ -1,5 +1,6 @@
 #ifndef _LINUX_MSG_H
 #define _LINUX_MSG_H
+
 #include <linux/ipc.h>
 
 /* msgrcv options */
@@ -8,37 +9,37 @@
 
 /* one msqid structure for each queue on the system */
 struct msqid_ds {
-    struct ipc_perm msg_perm;
-    struct msg *msg_first;  /* first message on queue */
-    struct msg *msg_last;   /* last message in queue */
-    time_t msg_stime;       /* last msgsnd time */
-    time_t msg_rtime;       /* last msgrcv time */
-    time_t msg_ctime;       /* last change time */
-    struct wait_queue *wwait;
-    struct wait_queue *rwait;
-    ushort msg_cbytes;      /* current number of bytes on queue */
-    ushort msg_qnum;        /* number of messages in queue */
-    ushort msg_qbytes;      /* max number of bytes on queue */
-    ushort msg_lspid;       /* pid of last msgsnd */
-    ushort msg_lrpid;       /* last receive pid */
+       struct ipc_perm msg_perm;
+       struct msg *msg_first;          /* first message on queue */
+       struct msg *msg_last;           /* last message in queue */
+       __kernel_time_t msg_stime;      /* last msgsnd time */
+       __kernel_time_t msg_rtime;      /* last msgrcv time */
+       __kernel_time_t msg_ctime;      /* last change time */
+       struct wait_queue *wwait;
+       struct wait_queue *rwait;
+       unsigned short msg_cbytes;      /* current number of bytes on queue */
+       unsigned short msg_qnum;        /* number of messages in queue */
+       unsigned short msg_qbytes;      /* max number of bytes on queue */
+       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
+       __kernel_pid_t msg_lrpid;       /* last receive pid */
 };
 
 /* message buffer for msgsnd and msgrcv calls */
 struct msgbuf {
-    long mtype;         /* type of message */
-    char mtext[1];      /* message text */
+       long mtype;         /* type of message */
+       char mtext[1];      /* message text */
 };
 
 /* buffer for msgctl calls IPC_INFO, MSG_INFO */
 struct msginfo {
-    int msgpool;
-    int msgmap; 
-    int msgmax; 
-    int msgmnb; 
-    int msgmni; 
-    int msgssz; 
-    int msgtql; 
-    ushort  msgseg; 
+       int msgpool;
+       int msgmap; 
+       int msgmax; 
+       int msgmnb; 
+       int msgmni; 
+       int msgssz; 
+       int msgtql; 
+       unsigned short  msgseg; 
 };
 
 #define MSGMNI   128   /* <= 1K */     /* max # of msg queue identifiers */
@@ -57,11 +58,11 @@ struct msginfo {
 
 /* one msg structure for each message */
 struct msg {
-    struct msg *msg_next;   /* next message on queue */
-    long  msg_type;          
-    char *msg_spot;         /* message text address */
-    time_t msg_stime;       /* msgsnd time */
-    short msg_ts;           /* message text size */
+       struct msg *msg_next;   /* next message on queue */
+       long  msg_type;          
+       char *msg_spot;         /* message text address */
+       time_t msg_stime;       /* msgsnd time */
+       short msg_ts;           /* message text size */
 };
 
 /* ipcs ctl commands */
index 39f193cf1d12ab7b0f7155a61c6bf21a1edcd147..f0ccb3bb9ada48e4b8bca73dee0267282f95bafe 100644 (file)
@@ -45,6 +45,12 @@ typedef struct fd_set {
        unsigned long fds_bits [__FDSET_LONGS];
 } __kernel_fd_set;
 
+/* Type of a signal handler.  */
+typedef void (*__kernel_sighandler_t)(int);
+
+/* Type of a SYSV IPC key.  */
+typedef int __kernel_key_t;
+
 #include <asm/posix_types.h>
 
 #endif /* _LINUX_POSIX_TYPES_H */
index 4a0f7322cfe7e5b685d2d666cd0afc9e99521d78..caccf16c238b5a2a6a903b3dee0fe6038d5710b6 100644 (file)
@@ -155,7 +155,7 @@ enum scsi_directory_inos {
 
 /*
  * This is not completely implemented yet. The idea is to
- * create a in-memory tree (like the actual /proc filesystem
+ * create an in-memory tree (like the actual /proc filesystem
  * tree) of these proc_dir_entries, so that we can dynamically
  * add new files to /proc.
  *
index 0eb1d0246e4f1a94b26edbfad143d223ba682cf9..6a94e1884825b7903a7625cbfe367229af36b440 100644 (file)
@@ -1,5 +1,6 @@
 #ifndef _LINUX_SEM_H
 #define _LINUX_SEM_H
+
 #include <linux/ipc.h>
 
 /* semop flags */
 
 /* One semid data structure for each set of semaphores in the system. */
 struct semid_ds {
-  struct ipc_perm sem_perm;            /* permissions .. see ipc.h */
-  time_t          sem_otime;           /* last semop time */
-  time_t          sem_ctime;           /* last change time */
-  struct sem      *sem_base;           /* ptr to first semaphore in array */
-  struct sem_queue *sem_pending;       /* pending operations to be processed */
-  struct sem_queue **sem_pending_last; /* last pending operation */
-  struct sem_undo *undo;              /* undo requests on this array */
-  ushort          sem_nsems;           /* no. of semaphores in array */
+       struct ipc_perm sem_perm;               /* permissions .. see ipc.h */
+       __kernel_time_t sem_otime;              /* last semop time */
+       __kernel_time_t sem_ctime;              /* last change time */
+       struct sem      *sem_base;              /* ptr to first semaphore in array */
+       struct sem_queue *sem_pending;          /* pending operations to be processed */
+       struct sem_queue **sem_pending_last;    /* last pending operation */
+       struct sem_undo *undo;                  /* undo requests on this array */
+       unsigned short  sem_nsems;              /* no. of semaphores in array */
 };
 
 /* semop system calls takes an array of these. */
 struct sembuf {
-  ushort  sem_num;        /* semaphore index in array */
-  short   sem_op;         /* semaphore operation */
-  short   sem_flg;        /* operation flags */
+       unsigned short  sem_num;        /* semaphore index in array */
+       short           sem_op;         /* semaphore operation */
+       short           sem_flg;        /* operation flags */
 };
 
 /* arg for semctl system calls. */
 union semun {
-  int val;                     /* value for SETVAL */
-  struct semid_ds *buf;                /* buffer for IPC_STAT & IPC_SET */
-  ushort *array;               /* array for GETALL & SETALL */
-  struct seminfo *__buf;       /* buffer for IPC_INFO */
-  void *__pad;
+       int val;                        /* value for SETVAL */
+       struct semid_ds *buf;           /* buffer for IPC_STAT & IPC_SET */
+       unsigned short *array;          /* array for GETALL & SETALL */
+       struct seminfo *__buf;          /* buffer for IPC_INFO */
+       void *__pad;
 };
 
 struct  seminfo {
-    int semmap;
-    int semmni;
-    int semmns;
-    int semmnu;
-    int semmsl;
-    int semopm;
-    int semume;
-    int semusz;
-    int semvmx;
-    int semaem;
+       int semmap;
+       int semmni;
+       int semmns;
+       int semmnu;
+       int semmsl;
+       int semopm;
+       int semume;
+       int semusz;
+       int semvmx;
+       int semaem;
 };
 
 #define SEMMNI  128             /* ?  max # of semaphore identifiers */
@@ -72,8 +73,8 @@ struct  seminfo {
 
 /* One semaphore structure for each semaphore in the system. */
 struct sem {
-  short   semval;         /* current value */
-  short   sempid;         /* pid of last operation */
+       int     semval;         /* current value */
+       int     sempid;         /* pid of last operation */
 };
 
 /* ipcs ctl cmds */
@@ -82,25 +83,25 @@ struct sem {
 
 /* One queue for each semaphore set in the system. */
 struct sem_queue {
-    struct sem_queue * next;    /* next entry in the queue */
-    struct sem_queue **        prev;    /* previous entry in the queue, *(q->prev) == q */
-    struct wait_queue *        sleeper; /* sleeping process */
-    struct sem_undo *  undo;    /* undo structure */
-    int                pid;     /* process id of requesting process */
-    int                status;  /* completion status of operation */
-    struct semid_ds *  sma;     /* semaphore array for operations */
-    struct sembuf *    sops;    /* array of pending operations */
-    int                        nsops;   /* number of operations */
+       struct sem_queue *      next;    /* next entry in the queue */
+       struct sem_queue **     prev;    /* previous entry in the queue, *(q->prev) == q */
+       struct wait_queue *     sleeper; /* sleeping process */
+       struct sem_undo *       undo;    /* undo structure */
+       int                     pid;     /* process id of requesting process */
+       int                     status;  /* completion status of operation */
+       struct semid_ds *       sma;     /* semaphore array for operations */
+       struct sembuf *         sops;    /* array of pending operations */
+       int                     nsops;   /* number of operations */
 };
 
 /* Each task has a list of undo requests. They are executed automatically
  * when the process exits.
  */
 struct sem_undo {
-    struct sem_undo *  proc_next; /* next entry on this process */
-    struct sem_undo *  id_next;          /* next entry on this semaphore set */
-    int                       semid;     /* semaphore set identifier */
-    short *           semadj;    /* array of adjustments, one per semaphore */
+       struct sem_undo *       proc_next;      /* next entry on this process */
+       struct sem_undo *       id_next;        /* next entry on this semaphore set */
+       int                     semid;          /* semaphore set identifier */
+       short *                 semadj;         /* array of adjustments, one per semaphore */
 };
 
 asmlinkage int sys_semget (key_t key, int nsems, int semflg);
index 042c54106f901966f767df1d84c33b9f59b4e697..7fb751360a288db182724017a294825700b0df6e 100644 (file)
@@ -7,13 +7,13 @@
 
 struct shmid_ds {
        struct ipc_perm shm_perm;       /* operation perms */
-       int     shm_segsz;              /* size of segment (bytes) */
-       time_t  shm_atime;              /* last attach time */
-       time_t  shm_dtime;              /* last detach time */
-       time_t  shm_ctime;              /* last change time */
-       unsigned short  shm_cpid;       /* pid of creator */
-       unsigned short  shm_lpid;       /* pid of last operator */
-       short   shm_nattch;             /* no. of current attaches */
+       int             shm_segsz;              /* size of segment (bytes) */
+       __kernel_time_t shm_atime;              /* last attach time */
+       __kernel_time_t shm_dtime;              /* last detach time */
+       __kernel_time_t shm_ctime;              /* last change time */
+       __kernel_pid_t  shm_cpid;       /* pid of creator */
+       __kernel_pid_t  shm_lpid;       /* pid of last operator */
+       unsigned short  shm_nattch;             /* no. of current attaches */
        /* the following are private */
        unsigned short   shm_npages;    /* size of segment (pages) */
        unsigned long   *shm_pages;     /* array of ptrs to frames -> SHMMAX */ 
@@ -34,11 +34,11 @@ struct shmid_ds {
 #define SHM_UNLOCK     12
 
 struct shminfo {
-    int shmmax;        
-    int shmmin;        
-    int shmmni;        
-    int shmseg;        
-    int shmall;        
+       int shmmax;
+       int shmmin;
+       int shmmni;
+       int shmseg;
+       int shmall;
 };
 
 #ifdef __KERNEL__
@@ -50,21 +50,21 @@ struct      shminfo {
 /* ipcs ctl commands */
 #define SHM_STAT       13
 #define SHM_INFO       14
+
 struct shm_info {
-       int   used_ids;
-       ulong shm_tot; /* total allocated shm */
-       ulong shm_rss; /* total resident shm */
-       ulong shm_swp; /* total swapped shm */
-       ulong swap_attempts;
-       ulong swap_successes;
+       int used_ids;
+       unsigned long shm_tot;  /* total allocated shm */
+       unsigned long shm_rss;  /* total resident shm */
+       unsigned long shm_swp;  /* total swapped shm */
+       unsigned long swap_attempts;
+       unsigned long swap_successes;
 };
 
 asmlinkage int sys_shmget (key_t key, int size, int flag);
-asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *addr);
+asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, unsigned long *addr);
 asmlinkage int sys_shmdt (char *shmaddr);
 asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
 
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_SHM_H_ */
-
index c1753186143c29f8bfefa851210e3df6d7274311..dee4875d1b7513ccbdb81a3f6e6b2c72d16516b3 100644 (file)
@@ -184,7 +184,7 @@ struct patch_info {
  *
  * The low_note and high_note fields define the minimum and maximum note
  * frequencies for which this sample is valid. It is possible to define
- * more than one samples for a instrument number at the same time. The
+ * more than one samples for an instrument number at the same time. The
  * low_note and high_note fields are used to select the most suitable one.
  *
  * The fields base_note, high_note and low_note should contain
@@ -267,7 +267,7 @@ struct patmgr_info {
          unsigned int key;     /* Don't worry. Reserved for communication
                                   between the patch manager and the driver. */
 #define PM_K_EVENT             1 /* Event from the /dev/sequencer driver */
-#define PM_K_COMMAND           2 /* Request from a application */
+#define PM_K_COMMAND           2 /* Request from an application */
 #define PM_K_RESPONSE          3 /* From patmgr to application */
 #define PM_ERROR               4 /* Error returned by the patmgr */
          int device;
index 9a0270bcdc552229e1a12acdba7521402bbb82c0..ff5420832ce870471a9a6b59a57bb08e4dfcdade 100644 (file)
@@ -73,7 +73,7 @@
 
 /*
  * The SHIFT_SCALE define establishes the decimal point of the time_phase
- * variable which serves as a an extension to the low-order bits of the
+ * variable which serves as an extension to the low-order bits of the
  * system clock variable. The SHIFT_UPDATE define establishes the decimal
  * point of the time_offset variable which represents the current offset
  * with respect to standard time. The FINEUSEC define represents 1 usec in
index 28e9bde7acee6e3da3ac5c3bc840d2738cf18f40..7f98711a41a29f7d7044faad7a92231fab371681 100644 (file)
@@ -16,6 +16,7 @@ typedef __kernel_pid_t                pid_t;
 typedef __kernel_uid_t         uid_t;
 typedef __kernel_gid_t         gid_t;
 typedef __kernel_daddr_t       daddr_t;
+typedef __kernel_key_t         key_t;
 
 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
 typedef __kernel_loff_t                loff_t;
index 82714831f8ef6af5f47c0c0af5501577123e77b1..d9e8a4e8a48d0f78e132b840bba0993e640fa198 100644 (file)
@@ -159,7 +159,7 @@ extern void tcp_send_delayed_ack(struct sock *sk, int max_timeout, unsigned long
 extern void tcp_send_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
          struct proto *prot, struct options *opt, struct device *dev, int tos, int ttl);
 
-extern void tcp_enqueue_partial(struct sk_buff *, struct sock *);
+extern void tcp_enqueue_partial(struct sock *, struct sk_buff *);
 extern struct sk_buff * tcp_dequeue_partial(struct sock *);
 extern void tcp_shrink_skb(struct sock *,struct sk_buff *,u32);
 
index 8922277d623b13a0fdf7d66fb5545c9251e43852..b81311860f882b43143988384272a49b870e2b42 100644 (file)
@@ -849,7 +849,7 @@ asmlinkage void start_kernel(void)
  * anything that can be useful, but shouldn't take time from the real
  * processes.
  *
- * Right now task[0] just does a infinite idle loop.
+ * Right now task[0] just does an infinite idle loop.
  */
        cpu_idle(NULL);
 }
index 650271d834ca99472ce50f3948be62a7bdcd2e62..38d01794f6bff4f9699e0737c52dcef223ab325a 100644 (file)
@@ -119,7 +119,7 @@ struct symbol_table symbol_table = {
 #endif
 
        /* process memory management */
-       X(verify_area),
+       X(__verify_write),
        X(do_mmap),
        X(do_munmap),
        X(exit_mm),
index 7626e4d22a65d3e13c660c7465108b0bddbd8948..a36f3b5e1b688af3a31bc73eab1f0fadfa4ac6d7 100644 (file)
@@ -657,14 +657,17 @@ success:
                 */
        {
                unsigned long offset, nr;
+
+               if (exception())
+                       goto page_read_exception;
                offset = pos & ~PAGE_MASK;
                nr = PAGE_SIZE - offset;
                if (nr > count)
                        nr = count;
-
                if (nr > inode->i_size - pos)
                        nr = inode->i_size - pos;
                memcpy_tofs(buf, (void *) (page_address(page) + offset), nr);
+               end_exception();
                release_page(page);
                buf += nr;
                pos += nr;
@@ -738,6 +741,11 @@ page_read_error:
                }
                release_page(page);
                break;
+
+page_read_exception:
+               error = -EFAULT;
+               release_page(page);
+               break;
        }
 
        filp->f_pos = pos;
index b9007738282f1707815ab741b5738ad27d6ea1dc..e50d8e79141a522f802ab4c25275ed96b9dcfbea 100644 (file)
@@ -678,16 +678,12 @@ end_wp_page:
 /*
  * Ugly, ugly, but the goto's result in better assembly..
  */
-int verify_area(int type, const void * addr, unsigned long size)
+int __verify_write(const void * addr, unsigned long size)
 {
        struct vm_area_struct * vma;
        unsigned long start = (unsigned long) addr;
 
-       /* If the current user space is mapped to kernel space (for the
-        * case where we use a fake user buffer with get_fs/set_fs()) we
-        * don't expect to find the address in the user vm map.
-        */
-       if (!size || get_fs() == KERNEL_DS)
+       if (!size)
                return 0;
 
        vma = find_vma(current->mm, start);
@@ -697,37 +693,8 @@ int verify_area(int type, const void * addr, unsigned long size)
                goto check_stack;
 
 good_area:
-       if (type == VERIFY_WRITE)
-               goto check_write;
-       for (;;) {
-               struct vm_area_struct * next;
-               if (!(vma->vm_flags & VM_READ))
-                       goto bad_area;
-               if (vma->vm_end - start >= size)
-                       return 0;
-               next = vma->vm_next;
-               if (!next || vma->vm_end != next->vm_start)
-                       goto bad_area;
-               vma = next;
-       }
-
-check_write:
        if (!(vma->vm_flags & VM_WRITE))
                goto bad_area;
-       if (!wp_works_ok)
-               goto check_wp_fault_by_hand;
-       for (;;) {
-               if (vma->vm_end - start >= size)
-                       break;
-               if (!vma->vm_next || vma->vm_end != vma->vm_next->vm_start)
-                       goto bad_area;
-               vma = vma->vm_next;
-               if (!(vma->vm_flags & VM_WRITE))
-                       goto bad_area;
-       }
-       return 0;
-
-check_wp_fault_by_hand:
        size--;
        size += start & ~PAGE_MASK;
        size >>= PAGE_SHIFT;
@@ -914,7 +881,7 @@ void do_no_page(struct task_struct * tsk, struct vm_area_struct * vma,
         * for other architectures too.
         *
         * Note that if write_access is true, we either now have
-        * a exclusive copy of the page, or this is a shared mapping,
+        * an exclusive copy of the page, or this is a shared mapping,
         * so we can make it writable and dirty to avoid having to
         * handle that later.
         */
index 69e4d402e36388dc2edeca1a651b128672af8aab..31ccee0910477af3305abba6c0743b15c9cb8935 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -255,7 +255,8 @@ unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len,
 
        /* Private writable mapping? Check memory availability.. */
        if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE) {
-               if (!vm_enough_memory(len >> PAGE_SHIFT)) {
+               if (!(flags & MAP_NORESERVE) &&
+                   !vm_enough_memory(len >> PAGE_SHIFT)) {
                        kfree(vma);
                        return -ENOMEM;
                }
index 393d0241c8fa7780cf936c5c14ab5c3dd49b0c8f..06047de205802d0a6410646fc8a3852291c5e5e2 100644 (file)
@@ -888,6 +888,54 @@ static void wait_for_tcp_memory(struct sock * sk)
        lock_sock(sk);
 }
 
+/*
+ * Add more stuff to the end of skb->len
+ */
+static int fill_in_partial_skb(struct sock *sk, struct sk_buff *skb,
+       unsigned char * from, int seglen)
+{
+       void (*send)(struct sock *sk, struct sk_buff *skb);
+       int copy, tcp_size;
+
+       tcp_size = skb->tail - (unsigned char *)(skb->h.th + 1);
+
+       /*
+        *      Now we may find the frame is as big, or too
+        *      big for our MSS. Thats all fine. It means the
+        *      MSS shrank (from an ICMP) after we allocated 
+        *      this frame.
+        */
+
+       copy = sk->mss - tcp_size;
+       if (copy <= 0) {
+               tcp_send_skb(sk, skb);
+               return 0;
+       }
+
+       /*
+        *      Otherwise continue to fill the buffer.
+        */
+       send = tcp_send_skb;
+       if (copy > seglen) {
+               send = tcp_enqueue_partial;
+               copy = seglen;
+       }
+       if (exception()) {
+               tcp_enqueue_partial(sk, skb);
+               return -EFAULT;
+       }
+       memcpy_fromfs(skb->tail, from, copy);
+       end_exception();
+       tcp_size += copy;
+       skb->tail += copy;
+       skb->len += copy;
+       skb->csum = csum_partial(skb->tail - tcp_size, tcp_size, 0);
+       if (!sk->packets_out)
+               send = tcp_send_skb;
+       send(sk, skb);
+       return copy;
+}
+
 
 /*
  *     This routine copies from a user buffer into a socket,
@@ -937,9 +985,10 @@ static int do_tcp_sendmsg(struct sock *sk,
 
                while(seglen > 0)
                {
-                       int copy, delay;
+                       int copy;
                        int tmp;
                        struct sk_buff *skb;
+                       void (*send)(struct sock *, struct sk_buff *);
 
                        /*
                         * Stop on errors
@@ -1004,56 +1053,21 @@ static int do_tcp_sendmsg(struct sock *sk,
                         *      If there is a partly filled frame we can fill
                         *      out.
                         */
-                       if ((skb = tcp_dequeue_partial(sk)) != NULL)
-                       {
-                               int tcp_size;
-
-                               tcp_size = skb->tail - (unsigned char *)(skb->h.th + 1);
-
-                               /* Add more stuff to the end of skb->len */
-                               if (!(flags & MSG_OOB))
-                               {
-                                       copy = min(sk->mss - tcp_size, seglen);
-                                       
-                                       /*
-                                        *      Now we may find the frame is as big, or too
-                                        *      big for our MSS. Thats all fine. It means the
-                                        *      MSS shrank (from an ICMP) after we allocated 
-                                        *      this frame.
-                                        */
-                                        
-                                       if (copy <= 0)
-                                       {
-                                               /*
-                                                *      Send the now forced complete frame out. 
-                                                *
-                                                *      Note for 2.1: The MSS reduce code ought to
-                                                *      flush any frames in partial that are now
-                                                *      full sized. Not serious, potential tiny
-                                                *      performance hit.
-                                                */
-                                               tcp_send_skb(sk,skb);
-                                               /*
-                                                *      Get a new buffer and try again.
-                                                */
-                                               continue;
-                                       }
-                                       /*
-                                        *      Otherwise continue to fill the buffer.
-                                        */
-                                       tcp_size += copy;
-                                       memcpy_fromfs(skb_put(skb,copy), from, copy);
-                                       skb->csum = csum_partial(skb->tail - tcp_size, tcp_size, 0);
-                                       from += copy;
-                                       copied += copy;
-                                       len -= copy;
-                                       sk->write_seq += copy;
-                                       seglen -= copy;
+                       skb = tcp_dequeue_partial(sk);
+                       if (skb) {
+                               if (!(flags & MSG_OOB)) {
+                                       int retval;
+                                       retval = fill_in_partial_skb(sk, skb, from, seglen);
+                                       if (retval < 0)
+                                               return retval;
+                                       seglen -= retval;
+                                       from += retval;
+                                       copied += retval;
+                                       len -= retval;
+                                       sk->write_seq += retval;
+                                       continue;
                                }
-                               if (tcp_size >= sk->mss || (flags & MSG_OOB) || !sk->packets_out)
-                                       tcp_send_skb(sk, skb);
-                               else
-                                       tcp_enqueue_partial(skb, sk);
+                               tcp_send_skb(sk, skb);
                                continue;
                        }
 
@@ -1084,12 +1098,12 @@ static int do_tcp_sendmsg(struct sock *sk,
                         *      We should really check the window here also.
                         */
 
-                       delay = 0;
+                       send = tcp_send_skb;
                        tmp = copy + sk->prot->max_header + 15;
                        if (copy < sk->mss && !(flags & MSG_OOB) && sk->packets_out)
                        {
                                tmp = tmp - copy + sk->mtu + 128;
-                               delay = 1;
+                               send = tcp_enqueue_partial;
                        }
                        skb = sock_wmalloc(sk, tmp, 0, GFP_KERNEL);
 
@@ -1156,23 +1170,27 @@ static int do_tcp_sendmsg(struct sock *sk,
                                skb->h.th->urg_ptr = ntohs(copy);
                        }
 
+                       if (exception())
+                               goto bad_access;
                        skb->csum = csum_partial_copy_fromuser(from,
-                               skb_put(skb,copy), copy, 0);
-
+                               skb->tail, copy, 0);
+                       end_exception();
+                       skb->tail += copy;
+                       skb->len += copy;
                        from += copy;
                        copied += copy;
                        len -= copy;
                        seglen -= copy;
-                       skb->free = 0;
                        sk->write_seq += copy;
+                       skb->free = 0;
 
-                       if (delay)
-                       {
-                               tcp_enqueue_partial(skb, sk);
-                               continue;
+                       send(sk, skb);
+                       continue;
+
+bad_access:
+                       sock_wfree(sk, skb);
+                       return -EFAULT;
                        }
-                       tcp_send_skb(sk, skb);
-               }
        }
        sk->err = 0;
 
@@ -1829,7 +1847,7 @@ static void tcp_close(struct sock *sk, unsigned long timeout)
 
 
 /*
- * Wait for a incoming connection, avoid race
+ * Wait for an incoming connection, avoid race
  * conditions. This must be called with the socket
  * locked.
  */
index 9cf24fb57ebf661c44a66f4ca52426c0ae33112e..179559551304c35e54b3b73892275ea71fca4fe7 100644 (file)
@@ -184,7 +184,7 @@ static inline struct sock * get_tcp_sock(u32 saddr, u16 sport, u32 daddr, u16 dp
 }
 
 /*
- * React to a out-of-window TCP sequence number in an incoming packet
+ * React to an out-of-window TCP sequence number in an incoming packet
  */
  
 static void bad_tcp_sequence(struct sock *sk, struct tcphdr *th, u32 end_seq,
index 9ca4ab140e9d4d525016616665d633402a1858f4..78a806952d0a205f87d830110038bc1570130cc6 100644 (file)
@@ -264,7 +264,7 @@ void tcp_send_partial(struct sock *sk)
  *     Queue a partial frame
  */
  
-void tcp_enqueue_partial(struct sk_buff * skb, struct sock * sk)
+void tcp_enqueue_partial(struct sock * sk, struct sk_buff * skb)
 {
        struct sk_buff * tmp;
        unsigned long flags;
@@ -895,7 +895,7 @@ void tcp_send_delayed_ack(struct sock * sk, int max_timeout, unsigned long timeo
                timeout = 0;
        timeout += jiffies;
 
-       /* Use new timeout only if there wasn't a older one earlier  */
+       /* Use new timeout only if there wasn't an older one earlier  */
        if (!del_timer(&sk->delack_timer) || timeout < sk->delack_timer.expires)
                sk->delack_timer.expires = timeout;
 
index ea0bda9c82ca31a660d2ca7916aab63ee72fcaa9..37cf7acb575c7624deb5f6adfda0bb183969c9d3 100644 (file)
@@ -931,9 +931,9 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
                 *      have suggested. Big mallocs stress the vm too
                 *      much.
                 */
-
-               if(size > 4000 && sock->type!=SOCK_DGRAM)
-                       limit = 4000;   /* Fall back to 4K if we can't grab a big buffer this instant */
+#define MAX_ALLOC (PAGE_SIZE*7/8)
+               if(size > MAX_ALLOC && sock->type!=SOCK_DGRAM)
+                       limit = MAX_ALLOC;      /* Fall back to 4K if we can't grab a big buffer this instant */
                else
                        limit = 0;      /* Otherwise just grab and wait */