## Automatically generated incremental diff
## From:   linux-2.0.31-pre9
## To:     linux-2.0.31-pre10
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.0.31-pre9/arch/i386/defconfig linux-2.0.31-pre10/arch/i386/defconfig
--- linux-2.0.31-pre9/arch/i386/defconfig	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/arch/i386/defconfig	2003-08-15 15:04:13.000000000 -0700
@@ -150,7 +150,6 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
 
 #
 # Character devices
diff -urN linux-2.0.31-pre9/arch/i386/kernel/entry.S linux-2.0.31-pre10/arch/i386/kernel/entry.S
--- linux-2.0.31-pre9/arch/i386/kernel/entry.S	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/arch/i386/kernel/entry.S	2003-08-15 15:04:13.000000000 -0700
@@ -259,7 +259,6 @@
 	iret
 #endif
 
-
 ENTRY(lcall7)
 	pushfl			# We get a different stack layout with call gates,
 	pushl %eax		# which has to be cleaned up later..
diff -urN linux-2.0.31-pre9/arch/i386/kernel/ksyms.c linux-2.0.31-pre10/arch/i386/kernel/ksyms.c
--- linux-2.0.31-pre9/arch/i386/kernel/ksyms.c	1997-04-08 08:47:45.000000000 -0700
+++ linux-2.0.31-pre10/arch/i386/kernel/ksyms.c	2003-08-15 15:04:13.000000000 -0700
@@ -2,6 +2,7 @@
 #include <linux/smp.h>
 #include <linux/user.h>
 #include <linux/elfcore.h>
+#include <linux/delay.h>
 
 #include <asm/semaphore.h>
 
@@ -13,6 +14,7 @@
 	/* platform dependent support */
 	X(dump_thread),
 	X(dump_fpu),
+	XNOVERS(__do_delay),
 	XNOVERS(down_failed),
 	XNOVERS(down_failed_interruptible),
 	XNOVERS(up_wakeup),
diff -urN linux-2.0.31-pre9/arch/i386/lib/delay.S linux-2.0.31-pre10/arch/i386/lib/delay.S
--- linux-2.0.31-pre9/arch/i386/lib/delay.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.0.31-pre10/arch/i386/lib/delay.S	2003-08-15 15:04:13.000000000 -0700
@@ -0,0 +1,14 @@
+#include <linux/linkage.h>
+
+/*
+ * BogoMips loop. Non-inlined because various x86's have so wildly
+ * varying results depending on the exact alignment.
+ */
+
+ENTRY(__do_delay)
+1:	decl %eax
+	jns 1b
+	ret
+
+
+
diff -urN linux-2.0.31-pre9/arch/i386/lib/Makefile linux-2.0.31-pre10/arch/i386/lib/Makefile
--- linux-2.0.31-pre9/arch/i386/lib/Makefile	1996-09-11 07:57:13.000000000 -0700
+++ linux-2.0.31-pre10/arch/i386/lib/Makefile	2003-08-15 15:04:13.000000000 -0700
@@ -11,6 +11,6 @@
 endif
 
 L_TARGET = lib.a
-L_OBJS  = checksum.o semaphore.o
+L_OBJS  = checksum.o semaphore.o delay.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.0.31-pre9/CREDITS linux-2.0.31-pre10/CREDITS
--- linux-2.0.31-pre9/CREDITS	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/CREDITS	2003-08-15 15:04:12.000000000 -0700
@@ -42,7 +42,7 @@
 D: Moving all VFS access checks into the file systems
 S: MIT Room E15-341
 S: 20 Ames Street
-S: Cambridge, Massachusetts  02139
+S: Cambridge, Massachusetts 02139
 S: USA
 
 N: John Aycock
@@ -107,7 +107,9 @@
 
 N: Randolph Bentson
 E: bentson@grieg.seaslug.org
-D: author of driver for Cyclades Cyclom-Y async mux
+W: http://www.aa.net/~bentson/
+P: 1024/39ED5729 5C A8 7A F4 B2 7A D1 3E  B5 3B 81 CF 47 30 11 71
+D: Author of driver for Cyclades Cyclom-Y async mux
 S: 2322 37th Ave SW
 S: Seattle, Washington 98126-2010
 S: USA
@@ -122,7 +124,9 @@
 S: The Netherlands
 
 N: Hennus Bergman
-E: hennus@sky.ow.nl [My uucp-fed Linux box at home]
+E: hennus@cybercomm.nl
+W: http://www.cybercomm.nl/~hennus/
+P: 1024/77D50909 76 99 FD 31 91 E1 96 1C  90 BB 22 80 62 F6 BD 63
 D: Author and maintainer of the QIC-02 tape driver
 S: The Netherlands
 
@@ -131,16 +135,14 @@
 D: Original author of the Linux networking code
 
 N: Philip Blundell
-E: pjb27@cam.ac.uk 
-E: pb@nexus.co.uk
-E: phil@tazenda.demon.co.uk
+E: Philip.Blundell@pobox.com
 D: Device driver hacking (especially EtherExpress16/3C505 net cards)
 D: Some Linux/ARM stuff
-S: Trinity College
-S: Cambridge, UK. CB2 1TQ
+S: 201 Gilbert Road
+S: Cambridge, UK. CB4 3PA
 
 N: Thomas Bogendoerfer
-E: tsbogend@bigbug.franken.de
+E: tsbogend@alpha.franken.de
 D: Lance32 driver
 D: strace for Linux/Alpha
 S: Baumgartenweg 5
@@ -148,12 +150,8 @@
 S: Germany
 
 N: Bill Bogstad
-E: bogstad@cs.jhu.edu
-D: Wrote /proc/self patch
-S: Johns Hopkins University
-S: Computer Science Department
-S: Baltimore, Maryland 21218
-S: USA
+E: bogstad@pobox.com
+D: wrote /proc/self hack, minor samba & dosemu patches
 
 N: Axel Boldt
 E: boldt@math.ucsb.edu
@@ -214,7 +212,7 @@
 S: Fremont, California 94536
 S: USA
 
-N: Chih-Jen Chang     
+N: Chih-Jen Chang
 E: chihjenc@scf.usc.edu
 E: chihjen@iis.sinica.edu.tw
 D: IGMP(Internet Group Management Protocol) version 2
@@ -240,9 +238,10 @@
 
 N: Juan Jose Ciarlante
 E: jjciarla@raiz.uncu.edu.ar
-E: irriga@impsat1.com.ar
+E: juanjo@irriga.uncu.edu.ar
 D: Network driver alias support
 D: IP masq hashing and app modules
+D: IP ip_dynaddr bits 
 S: Las Cuevas 2385 - Bo Guemes
 S: Las Heras, Mendoza CP 5539
 S: Argentina
@@ -256,16 +255,9 @@
 
 N: Alan Cox
 E: alan@lxorguk.ukuu.org.uk (linux related - except big patches)
-E: iialan@www.linux.org.uk (linux.org.uk/big patches)
+E: iialan@www.uk.linux.org (linux.org.uk/big patches)
 E: alan@cymru.net (commercial CymruNET stuff)
-E: gw4pts@gw4pts.ampr.org (amateur radio stuff)
-E: GW4PTS@GB7SWN (packet radio)
-E: Please don't use iialan@iifeak.swan.ac.uk for Linux stuff
-S: c/o 3Com/I^2IT Limited
-S: The Innovation Centre
-S: University Of Wales
-S: Swansea, SA2 8PP
-S: Wales, UK
+E: Alan.Cox@linux.org (if others fail)
 D: NET2Debugged/NET3 author
 D: Network layer debugging
 D: Initial AX.25 & IPX releases
@@ -273,6 +265,11 @@
 D: Current 3c501 hacker. >>More 3c501 info/tricks wanted<<.
 D: Watchdog timer drivers
 D: Linux/SMP
+S: CymruNet Limited
+S: The Innovation Centre
+S: Singleton Park
+S: Swansea, SA2 8PP
+S: Wales, United Kingdom
 
 N: Laurence Culhane
 E: loz@holmes.demon.co.uk
@@ -285,6 +282,7 @@
 N: Ray Dassen
 E: jdassen@wi.LeidenUniv.nl
 W: http://www.wi.leidenuniv.nl/~jdassen/
+P: 1024/672D05C1 DD 60 32 60 F7 90 64 80  E7 6F D4 E4 F8 C9 4A 58
 D: Debian GNU/Linux: www.debian.org maintainer, FAQ co-maintainer,
 D: packages testing, nit-picking & fixing. Enjoying BugFree (TM) kernels.
 S: Zuidsingel 10A
@@ -293,12 +291,12 @@
 
 N: David Davies
 E: davies@wanton.lkg.dec.com
-S: Digital Equipment Corporation
-S: 550 King Street
-S: Littleton, MA 01460
-S: U.S.A.
 D: Network driver author - depca, ewrk3 and de4x5
 D: Wrote shared interrupt support
+S: Digital Equipment Corporation
+S: 550 King Street
+S: Littleton, Massachusetts 01460
+S: USA
 
 N: Wayne Davison
 E: davison@borland.com
@@ -311,12 +309,10 @@
 
 N: Todd J. Derr
 E: tjd@fore.com
-D: x86 VESA console blanking enhancements
-D: maintainer of dual-monitor patches for 1.0+
-D: MouseMan driver for selection
-S: Fore Systems, Inc.
-S: 5800 Corporate Drive
-S: Pittsburgh, Pennsylvania 15237-5829
+W: http://www.wordsmith.org/~tjd
+D: Random console hacks and other miscellaneous stuff
+S: 3000 FORE Drive
+S: Warrendale, Pennsylvania 15086
 S: USA
 
 N: Eddie C. Dost
@@ -348,7 +344,7 @@
 D: SCSI code
 D: Assorted snippets elsewhere
 D: Boot sector "..." printing
-S: 2255 Spruce
+S: 2037 Walnut #6
 S: Boulder, Colorado 80302
 S: USA
 
@@ -413,7 +409,7 @@
 S: Australia
 
 N: Ralf Flaxa
-E: rf@lst.de
+E: rfflaxa@immd4.informatik.uni-erlangen.de
 D: The Linux Support Team Erlangen
 D: Creator of LST distribution
 D: Author of installation tool LISA
@@ -469,15 +465,6 @@
 E: philip@raptor.com
 D: Kernel / timekeeping stuff
 
-N: Michael A. Griffith
-E: grif@cs.ucr.edu
-W: http://www.cs.ucr.edu/~grif
-D: Loopback speedup, qlogic scsi hacking, VT_LOCKSWITCH
-S: Department of Computer Science
-S: University of California, Riverside
-S: Riverside, California  92521-0304
-S: USA
-
 N: Dmitry S. Gorodchanin
 E: begemot@bgm.rosprint.net
 D: RISCom/8 driver, misc kernel fixes.
@@ -499,7 +486,16 @@
 E: jgotts@engin.umich.edu
 D: kernel hacker
 S: 8124 Constitution Apt. 7
-S: Sterling Heights, Michigan  48313
+S: Sterling Heights, Michigan 48313
+S: USA
+
+N: Michael A. Griffith
+E: grif@cs.ucr.edu
+W: http://www.cs.ucr.edu/~grif
+D: Loopback speedup, qlogic scsi hacking, VT_LOCKSWITCH
+S: Department of Computer Science
+S: University of California, Riverside
+S: Riverside, California 92521-0304
 S: USA
 
 N: Grant Guenther
@@ -561,11 +557,9 @@
 S: Germany
 
 N: Richard Henderson
-E: rth@tamu.edu
+E: richard@gnu.ai.mit.edu
+E: rth@cygnus.com
 D: Alpha/ELF, gcc, binutils, and glibc
-S: 304 E. North Ave.
-S: Bryan, Texas  77801-3431
-S: USA
 
 N: Sebastian Hetze
 E: she@lunetix.de
@@ -674,6 +668,7 @@
 S: USA
 
 N: Bernhard Kaindl
+E: bkaindl@netway.at
 E: edv@bartelt.via.at
 D: Author of a menu based configuration tool, kmenu, which 
 D: is the predecessor of 'make menuconfig' and 'make xconfig'.
@@ -713,7 +708,7 @@
 S: USA
 
 N: Alain L. Knaff
-E: Alain.Knaff@imag.fr
+E: Alain.Knaff@poboxes.com
 D: floppy driver
 S: 19, rue Jean l'Aveugle
 S: L-1148 Luxembourg-City
@@ -793,7 +788,7 @@
 D: Promised to send money if I would put his name in the source tree.
 S: PO Box 371
 S: North Little Rock, Arkansas 72115
-S: US
+S: USA
 
 N: Martin von Loewis
 E: loewis@informatik.hu-berlin.de
@@ -812,7 +807,7 @@
 E: imp@village.org
 D: Linux/MIPS Deskstation support, Provided OI/OB for Linux
 S: 8786 Niwot Rd
-S: Niwot, CO 80503
+S: Niwot, Colorado 80503
 S: USA
 
 N: H.J. Lu
@@ -842,6 +837,14 @@
 D: SLS distribution
 D: Initial implementation of VC's, pty's and select()
 
+N: Pat Mackinlay
+E: pat@it.com.au
+D: 8 bit XT hard disk driver
+D: Miscellaneous ST0x, TMC-8xx and other SCSI hacking
+S: 25 McMillan Street
+S: Victoria Park 6100
+S: Australia
+
 N: James B. MacLean
 E: macleajb@ednet.ns.ca
 W: http://www.ednet.ns.ca/~macleajb/dosemu.html
@@ -851,14 +854,6 @@
 S: Halifax, Nova Scotia
 S: Canada B3J 3C8
 
-N: Pat Mackinlay
-E: pat@it.com.au
-D: 8 bit XT hard disk driver
-D: Miscellaneous ST0x, TMC-8xx and other SCSI hacking
-S: 25 McMillan Street
-S: Victoria Park 6100
-S: Australia
-
 N: Martin Mares
 E: mj@k332.feld.cvut.cz
 W: http://atrey.karlin.mff.cuni.cz/~mj/
@@ -872,6 +867,9 @@
 
 N: John A. Martin
 E: jam@acm.org
+W: http://linux.wauug.org/~jam/
+P: 1024/04456D53 9D A3 6C 6B 88 80 8A 61  D7 06 22 4F 95 40 CE D2
+P: 1024/3B986635 5A61 7EE6 9E20 51FB 59FB  2DA5 3E18 DD55 3B98 6635
 D: FSSTND contributor
 D: Credit file compilator
 
@@ -890,7 +888,7 @@
 D: DLCI/FRAD drivers for Sangoma SDLAs
 S: Innovative Logic Corp
 S: P.O. Box 1068
-S: Laurel, MD  20732
+S: Laurel, Maryland 20732
 S: USA
 
 N: Bradley McLean
@@ -909,12 +907,13 @@
 S: Germany
 
 N: Michael Meskes
-E: meskes@informatik.rwth-aachen.de
+E: meskes@topsystem.de
+P: 1024/04B6E8F5 6C 77 33 CA CC D6 22 03  AB AB 15 A3 AE AD 39 7D
 D: Kernel hacker. Software watchdog daemon.
 D: Maintainer of several Debian packages
-S: Lehrstuhl fuer angewandte Mathematik insb. Informatik
-S: RWTH-Aachen
-S: D-52056 Aachen
+S: topsystem Systemhaus GmbH
+S: Europark A2, Adenauerstr. 20
+S: D-52146 Wuerselen
 S: Germany
 
 N: Nigel Metheringham
@@ -923,14 +922,11 @@
 D: IP Masquerading work and minor fixes
 S: Planet Online
 S: The White House, Melbourne Street, LEEDS
-S: LS2  7PS,   UK
+S: LS2 7PS, United Kingdom
 
 N: Craig Metz
-E: cmetz@tjhsst.edu
+E: cmetz@inner.net
 D: Some of PAS 16 mixer & PCM support
-S: 12305 Country Ridge Lane
-S: Fairfax, Virginia 22033
-S: USA
 
 N: William (Bill) Metzenthen
 E: billm@suburbia.net
@@ -959,8 +955,9 @@
 S: USA
 
 N: Rick Miller
-E: rick@digalogsys.com
-D: Original Linux Device Registrar (Major/minor numbers), au-play, bwBASIC
+E: rdmiller@execpc.com
+D: Original Linux Device Registrar (Major/minor numbers)
+D: au-play, bwBASIC
 S: S78 W16203 Woods Road
 S: Muskego, Wisconsin 53150
 S: USA
@@ -993,7 +990,7 @@
 E: davidm@azstarnet.com
 D: Linux/Alpha
 S: 2552 E. Copper Street
-S: Tucson, AZ 85716-2406
+S: Tucson, Arizona 85716-2406
 S: USA
 
 N: Ian A. Murdock
@@ -1011,9 +1008,9 @@
 S: Finland
 
 N: Jonathan Naylor
-E: jsn@cs.nott.ac.uk
+E: g4klx@g4klx.demon.co.uk
 E: g4klx@amsat.org
-E: G4KLX@GB7DAD (Packet Radio)
+W: http://zone.pspt.fi/~jsn/
 D: AX.25 and NET/ROM protocol suites
 S: 24 Castle View Drive
 S: Cromford
@@ -1055,7 +1052,7 @@
 D: IPX development and support
 
 N: Avery Pennarun
-E: apenwarr@foxnet.net
+E: apenwarr@bond.net
 D: ARCnet driver
 D: "make xconfig" improvements
 D: Various minor hacking
@@ -1125,17 +1122,16 @@
 S: Germany
 
 N: Joerg Reuter
-E: jreuter@poboxes.com
+E: jreuter@lykos.oche.de
 E: dl1bke@db0pra.ampr.org (amateur radio)
-W: http://www.rat.de/jr
 D: Z8530 SCC driver and DAMA Slave for AX.25
 
 N: William E. Roadcap
-E: roadcapw@titus.org
+E: roadcapw@cfw.com
 W: http://www.cfw.com/~roadcapw
 D: Author of ncurses based configuration tool, Menuconfig.
 S: 1407 Broad Street
-S: Waynesboro, Virginia  22980
+S: Waynesboro, Virginia 22980
 S: USA
 
 N: Florian La Roche
@@ -1167,6 +1163,7 @@
 
 N: Thomas Sailer
 E: sailer@ife.ee.ethz.ch
+E: HB9JNX@HB9W.CHE.EU (packet radio)
 D: Baycom radio modem driver
 S: Weinbergstrasse 76
 S: 8408 Winterthur
@@ -1222,7 +1219,7 @@
 D: SCSI debugging
 D: Maintainer of the Debian Kernel packages
 S: 14355 SW Allen Blvd., Suite #140
-S: Beaverton, OR 97008
+S: Beaverton, Oregon 97008
 S: USA
 
 N: Mike Shaver
@@ -1287,7 +1284,7 @@
 E: leo@netlabs.net
 W: http://www.netlabs.net/hp/leo/
 D: Optics Storage 8000AT cdrom driver
-S: Cliffwood, NJ 07721
+S: Cliffwood, New Jersey 07721
 S: USA
 
 N: Henrik Storner
@@ -1329,13 +1326,13 @@
 S: Spain
 
 N: Linus Torvalds
-E: Linus.Torvalds@Helsinki.FI
+E: torvalds@transmeta.com
 W: http://www.cs.helsinki.fi/~torvalds/
 P: 1024/A86B35C5 96 54 50 29 EC 11 44 7A  BE 67 3C 24 03 13 62 C8
-D: General kernel hacker
-S: Kalevankatu 55 B 37
-S: 00180 Helsinki
-S: Finland
+D: Original kernel hacker
+S: 3665 Benton Street #36
+S: Santa Clara, California 95051
+S: USA
 
 N: Jeff Tranter
 E: Jeff_Tranter@Mitel.COM
@@ -1355,10 +1352,11 @@
 S: 2615 Australia
 
 N: Winfried Trümper
-E: truemper@MI.Uni-Koeln.DE
+E: winni@xpilot.org
+W: http://www.shop.de/~winni/
 D: German HOWTO, Enhanced German HOWTO, Crash-Kurs Linux (German)
-D: 1- or 5-days tutorials on Linux twice a year (free of charge)
-D: Linux-Workshop Köln (aka LUUG cologne, germany)
+D: Day and week tutorials on Linux twice a year (free of charge)
+D: Linux-Workshop Köln (aka LUUG Cologne, Germany)
 S: Tacitusstr. 6
 S: D-50968 Köln
 
@@ -1489,7 +1487,7 @@
 S: Oncology Research Division Computing Facility
 S: Roger Maris Cancer Center
 S: 820 4th St. N.
-S: Fargo, North Dakota  58122
+S: Fargo, North Dakota 58122
 S: USA
 
 N: Hans-Joachim Widmaier
@@ -1530,7 +1528,7 @@
 S: Finland
 
 N: Roger E. Wolff
-E: R.E.Wolff@BitWizard.nl
+E: wolff@dutecai.et.tudelft.nl
 D: Written kmalloc/kfree
 D: Written Specialix IO8+ driver
 S: Oosterstraat 23
diff -urN linux-2.0.31-pre9/Documentation/networking/alias.txt linux-2.0.31-pre10/Documentation/networking/alias.txt
--- linux-2.0.31-pre9/Documentation/networking/alias.txt	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/Documentation/networking/alias.txt	2003-08-15 15:04:12.000000000 -0700
@@ -6,6 +6,7 @@
   (specific IP) support.
   From version 0.50, dynamic configuration of max alias per device and
   tx/rx stats for aliases added.
+  Also fixed inter-alias routing and arping problems.
 
 Features
 --------
@@ -35,9 +36,38 @@
      # modprobe ip_alias.o
      
      Also, dynamic loading is supported (kerneld).
-       You should have the following line in /etc/conf.modules:
+       You should have the following line in /etc/conf.modules (not needed
+       for newer modutils):
        alias net_alias-2 ip_alias
 
+  Module options
+  --------------
+  From 0.5x ip_alias module supports a new option ("no_sel" symbol).
+  If no_sel is set (default is 0), alias association (device selection) with
+  foreign addresses will be disabled.
+
+    You will get:
+    - Faster operation by avoiding completely routing lookups. 
+      Due to the "logical nature" of aliasing, netdevice SELection can only be
+      done based on info from network layer. When packet dst address isn't 
+      one of my addresses, I query the routing table to see which netdevice
+      would be selected for packet _source_ address. This option avoids
+      doing so, and you must consider using it if you *only* have same-net
+      aliases (common usage).
+
+    You will loose:
+    - Inter-alias routing
+    - Proxyarp over aliases
+
+  To activate:
+    # insmod ip_alias.o no_sel=1  
+      or
+    # modprobe ip_alias.o no_sel=1
+      or
+    add the following line to /etc/conf.modules:
+      options ip_alias no_sel=1
+
+
 o Alias creation.
   Alias creation is done by 'magic' iface naming: eg. to create a
   200.1.1.1 alias for eth0 ...
@@ -81,9 +111,9 @@
      device           family address                                
      eth0:0           2      200.1.1.1
      
-o PROCfs dynamic configuration
+o PROCfs dynamic configuration (from v0.50)
   You can now change the max aliases per device limit via
-  /proc/sys/net/core/net_alias_max entry
+  /proc/sys/net/core/net_alias_max entry (default=256)
      # cat /proc/sys/net/core/net_alias_max
      256
      # echo 1000 > /proc/sys/net/core/net_alias_max
@@ -111,9 +141,9 @@
   Fake rx/tx stats are accounted:
   - TX
     When the packet is ``switched'' from logical alias device to
-    physical device, tx counter gets incr.
+    physical device, tx counter gets incremented.
   - RX
-    When an incoming packet's address equals alias device's addr it
+    When an incoming packet's address equals alias network device's addr it
     gets ``switched'' from physical to logical device, rx counter gets
     incr.
     
@@ -122,7 +152,23 @@
   will NOT pass down via alias device (so, no tx++ will occur).
   
   Also NOTE that currently ifconfig does not handle the ``:'' of alias devices
-  names, a little patch (attached) solves the problem.
+  names, a little patch solves the problem:
+--- ifconfig.c.dist	Tue Apr  4 17:58:32 1995
++++ ifconfig.c	Fri Oct 25 13:11:23 1996
+@@ -243,7 +243,12 @@
+   		bp++;
+   	if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':')
+   	{
+- 		bp=strchr(bp,':');
++	   	/* 
++		 * 	start bp at ifname end to prevent ':' ambiguity
++		 * 	with alias devices (eg. eth0:0)
++		 * 	
++		 */
++		bp+=strlen(ifname);
+  		bp++;
+  		sscanf(bp,"%d %d %d %d %d %d %d %d %d %d %d",
+  			&ife->stats.rx_packets,
   
 Relationship with main device
 -----------------------------
@@ -138,7 +184,12 @@
 Please e-mail me:
    Juan Jose Ciarlante <irriga@impsat1.com.ar> or <jjciarla@raiz.uncu.edu.ar>
    
-		   		
+Acknowledments
+--------------
+Special thanks to Claudia for all her love an patience.
+Also thanks to Antonio Trevi~o <antonio@ecord.gov.ar> great human being 
+and un*x guru.
+
 ; local variables:
 ; mode: indented-text
 ; mode: auto-fill
diff -urN linux-2.0.31-pre9/Documentation/networking/ip_dynaddr.txt linux-2.0.31-pre10/Documentation/networking/ip_dynaddr.txt
--- linux-2.0.31-pre9/Documentation/networking/ip_dynaddr.txt	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.0.31-pre10/Documentation/networking/ip_dynaddr.txt	2003-08-15 15:04:12.000000000 -0700
@@ -0,0 +1,29 @@
+IP dynamic address hack-port v0.03
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This stuff allows diald ONESHOT connections to get established by
+dynamically changing packet source address (and socket's if local procs).
+It is implemented for TCP diald-box connections(1) and IP_MASQuerading(2).
+
+If enabled[*] and forwarding interface has changed:
+  1)  Socket (and packet) source address is rewritten ON RETRANSMISSIONS
+      while in SYN_SENT state (diald-box processes).
+  2)  Out-bounded MASQueraded source address changes ON OUTPUT (when
+      internal host does retransmission) until a packet from outside is
+      received by the tunnel.
+
+This is specially helpful for auto dialup links (diald), where the
+``actual'' outgoing address is unknown at the moment the link is
+going up. So, the *same* (local AND masqueraded) connections requests that
+bring the link up will be able to get established.
+
+[*] At boot, by default no address rewriting is attempted. 
+  To enable:
+     # echo 1 > /proc/sys/net/ipv4/ip_dynaddr
+  To enable verbose mode:
+     # echo 2 > /proc/sys/net/ipv4/ip_dynaddr
+  To disable (default)
+     # echo 0 > /proc/sys/net/ipv4/ip_dynaddr
+
+Enjoy!
+
+-- Juanjo  <jjciarla@raiz.uncu.edu.ar>
diff -urN linux-2.0.31-pre9/drivers/char/mem.c linux-2.0.31-pre10/drivers/char/mem.c
--- linux-2.0.31-pre9/drivers/char/mem.c	1996-09-20 07:00:34.000000000 -0700
+++ linux-2.0.31-pre10/drivers/char/mem.c	2003-08-15 15:04:13.000000000 -0700
@@ -194,12 +194,6 @@
 	return 0;
 }
 
-static int read_full(struct inode * node, struct file * file, char * buf,int count)
-{
-	file->f_pos += count;
-	return count;
-}
-
 static int write_full(struct inode * inode, struct file * file, const char * buf, int count)
 {
 	return -ENOSPC;
@@ -242,7 +236,9 @@
 #define write_kmem	write_mem
 #define mmap_kmem	mmap_mem
 #define zero_lseek	null_lseek
+#define full_lseek	null_lseek
 #define write_zero	write_null
+#define read_full	read_null
 
 static struct file_operations ram_fops = {
 	memory_lseek,
@@ -322,7 +318,7 @@
 };
 
 static struct file_operations full_fops = {
-	memory_lseek,
+	full_lseek,
 	read_full,
 	write_full,
 	NULL,		/* full_readdir */
diff -urN linux-2.0.31-pre9/drivers/char/tty_io.c linux-2.0.31-pre10/drivers/char/tty_io.c
--- linux-2.0.31-pre9/drivers/char/tty_io.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/drivers/char/tty_io.c	2003-08-15 15:04:13.000000000 -0700
@@ -1474,11 +1474,10 @@
 	if (on) {
 		if (!waitqueue_active(&tty->read_wait))
 			tty->minimum_to_wake = 1;
-		if (filp->f_owner == 0) {
-			if (tty->pgrp)
-				filp->f_owner = -tty->pgrp;
-			else
-				filp->f_owner = current->pid;
+		if (filp->f_owner.pid == 0) {
+			filp->f_owner.pid = (-tty->pgrp) ? : current->pid;
+			filp->f_owner.uid = current->uid;
+			filp->f_owner.euid = current->euid;
 		}
 	} else {
 		if (!tty->fasync && !waitqueue_active(&tty->read_wait))
diff -urN linux-2.0.31-pre9/drivers/net/3c59x.c linux-2.0.31-pre10/drivers/net/3c59x.c
--- linux-2.0.31-pre9/drivers/net/3c59x.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/drivers/net/3c59x.c	2003-08-15 15:04:13.000000000 -0700
@@ -1,4 +1,4 @@
-/* EtherLink.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */
+/* EtherLinkXL.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */
 /*
 	Written 1996-1997 by Donald Becker.
 
@@ -15,14 +15,16 @@
 */
 
 static char *version =
-"3c59x.c:v0.43 9/2/97 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
+"3c59x.c:v0.44 9/9/97 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
 
-/* "Knobs" that turn on special features. */
+/* "Knobs" that adjust features and parameters. */
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1512 effectively disables this feature. */
 static const rx_copybreak = 200;
 /* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
 static const mtu = 1500;
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static const max_interrupt_work = 12;
 
 /* Enable the automatic media selection code -- usually set. */
 #define AUTOMEDIA 1
@@ -135,14 +137,17 @@
 #endif
 
 #ifdef VORTEX_DEBUG
-int vortex_debug = VORTEX_DEBUG;
+static int vortex_debug = VORTEX_DEBUG;
 #else
-int vortex_debug = 1;
+static int vortex_debug = 1;
 #endif
 
+/* Set iff a MII transceiver on any interface requires mdio preamble. */
+static char mii_preamble_required = 0;
+
 /* Caution!  These entries must be consistent, with the EISA ones last. */
-static int product_ids[] = {0x5900, 0x5950, 0x5951, 0x5952, 0x9000, 0x9001,
-								0x9050, 0x9051, 0, 0};
+static const int product_ids[] = {
+	0x5900, 0x5950, 0x5951, 0x5952, 0x9000, 0x9001, 0x9050, 0x9051, 0, 0};
 static const char *product_names[] = {
 	"3c590 Vortex 10Mbps",
 	"3c595 Vortex 100baseTX",
@@ -316,7 +321,7 @@
 };
 
 enum Window4 {		/* Window 4: Xcvr/media bits. */
-	Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10,
+	Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10,
 };
 enum Win4_Media_bits {
 	Media_SQE = 0x0008,		/* Enable SQE error counting for AUI. */
@@ -423,7 +428,11 @@
 										  int options, int card_idx);
 static int vortex_probe1(struct device *dev);
 static int vortex_open(struct device *dev);
+static void mdio_sync(int ioaddr, int bits);
 static int mdio_read(int ioaddr, int phy_id, int location);
+#ifdef HAVE_PRIVATE_IOCTL
+static void mdio_write(int ioaddr, int phy_id, int location, int value);
+#endif
 static void vortex_timer(unsigned long arg);
 static int vortex_start_xmit(struct sk_buff *skb, struct device *dev);
 static int boomerang_start_xmit(struct sk_buff *skb, struct device *dev);
@@ -434,6 +443,9 @@
 static void update_stats(int addr, struct device *dev);
 static struct enet_statistics *vortex_get_stats(struct device *dev);
 static void set_rx_mode(struct device *dev);
+#ifdef HAVE_PRIVATE_IOCTL
+static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+#endif
 #ifndef NEW_MULTICAST
 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
 #endif
@@ -758,11 +770,16 @@
 		int phy, phy_idx = 0;
 		EL3WINDOW(4);
 		for (phy = 0; phy < 32 && phy_idx < sizeof(vp->phys); phy++) {
-			int mii_status = mdio_read(ioaddr, phy, 0);
-			if (mii_status != 0xffff  && mii_status != 0x0000) {
+			int mii_status;
+			mdio_sync(ioaddr, 32);
+			mii_status = mdio_read(ioaddr, phy, 0);
+			if (mii_status != 0xffff) {
 				vp->phys[phy_idx++] = phy;
 				printk("%s: MII transceiver found at address %d.\n",
 					   dev->name, phy);
+				mdio_sync(ioaddr, 32);
+				if ((mdio_read(ioaddr, phy, 1) & 0x0040) == 0)
+					mii_preamble_required = 1;
 			}
 		}
 		if (phy_idx == 0) {
@@ -790,6 +807,9 @@
 	dev->hard_start_xmit = &vortex_start_xmit;
 	dev->stop = &vortex_close;
 	dev->get_stats = &vortex_get_stats;
+#ifdef HAVE_PRIVATE_IOCTL
+	dev->do_ioctl = &vortex_ioctl;
+#endif
 #ifdef NEW_MULTICAST
 	dev->set_multicast_list = &set_rx_mode;
 #else
@@ -801,7 +821,7 @@
 
 /* Read and write the MII registers using software-generated serial
    MDIO protocol.  The maxium data clock rate is 2.5 Mhz. */
-#define mdio_delay(microsecs) udelay(microsecs)
+#define mdio_delay() udelay(1)
 
 #define MDIO_SHIFT_CLK	0x01
 #define MDIO_DIR_WRITE	0x04
@@ -810,41 +830,73 @@
 #define MDIO_DATA_READ	0x02
 #define MDIO_ENB_IN		0x00
 
+static void mdio_sync(int ioaddr, int bits)
+{
+	int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+
+	/* Establish sync by sending at least 32 logic ones. */ 
+	while (-- bits >= 0) {
+		outw(MDIO_DATA_WRITE1, mdio_addr);
+		mdio_delay();
+		outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+}
 static int mdio_read(int ioaddr, int phy_id, int location)
 {
 	int i;
 	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
-	unsigned short retval = 0;
+	unsigned int retval = 0;
 	int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
 
+	if (mii_preamble_required)
+		mdio_sync(ioaddr, 32);
+
 	/* Shift the read command bits out. */
-	for (i = 17; i >= 0; i--) {
+	for (i = 14; i >= 0; i--) {
 		int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
 		outw(dataval, mdio_addr);
-		mdio_delay(1);
+		mdio_delay();
 		outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay(1);
-		outw(dataval, mdio_addr);
-		mdio_delay(1);
+		mdio_delay();
 	}
-	outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
-	outw(MDIO_ENB_IN, mdio_addr);
-
-	for (i = 16; i > 0; i--) {
-		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay(1);
-		retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+	/* Read the two transition, 16 data, and wire-idle bits. */
+	for (i = 19; i > 0; i--) {
 		outw(MDIO_ENB_IN, mdio_addr);
-		mdio_delay(1);
-	}
-	/* Clear out extra bits.  Needed? */
-	for (i = 16; i > 0; i--) {
+		mdio_delay();
+		retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
 		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay(1);
+		mdio_delay();
+	}
+	return retval>>1 & 0xffff;
+}
+
+static void mdio_write(int ioaddr, int phy_id, int location, int value)
+{
+	int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
+	int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+	int i;
+
+	if (mii_preamble_required)
+		mdio_sync(ioaddr, 32);
+
+	/* Shift the command bits out. */
+	for (i = 31; i >= 0; i--) {
+		int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+		outw(dataval, mdio_addr);
+		mdio_delay();
+		outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+	/* Leave the interface idle. */
+	for (i = 1; i >= 0; i--) {
 		outw(MDIO_ENB_IN, mdio_addr);
-		mdio_delay(1);
+		mdio_delay();
+		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
 	}
-	return retval;
+
+	return;
 }
 
 
@@ -888,19 +940,22 @@
 	outl(config.i, ioaddr + Wn3_Config);
 
 	if (dev->if_port == XCVR_MII) {
-		int mii_reg1, mii_reg25;
+		int mii_reg1, mii_reg5;
 		/* We cheat here: we know that we are using the 83840 transceiver
 		   which summarizes the FD status in an extended register. */
 		EL3WINDOW(4);
 		/* Read BMSR (reg1) only to clear old status. */
 		mii_reg1 = mdio_read(ioaddr, vp->phys[0], 1);
-		mii_reg25 = mdio_read(ioaddr, vp->phys[0], 0x19);
+		mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);
+		if (mii_reg5 == 0xffff  ||  mii_reg5 == 0x0000)
+			;					/* No MII device or no link partner report */
+		else if ((mii_reg5 & 0x0100) != 0	/* 100baseTx-FD */
+				 || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */
+			vp->full_duplex = 1;
 		if (vortex_debug > 1)
-			printk("%s: MII #%d status %4.4x, duplex report %4.4x,"
+			printk("%s: MII #%d status %4.4x, link partner capability %4.4x,"
 				   " setting %s-duplex.\n", dev->name, vp->phys[0],
-				   mii_reg1, mii_reg25, mii_reg25 & 0x0080 ? "full" : "half");
-		if (mii_reg25 & 0x0080)
-			vp->full_duplex = 1;
+				   mii_reg1, mii_reg5, vp->full_duplex ? "full" : "half");
 		EL3WINDOW(3);
 	}
 
@@ -1030,6 +1085,7 @@
 	outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
 		 ioaddr + EL3_CMD);
 	outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
+		 | AdapterFailure
 		 | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
 			ioaddr + EL3_CMD);
 
@@ -1071,9 +1127,11 @@
 	  case XCVR_MII:
 		  {
 			  int mii_reg1 = mdio_read(ioaddr, vp->phys[0], 1);
+			  int mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);
 			  if (vortex_debug > 1)
-				  printk("%s: MII #%d status register is %4.4x.\n",
-						 dev->name, vp->phys[0], mii_reg1);
+				  printk("%s: MII #%d status register is %4.4x, "
+						 "link partner capability %4.4x.\n",
+						 dev->name, vp->phys[0], mii_reg1, mii_reg5);
 			  if (mii_reg1 & 0x0004)
 				  ok = 1;
 			  break;
@@ -1134,19 +1192,28 @@
 		   inw(ioaddr + EL3_STATUS));
 	/* Slight code bloat to be user friendly. */
 	if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
-	  printk("%s: Transmitter encountered 16 collisions -- network"
-			 " network cable problem?\n", dev->name);
+		printk("%s: Transmitter encountered 16 collisions --"
+			   " network cable problem?\n", dev->name);
+	if (inw(ioaddr + EL3_STATUS) & IntLatch) {
+		printk("%s: Interrupt posted but not handled --"
+			   " IRQ blocked by another device?\n", dev->name);
+		/* Bad idea here.. but we might as well handle a few events. */
+		vortex_interrupt IRQ(dev->irq, dev, 0);
+	}
 #ifndef final_version
-	printk("  Flags; bus-master %d, full %d; dirty %d current %d.\n",
-		   vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->cur_tx);
-	printk("  Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr),
-		   &vp->tx_ring[0]);
-	for (i = 0; i < TX_RING_SIZE; i++) {
-	  printk("  %d: %p  length %8.8x status %8.8x\n", i,
-			 &vp->tx_ring[i],
-			 vp->tx_ring[i].length,
-			 vp->tx_ring[i].status);
+	if (vp->full_bus_master_tx) {
+		printk("  Flags; bus-master %d, full %d; dirty %d current %d.\n",
+			   vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->cur_tx);
+		printk("  Transmit list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr),
+			   &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			printk("  %d: @%p  length %8.8x status %8.8x\n", i,
+				   &vp->tx_ring[i],
+				   vp->tx_ring[i].length,
+				   vp->tx_ring[i].status);
+		}
 	}
+#ifdef notdef
 	if (vp->full_bus_master_rx) {
 		printk("  Switching to non-bus-master receives.\n");
 		outw(SetStatusEnb | AdapterFailure|IntReq|StatsFull |
@@ -1154,12 +1221,13 @@
 			 RxComplete | (vp->bus_master ? DMADone : 0),
 			 ioaddr + EL3_CMD);
 	}
-#endif
 	/* Issue TX_RESET and TX_START commands. */
 	outw(TxReset, ioaddr + EL3_CMD);
 	for (i = 20; i >= 0 ; i--)
 	  if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
 		break;
+#endif
+#endif
 	if (vp->full_bus_master_tx) {
 	  /*  Change 6/25/97 Michael Sievers sieversm@mail.desy.de
               The card has been resetted, but the Tx Ring is still full.
@@ -1170,19 +1238,23 @@
    
 	  unsigned int dirty_tx = vp->dirty_tx;
 	  
+	  if (vortex_debug > 0)
+		  printk("%s: Freeing Tx ring entries:", dev->name);
 	  while (vp->cur_tx - dirty_tx > 0) {
 		int entry = dirty_tx % TX_RING_SIZE;
 		if (inl(ioaddr + DownListPtr) ==
 			virt_to_bus(&vp->tx_ring[entry]))
 		  break;			/* It still hasn't been processed. */
 		if (vp->tx_skbuff[entry]) {
-		  if (vortex_debug > 0)
-			printk("%s: Freeing Tx ring entry %d\n",dev->name,entry);
-		  dev_kfree_skb(vp->tx_skbuff[entry], FREE_WRITE);
-		  vp->tx_skbuff[entry] = 0;
+			if (vortex_debug > 0)
+				printk(" %d\n", entry);
+			dev_kfree_skb(vp->tx_skbuff[entry], FREE_WRITE);
+			vp->tx_skbuff[entry] = 0;
+			vp->stats.tx_dropped++;
 		}
+		if (vortex_debug > 0)
+			printk(".\n");
 		vp->stats.tx_errors++;
-		vp->stats.tx_dropped++;
 		dirty_tx++;
 	  }
 	  vp->dirty_tx = dirty_tx;
@@ -1323,10 +1395,10 @@
 			printk("%s: Trying to send a packet, Tx index %d.\n",
 				   dev->name, vp->cur_tx);
 		if (vp->tx_full) {
-		  if (vortex_debug >0)
-			printk("%s: Tx Ring full, refusing to send buffer.\n",
-				   dev->name);
-		  return 1;
+			if (vortex_debug >0)
+				printk("%s: Tx Ring full, refusing to send buffer.\n",
+					   dev->name);
+			return 1;
 		} 
 		/* end change 06/25/97 M. Sievers */	
 		vp->tx_skbuff[entry] = skb;
@@ -1339,7 +1411,7 @@
 		cli();
 		outw(DownStall, ioaddr + EL3_CMD);
 		/* Wait for the stall to complete. */
-		for (i = 20; i >= 0 ; i--)
+		for (i = 60; i >= 0 ; i--)
 			if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
 				break;
 		prev_entry->next = virt_to_bus(&vp->tx_ring[entry]);
@@ -1374,7 +1446,7 @@
 	struct vortex_private *lp;
 	int ioaddr, status;
 	int latency;
-	int i = 0;
+	int i = max_interrupt_work;
 
 	if (dev->interrupt)
 		printk("%s: Re-entering the interrupt handler.\n", dev->name);
@@ -1389,17 +1461,20 @@
 	if (vortex_debug > 4)
 		printk("%s: interrupt, status %4.4x, timer %d.\n", dev->name,
 			   status, latency);
-	if ((status & 0xE000) != 0xE000) {
+#ifdef notdef
+	/* This code guard against bogus hangs, but fails with shared IRQs. */
+	if ((status & ~0xE000) == 0x0000) {
 		static int donedidthis=0;
 		/* Some interrupt controllers store a bogus interrupt from boot-time.
 		   Ignore a single early interrupt, but don't hang the machine for
 		   other interrupt problems. */
-		if (donedidthis++ > 1) {
+		if (donedidthis++ > 100) {
 			printk("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n",
 				   dev->name, status, dev->start);
 			FREE_IRQ(dev->irq, dev);
 		}
 	}
+#endif
 
 	do {
 		if (vortex_debug > 5)
@@ -1416,6 +1491,13 @@
 			dev->tbusy = 0;
 			mark_bh(NET_BH);
 		}
+		if (status & TxComplete) { /* Really "TxError" for us. */
+			/* Presumably a tx-timeout. We must merely re-enable. */
+			if (vortex_debug > 0)
+				printk("%s: Host error, Tx status register %2.2x.\n",
+					   dev->name, inb(TxStatus));
+			outw(TxEnable, ioaddr + EL3_CMD);
+		}
 		if (status & DownComplete) {
 			unsigned int dirty_tx = lp->dirty_tx;
 
@@ -1431,13 +1513,13 @@
 				/* lp->stats.tx_packets++;  Counted below. */
 				dirty_tx++;
 			}
+			lp->dirty_tx = dirty_tx;
 			outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
-			if (lp->tx_full) {
+			if (lp->tx_full && (lp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
 				lp->tx_full= 0;
 				dev->tbusy = 0;
 				mark_bh(NET_BH);
 			}
-			lp->dirty_tx = dirty_tx;
 		}
 #ifdef VORTEX_BUS_MASTER
 		if (status & DMADone) {
@@ -1476,22 +1558,38 @@
 							printk(" %2.2x", inb(ioaddr+reg));
 					}
 					EL3WINDOW(7);
-					outw(SetIntrEnb | TxAvailable | RxComplete
+					outw(SetIntrEnb | TxAvailable | RxComplete | AdapterFailure
 						 | UpComplete | DownComplete, ioaddr + EL3_CMD);
 					DoneDidThat++;
 				}
 			}
 			if (status & AdapterFailure) {
-				/* Adapter failure requires Rx reset and reinit. */
-				outw(RxReset, ioaddr + EL3_CMD);
-				/* Set the Rx filter to the current state. */
-				set_rx_mode(dev);
-				outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
-				outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
+				u16 fifo_diag;
+				EL3WINDOW(4);
+				fifo_diag = inw(ioaddr + Wn4_FIFODiag);
+				if (vortex_debug > 0)
+					printk("%s: Host error, FIFO diagnostic register %4.4x.\n",
+						   dev->name, fifo_diag);
+				/* Adapter failure requires Tx/Rx reset and reinit. */
+				if (fifo_diag & 0x0400) {
+					int j;
+					outw(TxReset, ioaddr + EL3_CMD);
+					for (j = 20; j >= 0 ; j--)
+						if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+							break;
+					outw(TxEnable, ioaddr + EL3_CMD);
+				}
+				if (fifo_diag & 0x2000) {
+					outw(RxReset, ioaddr + EL3_CMD);
+					/* Set the Rx filter to the current state. */
+					set_rx_mode(dev);
+					outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
+					outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
+				}
 			}
 		}
 
-		if (++i > 10) {
+		if (--i < 0) {
 			printk("%s: Infinite loop in interrupt, status %4.4x.  "
 				   "Disabling functions (%4.4x).\n",
 				   dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
@@ -1595,7 +1693,7 @@
 	while ((rx_status = vp->rx_ring[entry].status) & RxDComplete) {
 		if (rx_status & RxDError) { /* Error, update stats. */
 			unsigned char rx_error = rx_status >> 16;
-			if (vortex_debug > 4)
+			if (vortex_debug > 2)
 				printk(" Rx error: status %2.2x.\n", rx_error);
 			vp->stats.rx_errors++;
 			if (rx_error & 0x01)  vp->stats.rx_over_errors++;
@@ -1789,6 +1887,37 @@
 	return;
 }
 
+#ifdef HAVE_PRIVATE_IOCTL
+static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	int ioaddr = dev->base_addr;
+	u16 *data = (u16 *)&rq->ifr_data;
+	int phy = vp->phys[0] & 0x1f;
+
+	if (vortex_debug > 2)
+		printk("%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n",
+			   dev->name, rq->ifr_ifrn.ifrn_name, cmd,
+			   data[0], data[1], data[2], data[3]);
+
+    switch(cmd) {
+	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
+		data[0] = phy;
+	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+		EL3WINDOW(4);
+		data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+		return 0;
+	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+		if (!suser())
+			return -EPERM;
+		mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+#endif  /* HAVE_PRIVATE_IOCTL */
+
 /* This new version of set_rx_mode() supports v1.4 kernels.
    The Vortex chip has no documented multicast filter, so the only
    multicast setting is to receive all multicast frames.  At least
diff -urN linux-2.0.31-pre9/drivers/net/tulip.c linux-2.0.31-pre10/drivers/net/tulip.c
--- linux-2.0.31-pre9/drivers/net/tulip.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/drivers/net/tulip.c	2003-08-15 15:04:13.000000000 -0700
@@ -1444,7 +1444,7 @@
 				  }
 				  if (tulip_debug > 0) /* Gurppp, should be >1 */
 					  printk(KERN_INFO "%s: Setting %s-duplex based on MII"
-							 " Xcvr #%d parter capability of %4.4x.\n",
+							 " Xcvr #%d partner capability of %4.4x.\n",
 							 dev->name, full_duplex ? "full" : "half",
 							 tp->phys[0], mii_reg5);
 			  }
diff -urN linux-2.0.31-pre9/drivers/scsi/aic7xxx/aic7xxx.reg linux-2.0.31-pre10/drivers/scsi/aic7xxx/aic7xxx.reg
--- linux-2.0.31-pre9/drivers/scsi/aic7xxx/aic7xxx.reg	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/drivers/scsi/aic7xxx/aic7xxx.reg	2003-08-15 15:04:13.000000000 -0700
@@ -1079,10 +1079,25 @@
 	CUR_SCBID {
 		size		1
 	}
+	ARG_1 {
+		size		1
+		mask	SEND_MSG	0x80
+		mask	SEND_SENSE	0x40
+		mask	SEND_REJ	0x20
+		alias	RETURN_1
+	}
 	/*
 	 * Running count of commands placed in
 	 * the QOUTFIFO.  This is cleared by the
 	 * kernel driver every FIFODEPTH commands.
+	 *
+	 * NOTE: these scratch RAM registers are *only* used on cards
+	 * that enable SCB paging.  The 2742 is unable to page.  We
+	 * won't use these on a 2742, and we can't init these registers
+	 * in the kernel driver for 2742 cards because these locations are
+	 * are used by the 2742 cards to control things like bus
+	 * termination.  Touching these memory locations is a no-no on all
+	 * non-paging cards as far as we are concerned.
 	 */
 	CMDOUTCNT {
 		size		1
@@ -1094,13 +1109,6 @@
 	FIFODEPTH {
 		size		1
 	}
-	ARG_1 {
-		size		1
-		mask	SEND_MSG	0x80
-		mask	SEND_SENSE	0x40
-		mask	SEND_REJ	0x20
-		alias	RETURN_1
-	}
 	/*
 	 * These are reserved registers in the card's scratch ram.  Some of
 	 * the values are specified in the AHA2742 technical reference manual
@@ -1111,6 +1119,11 @@
 		size		1
 		bit	RESET_SCSI	0x40
 	}
+        SCSICONF2 {
+		address		0x05b
+		size		1
+		bit	RESET_SCSI	0x40
+	}
 	HOSTCONF {
 		address		0x05d
 		size		1
diff -urN linux-2.0.31-pre9/drivers/scsi/aic7xxx.c linux-2.0.31-pre10/drivers/scsi/aic7xxx.c
--- linux-2.0.31-pre9/drivers/scsi/aic7xxx.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/drivers/scsi/aic7xxx.c	2003-08-15 15:04:13.000000000 -0700
@@ -871,7 +871,7 @@
     long r_total;                            /* total reads */
     long r_total512;                         /* 512 byte blocks read */
     long r_bins[10];                         /* binned reads */
-  } stats[2][16][8];                         /* channel, target, lun */
+  } stats[16][8];                            /* channel, target, lun */
 #endif /* AIC7XXX_PROC_STATS */
 };
 
@@ -968,7 +968,13 @@
  * These functions are not used yet, but when we do memory mapped
  * IO, we'll use them then.
  *
+ * For now we leave these commented out as the x86 inline assembly causes
+ * compiles to barf on DEC Alphas.  Besides, they aren't even used yet, so
+ * they constitute wasted .text space right now.
  ***************************************************************************/
+
+/***************************************************************************
+
 static inline unsigned char
 aic_inb(struct aic7xxx_host *p, long port)
 {
@@ -1007,6 +1013,7 @@
     outsb(p->base + port, valp, size);
   }
 }
+ ***************************************************************************/
 
 /*+F*************************************************************************
  * Function:
@@ -1985,6 +1992,8 @@
   aic7xxx_queue_cmd_complete(p, cmd);
 
 #ifdef AIC7XXX_PROC_STATS
+  if ( (cmd->cmnd[0] != TEST_UNIT_READY) &&
+       (cmd->cmnd[0] != INQUIRY) )
   {
     int actual;
 
@@ -2000,7 +2009,7 @@
       long *ptr;
       int x;
 
-      sp = &p->stats[cmd->channel & 0x01][cmd->target & 0x0F][cmd->lun & 0x07];
+      sp = &p->stats[((cmd->channel << 3) | cmd->target) & 0xf][cmd->lun & 0x7];
       sp->xfers++;
 
       if (cmd->request.cmd == WRITE)
@@ -4062,7 +4071,7 @@
 #ifndef AIC7XXX_TAGGED_QUEUEING_BY_DEVICE
       device->queue_depth = default_depth;
 #else
-      if (p->instance > NUMBER(aic7xxx_tag_info))
+      if (p->instance >= NUMBER(aic7xxx_tag_info))
       {
         device->queue_depth = default_depth;
       }
@@ -5022,7 +5031,7 @@
   scbq_init(&p->scb_data->free_scbs);
   scbq_init(&p->waiting_scbs);
 
-  for (i = 0; i <= NUMBER(p->device_status); i++)
+  for (i = 0; i < NUMBER(p->device_status); i++)
   {
     p->device_status[i].commands_sent = 0;
     p->device_status[i].flags = 0;
@@ -5305,8 +5314,11 @@
     */
   outb(p->qcntmask, p->base + QCNTMASK);
 
-  outb(p->qfullcount, p->base + FIFODEPTH);
-  outb(0, p->base + CMDOUTCNT);
+  if (p->flags & PAGE_ENABLED)
+  {
+    outb(p->qfullcount, p->base + FIFODEPTH);
+    outb(0, p->base + CMDOUTCNT);
+  }
 
   /*
    * We don't have any waiting selections or disconnected SCBs.
@@ -5721,7 +5733,7 @@
    * a NULL entry to indicate that no prior hosts have
    * been found/registered for that IRQ.
    */
-  for (i = 0; i <= NUMBER(aic7xxx_boards); i++)
+  for (i = 0; i < NUMBER(aic7xxx_boards); i++)
   {
     aic7xxx_boards[i] = NULL;
   }
@@ -6887,7 +6899,7 @@
   scb = (p->scb_data->scb_array[aic7xxx_position(cmd)]);
   base = p->base;
   channel = cmd->channel ? 'B': 'A';
-  tindex = (cmd->channel << 4) | cmd->target;
+  tindex = (cmd->channel << 3) | cmd->target;
 
 #ifdef 0   /* AIC7XXX_DEBUG_ABORT */
   if (scb != NULL)
@@ -7128,4 +7140,3 @@
  * tab-width: 8
  * End:
  */
-
diff -urN linux-2.0.31-pre9/drivers/scsi/aic7xxx_proc.c linux-2.0.31-pre10/drivers/scsi/aic7xxx_proc.c
--- linux-2.0.31-pre9/drivers/scsi/aic7xxx_proc.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/drivers/scsi/aic7xxx_proc.c	2003-08-15 15:04:13.000000000 -0700
@@ -21,13 +21,15 @@
  *  o Modified from the EATA-DMA /proc support.
  *  o Additional support for device block statistics provided by
  *    Matthew Jacob.
+ *  o Correction of overflow by Heinz Mauelshagen
+ *  o Adittional corrections by Doug Ledford
  *
  *  Dean W. Gehnert, deang@teleport.com, 05/01/96
  *
  *  $Id: aic7xxx_proc.c,v 4.1 1997/06/97 08:23:42 deang Exp $
  *-M*************************************************************************/
 
-#define BLS buffer + len + size
+#define	BLS	(&aic7xxx_buffer[size])
 #define HDRB \
 "        < 512 512-1K   1-2K   2-4K   4-8K  8-16K 16-32K 32-64K 64-128K >128K"
 
@@ -62,7 +64,7 @@
   proc_debug("aic7xxx_set_info(): %s\n", buffer);
   return (-ENOSYS);  /* Currently this is a no-op */
 }
-
+ 
 /*+F*************************************************************************
  * Function:
  *   aic7xxx_proc_info
@@ -71,20 +73,23 @@
  *   Return information to handle /proc support for the driver.
  *-F*************************************************************************/
 int
-aic7xxx_proc_info(char *buffer, char **start, off_t offset, int length, 
-    int hostno, int inout)
+aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length, 
+                    int hostno, int inout)
 {
   struct Scsi_Host *HBAptr;
   struct aic7xxx_host *p;
-  int   i;
-  int   found = FALSE;
-  int   size = 0;
-  int   len = 0;
-  off_t begin = 0;
-  off_t pos = 0;
+  static int aic7xxx_buffer_size = 0;
+  int    found = FALSE;
+  static int   size = 0;
+  unsigned char i;
+  static char *aic7xxx_buffer = NULL;
   static char *bus_names[] = { "Single", "Twin", "Wide" };
   static char *chip_names[] = { "AIC-777x", "AIC-785x", "AIC-786x",
       "AIC-787x", "AIC-788x" };
+#ifdef AIC7XXX_PROC_STATS
+  struct aic7xxx_xferstats *sp;
+  unsigned char target, lun;
+#endif
 
   HBAptr = NULL;
   for (i=0; i < NUMBER(aic7xxx_boards); i++)
@@ -95,7 +100,7 @@
       {
         break;
       }
-
+      
       while ((HBAptr->hostdata != NULL) && !found &&
           ((HBAptr = ((struct aic7xxx_host *) HBAptr->hostdata)->next) != NULL))
       {
@@ -104,7 +109,7 @@
           found = TRUE;
         }
       }
-
+      
       if (!found)
       {
         HBAptr = NULL;
@@ -115,43 +120,69 @@
       }
     }
   }
-
+  
   if (HBAptr == NULL)
   {
-    size += sprintf(BLS, "Can't find adapter for host number %d\n", hostno);
-    len += size; pos = begin + len; size = 0;
-    goto stop_output;
+    size += sprintf( buffer, "Can't find adapter for host number %d\n", hostno);
+    if ( size > length) return size;
+    return length;
   }
-
+  
   if (inout == TRUE) /* Has data been written to the file? */ 
   {
     return (aic7xxx_set_info(buffer, length, HBAptr));
   }
-
+  
   p = (struct aic7xxx_host *) HBAptr->hostdata;
 
+  /* It takes roughly 1K of space to hold all relevant card info, not     */
+  /* counting any proc stats, so we start out with a 1.5k buffer size and */
+  /* if proc_stats is defined, then we sweep the stats structure to see   */
+  /* how many drives we will be printing out for and add 384 bytes per    */
+  /* device with active stats.                                            */
+
+  size = 1536;
+#ifdef AIC7XXX_PROC_STATS
+  for (target=0; target<16; target++)
+  {
+    for (lun=0; lun<8; lun++)
+    {
+      if (p->stats[target][lun].xfers != 0)
+        size += 384;
+    }
+  }
+#endif
+  if ( aic7xxx_buffer_size != size) {
+    if ( aic7xxx_buffer != NULL) 
+    {
+      kfree  ( aic7xxx_buffer);
+      aic7xxx_buffer_size = 0;
+    }
+    aic7xxx_buffer = kmalloc ( size, GFP_KERNEL);
+  }
+  if ( aic7xxx_buffer == NULL) {
+    size = sprintf ( buffer, "AIC7xxx - kmalloc error at line %d\n",
+                                     __LINE__);
+    return size;
+  }
+  aic7xxx_buffer_size = size;
+
+  size = 0;
   size += sprintf(BLS, "Adaptec AIC7xxx driver version: ");
   size += sprintf(BLS, "%s/", rcs_version(AIC7XXX_C_VERSION));
   size += sprintf(BLS, "%s", rcs_version(AIC7XXX_H_VERSION));
 #if 0
   size += sprintf(BLS, "%s\n", rcs_version(AIC7XXX_SEQ_VER));
 #endif
-  if (size > 512)
-    printk(KERN_CRIT "aic7xxx: possible overflow at first position\n");
-  len += size; pos = begin + len; size = 0;
-  if (pos < offset)
-  {
-    begin = pos;
-    len = 0;
-  }
-
   size += sprintf(BLS, "\n");
   size += sprintf(BLS, "Compile Options:\n");
 #ifdef AIC7XXX_RESET_DELAY
-  size += sprintf(BLS, "  AIC7XXX_RESET_DELAY    : %d\n", AIC7XXX_RESET_DELAY);
+  size += sprintf(BLS, "  AIC7XXX_RESET_DELAY    : %d\n",
+                     AIC7XXX_RESET_DELAY);
 #endif
 #ifdef AIC7XXX_CMDS_PER_LUN
-  size += sprintf(BLS, "  AIC7XXX_CMDS_PER_LUN   : %d\n", AIC7XXX_CMDS_PER_LUN);
+  size += sprintf(BLS, "  AIC7XXX_CMDS_PER_LUN   : %d\n",
+                     AIC7XXX_CMDS_PER_LUN);
 #endif
 #ifdef AIC7XXX_TAGGED_QUEUEING
   size += sprintf(BLS, "  AIC7XXX_TAGGED_QUEUEING: Enabled\n");
@@ -168,29 +199,19 @@
 #else
   size += sprintf(BLS, "  AIC7XXX_PROC_STATS     : Disabled\n");
 #endif
-  if (size > 512)
-    printk(KERN_CRIT "aic7xxx: possible overflow at second position\n");
-  len += size; pos = begin + len; size = 0;
-  if (pos < offset)
-  {
-    begin = pos;
-    len = 0;
-  }
-  else if (pos >= offset + length)
-    goto stop_output;
-
   size += sprintf(BLS, "\n");
   size += sprintf(BLS, "Adapter Configuration:\n");
   size += sprintf(BLS, "          SCSI Adapter: %s\n",
-      board_names[p->chip_type]);
+         board_names[p->chip_type]);
   size += sprintf(BLS, "                        (%s chipset)\n",
-      chip_names[p->chip_class]);
-  size += sprintf(BLS, "              Host Bus: %s\n", bus_names[p->bus_type]);
+         chip_names[p->chip_class]);
+  size += sprintf(BLS, "              Host Bus: %s\n",
+                     bus_names[p->bus_type]);
   size += sprintf(BLS, "               Base IO: %#.4x\n", p->base);
   size += sprintf(BLS, "        Base IO Memory: 0x%x\n", p->mbase);
   size += sprintf(BLS, "                   IRQ: %d\n", HBAptr->irq);
   size += sprintf(BLS, "                  SCBs: Used %d, HW %d, Page %d\n",
-      p->scb_data->numscbs, p->scb_data->maxhscbs, p->scb_data->maxscbs);
+         p->scb_data->numscbs, p->scb_data->maxhscbs, p->scb_data->maxscbs);
   size += sprintf(BLS, "            Interrupts: %d", p->isr_count);
   if (p->chip_class == AIC_777x)
   {
@@ -211,92 +232,56 @@
       (p->flags & ULTRA_ENABLED) ? "En" : "Dis");
   size += sprintf(BLS, "     Target Disconnect: %sabled\n",
       p->discenable ? "En" : "Dis");
-  if (size > 512)
-    printk(KERN_CRIT "aic7xxx: possible overflow at third position\n");
-  len += size; pos = begin + len; size = 0;
-  if (pos < offset)
-  {
-    begin = pos;
-    len = 0;
-  }
-  else if (pos >= offset + length)
-    goto stop_output;
-
+  
 #ifdef AIC7XXX_PROC_STATS
+  size += sprintf(BLS, "\n");
+  size += sprintf(BLS, "Statistics:\n");
+  for (target = 0; target < 16; target++)
   {
-    struct aic7xxx_xferstats *sp;
-    int channel, target, lun;
-
-    /*
-     * XXX: Need to fix this to avoid overflow...
-     * Fixed - gordo.
-     */
-    size += sprintf(BLS, "\n");
-    size += sprintf(BLS, "Statistics:\n");
-    for (channel = 0; channel < 2; channel++)
+    for (lun = 0; lun < 8; lun++)
     {
-      for (target = 0; target < 16; target++)
+      sp = &p->stats[target][lun];
+      if (sp->xfers == 0)
       {
-        for (lun = 0; lun < 8; lun++)
-        {
-          sp = &p->stats[channel][target][lun];
-          if (sp->xfers == 0)
-          {
-            continue;
-          }
-          size += sprintf(BLS, "CHAN#%c (TGT %d LUN %d):\n",
-              'A' + channel, target, lun);
-          size += sprintf(BLS, "nxfers %ld (%ld read;%ld written)\n",
-              sp->xfers, sp->r_total, sp->w_total);
-          size += sprintf(BLS, "blks(512) rd=%ld; blks(512) wr=%ld\n",
-              sp->r_total512, sp->w_total512);
-          size += sprintf(BLS, "%s\n", HDRB);
-          size += sprintf(BLS, " Reads:");
-          size += sprintf(BLS, "%6ld %6ld %6ld %6ld ", sp->r_bins[0],
-              sp->r_bins[1], sp->r_bins[2], sp->r_bins[3]);
-          size += sprintf(BLS, "%6ld %6ld %6ld %6ld ", sp->r_bins[4],
-              sp->r_bins[5], sp->r_bins[6], sp->r_bins[7]);
-          size += sprintf(BLS, "%6ld %6ld\n", sp->r_bins[8],
-              sp->r_bins[9]);
-          size += sprintf(BLS, "Writes:");
-          size += sprintf(BLS, "%6ld %6ld %6ld %6ld ", sp->w_bins[0],
-              sp->w_bins[1], sp->w_bins[2], sp->w_bins[3]);
-          size += sprintf(BLS, "%6ld %6ld %6ld %6ld ", sp->w_bins[4],
-              sp->w_bins[5], sp->w_bins[6], sp->w_bins[7]);
-          size += sprintf(BLS, "%6ld %6ld\n", sp->w_bins[8],
-              sp->w_bins[9]);
-          size += sprintf(BLS, "\n");
-        }
-	if (size > 512)
-	  printk(KERN_CRIT "aic7xxx: possible overflow at loop %d:%d\n", target, lun);
-        len += size; pos = begin + len; size = 0;
-	if (pos < offset)
-	{
-	  begin = pos;
-	  len = 0;
-	}
-	else if (pos >= offset + length)
-	  goto stop_output;
+        continue;
       }
+      if (p->bus_type == AIC_TWIN)
+        size += sprintf(BLS, "CHAN#%c (TGT %d LUN %d):\n",
+            'A' + (target >> 3), (target & 0x7), lun);
+      else
+        size += sprintf(BLS, "CHAN#%c (TGT %d LUN %d):\n",
+            'A', target, lun);
+      size += sprintf(BLS, "nxfers %ld (%ld read;%ld written)\n",
+               sp->xfers, sp->r_total, sp->w_total);
+      size += sprintf(BLS, "blks(512) rd=%ld; blks(512) wr=%ld\n",
+               sp->r_total512, sp->w_total512);
+      size += sprintf(BLS, "%s\n", HDRB);
+      size += sprintf(BLS, " Reads:");
+      for (i=0; i<10; i++)
+             size += sprintf(BLS, "%6ld ", sp->r_bins[i]);
+      size += sprintf(BLS, "\n");
+      size += sprintf(BLS, "Writes:");
+      for (i=0; i<10; i++)
+             size += sprintf(BLS, "%6ld ", sp->w_bins[i]);
+      size += sprintf(BLS, "\n\n");
     }
   }
 #endif /* AIC7XXX_PROC_STATS */
 
-stop_output:
-  proc_debug("2pos: %ld offset: %ld len: %d\n", pos, offset, len);
-  *start = buffer + (offset - begin);   /* Start of wanted data */
-  len -= (offset - begin);      /* Start slop */
-  if (len < 0)
-  {
-    len = 0;			/* off end of file */
-  }
-  else if (len > length)
-  {
-    len = length;               /* Ending slop */
+  if ( size >= aic7xxx_buffer_size )
+    printk(KERN_WARNING "aic7xxx: Overflow in aic7xxx_proc.c\n");
+
+  if ( offset > size - 1) {
+     kfree ( aic7xxx_buffer);
+     aic7xxx_buffer = NULL;
+     aic7xxx_buffer_size = length = 0;
+     *start = NULL;
+  } else {
+     *start = &aic7xxx_buffer[offset];   /* Start of wanted data */
+     if ( size - offset < length) length = size - offset;
   }
-  proc_debug("3pos: %ld offset: %ld len: %d\n", pos, offset, len);
   
-  return (len);     
+  return length;
 }
 
 /*
diff -urN linux-2.0.31-pre9/drivers/scsi/aic7xxx_reg.h linux-2.0.31-pre10/drivers/scsi/aic7xxx_reg.h
--- linux-2.0.31-pre9/drivers/scsi/aic7xxx_reg.h	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/drivers/scsi/aic7xxx_reg.h	2003-08-15 15:04:13.000000000 -0700
@@ -252,18 +252,20 @@
 
 #define	CUR_SCBID       		0x58
 
-#define	CMDOUTCNT       		0x59
+#define	ARG_1           		0x59
+#define	RETURN_1        		0x59
+#define		SEND_MSG        	0x80
+#define		SEND_SENSE      	0x40
+#define		SEND_REJ        	0x20
 
 #define	SCSICONF        		0x5a
-#define		RESET_SCSI      	0x40
 
-#define	FIFODEPTH       		0x5a
+#define	CMDOUTCNT       		0x5a
 
-#define	ARG_1           		0x5b
-#define	RETURN_1        		0x5b
-#define		SEND_MSG        	0x80
-#define		SEND_SENSE      	0x40
-#define		SEND_REJ        	0x20
+#define	FIFODEPTH       		0x5b
+
+#define	SCSICONF2       		0x5b
+#define		RESET_SCSI      	0x40
 
 #define	HOSTCONF        		0x5d
 
diff -urN linux-2.0.31-pre9/drivers/scsi/aic7xxx_seq.h linux-2.0.31-pre10/drivers/scsi/aic7xxx_seq.h
--- linux-2.0.31-pre9/drivers/scsi/aic7xxx_seq.h	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/drivers/scsi/aic7xxx_seq.h	2003-08-15 15:04:13.000000000 -0700
@@ -26,8 +26,8 @@
 	0x50, 0x6a, 0x60, 0x00,
 	0xff, 0x90, 0x4a, 0x02,
 	0x00, 0xa1, 0xa1, 0x17,
-	0xff, 0x6c, 0x5b, 0x02,
-	0xff, 0x5b, 0x27, 0x1c,
+	0xff, 0x6c, 0x59, 0x02,
+	0xff, 0x59, 0x27, 0x1c,
 	0xff, 0x4a, 0x90, 0x02,
 	0x00, 0x65, 0xaa, 0x17,
 	0x00, 0x6a, 0x52, 0x17,
@@ -37,7 +37,7 @@
 	0x00, 0x65, 0xbb, 0x17,
 	0x10, 0x6a, 0x60, 0x00,
 	0x00, 0x65, 0x03, 0x10,
-	0xff, 0x5b, 0x90, 0x02,
+	0xff, 0x59, 0x90, 0x02,
 	0xff, 0x58, 0xb3, 0x02,
 	0x10, 0x6a, 0x60, 0x00,
 	0x00, 0x65, 0x03, 0x10,
@@ -217,7 +217,7 @@
 	0x00, 0xb9, 0x77, 0x17,
 	0xff, 0xa2, 0xda, 0x1e,
 	0x71, 0x6a, 0x91, 0x00,
-	0x40, 0x5b, 0xda, 0x18,
+	0x40, 0x59, 0xda, 0x18,
 	0xff, 0xb9, 0xb3, 0x02,
 	0x00, 0x65, 0xe7, 0x10,
 	0x20, 0xa0, 0xe0, 0x1a,
@@ -226,9 +226,9 @@
 	0x00, 0xa1, 0xa1, 0x17,
 	0xff, 0x49, 0x6d, 0x02,
 	0xff, 0x4a, 0x90, 0x02,
-	0xff, 0x5a, 0x64, 0x02,
-	0x00, 0x59, 0xe1, 0x1c,
-	0x01, 0x59, 0x59, 0x06,
+	0xff, 0x5b, 0x64, 0x02,
+	0x00, 0x5a, 0xe1, 0x1c,
+	0x01, 0x5a, 0x5a, 0x06,
 	0xff, 0xb9, 0x9d, 0x02,
 	0x02, 0x6a, 0x91, 0x00,
 	0x08, 0xa0, 0xe7, 0x1e,
@@ -255,8 +255,8 @@
 	0xff, 0x66, 0x66, 0x06,
 	0xff, 0x64, 0xf7, 0x1a,
 	0x41, 0x6a, 0x91, 0x00,
-	0x20, 0x5b, 0xcd, 0x1c,
-	0x80, 0x5b, 0xcf, 0x18,
+	0x20, 0x59, 0xcd, 0x1c,
+	0x80, 0x59, 0xcf, 0x18,
 	0x10, 0x4c, 0x03, 0x00,
 	0x00, 0x65, 0xcf, 0x10,
 	0x04, 0xa0, 0xa0, 0x00,
@@ -276,10 +276,10 @@
 	0x07, 0x64, 0x64, 0x02,
 	0x00, 0x42, 0x42, 0x00,
 	0x00, 0x42, 0xa1, 0x17,
-	0xff, 0x6c, 0x5b, 0x02,
-	0xff, 0x5b, 0x28, 0x19,
-	0xff, 0x5b, 0x18, 0x1d,
-	0xff, 0x5b, 0x90, 0x02,
+	0xff, 0x6c, 0x59, 0x02,
+	0xff, 0x59, 0x28, 0x19,
+	0xff, 0x59, 0x18, 0x1d,
+	0xff, 0x59, 0x90, 0x02,
 	0x04, 0xa0, 0x2d, 0x1f,
 	0x00, 0x65, 0x2a, 0x11,
 	0xff, 0x06, 0x6a, 0x02,
@@ -289,11 +289,11 @@
 	0xe0, 0x4c, 0x2d, 0x19,
 	0x20, 0x12, 0x2d, 0x19,
 	0x20, 0x41, 0x41, 0x00,
-	0x5b, 0x6a, 0x3a, 0x17,
+	0x59, 0x6a, 0x3a, 0x17,
 	0xff, 0x3f, 0x64, 0x02,
-	0x00, 0x5b, 0x65, 0x06,
+	0x00, 0x59, 0x65, 0x06,
 	0x00, 0x65, 0x2d, 0x13,
-	0xff, 0x5b, 0x90, 0x02,
+	0xff, 0x59, 0x90, 0x02,
 	0xff, 0x42, 0x64, 0x02,
 	0x00, 0xa1, 0x2d, 0x19,
 	0x20, 0xa0, 0x2d, 0x1f,
@@ -341,7 +341,7 @@
 	0x40, 0x41, 0x4e, 0x1b,
 	0x21, 0x6a, 0x91, 0x01,
 	0xff, 0x65, 0x90, 0x02,
-	0xff, 0x5b, 0x64, 0x02,
+	0xff, 0x59, 0x64, 0x02,
 	0x00, 0xb9, 0x56, 0x19,
 	0x04, 0xa0, 0x60, 0x1b,
 	0x01, 0x65, 0x65, 0x06,
@@ -349,7 +349,7 @@
 	0x00, 0x65, 0x52, 0x19,
 	0x00, 0x6a, 0xad, 0x17,
 	0x0d, 0x6a, 0x3d, 0x00,
-	0x00, 0x5b, 0x77, 0x17,
+	0x00, 0x59, 0x77, 0x17,
 	0xff, 0xa8, 0x5e, 0x1f,
 	0x10, 0xa0, 0xa0, 0x00,
 	0x08, 0xa0, 0x4e, 0x1f,
diff -urN linux-2.0.31-pre9/drivers/scsi/Config.in linux-2.0.31-pre10/drivers/scsi/Config.in
--- linux-2.0.31-pre9/drivers/scsi/Config.in	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/drivers/scsi/Config.in	2003-08-15 15:04:13.000000000 -0700
@@ -42,7 +42,7 @@
 dep_tristate 'EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support' CONFIG_SCSI_EATA $CONFIG_SCSI
   if [ "$CONFIG_SCSI_EATA" != "n" ]; then
     bool '  enable tagged command queueing' CONFIG_SCSI_EATA_TAGGED_QUEUE
-    bool '  enable linked commands' CONFIG_SCSI_EATA_LINKED_COMMANDS
+    bool '  enable elevator sorting' CONFIG_SCSI_EATA_LINKED_COMMANDS
     int  '  maximum number of queued commands' CONFIG_SCSI_EATA_MAX_TAGS 16
   fi
 dep_tristate 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
@@ -91,7 +91,7 @@
 dep_tristate 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 $CONFIG_SCSI
 dep_tristate 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F $CONFIG_SCSI
   if [ "$CONFIG_SCSI_U14_34F" != "n" ]; then
-    bool '  enable linked commands' CONFIG_SCSI_U14_34F_LINKED_COMMANDS
+    bool '  enable elevator sorting' CONFIG_SCSI_U14_34F_LINKED_COMMANDS
     int  '  maximum number of queued commands' CONFIG_SCSI_U14_34F_MAX_TAGS 8
   fi
 dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI
diff -urN linux-2.0.31-pre9/drivers/scsi/eata.c linux-2.0.31-pre10/drivers/scsi/eata.c
--- linux-2.0.31-pre9/drivers/scsi/eata.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/drivers/scsi/eata.c	2003-08-15 15:04:13.000000000 -0700
@@ -1,5 +1,14 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
+ *   
+ *      12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55
+ *          Use of udelay inside the wait loops to avoid timeout
+ *          problems with fast cpus.
+ *          Removed check about useless calls to the interrupt service
+ *          routine (reported on SMP systems only).
+ *          At initialization time "sorted/unsorted" is displayed instead
+ *          of "linked/unlinked" to reinforce the fact that "linking" is
+ *          nothing but "elevator sorting" in the actual implementation.
  *
  *      17 May 1997 rev. 3.10 for linux 2.0.30 and 2.1.38
  *          Use of serial_number_at_timeout in abort and reset processing.
@@ -283,6 +292,7 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/byteorder.h>
@@ -323,6 +333,7 @@
 #undef  DEBUG_INTERRUPT
 #undef  DEBUG_STATISTICS
 #undef  DEBUG_RESET
+#undef  DEBUG_SMP
 
 #define MAX_ISA 4
 #define MAX_VESA 0 
@@ -351,7 +362,7 @@
 #define READY    5
 #define ABORTING 6
 #define NO_DMA  0xff
-#define MAXLOOP 200000
+#define MAXLOOP  10000
 #define TAG_MIXED    0
 #define TAG_SIMPLE   1
 #define TAG_HEAD     2
@@ -630,9 +641,9 @@
 
       if (TLDEV(dev->type)) {
          if (linked_comm && dev->queue_depth > 2)
-            link_suffix = ", linked";
+            link_suffix = ", sorted";
          else
-            link_suffix = ", unlinked";
+            link_suffix = ", unsorted";
          }
 
       if (tagged_comm && dev->tagged_supported && TLDEV(dev->type)) {
@@ -656,8 +667,10 @@
 
 static inline int wait_on_busy(unsigned int iobase, unsigned int loop) {
 
-   while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED)
+   while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) {
+      udelay(1L);
       if (--loop == 0) return TRUE;
+      }
 
    return FALSE;
 }
@@ -683,8 +696,10 @@
 
    for (p = start; p <= end; p++) {
 
-      while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) 
+      while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) {
+         udelay(1L);
 	 if (--loop == 0) return TRUE;
+         }
 
       loop = MAXLOOP;
       *p = inw(iobase);
@@ -1416,7 +1431,7 @@
    HD(j)->in_reset = TRUE;
    sti();
    time = jiffies;
-   while ((jiffies - time) < HZ && limit++ < 100000000);
+   while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L);
    cli();
    printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit);
 
@@ -1831,9 +1846,11 @@
 
    calls[irq]++;
 
+#if defined (DEBUG_SMP)
    if (total_loops == 0) 
      printk("%s: ihdlr, irq %d, no command completed, calls %d.\n",
 	    driver_name, irq, calls[irq]);
+#endif
 
    if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n", 
 			driver_name, irq, calls[irq]);
diff -urN linux-2.0.31-pre9/drivers/scsi/eata.h linux-2.0.31-pre10/drivers/scsi/eata.h
--- linux-2.0.31-pre9/drivers/scsi/eata.h	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/drivers/scsi/eata.h	2003-08-15 15:04:13.000000000 -0700
@@ -12,7 +12,7 @@
 int eata2x_abort(Scsi_Cmnd *);
 int eata2x_reset(Scsi_Cmnd *, unsigned int);
 
-#define EATA_VERSION "3.10.00"
+#define EATA_VERSION "3.11.00"
 
 
 #define EATA {                                                 \
diff -urN linux-2.0.31-pre9/drivers/scsi/scsi_module.c linux-2.0.31-pre10/drivers/scsi/scsi_module.c
--- linux-2.0.31-pre9/drivers/scsi/scsi_module.c	1995-11-08 22:24:08.000000000 -0800
+++ linux-2.0.31-pre10/drivers/scsi/scsi_module.c	2003-08-15 15:04:13.000000000 -0700
@@ -34,7 +34,11 @@
 int init_module(void) {
     driver_template.usage_count = &mod_use_count_;
     scsi_register_module(MODULE_SCSI_HA, &driver_template);
-    return (driver_template.present == 0);
+    if (driver_template.present)
+    	return 0;
+
+    scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
+    return -1;
 }
 
 void cleanup_module( void) {
diff -urN linux-2.0.31-pre9/drivers/scsi/u14-34f.c linux-2.0.31-pre10/drivers/scsi/u14-34f.c
--- linux-2.0.31-pre9/drivers/scsi/u14-34f.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/drivers/scsi/u14-34f.c	2003-08-15 15:04:13.000000000 -0700
@@ -1,6 +1,15 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *      12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55
+ *          Use of udelay inside the wait loops to avoid timeout
+ *          problems with fast cpus.
+ *          Removed check about useless calls to the interrupt service
+ *          routine (reported on SMP systems only).
+ *          At initialization time "sorted/unsorted" is displayed instead
+ *          of "linked/unlinked" to reinforce the fact that "linking" is
+ *          nothing but "elevator sorting" in the actual implementation.
+ *
  *      17 May 1997 rev. 3.10 for linux 2.0.30 and 2.1.38
  *          Use of serial_number_at_timeout in abort and reset processing.
  *          Use of the __initfunc and __initdata macro in setup code.
@@ -269,6 +278,7 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/byteorder.h>
@@ -321,6 +331,7 @@
 #undef  DEBUG_INTERRUPT
 #undef  DEBUG_STATISTICS
 #undef  DEBUG_RESET
+#undef  DEBUG_SMP
 
 #define MAX_ISA 3
 #define MAX_VESA 1 
@@ -349,7 +360,7 @@
 #define READY    5
 #define ABORTING 6
 #define NO_DMA  0xff
-#define MAXLOOP 200000
+#define MAXLOOP  10000
 
 #define REG_LCL_MASK      0
 #define REG_LCL_INTR      1
@@ -530,9 +541,9 @@
 
       if (TLDEV(dev->type)) {
          if (linked_comm && dev->queue_depth > 2)
-            link_suffix = ", linked";
+            link_suffix = ", sorted";
          else
-            link_suffix = ", unlinked";
+            link_suffix = ", unsorted";
          }
 
       if (dev->tagged_supported && TLDEV(dev->type) && dev->tagged_queue)
@@ -551,8 +562,10 @@
 
 static inline int wait_on_busy(unsigned int iobase, unsigned int loop) {
 
-   while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED)
+   while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) {
+      udelay(1L);
       if (--loop == 0) return TRUE;
+      }
 
    return FALSE;
 }
@@ -588,7 +601,7 @@
 
    sti();
    time = jiffies;
-   while ((jiffies - time) < HZ && limit++ < 100000000);
+   while ((jiffies - time) < HZ && limit++ < 20000) udelay(100L);
    cli();
 
    if (cpp->adapter_status || HD(j)->cp_stat[0] != FREE) {
@@ -1195,7 +1208,7 @@
    HD(j)->in_reset = TRUE;
    sti();
    time = jiffies;
-   while ((jiffies - time) < HZ && limit++ < 100000000);
+   while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L);
    cli();
    printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit);
 
@@ -1616,9 +1629,11 @@
 
    calls[irq]++;
 
+#if defined (DEBUG_SMP)
    if (total_loops == 0) 
      printk("%s: ihdlr, irq %d, no command completed, calls %d.\n",
 	    driver_name, irq, calls[irq]);
+#endif
 
    if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n",
 			driver_name, irq, calls[irq]);
diff -urN linux-2.0.31-pre9/drivers/scsi/u14-34f.h linux-2.0.31-pre10/drivers/scsi/u14-34f.h
--- linux-2.0.31-pre9/drivers/scsi/u14-34f.h	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/drivers/scsi/u14-34f.h	2003-08-15 15:04:13.000000000 -0700
@@ -11,7 +11,7 @@
 int u14_34f_reset(Scsi_Cmnd *, unsigned int);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "3.10.00"
+#define U14_34F_VERSION "3.11.00"
 
 #define ULTRASTOR_14_34F {                                            \
 		NULL, /* Ptr for modules */                           \
diff -urN linux-2.0.31-pre9/fs/buffer.c linux-2.0.31-pre10/fs/buffer.c
--- linux-2.0.31-pre9/fs/buffer.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/fs/buffer.c	2003-08-15 15:04:13.000000000 -0700
@@ -559,7 +559,7 @@
 static struct buffer_head *find_candidate(struct buffer_head *bh,
 					  int *list_len, int size)
 {
-	int behind = 0;
+	int lookahead  = 7;
 
 	if (!bh)
 		goto no_candidate;
@@ -572,11 +572,12 @@
 			try_to_free_buffer(bh,&bh,1);
 			if (!bh)
 				break;
+			lookahead = 7;
 			continue;
 		}
 		else if (buffer_locked(bh) && 
 			 (bh->b_list == BUF_LOCKED || bh->b_list == BUF_LOCKED1)) {
-			if (behind++ > 10) {
+			if (!--lookahead) {
 				(*list_len) = 0;
 				goto no_candidate;
 			}
@@ -595,9 +596,10 @@
 {
 	struct buffer_head * bh;
 	struct buffer_head * candidate[BUF_DIRTY];
+	extern struct task_struct *bdflush_tsk;
 	unsigned int best_time, winner;
 	int buffers[BUF_DIRTY];
-	int i;
+	int i, limit = ((min_free_pages + free_pages_low) >> 1);
 	int needed;
 
 	refilled = 1;
@@ -606,7 +608,7 @@
 	   for user processes to use (and dirty) */
 	
 	/* We are going to try to locate this much memory */
-	needed =bdf_prm.b_un.nrefill * size;  
+	needed = bdf_prm.b_un.nrefill * size;  
 
 	while (nr_free_pages > min_free_pages*2 && needed > 0 &&
 	       grow_buffers(GFP_BUFFER, size)) {
@@ -661,21 +663,38 @@
 
 	/* Dirty buffers should not overtake, wakeup_bdflush(1) calls
 	   bdflush and sleeps, therefore kswapd does his important work. */
-	if ((nr_buffers_type[BUF_DIRTY] > nr_buffers * bdf_prm.b_un.nfract/100) ||
-	    (nr_free_pages < min_free_pages))
+	if (nr_buffers_type[BUF_DIRTY] > nr_buffers * bdf_prm.b_un.nfract/100)
 		wakeup_bdflush(1);
 	
 	/* Too bad, that was not enough. Try a little harder to grow some. */
 	
-	if (nr_free_pages > min_free_pages + 5) {
+	if (nr_free_pages > limit) {
 		if (grow_buffers(GFP_BUFFER, size)) {
 			needed -= PAGE_SIZE;
 			goto repeat;
 		};
 	}
 
+	/* If we are not bdflush we should wake up bdflush and try it again. */
+
+	if (current != bdflush_tsk) {
+		wakeup_bdflush(1);
+		needed -= PAGE_SIZE;
+		goto repeat;
+	}
+
+	/* We are bdflush: let's try our best */
+
+	/*
+	 * In order to protect our reserved pages, 
+	 * return now if we got any buffers.
+	 */
+	allow_interrupts();
+	if (free_list[BUFSIZE_INDEX(size)])
+		return;
+
 	/* and repeat until we find something good */
-	wakeup_bdflush(1);
+	grow_buffers(GFP_BUFFER, size);
 
 	/* decrease needed even if there is no success */
 	needed -= PAGE_SIZE;
@@ -966,11 +985,15 @@
 		 * This is critical.  We can't swap out pages to get
 		 * more buffer heads, because the swap-out may need
 		 * more buffer-heads itself.  Thus GFP_ATOMIC.
+		 *
+		 * This is no longer true, it is GFP_BUFFER again, the
+		 * swapping code now knows not to perform I/O when that
+		 * GFP level is specified... -DaveM
 		 */
 		/* we now use kmalloc() here instead of gfp as we want
                    to be able to easily release buffer heads - they
                    took up quite a bit of memory (tridge) */
-		bh = (struct buffer_head *) kmalloc(sizeof(*bh),GFP_ATOMIC);
+		bh = (struct buffer_head *) kmalloc(sizeof(*bh),GFP_BUFFER);
 		if (bh) {
 			put_unused_buffer_head(bh);
 			nr_buffer_heads++;
diff -urN linux-2.0.31-pre9/fs/fcntl.c linux-2.0.31-pre10/fs/fcntl.c
--- linux-2.0.31-pre9/fs/fcntl.c	1996-07-04 11:23:45.000000000 -0700
+++ linux-2.0.31-pre10/fs/fcntl.c	2003-08-15 15:04:13.000000000 -0700
@@ -55,8 +55,6 @@
 asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {	
 	struct file * filp;
-	struct task_struct *p;
-	int task_found = 0;
 
 	if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
 		return -EBADF;
@@ -108,49 +106,11 @@
 			 * current syscall conventions, the only way
 			 * to fix this will be in libc.
 			 */
-			return filp->f_owner;
+			return filp->f_owner.pid;
 		case F_SETOWN:
-			/*
-			 *	Add the security checks - AC. Without
-			 *	this there is a massive Linux security
-			 *	hole here - consider what happens if
-			 *	you do something like
-			 * 
-			 *		fcntl(0,F_SETOWN,some_root_process);
-			 *		getchar();
-			 * 
-			 *	and input a line!
-			 * 
-			 * BTW: Don't try this for fun. Several Unix
-			 *	systems I tried this on fall for the
-			 *	trick!
-			 * 
-			 * I had to fix this botch job as Linux
-			 *	kill_fasync asserts priv making it a
-			 *	free all user process killer!
-			 *
-			 * Changed to make the security checks more
-			 * liberal.  -- TYT
-			 */
-			if (current->pgrp == -arg || current->pid == arg)
-				goto fasync_ok;
-			
-			for_each_task(p) {
-				if ((p->pid == arg) || (p->pid == -arg) || 
-				    (p->pgrp == -arg)) {
-					task_found++;
-					if ((p->session != current->session) &&
-					    (p->uid != current->uid) &&
-					    (p->euid != current->euid) &&
-					    !suser())
-						return -EPERM;
-					break;
-				}
-			}
-			if ((task_found == 0) && !suser())
-				return -EINVAL;
-		fasync_ok:
-			filp->f_owner = arg;
+			filp->f_owner.pid = arg;
+			filp->f_owner.uid = current->uid;
+			filp->f_owner.euid = current->euid;
 			if (S_ISSOCK (filp->f_inode->i_mode))
 				sock_fcntl (filp, F_SETOWN, arg);
 			return 0;
@@ -164,18 +124,38 @@
 	}
 }
 
+static void send_sigio(int sig, int pid, uid_t uid, uid_t euid)
+{
+	struct task_struct * p;
+
+	for_each_task(p) {
+		int match = p->pid;
+		if (pid < 0)
+			match = -p->pgrp;
+		if (pid != match)
+			continue;
+		if (!euid &&
+		    (euid ^ p->suid) && (euid ^ p->uid) &&
+		    (uid ^ p->suid) && (uid ^ p->uid))
+			continue;
+		p->signal |= 1 << (sig-1);
+		if (p->state == TASK_INTERRUPTIBLE && (p->signal & ~p->blocked))
+			wake_up_process(p);
+	}
+}
+
 void kill_fasync(struct fasync_struct *fa, int sig)
 {
 	while (fa) {
+		struct fown_struct * fown;
 		if (fa->magic != FASYNC_MAGIC) {
 			printk("kill_fasync: bad magic number in "
 			       "fasync_struct!\n");
 			return;
 		}
-		if (fa->fa_file->f_owner > 0)
-			kill_proc(fa->fa_file->f_owner, sig, 1);
-		else
-			kill_pg(-fa->fa_file->f_owner, sig, 1);
+		fown = &fa->fa_file->f_owner;
+		if (fown->pid)
+			send_sigio(sig, fown->pid, fown->uid, fown->euid);
 		fa = fa->fa_next;
 	}
 }
diff -urN linux-2.0.31-pre9/fs/smbfs/inode.c linux-2.0.31-pre10/fs/smbfs/inode.c
--- linux-2.0.31-pre9/fs/smbfs/inode.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/fs/smbfs/inode.c	2003-08-15 15:04:13.000000000 -0700
@@ -232,10 +232,13 @@
 	kdev_t dev = sb->s_dev;
 	int error;
 
+	MOD_INC_USE_COUNT;
+
 	if (smb_get_mount_data(&data, raw_data) != 0)
 	{
 		printk("smb_read_super: wrong data argument\n");
 		sb->s_dev = 0;
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	fd = data.fd;
@@ -243,12 +246,14 @@
 	{
 		printk("smb_read_super: invalid file descriptor\n");
 		sb->s_dev = 0;
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	if (!S_ISSOCK(filp->f_inode->i_mode))
 	{
 		printk("smb_read_super: not a socket!\n");
 		sb->s_dev = 0;
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	/* We must malloc our own super-block info */
@@ -258,6 +263,8 @@
 	if (smb_sb == NULL)
 	{
 		printk("smb_read_super: could not alloc smb_sb_info\n");
+		sb->s_dev = 0;
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	filp->f_count += 1;
@@ -328,7 +335,6 @@
 		printk("smb_read_super: get root inode failed\n");
 		goto fail;
 	}
-	MOD_INC_USE_COUNT;
 	return sb;
 
       fail:
@@ -340,6 +346,7 @@
 	filp->f_count -= 1;
 	smb_dont_catch_keepalive(server);
 	smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));
+	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
@@ -385,9 +392,32 @@
 	     (attr->ia_gid != SMB_SERVER(inode)->m.gid)))
 		return -EPERM;
 
-	if (((attr->ia_valid & ATTR_MODE) &&
-	(attr->ia_mode & ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
-		return -EPERM;
+	if (attr->ia_valid & ATTR_MODE) {
+		struct smb_dirent *fold = SMB_FINFO(inode);
+		struct smb_dirent finfo;
+
+		if (attr->ia_mode & ~(S_IFREG | S_IFDIR |
+				      S_IRWXU | S_IRWXG | S_IRWXO))
+			return -EPERM;
+
+		memset((char *)&finfo, 0, sizeof(finfo));
+		finfo.attr = fold->attr;
+
+		if((attr->ia_mode & 0200) == 0)
+		    finfo.attr |= aRONLY;
+		else
+		    finfo.attr &= ~aRONLY;
+
+		if ((error = smb_proc_setattr(SMB_SERVER(inode),
+					      inode, &finfo)) >= 0)
+		{
+			fold->attr = finfo.attr;
+			if ((attr->ia_mode & 0200) == 0)
+				inode->i_mode &= ~0222;
+			else
+				inode->i_mode |= 0222;
+		}
+	}
 
 	if ((attr->ia_valid & ATTR_SIZE) != 0)
 	{
@@ -401,41 +431,18 @@
 			goto fail;
 
 	}
-	if ((attr->ia_valid & (ATTR_CTIME | ATTR_MTIME | ATTR_ATIME)) != 0)
-	{
-
-		struct smb_dirent finfo;
 
-		finfo.attr = 0;
-		finfo.f_size = inode->i_size;
-		finfo.f_blksize = inode->i_blksize;
-
-		if ((attr->ia_valid & ATTR_CTIME) != 0)
-			finfo.f_ctime = attr->ia_ctime;
-		else
-			finfo.f_ctime = inode->i_ctime;
-
-		if ((attr->ia_valid & ATTR_MTIME) != 0)
-			finfo.f_mtime = attr->ia_mtime;
-		else
-			finfo.f_mtime = inode->i_mtime;
+	/* ATTR_CTIME and ATTR_ATIME can not be set via SMB, so ignore it. */
 
-		if ((attr->ia_valid & ATTR_ATIME) != 0)
-			finfo.f_atime = attr->ia_atime;
+	if (attr->ia_valid & ATTR_MTIME)
+	{
+		if (smb_make_open(inode, O_WRONLY) != 0)
+			error = -EACCES;
 		else
-			finfo.f_atime = inode->i_atime;
-
-		if ((error = smb_proc_setattr(SMB_SERVER(inode),
-					      inode, &finfo)) >= 0)
-		{
-			inode->i_ctime = finfo.f_ctime;
-			inode->i_mtime = finfo.f_mtime;
-			inode->i_atime = finfo.f_atime;
-		}
+			inode->i_mtime = attr->ia_mtime;
 	}
       fail:
 	smb_invalid_dir_cache(smb_info_ino(SMB_INOP(inode)->dir));
-
 	return error;
 }
 
diff -urN linux-2.0.31-pre9/fs/smbfs/proc.c linux-2.0.31-pre10/fs/smbfs/proc.c
--- linux-2.0.31-pre9/fs/smbfs/proc.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/fs/smbfs/proc.c	2003-08-15 15:04:13.000000000 -0700
@@ -230,40 +230,6 @@
 	return local2utc(secs);
 }
 
-
-/* Convert linear UNIX date to a MS-DOS time/date pair. */
-
-static void
-date_unix2dos(int unix_date, byte * date, byte * time)
-{
-	int day, year, nl_day, month;
-
-	unix_date = utc2local(unix_date);
-	WSET(time, 0,
-	     (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
-	     (((unix_date / 3600) % 24) << 11));
-	day = unix_date / 86400 - 3652;
-	year = day / 365;
-	if ((year + 3) / 4 + 365 * year > day)
-		year--;
-	day -= (year + 3) / 4 + 365 * year;
-	if (day == 59 && !(year & 3))
-	{
-		nl_day = day;
-		month = 2;
-	} else
-	{
-		nl_day = (year & 3) || day <= 59 ? day : day - 1;
-		for (month = 0; month < 12; month++)
-			if (day_n[month] > nl_day)
-				break;
-	}
-	WSET(date, 0,
-	     nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
-}
-
-
-
 /*****************************************************************************/
 /*                                                                           */
 /*  Support section.                                                         */
@@ -922,6 +888,9 @@
 		entry->f_mode = server->m.file_mode;
 	}
 
+	if (entry->attr & aRONLY)
+		entry->f_mode &= ~0222;
+
 	if ((entry->f_blksize != 0) && (entry->f_size != 0))
 	{
 		entry->f_blocks =
@@ -1414,80 +1383,15 @@
 	return 0;
 }
 
-static int
-smb_proc_getattr_trans2(struct inode *dir, const char *name, int len,
-			struct smb_dirent *entry)
-{
-	struct smb_server *server = SMB_SERVER(dir);
-	char param[SMB_MAXPATHLEN + 20];
-	char *p;
-	int result;
-
-	unsigned char *resp_data = NULL;
-	unsigned char *resp_param = NULL;
-	int resp_data_len = 0;
-	int resp_param_len = 0;
-
-	WSET(param, 0, 1);	/* Info level SMB_INFO_STANDARD */
-	DSET(param, 2, 0);
-	p = smb_encode_path(server, param + 6, SMB_INOP(dir), name, len);
-
-	smb_lock_server(server);
-      retry:
-	result = smb_trans2_request(server, TRANSACT2_QPATHINFO,
-				    0, NULL, p - param, param,
-				    &resp_data_len, &resp_data,
-				    &resp_param_len, &resp_param);
-
-	if (server->rcls != 0)
-	{
-		smb_unlock_server(server);
-		return -smb_errno(server->rcls, server->err);
-	}
-	if (result < 0)
-	{
-		if (smb_retry(server))
-		{
-			goto retry;
-		}
-		smb_unlock_server(server);
-		return result;
-	}
-	if (resp_data_len < 22)
-	{
-		smb_unlock_server(server);
-		return -ENOENT;
-	}
-	entry->f_ctime = date_dos2unix(WVAL(resp_data, 2),
-				       WVAL(resp_data, 0));
-	entry->f_atime = date_dos2unix(WVAL(resp_data, 6),
-				       WVAL(resp_data, 4));
-	entry->f_mtime = date_dos2unix(WVAL(resp_data, 10),
-				       WVAL(resp_data, 8));
-	entry->f_size = DVAL(resp_data, 12);
-	entry->attr = WVAL(resp_data, 20);
-	smb_unlock_server(server);
-
-	return 0;
-}
-
 int
 smb_proc_getattr(struct inode *dir, const char *name, int len,
 		 struct smb_dirent *entry)
 {
 	struct smb_server *server = SMB_SERVER(dir);
-	int result = 0;
+        int result;
 
 	smb_init_dirent(server, entry);
-
-	if (server->protocol >= PROTOCOL_LANMAN2)
-	{
-		result = smb_proc_getattr_trans2(dir, name, len, entry);
-	}
-	if ((server->protocol < PROTOCOL_LANMAN2) || (result < 0))
-	{
-		result = smb_proc_getattr_core(dir, name, len, entry);
-	}
+        result = smb_proc_getattr_core(dir, name, len, entry);
 	smb_finish_dirent(server, entry);
 
 	entry->len = len;
@@ -1497,12 +1401,9 @@
 	return result;
 }
 
-
-/* In core protocol, there is only 1 time to be set, we use
-   entry->f_mtime, to make touch work. */
-static int
-smb_proc_setattr_core(struct smb_server *server,
-		      struct inode *i, struct smb_dirent *new_finfo)
+int
+smb_proc_setattr(struct smb_server *server,
+                 struct inode *i, struct smb_dirent *new_finfo)
 {
 	char *p;
 	char *buf;
@@ -1514,12 +1415,14 @@
 	buf = server->packet;
 	p = smb_setup_header(server, SMBsetatr, 8, 0);
 	WSET(buf, smb_vwv0, new_finfo->attr);
-	DSET(buf, smb_vwv1, utc2local(new_finfo->f_mtime));
+	DSET(buf, smb_vwv1, 0);
+	DSET(buf, smb_vwv3, 0);
+	DSET(buf, smb_vwv5, 0);
+	WSET(buf, smb_vwv7, 0);
 	*p++ = 4;
 	p = smb_encode_path(server, p,
 			    SMB_INOP(i)->dir, SMB_INOP(i)->finfo.name,
 			    SMB_INOP(i)->finfo.len);
-	p = smb_encode_ascii(p, "", 0);
 
 	smb_setup_bcc(server, p);
 	if ((result = smb_request_ok(server, SMBsetatr, 0, 0)) < 0)
@@ -1533,74 +1436,6 @@
 	return result;
 }
 
-static int
-smb_proc_setattr_trans2(struct smb_server *server,
-			struct inode *i, struct smb_dirent *new_finfo)
-{
-	char param[SMB_MAXPATHLEN + 20];
-	char data[26];
-	char *p;
-	int result;
-
-	unsigned char *resp_data = NULL;
-	unsigned char *resp_param = NULL;
-	int resp_data_len = 0;
-	int resp_param_len = 0;
-
-	WSET(param, 0, 1);	/* Info level SMB_INFO_STANDARD */
-	DSET(param, 2, 0);
-	p = smb_encode_path(server, param + 6,
-			    SMB_INOP(i)->dir, SMB_INOP(i)->finfo.name,
-			    SMB_INOP(i)->finfo.len);
-
-	date_unix2dos(new_finfo->f_ctime, &(data[0]), &(data[2]));
-	date_unix2dos(new_finfo->f_atime, &(data[4]), &(data[6]));
-	date_unix2dos(new_finfo->f_mtime, &(data[8]), &(data[10]));
-	DSET(data, 12, new_finfo->f_size);
-	DSET(data, 16, new_finfo->f_blksize);
-	WSET(data, 20, new_finfo->attr);
-	WSET(data, 22, 0);
-
-	smb_lock_server(server);
-      retry:
-	result = smb_trans2_request(server, TRANSACT2_SETPATHINFO,
-				    26, data, p - param, param,
-				    &resp_data_len, &resp_data,
-				    &resp_param_len, &resp_param);
-
-	if (server->rcls != 0)
-	{
-		smb_unlock_server(server);
-		return -smb_errno(server->rcls, server->err);
-	}
-	if (result < 0)
-	{
-		if (smb_retry(server))
-		{
-			goto retry;
-		}
-	}
-	smb_unlock_server(server);
-	return 0;
-}
-
-int
-smb_proc_setattr(struct smb_server *server, struct inode *inode,
-		 struct smb_dirent *new_finfo)
-{
-	int result;
-
-	if (server->protocol >= PROTOCOL_LANMAN2)
-	{
-		result = smb_proc_setattr_trans2(server, inode, new_finfo);
-	}
-	if ((server->protocol < PROTOCOL_LANMAN2) || (result < 0))
-	{
-		result = smb_proc_setattr_core(server, inode, new_finfo);
-	}
-	return result;
-}
-
 int
 smb_proc_dskattr(struct super_block *super, struct smb_dskattr *attr)
 {
diff -urN linux-2.0.31-pre9/fs/smbfs/sock.c linux-2.0.31-pre10/fs/smbfs/sock.c
--- linux-2.0.31-pre9/fs/smbfs/sock.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/fs/smbfs/sock.c	2003-08-15 15:04:13.000000000 -0700
@@ -437,8 +437,10 @@
 			result = -EIO;
 			goto fail;
 		}
-		DDPRINTK("target: %X\n", *data + WVAL(inbuf, smb_drdisp));
+		DDPRINTK("target: %X\n",
+			 (unsigned int) *data + WVAL(inbuf, smb_drdisp));
 		DDPRINTK("source: %X\n",
+			 (unsigned int)
 			 smb_base(inbuf) + WVAL(inbuf, smb_droff));
 		DDPRINTK("disp: %d, off: %d, cnt: %d\n",
 			 WVAL(inbuf, smb_drdisp), WVAL(inbuf, smb_droff),
@@ -553,7 +555,7 @@
 	}
 	len = smb_len(buffer) + 4;
 
-	DDPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]);
+	DPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]);
 
 	old_mask = current->blocked;
 	current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
@@ -672,8 +674,8 @@
 	unsigned short fs;
 	int result;
 
-	DDPRINTK("smb_trans2_request: com=%d, ld=%d, lp=%d\n",
-		 trans2_command, ldata, lparam);
+	DPRINTK("smb_trans2_request: com=%d, ld=%d, lp=%d\n",
+		trans2_command, ldata, lparam);
 
 	if (server->state != CONN_VALID)
 	{
diff -urN linux-2.0.31-pre9/include/asm-i386/delay.h linux-2.0.31-pre10/include/asm-i386/delay.h
--- linux-2.0.31-pre9/include/asm-i386/delay.h	1996-10-08 09:43:30.000000000 -0700
+++ linux-2.0.31-pre10/include/asm-i386/delay.h	2003-08-15 15:04:13.000000000 -0700
@@ -6,15 +6,19 @@
  *
  * Delay routines, using a pre-computed "loops_per_second" value.
  */
- 
+
+#include <linux/linkage.h>
+
 #ifdef __SMP__
 #include <asm/smp.h>
 #endif 
 
+extern void __do_delay(void);	/* Special register call calling convention */
+
 extern __inline__ void __delay(int loops)
 {
 	__asm__ __volatile__(
-		".align 2,0x90\n1:\tdecl %0\n\tjns 1b"
+		"call " SYMBOL_NAME_STR(__do_delay)
 		:/* no outputs */
 		:"a" (loops)
 		:"ax");
diff -urN linux-2.0.31-pre9/include/linux/fs.h linux-2.0.31-pre10/include/linux/fs.h
--- linux-2.0.31-pre9/include/linux/fs.h	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/include/linux/fs.h	2003-08-15 15:04:13.000000000 -0700
@@ -79,7 +79,7 @@
 /*
  * Flags that can be altered by MS_REMOUNT
  */
-#define MS_RMT_MASK (MS_RDONLY|MS_MANDLOCK|MS_NOATIME)
+#define MS_RMT_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME)
 
 /*
  * Magic mount flag number. Has to be or-ed to the flag values.
@@ -332,6 +332,11 @@
 	} u;
 };
 
+struct fown_struct {
+	int pid;		/* pid or -pgrp where SIGIO should be sent */
+	uid_t uid, euid;	/* uid/euid of process setting the owner */
+};
+
 struct file {
 	mode_t f_mode;
 	loff_t f_pos;
@@ -339,7 +344,7 @@
 	unsigned short f_count;
 	unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;
 	struct file *f_next, *f_prev;
-	int f_owner;		/* pid or -pgrp where SIGIO should be sent */
+	struct fown_struct f_owner;
 	struct inode * f_inode;
 	struct file_operations * f_op;
 	unsigned long f_version;
diff -urN linux-2.0.31-pre9/include/linux/mroute.h linux-2.0.31-pre10/include/linux/mroute.h
--- linux-2.0.31-pre9/include/linux/mroute.h	1997-03-28 16:11:24.000000000 -0800
+++ linux-2.0.31-pre10/include/linux/mroute.h	2003-08-15 15:04:13.000000000 -0700
@@ -147,6 +147,8 @@
 	struct sk_buff_head mfc_unresolved;	/* Unresolved buffers		*/
 	int mfc_queuelen;			/* Unresolved buffer counter	*/
 	unsigned char mfc_ttls[MAXVIFS];	/* TTL thresholds		*/
+	unsigned long mfc_packets;		/* Packets on this entry	*/
+	unsigned long mfc_bytes;		/* Bytes on this entry		*/
 };
 
 #define MFC_QUEUED		1
diff -urN linux-2.0.31-pre9/include/linux/tty_flip.h linux-2.0.31-pre10/include/linux/tty_flip.h
--- linux-2.0.31-pre9/include/linux/tty_flip.h	1994-05-22 21:55:15.000000000 -0700
+++ linux-2.0.31-pre10/include/linux/tty_flip.h	2003-08-15 15:04:13.000000000 -0700
@@ -10,10 +10,11 @@
 _INLINE_ void tty_insert_flip_char(struct tty_struct *tty,
 				   unsigned char ch, char flag)
 {
-	if (tty->flip.count++ >= TTY_FLIPBUF_SIZE)
-		return;
-	*tty->flip.flag_buf_ptr++ = flag;
-	*tty->flip.char_buf_ptr++ = ch;
+	if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+		tty->flip.count++;
+		*tty->flip.flag_buf_ptr++ = flag;
+		*tty->flip.char_buf_ptr++ = ch;
+	}
 }
 
 _INLINE_ void tty_schedule_flip(struct tty_struct *tty)
diff -urN linux-2.0.31-pre9/include/net/ip_alias.h linux-2.0.31-pre10/include/net/ip_alias.h
--- linux-2.0.31-pre9/include/net/ip_alias.h	1995-12-25 20:03:01.000000000 -0800
+++ linux-2.0.31-pre10/include/net/ip_alias.h	2003-08-15 15:04:13.000000000 -0700
@@ -2,7 +2,7 @@
  *		IP_ALIAS (AF_INET) aliasing definitions.
  *
  *
- * Version:	@(#)ip_alias.h	0.43   12/20/95
+ * Version:	@(#)ip_alias.h	0.50   4/20/97
  *
  * Author:	Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar>
  *
diff -urN linux-2.0.31-pre9/include/net/route.h linux-2.0.31-pre10/include/net/route.h
--- linux-2.0.31-pre9/include/net/route.h	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/include/net/route.h	2003-08-15 15:04:13.000000000 -0700
@@ -85,6 +85,7 @@
 extern void		ip_rt_update(int event, struct device *dev);
 extern void		ip_rt_redirect(__u32 src, __u32 dst, __u32 gw, struct device *dev);
 extern struct rtable	*ip_rt_slow_route(__u32 daddr, int local, struct device *dev);
+extern struct device	*ip_rt_dev(__u32 addr);
 extern int		rt_get_info(char * buffer, char **start, off_t offset, int length, int dummy);
 extern int		rt_cache_get_info(char *buffer, char **start, off_t offset, int length, int dummy);
 extern int		ip_rt_ioctl(unsigned int cmd, void *arg);
diff -urN linux-2.0.31-pre9/kernel/sched.c linux-2.0.31-pre10/kernel/sched.c
--- linux-2.0.31-pre9/kernel/sched.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/kernel/sched.c	2003-08-15 15:04:13.000000000 -0700
@@ -340,15 +340,19 @@
   if (smp_processor_id() == boot_cpu_id) return;
   if (smp_blocked_interrupt_pending)
     {
-      long timeout_counter = loops_per_sec;
       unsigned long saved_kernel_counter;
+      long timeout_counter;
       saved_active_kernel_processor = active_kernel_processor;
       saved_kernel_counter = kernel_counter;
       kernel_counter = 0;
       active_kernel_processor = boot_cpu_id;
+      timeout_counter = 6000000;
       while (active_kernel_processor != saved_active_kernel_processor &&
 	     --timeout_counter >= 0)
-	barrier();
+	{
+	  udelay(10);
+	  barrier();
+	}
       if (timeout_counter < 0)
 	panic("FORWARDED INTERRUPT TIMEOUT (AKP = %d, Saved AKP = %d)\n",
 	      active_kernel_processor, saved_active_kernel_processor);
diff -urN linux-2.0.31-pre9/mm/kmalloc.c linux-2.0.31-pre10/mm/kmalloc.c
--- linux-2.0.31-pre9/mm/kmalloc.c	1996-06-08 08:12:33.000000000 -0700
+++ linux-2.0.31-pre10/mm/kmalloc.c	2003-08-15 15:04:13.000000000 -0700
@@ -447,6 +447,6 @@
 	return;
 
 not_on_freelist:
-	printk("Ooops. page %p doesn't show on freelist.\n", page);
 	restore_flags(flags);
+	printk("Ooops. page %p doesn't show on freelist.\n", page);
 }
diff -urN linux-2.0.31-pre9/mm/vmscan.c linux-2.0.31-pre10/mm/vmscan.c
--- linux-2.0.31-pre9/mm/vmscan.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/mm/vmscan.c	2003-08-15 15:04:13.000000000 -0700
@@ -406,11 +406,8 @@
 	can_do_io = 1;
 	if (wait)
 		stop = 0;
-	if (priority == GFP_BUFFER) {
-		/* bdflush() should do the rest if we fail */
-		stop = 3;
+	if (priority == GFP_BUFFER)
 		can_do_io = 0;
-	}
 	switch (state) {
 		do {
 		case 0:
@@ -492,10 +489,14 @@
 		interruptible_sleep_on(&kswapd_wait);
 		kswapd_awake = 1;
 		swapstats.wakeups++;
+		/* Protect our reserved pages: */
+		i = 0;
+		if (nr_free_pages <= min_free_pages)
+			i = (1+min_free_pages) - nr_free_pages;
 		/* Do the background pageout: */
-		for (i=0; i < kswapd_ctl.maxpages; i++)
+		for (i += kswapd_ctl.maxpages; i > 0; i--)
 			try_to_free_page(GFP_KERNEL, 0,
-					 (nr_free_pages < min_free_pages));
+					 (nr_free_pages <= min_free_pages));
 	}
 }
 
diff -urN linux-2.0.31-pre9/net/ipv4/arp.c linux-2.0.31-pre10/net/ipv4/arp.c
--- linux-2.0.31-pre9/net/ipv4/arp.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/net/ipv4/arp.c	2003-08-15 15:04:13.000000000 -0700
@@ -1921,6 +1921,7 @@
 	{
 		/*
 		 *	net_alias_dev_rx32 returns main dev if it fails to found other.
+		 *  	if successful, also incr. alias rx count.
 		 */
 		dev = net_alias_dev_rx32(dev, AF_INET, sip, tip);
 
diff -urN linux-2.0.31-pre9/net/ipv4/icmp.c linux-2.0.31-pre10/net/ipv4/icmp.c
--- linux-2.0.31-pre9/net/ipv4/icmp.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/net/ipv4/icmp.c	2003-08-15 15:04:13.000000000 -0700
@@ -40,6 +40,8 @@
  *					valid (RFC 1812).
  *		Alan Cox	:	Spoofing and junk icmp protections.
  *              Elliot Poger    :       Added support for SO_BINDTODEVICE.
+ *	Willy Konynenberg	:	Transparent proxy adapted to new
+ *					socket hash code.
  *
  *
  * RFC1122 (Host Requirements -- Comm. Layer) Status:
@@ -993,15 +995,8 @@
  *	in udp.c or tcp.c...
  */
 
-/* This should work with the new hashes now. -DaveM */
-extern struct sock *tcp_v4_proxy_lookup(unsigned short num, unsigned long raddr,
-					unsigned short rnum, unsigned long laddr,
-					unsigned long paddr, unsigned short pnum,
-					struct device *dev);
-extern struct sock *udp_v4_proxy_lookup(unsigned short num, unsigned long raddr,
-					unsigned short rnum, unsigned long laddr,
-					unsigned long paddr, unsigned short pnum,
-					struct device *dev);
+extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, struct device *dev);
+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, struct device *dev);
 
 int icmp_chkaddr(struct sk_buff *skb)
 {
@@ -1017,8 +1012,7 @@
 			{
 			struct tcphdr *th = (struct tcphdr *)(((unsigned char *)iph)+(iph->ihl<<2));
 
-			sk = tcp_v4_proxy_lookup(th->source, iph->daddr, th->dest,
-						 iph->saddr, 0, 0, skb->dev);
+			sk = tcp_v4_lookup(iph->saddr, th->source, iph->daddr, th->dest, skb->dev);
 			if (!sk) return 0;
 			if (sk->saddr != iph->saddr) return 0;
 			if (sk->daddr != iph->daddr) return 0;
@@ -1032,8 +1026,7 @@
 			{
 			struct udphdr *uh = (struct udphdr *)(((unsigned char *)iph)+(iph->ihl<<2));
 
-			sk = udp_v4_proxy_lookup(uh->source, iph->daddr, uh->dest,
-						 iph->saddr, 0, 0, skb->dev);
+			sk = udp_v4_lookup(iph->saddr, uh->source, iph->daddr, uh->dest, skb->dev);
 			if (!sk) return 0;
 			if (sk->saddr != iph->saddr && ip_chk_addr(iph->saddr) != IS_MYADDR)
 				return 0;
diff -urN linux-2.0.31-pre9/net/ipv4/ip_alias.c linux-2.0.31-pre10/net/ipv4/ip_alias.c
--- linux-2.0.31-pre9/net/ipv4/ip_alias.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/net/ipv4/ip_alias.c	2003-08-15 15:04:13.000000000 -0700
@@ -2,12 +2,14 @@
  *		IP_ALIAS (AF_INET) aliasing module.
  *
  *
- * Version:	@(#)ip_alias.c	0.43   12/20/95
+ * Version:	@(#)ip_alias.c	0.50   6/14/97
  *
  * Author:	Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar>
  *
  * Fixes:
  *	JJC	:	ip_alias_dev_select method.
+ *	JJC	:	use ip_rt_dev instead of ip_rt_route 
+ *	JJC	:	new no_sel semantics
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -76,11 +78,13 @@
 		(p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
 }
 
+/*
+ *	Called by net_alias module when no local alias address has been hit,
+ *	to find out if an alias is a better candidate for handling given addr
+ */
 struct device *ip_alias_dev_select(struct net_alias_type *this, struct device *main_dev, struct sockaddr *sa)
 {
 	__u32 addr;
-	struct rtable *rt;
-	struct device *dev=NULL;
   
 	/*
 	 *	Defensive...	
@@ -102,13 +106,12 @@
 	 *	net_alias module will check if returned device is main_dev's alias
 	 */
 
-	rt = ip_rt_route(addr, 0, NULL);
-	if(rt)
-	{
-		dev=rt->rt_dev;
-		ip_rt_put(rt);
-	}
-	return dev;
+	/*
+	 *	Fixed arping caused by incorrectly using ip_rt_route(), 
+	 *	ip_rt_dev() just returns routing device without hh generation.
+	 */
+
+	return ip_rt_dev(addr);
 }
 
 /*
@@ -149,8 +152,23 @@
 
 #ifdef MODULE
 
+/*
+ *	If no_sel is set, alias association (device selection) with
+ *	foreign addresses will be disabled.
+ *	You will get:
+ *	- faster operation by avoiding completely routing lookups
+ *	You will loose:
+ *	- inter-alias routing
+ *	- proxyarp over aliases
+ */
+
+int no_sel = 0;
+
 int init_module(void)
 {
+	if (no_sel)
+		ip_alias_type.dev_select = NULL;
+
 	if (ip_alias_init() != 0)
 		return -EIO;
 	return 0;
diff -urN linux-2.0.31-pre9/net/ipv4/ip_input.c linux-2.0.31-pre10/net/ipv4/ip_input.c
--- linux-2.0.31-pre9/net/ipv4/ip_input.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/net/ipv4/ip_input.c	2003-08-15 15:04:13.000000000 -0700
@@ -299,10 +299,13 @@
 	 *	Try to select closest <src,dst> alias device, if any.
 	 *	net_alias_dev_rx32 returns main device if it 
 	 *	fails to found other.
+ 	 *  	If successful, also incr. alias rx count.
+	 *
+	 *	Only makes sense for unicasts - Thanks ANK.
 	 */
 
 #ifdef CONFIG_NET_ALIAS
-	if (iph->daddr != skb->dev->pa_addr && net_alias_has(skb->dev)) {
+	if (skb->pkt_type == PACKET_HOST && iph->daddr != skb->dev->pa_addr && net_alias_has(skb->dev)) {
 		skb->dev = dev = net_alias_dev_rx32(skb->dev, AF_INET, iph->saddr, iph->daddr);
 	}
 #endif
diff -urN linux-2.0.31-pre9/net/ipv4/ipmr.c linux-2.0.31-pre10/net/ipv4/ipmr.c
--- linux-2.0.31-pre9/net/ipv4/ipmr.c	1996-11-14 05:20:10.000000000 -0800
+++ linux-2.0.31-pre10/net/ipv4/ipmr.c	2003-08-15 15:04:13.000000000 -0700
@@ -193,6 +193,8 @@
 	init_timer(&c->mfc_timer);
 	c->mfc_timer.data=(long)c;
 	c->mfc_timer.function=ipmr_cache_timer;
+	c->mfc_packets=0;
+	c->mfc_bytes=0;
 	return c;
 }
  
@@ -591,6 +593,7 @@
 	struct sioc_sg_req sr;
 	struct sioc_vif_req vr;
 	struct vif_device *vif;
+	struct mfc_cache *cl;
 	
 	switch(cmd)
 	{
@@ -617,6 +620,19 @@
 			if(err)
 				return err;
 			memcpy_fromfs(&sr,(void *)arg,sizeof(sr));
+			cl=ipmr_cache_find(sr.src.s_addr,sr.grp.s_addr);
+			if(cl==NULL)
+			{
+				sr.pktcnt=0;
+				sr.bytecnt=0;
+				sr.wrong_if=0;
+			}
+			else
+			{
+				sr.pktcnt=cl->mfc_packets;
+				sr.bytecnt=cl->mfc_bytes;
+				sr.wrong_if=0;
+			}
 			memcpy_tofs((void *)arg,&sr,sizeof(sr));
 			return 0;
 		default:
@@ -753,6 +769,8 @@
 	
 	vif_table[vif].pkt_in++;
 	vif_table[vif].bytes_in+=skb->len;
+	cache->mfc_packets++;
+	cache->mfc_bytes+=skb->len;
 	
 	/*
 	 *	Forward the frame
@@ -785,9 +803,7 @@
 	if(psend==-1)
 		kfree_skb(skb, FREE_WRITE);
 	else
-	{
 		ipmr_queue_xmit(skb, &vif_table[psend], skb->dev, is_frag);
-	}
 }
 
 /*
@@ -907,7 +923,7 @@
  
 void ip_mr_init(void)
 {
-	printk(KERN_INFO "Linux IP multicast router 0.06.\n");
+	printk(KERN_INFO "Linux IP multicast router 0.07.\n");
 	register_netdevice_notifier(&ip_mr_notifier);
 #ifdef CONFIG_PROC_FS	
 	proc_net_register(&(struct proc_dir_entry) {
diff -urN linux-2.0.31-pre9/net/ipv4/ip_output.c linux-2.0.31-pre10/net/ipv4/ip_output.c
--- linux-2.0.31-pre9/net/ipv4/ip_output.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/net/ipv4/ip_output.c	2003-08-15 15:04:13.000000000 -0700
@@ -983,8 +983,7 @@
 		}
 #endif		
 #ifdef CONFIG_IP_ACCT
-		if(!offset)
-			ip_fw_chk(iph, dev, NULL, ip_acct_chain, 0, IP_FW_MODE_ACCT_OUT);
+		ip_fw_chk(iph, dev, NULL, ip_acct_chain, 0, IP_FW_MODE_ACCT_OUT);
 #endif	
 		offset -= (maxfraglen-fragheaderlen);
 		fraglen = maxfraglen;
diff -urN linux-2.0.31-pre9/net/ipv4/route.c linux-2.0.31-pre10/net/ipv4/route.c
--- linux-2.0.31-pre9/net/ipv4/route.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/net/ipv4/route.c	2003-08-15 15:04:13.000000000 -0700
@@ -46,6 +46,7 @@
  *		Andi Kleen	:	Don't send multicast addresses to
  *					kerneld.	
  *
+ *	Juan Jose Ciarlante     :	Added ip_rt_dev 
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
  *		as published by the Free Software Foundation; either version
@@ -1535,6 +1536,20 @@
 		rt_free(rt);
 }
 
+/*
+ *	Return routing dev for given address.
+ *	Called by ip_alias module to avoid using ip_rt_route and
+ *	generating hhs.
+ */
+struct device * ip_rt_dev(__u32 addr)
+{
+	struct fib_node *f;
+	f = fib_lookup(addr, NULL);
+	if (f) 
+		return f->fib_info->fib_dev;
+	return NULL;
+}
+
 struct rtable * ip_rt_route(__u32 daddr, int local, struct device *dev)
 {
 	struct rtable * rth;
diff -urN linux-2.0.31-pre9/net/ipv4/tcp_input.c linux-2.0.31-pre10/net/ipv4/tcp_input.c
--- linux-2.0.31-pre9/net/ipv4/tcp_input.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/net/ipv4/tcp_input.c	2003-08-15 15:04:13.000000000 -0700
@@ -34,6 +34,8 @@
  *		David S. Miller	:	New socket lookup architecture for ISS.
  *					This code is dedicated to John Dyson.
  *              Elliot Poger    :       Added support for SO_BINDTODEVICE.
+ *	Willy Konynenberg	:	Transparent proxy adapted to new
+ *					socket hash code.
  */
 
 #include <linux/config.h>
@@ -301,76 +303,41 @@
 }
 
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
-#define secondlist(hpnum, sk, fpass) \
-({ struct sock *s1; if((hpnum) && !(sk) && (fpass)--) \
-	s1 = tcp_bound_hash[tcp_bhashfn(hpnum)]; \
-   else \
-	s1 = (sk); \
-   s1; \
-})
-
-#define tcp_v4_proxy_loop_init(hnum, hpnum, sk, fpass) \
-	secondlist((hpnum), tcp_bound_hash[tcp_bhashfn(hnum)],(fpass))
-
-#define tcp_v4_proxy_loop_next(hnum, hpnum, sk, fpass) \
-	secondlist((hpnum),(sk)->bind_next,(fpass))
-
-struct sock *tcp_v4_proxy_lookup(unsigned short num, unsigned long raddr,
-				 unsigned short rnum, unsigned long laddr,
-				 unsigned long paddr, unsigned short pnum,
+/* I am not entirely sure this is fully equivalent to the old lookup code, but it does
+ * look reasonable.  WFK
+ */
+struct sock *tcp_v4_proxy_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, u32 paddr, u16 rport,
 				 struct device *dev)
 {
-	struct sock *s, *result = NULL;
-	int badness = -1;
-	unsigned short hnum = ntohs(num);
-	unsigned short hpnum = ntohs(pnum);
-	int firstpass = 1;
-
-	/* This code must run only from NET_BH. */
-	for(s = tcp_v4_proxy_loop_init(hnum, hpnum, s, firstpass);
-	    s != NULL;
-	    s = tcp_v4_proxy_loop_next(hnum, hpnum, s, firstpass)) {
-		if(s->num == hnum || s->num == hpnum) {
-			int score = 0;
-			if(s->dead && (s->state == TCP_CLOSE))
-				continue;
-			if(s->rcv_saddr) {
-				if((s->num != hpnum || s->rcv_saddr != paddr) &&
-				   (s->num != hnum || s->rcv_saddr != laddr))
-					continue;
-				score++;
-			}
-			if(s->daddr) {
-				if(s->daddr != raddr)
-					continue;
-				score++;
-			}
-			if(s->dummy_th.dest) {
-				if(s->dummy_th.dest != rnum)
-					continue;
-				score++;
-			}
-			if(s->bound_device) {
-				if (s->bound_device != dev)
-					continue;
-				score++;
-			}
-			if(score == 4 && s->num == hnum) {
-				result = s;
-				break;
-			} else if(score > badness && (s->num == hpnum || s->rcv_saddr)) {
-					result = s;
-					badness = score;
-			}
-		}
+	unsigned short hnum = ntohs(dport);
+	unsigned short hrnum = ntohs(rport);
+	struct sock *sk;
+
+	/* Optimize here for direct hit, only listening connections can
+	 * have wildcards anyways.  It is assumed that this code only
+	 * gets called from within NET_BH.
+	 */
+	sk = tcp_established_hash[tcp_hashfn(daddr, hnum, saddr, sport)];
+	for(; sk; sk = sk->next)
+		if(sk->daddr		== saddr		&& /* remote address */
+		   sk->dummy_th.dest	== sport		&& /* remote port    */
+		   sk->num		== hnum			&& /* local port     */
+		   sk->rcv_saddr	== daddr		&& /* local address  */
+		   ((sk->bound_device==NULL) || (sk->bound_device==dev))  )
+			goto hit; /* You sunk my battleship! */
+	/* If we don't match on a bound socket, try to find one explicitly listening
+	 * on the remote address (a proxy bind).
+	 */
+	sk = tcp_v4_lookup_longway(daddr, hnum, dev);
+	/* If that didn't yield an exact match, look for a socket listening on the
+	 * redirect port.
+	 */
+	if (!sk || sk->rcv_saddr != daddr) {
+		sk = tcp_v4_lookup_longway(paddr, hrnum, dev);
 	}
-	return result;
+hit:
+	return sk;
 }
-
-#undef secondlist
-#undef tcp_v4_proxy_loop_init
-#undef tcp_v4_proxy_loop_next
-
 #endif
 
 /*
@@ -2258,8 +2225,8 @@
 	struct tcphdr *th = (struct tcphdr *)(skb->h.raw + iph->ihl*4);
 	struct sock *sk;
 
-	sk = tcp_v4_proxy_lookup(th->dest, iph->saddr, th->source, iph->daddr,
-				 0, 0, skb->dev);
+	sk = tcp_v4_lookup(iph->saddr, th->source, iph->daddr, th->dest,
+			   skb->dev);
 	if (!sk)
 		return 0;
 	/* 0 means accept all LOCAL addresses here, not all the world... */
@@ -2327,8 +2294,7 @@
 #endif
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
 		if (skb->redirport)
-			sk = tcp_v4_proxy_lookup(th->dest, saddr, th->source, daddr,
-						 dev->pa_addr, skb->redirport, dev);
+			sk = tcp_v4_proxy_lookup(saddr, th->source, daddr, th->dest, dev->pa_addr, skb->redirport, dev);
 		else
 #endif
 		sk = __tcp_v4_lookup(th, saddr, th->source, daddr, th->dest, dev);
@@ -2643,11 +2609,17 @@
 			tcp_set_state(sk, TCP_CLOSE);
 			sk->shutdown = SHUTDOWN_MASK;
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
-			sk = tcp_v4_proxy_lookup(th->dest, saddr, th->source, daddr,
-						 dev->pa_addr, skb->redirport, dev);
-#else
-			sk = NULL;
+			/* What to do here?
+			 * For the non-proxy case, this code is effectively almost a no-op,
+			 * due to the sk = NULL.  Is that intentional?  If so, why shouldn't we
+			 * do the same for the proxy case and get rid of some useless code?
+			 */
+			if (skb->redirport)
+				sk = tcp_v4_proxy_lookup(saddr, th->source, daddr, th->dest,
+							 dev->pa_addr, skb->redirport, dev);
+			else
 #endif
+			sk = NULL;
 			/* this is not really correct: we should check sk->users */
 			if (sk && sk->state==TCP_LISTEN)
 			{
diff -urN linux-2.0.31-pre9/net/ipv4/tcp_output.c linux-2.0.31-pre10/net/ipv4/tcp_output.c
--- linux-2.0.31-pre9/net/ipv4/tcp_output.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/net/ipv4/tcp_output.c	2003-08-15 15:04:13.000000000 -0700
@@ -537,6 +537,7 @@
 					skb2->raddr=rt->rt_gateway;
                                         if (sk->state == TCP_SYN_SENT && sysctl_ip_dynaddr)
                                                 ip_rewrite_addrs (sk, skb2, dev);
+					skb_pull(skb2,((unsigned char *)skb2->ip_hdr)-skb2->data);
 					skb2->dev = dev;
 					skb2->arp=1;
 					if (rt->rt_hh)
diff -urN linux-2.0.31-pre9/net/ipv4/udp.c linux-2.0.31-pre10/net/ipv4/udp.c
--- linux-2.0.31-pre9/net/ipv4/udp.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/net/ipv4/udp.c	2003-08-15 15:04:13.000000000 -0700
@@ -53,6 +53,8 @@
  *					Last socket cache retained as it
  *					does have a high hit rate.
  *              Elliot Poger    :       Added support for SO_BINDTODEVICE.
+ *	Willy Konynenberg	:	Transparent proxy adapted to new
+ *					socket hash code.
  *
  *
  *		This program is free software; you can redistribute it and/or
@@ -313,79 +315,60 @@
 }
 
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
-#define secondlist(hpnum, sk, fpass) \
-({ struct sock *s1; if(!(sk) && (fpass)--) \
-	s1 = udp_hash[(hpnum) & (TCP_HTABLE_SIZE - 1)]; \
-   else \
-	s1 = (sk); \
-   s1; \
-})
-
-#define udp_v4_proxy_loop_init(hnum, hpnum, sk, fpass) \
-	secondlist((hpnum), udp_hash[(hnum)&(TCP_HTABLE_SIZE-1)],(fpass))
-
-#define udp_v4_proxy_loop_next(hnum, hpnum, sk, fpass) \
-	secondlist((hpnum),(sk)->next,(fpass))
-
-struct sock *udp_v4_proxy_lookup(unsigned short num, unsigned long raddr,
-				 unsigned short rnum, unsigned long laddr,
-				 unsigned long paddr, unsigned short pnum,
+struct sock *udp_v4_proxy_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, u32 paddr, u16 rport,
 				 struct device *dev)
 {
-	struct sock *s, *result = NULL;
+	struct sock *hh[3], *sk, *result = NULL;
+	int i;
 	int badness = -1;
-	unsigned short hnum = ntohs(num);
-	unsigned short hpnum = ntohs(pnum);
-	int firstpass = 1;
+	unsigned short hnum = ntohs(dport);
+	unsigned short hpnum = ntohs(rport);
 
 	SOCKHASH_LOCK();
-	for(s = udp_v4_proxy_loop_init(hnum, hpnum, s, firstpass);
-	    s != NULL;
-	    s = udp_v4_proxy_loop_next(hnum, hpnum, s, firstpass)) {
-		if(s->num == hnum || s->num == hpnum) {
-			int score = 0;
-			if(s->dead && (s->state == TCP_CLOSE))
-				continue;
-			if(s->rcv_saddr) {
-				if((s->num != hpnum || s->rcv_saddr != paddr) &&
-				   (s->num != hnum || s->rcv_saddr != laddr))
-					continue;
-				score++;
-			}
-			if(s->daddr) {
-				if(s->daddr != raddr)
-					continue;
-				score++;
-			}
-			if(s->dummy_th.dest) {
-				if(s->dummy_th.dest != rnum)
-					continue;
-				score++;
-			}
-			/* If this socket is bound to a particular interface,
-			 * did the packet come in on it? */
-			if(s->bound_device) {
-				if (s->bound_device != dev)
+	hh[0] = udp_hash[hnum & (UDP_HTABLE_SIZE - 1)];
+	hh[1] = udp_hash[hpnum & (UDP_HTABLE_SIZE - 1)];
+	for (i = 0; i < 2; i++) {
+		for(sk = hh[i]; sk != NULL; sk = sk->next) {
+			if(sk->num == hnum || sk->num == hpnum) {
+				int score = 0;
+				if(sk->dead && (sk->state == TCP_CLOSE))
 					continue;
-				score++;
-			}
-			if(score == 4 && s->num == hnum) {
-				result = s;
-				break;
-			} else if(score > badness && (s->num == hpnum || s->rcv_saddr)) {
-					result = s;
+				if(sk->rcv_saddr) {
+					if((sk->num != hpnum || sk->rcv_saddr != paddr) &&
+					   (sk->num != hnum || sk->rcv_saddr != daddr))
+						continue;
+					score++;
+				}
+				if(sk->daddr) {
+					if(sk->daddr != saddr)
+						continue;
+					score++;
+				}
+				if(sk->dummy_th.dest) {
+					if(sk->dummy_th.dest != sport)
+						continue;
+					score++;
+				}
+				/* If this socket is bound to a particular interface,
+				 * did the packet come in on it? */
+				if(sk->bound_device) {
+					if (sk->bound_device != dev)
+						continue;
+					score++;
+				}
+				if(score == 4 && sk->num == hnum) {
+					result = sk;
+					break;
+				} else if(score > badness && (sk->num == hpnum || sk->rcv_saddr)) {
+					result = sk;
 					badness = score;
+				}
 			}
 		}
 	}
 	SOCKHASH_UNLOCK();
 	return result;
 }
-
-#undef secondlist
-#undef udp_v4_proxy_loop_init
-#undef udp_v4_proxy_loop_next
-
 #endif
 
 static inline struct sock *udp_v4_mcast_next(struct sock *sk,
@@ -950,8 +933,8 @@
 	struct udphdr *uh = (struct udphdr *)(skb->h.raw + iph->ihl*4);
 	struct sock *sk;
 
-	sk = udp_v4_proxy_lookup(uh->dest, iph->saddr, uh->source, iph->daddr,
-				 0, 0, skb->dev);
+	sk = udp_v4_lookup(iph->saddr, uh->source, iph->daddr, uh->dest,
+			   skb->dev);
 	if (!sk)
 		return 0;
 	/* 0 means accept all LOCAL addresses here, not all the world... */
@@ -1098,8 +1081,8 @@
 #endif
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
 	if(skb->redirport)
-		sk = udp_v4_proxy_lookup(uh->dest, saddr, uh->source,
-					 daddr, dev->pa_addr, skb->redirport, dev);
+		sk = udp_v4_proxy_lookup(saddr, uh->source, daddr, uh->dest,
+					 dev->pa_addr, skb->redirport, dev);
 	else
 #endif
 	sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, dev);
diff -urN linux-2.0.31-pre9/net/netsyms.c linux-2.0.31-pre10/net/netsyms.c
--- linux-2.0.31-pre9/net/netsyms.c	2003-08-15 15:04:12.000000000 -0700
+++ linux-2.0.31-pre10/net/netsyms.c	2003-08-15 15:04:13.000000000 -0700
@@ -100,6 +100,7 @@
 
 	X(init_etherdev),
 	X(ip_rt_route),
+	X(ip_rt_dev),
 	X(icmp_send),
 	X(ip_options_compile),
 	X(ip_rt_put),
