]> git.neil.brown.name Git - history.git/commitdiff
Import 2.0.31pre10 2.0.31pre10
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:11:32 +0000 (15:11 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:11:32 +0000 (15:11 -0500)
48 files changed:
CREDITS
Documentation/networking/alias.txt
Documentation/networking/ip_dynaddr.txt [new file with mode: 0644]
arch/i386/defconfig
arch/i386/kernel/entry.S
arch/i386/kernel/ksyms.c
arch/i386/lib/Makefile
arch/i386/lib/delay.S [new file with mode: 0644]
drivers/char/mem.c
drivers/char/tty_io.c
drivers/net/3c59x.c
drivers/net/tulip.c
drivers/scsi/Config.in
drivers/scsi/aic7xxx.c
drivers/scsi/aic7xxx/aic7xxx.reg
drivers/scsi/aic7xxx_proc.c
drivers/scsi/aic7xxx_reg.h
drivers/scsi/aic7xxx_seq.h
drivers/scsi/eata.c
drivers/scsi/eata.h
drivers/scsi/scsi_module.c
drivers/scsi/u14-34f.c
drivers/scsi/u14-34f.h
fs/buffer.c
fs/fcntl.c
fs/smbfs/inode.c
fs/smbfs/proc.c
fs/smbfs/sock.c
include/asm-i386/delay.h
include/linux/fs.h
include/linux/mroute.h
include/linux/tty_flip.h
include/net/ip_alias.h
include/net/route.h
kernel/sched.c
mm/kmalloc.c
mm/vmscan.c
net/ipv4/arp.c
net/ipv4/icmp.c
net/ipv4/ip_alias.c
net/ipv4/ip_input.c
net/ipv4/ip_output.c
net/ipv4/ipmr.c
net/ipv4/route.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/netsyms.c

diff --git a/CREDITS b/CREDITS
index a440de4ffca57bf7698b92a5af4721d7c0257155..8ab09458bbf37509a7e81ec63d0c406296412332 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -42,7 +42,7 @@ D: VFS fixes (new notify_change in particular)
 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 @@ S: USA
 
 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: 6369 BG Simpelveld
 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 @@ E: bir7@leland.Stanford.Edu
 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: 91452 Wilhermsdorf
 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: 3674 Oakwood Terrace #201
 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 @@ S: USA
 
 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 @@ S: Australia
 
 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: Original Linux netatalk patches.
 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 @@ S: United Kingdom
 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 @@ S: The Netherlands
 
 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 @@ D: AX25-HOWTO, HAM-HOWTO, IPX-HOWTO, NET-2-HOWTO
 
 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 @@ E: drew@PoohSticks.ORG
 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: Newtown 2042
 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 @@ N: Philip Gladstone
 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 @@ N: John E. Gotts
 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: 34131 Kassel
 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: Chapel Hill, North Carolina 27514-4818
 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: Santa Clara, California 95050-3452
 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 @@ E: beans@bucket.ualr.edu
 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 @@ N: Warner Losh
 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 @@ N: Peter MacDonald
 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: PO BOX 220, HFX. CENTRAL
 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 @@ S: Czech Republic
 
 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 @@ W: http://www.invlogic.com/~mmclagan
 D: DLCI/FRAD drivers for Sangoma SDLAs
 S: Innovative Logic Corp
 S: P.O. Box 1068
-S: Laurel, M 20732
+S: Laurel, Maryland 20732
 S: USA
 
 N: Bradley McLean
@@ -909,12 +907,13 @@ S: D-91056 Erlangen
 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 @@ P: 1024/31455639 B7 99 BD B8 00 17 BD 46  C1 15 B8 AB 87 BC 25 FA
 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: East Brunswick, New Jersey 08816
 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 @@ N: David Mosberger-Tang
 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: FIN-00330 Helsingfors
 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 @@ E: greg@caldera.com
 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: 79539 Loerrach
 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 @@ D: the gpm mouse server and kernel support for it
 
 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 @@ W: http://www.-i-Connect.Net/~shimon
 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 @@ N: Leo Spiekman
 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: Sevilla 41005
 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: MacGregor A.C.T
 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: Dr. Greg Wettstein, Ph.D.
 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: Fin-00150 Helsinki
 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
index 4889c683bf660c5735040d7a958e5adc36ef0bec..d05018be2d137bb30e1aa63ba5afa67c78f6d6a5 100644 (file)
@@ -6,6 +6,7 @@ NET_ALIAS device aliasing v0.5x
   (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 @@ Usage (IP aliasing)
      # 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 @@ o PROCfs entries
      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 @@ o Alias devices rx/tx stats
   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 @@ o Alias devices rx/tx stats
   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 @@ Contact
 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 --git a/Documentation/networking/ip_dynaddr.txt b/Documentation/networking/ip_dynaddr.txt
new file mode 100644 (file)
index 0000000..45f3c12
--- /dev/null
@@ -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>
index c23faa687c70e56cf4120b89e9c13212873fb99f..b568a45b0e8547ed0a0601d31b23c8cb3c88d9f0 100644 (file)
@@ -150,7 +150,6 @@ CONFIG_ISO9660_FS=y
 # 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
index 214170b53766513242853f1b1816c25744ff19ea..e11b68ec93bdc9718595d31b50c23e67105c0c68 100644 (file)
@@ -259,7 +259,6 @@ ENOSYS = 38
        iret
 #endif
 
-
 ENTRY(lcall7)
        pushfl                  # We get a different stack layout with call gates,
        pushl %eax              # which has to be cleaned up later..
index 2f59c1a19992ac7a2e289efac0b1a6cf75a1a487..e27cc4819dbb99a1a89db768d61135dbdd7985fa 100644 (file)
@@ -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 @@ static struct symbol_table arch_symbol_table = {
        /* platform dependent support */
        X(dump_thread),
        X(dump_fpu),
+       XNOVERS(__do_delay),
        XNOVERS(down_failed),
        XNOVERS(down_failed_interruptible),
        XNOVERS(up_wakeup),
index cf54dd7df623d9ebb1347ba42dfa018714b218fe..834f4d6282a82b90b2d3d3adf3376906ae913b5b 100644 (file)
@@ -11,6 +11,6 @@ else
 endif
 
 L_TARGET = lib.a
-L_OBJS  = checksum.o semaphore.o
+L_OBJS  = checksum.o semaphore.o delay.o
 
 include $(TOPDIR)/Rules.make
diff --git a/arch/i386/lib/delay.S b/arch/i386/lib/delay.S
new file mode 100644 (file)
index 0000000..c6079a7
--- /dev/null
@@ -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
+
+
+
index 94732f1a2cab1399c2a03912fdb750a6ed4e365c..c272d602d0e96b82d460ef68d7f6e9efe3597c8d 100644 (file)
@@ -194,12 +194,6 @@ static int mmap_zero(struct inode * inode, struct file * file, struct vm_area_st
        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 @@ static int memory_lseek(struct inode * inode, struct file * file, off_t offset,
 #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 zero_fops = {
 };
 
 static struct file_operations full_fops = {
-       memory_lseek,
+       full_lseek,
        read_full,
        write_full,
        NULL,           /* full_readdir */
index 7f53c7070492e60b589d61cfc257e0ca466bddb8..81b3122609f6f4a6844af67c4c991af83da9b331 100644 (file)
@@ -1474,11 +1474,10 @@ static int tty_fasync(struct inode * inode, struct file * filp, int on)
        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))
index 609383240c0c5a2ff9c869b32a0bd1d1d2b44f83..e40f8f7daeaf2561a305142bcfc9830c203a0097 100644 (file)
@@ -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.
 
 */
 
 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 @@ struct netdev_entry tc59x_drv =
 #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 @@ union wn3_config {
 };
 
 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 @@ static struct device *vortex_found_device(struct device *dev, int ioaddr,
                                                                                  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 int vortex_close(struct device *dev);
 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 @@ static int vortex_probe1(struct device *dev)
                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 @@ static int vortex_probe1(struct device *dev)
        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 @@ static int vortex_probe1(struct device *dev)
 \f
 /* 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 @@ static int vortex_probe1(struct device *dev)
 #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;
 }
 
 \f
@@ -888,19 +940,22 @@ vortex_open(struct device *dev)
        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 @@ vortex_open(struct device *dev)
        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 @@ static void vortex_timer(unsigned long data)
          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 @@ static void vortex_tx_timeout(struct device *dev)
                   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 @@ static void vortex_tx_timeout(struct device *dev)
                         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 @@ static void vortex_tx_timeout(struct device *dev)
    
          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 @@ boomerang_start_xmit(struct sk_buff *skb, struct device *dev)
                        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 @@ boomerang_start_xmit(struct sk_buff *skb, struct device *dev)
                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 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
        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 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
        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 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
                        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 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
                                /* 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 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
                                                        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 @@ boomerang_rx(struct device *dev)
        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 @@ static void update_stats(int ioaddr, struct device *dev)
        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
index 3f74b8d0cb58c86b04ce58679981d39d08024773..ccdcd5d0ff58d6032ef27a0cd86eeb97d4ce8c49 100644 (file)
@@ -1444,7 +1444,7 @@ static void tulip_timer(unsigned long data)
                                  }
                                  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);
                          }
index d509842eb766c741fb5b7ad924fd8738828523b0..7fbdaa58745b2956f2e301850e595d84a16cccd3 100644 (file)
@@ -42,7 +42,7 @@ dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $
 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 @@ fi
 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
index 5551cbad836dc50a7ee2afc88fdd2688ed218698..10fa67f86d8127f259f7fbe1ab721a9892f15956 100644 (file)
@@ -871,7 +871,7 @@ struct aic7xxx_host {
     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 @@ static int aic7xxx_verbose = 0;                 /* verbose messages */
  * 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 @@ aic_outsb(struct aic7xxx_host *p, long port, unsigned char *valp, size_t size)
     outsb(p->base + port, valp, size);
   }
 }
+ ***************************************************************************/
 
 /*+F*************************************************************************
  * Function:
@@ -1985,6 +1992,8 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
   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 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
       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 @@ aic7xxx_device_queue_depth(struct aic7xxx_host *p, Scsi_Device *device)
 #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 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p)
   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 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p)
     */
   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 @@ aic7xxx_detect(Scsi_Host_Template *template)
    * 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 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
   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 @@ Scsi_Host_Template driver_template = AIC7XXX;
  * tab-width: 8
  * End:
  */
-
index 6ecae3bcdefd52f734059572da68f0a9113edc27..d25365a8ed7ce7b57e652a8c27232cd9a4db1371 100644 (file)
@@ -1079,10 +1079,25 @@ scratch_ram {
        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 @@ scratch_ram {
        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 @@ scratch_ram {
                size            1
                bit     RESET_SCSI      0x40
        }
+        SCSICONF2 {
+               address         0x05b
+               size            1
+               bit     RESET_SCSI      0x40
+       }
        HOSTCONF {
                address         0x05d
                size            1
index dee247534ae72475732e971fa1c70adecde142da..064e3833e71d7d5053de40e2dea1cea3c9a6f912 100644 (file)
  *  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 @@ aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
   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 @@ aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
  *   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 @@ aic7xxx_proc_info(char *buffer, char **start, off_t offset, int length,
       {
         break;
       }
-
+      
       while ((HBAptr->hostdata != NULL) && !found &&
           ((HBAptr = ((struct aic7xxx_host *) HBAptr->hostdata)->next) != NULL))
       {
@@ -104,7 +109,7 @@ aic7xxx_proc_info(char *buffer, char **start, off_t offset, int length,
           found = TRUE;
         }
       }
-
+      
       if (!found)
       {
         HBAptr = NULL;
@@ -115,43 +120,69 @@ aic7xxx_proc_info(char *buffer, char **start, off_t offset, int length,
       }
     }
   }
-
+  
   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 @@ aic7xxx_proc_info(char *buffer, char **start, off_t offset, int length,
 #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 @@ aic7xxx_proc_info(char *buffer, char **start, off_t offset, int length,
       (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;
 }
 
 /*
index 8fbf84fa630c24bf4f890176d4c529203457f58d..92b5afa54e9019eab515cfac99de4f08e8513b86 100644 (file)
 
 #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
 
index c90bad94dcc2059910711e4ac4d15a9f27c60190..78359fb4e90d97ee73ff87c7f654a1f5ab798980 100644 (file)
@@ -26,8 +26,8 @@ static u_int8_t seqprog[] = {
        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 @@ static u_int8_t seqprog[] = {
        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 @@ static u_int8_t seqprog[] = {
        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 @@ static u_int8_t seqprog[] = {
        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 @@ static u_int8_t seqprog[] = {
        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 @@ static u_int8_t seqprog[] = {
        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 @@ static u_int8_t seqprog[] = {
        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 @@ static u_int8_t seqprog[] = {
        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 @@ static u_int8_t seqprog[] = {
        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,
index cfff8bfa3cf936fdddcba076ee7649a6779e8606..aeda681c1a8055d5f7e41edfb7f5782277d956ea 100644 (file)
@@ -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 @@ MODULE_AUTHOR("Dario Ballabio");
 #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 @@ struct proc_dir_entry proc_scsi_eata2x = {
 #undef  DEBUG_INTERRUPT
 #undef  DEBUG_STATISTICS
 #undef  DEBUG_RESET
+#undef  DEBUG_SMP
 
 #define MAX_ISA 4
 #define MAX_VESA 0 
@@ -351,7 +362,7 @@ struct proc_dir_entry proc_scsi_eata2x = {
 #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 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
 
       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 void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
 
 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 @@ static inline int read_pio(unsigned int iobase, ushort *start, ushort *end) {
 
    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 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
    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 @@ static void eata2x_interrupt_handler(int irq, void *dev_id,
 
    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]);
index cba3914145590a73baed192419f19583cce427dc..8292ef5148065053973471a87861f886f9ab1fc2 100644 (file)
@@ -12,7 +12,7 @@ int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 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 {                                                 \
index 9ba78d835eaf2dd2e32ce9763e850a2dbc878850..9b1851033950c7358cf183f511380782b3e5d4fd 100644 (file)
 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) {
index 6a0076ddeb93a9d204ffd72b57719e9892015f7e..fa980051a6510ecf30234d9ca2382f0056e81a89 100644 (file)
@@ -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 @@ MODULE_AUTHOR("Dario Ballabio");
 #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 @@ struct proc_dir_entry proc_scsi_u14_34f = {
 #undef  DEBUG_INTERRUPT
 #undef  DEBUG_STATISTICS
 #undef  DEBUG_RESET
+#undef  DEBUG_SMP
 
 #define MAX_ISA 3
 #define MAX_VESA 1 
@@ -349,7 +360,7 @@ struct proc_dir_entry proc_scsi_u14_34f = {
 #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 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
 
       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 void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
 
 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 @@ static int board_inquiry(unsigned int j) {
 
    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 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
    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 @@ static void u14_34f_interrupt_handler(int irq, void *dev_id,
 
    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]);
index 9381f7729421ddae5466e1daf1c31acdde9e0b65..004936393518b9c647be987a4aafa4a6ae8b33b1 100644 (file)
@@ -11,7 +11,7 @@ int u14_34f_abort(Scsi_Cmnd *);
 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 */                           \
index a547a571d11f7a38c7086aea4e9be7aa7eec47d7..7fb908c40ca8e48ee147f617c8197b621bd2c49d 100644 (file)
@@ -559,7 +559,7 @@ static inline int can_reclaim(struct buffer_head *bh, int size)
 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 @@ static struct buffer_head *find_candidate(struct buffer_head *bh,
                        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 @@ static void refill_freelist(int size)
 {
        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 @@ static void refill_freelist(int size)
           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 @@ repeat:
 
        /* 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 @@ static void get_more_buffer_heads(void)
                 * 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++;
index b5dde216d920be7a225eaa87bc5d93d7653ecc6b..268bac5ccba2165d6d30b06c7b2eb74ec843f885 100644 (file)
@@ -55,8 +55,6 @@ asmlinkage int sys_dup(unsigned int fildes)
 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 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
                         * 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 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
        }
 }
 
+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;
        }
 }
index c54e6a1350318fdd50cd00e77ea399b36e77140f..33a05940f5ed5665cd424e601e12c28556615b87 100644 (file)
@@ -232,10 +232,13 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
        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 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
        {
                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 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
        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 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
                printk("smb_read_super: get root inode failed\n");
                goto fail;
        }
-       MOD_INC_USE_COUNT;
        return sb;
 
       fail:
@@ -340,6 +346,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
        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 @@ smb_notify_change(struct inode *inode, struct iattr *attr)
             (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 @@ smb_notify_change(struct inode *inode, struct iattr *attr)
                        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;
 }
 
index ef65be7ce2eecae92b1311a0eaabbd1db23cb8d3..ed7358baa198249ce02cca5808223ba3655caef1 100644 (file)
@@ -230,40 +230,6 @@ date_dos2unix(unsigned short time, unsigned short date)
        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 @@ smb_finish_dirent(struct smb_server *server, struct smb_dirent *entry)
                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 @@ smb_proc_getattr_core(struct inode *dir, const char *name, int len,
        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 @@ smb_proc_getattr(struct inode *dir, const char *name, int len,
        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 @@ smb_proc_setattr_core(struct smb_server *server,
        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 @@ smb_proc_setattr_core(struct smb_server *server,
        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)
 {
index 64ec6fec52fcf193b7648ec6f6744e59f1b14b84..454eb4d297b2d8bf589b13f23bcfa5b2c8b6efe6 100644 (file)
@@ -437,8 +437,10 @@ smb_receive_trans2(struct smb_server *server,
                        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 @@ smb_request(struct smb_server *server)
        }
        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 @@ smb_trans2_request(struct smb_server *server, __u16 trans2_command,
        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)
        {
index e22e8d6b20e4d9cc92b588a962ec5ef16255cdbb..2f4a41b9fc9f1e57b1f5dd88a8011e37fae2eaaa 100644 (file)
@@ -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");
index 4fe28f511b5a0b3e6704b41f16a80287fe181f5e..7766d8b99919a5db75015181e25b7e46de6fe746 100644 (file)
@@ -79,7 +79,7 @@ extern int max_files, nr_files;
 /*
  * 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 @@ struct inode {
        } 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 @@ struct file {
        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;
index 6772a60f8e601b220b735ea688a56124d656770d..2dda58bcd8d7514c9fb4997724269a0b3962a180 100644 (file)
@@ -147,6 +147,8 @@ struct mfc_cache
        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
index 97316607bb4f43ab16283f9196f8bb3b6654aabd..948e54550d95b54bfa0bfa7145a158585b959a25 100644 (file)
 _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)
index 683a04276434ee4e50c9739eca17d6dc8e5394d6..ee9aa339f2bec84b2de985d5a90de5c5e36b73f3 100644 (file)
@@ -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>
  *
index fa072b7a45a48a8be269480499a3693495c2448f..3af796f9670e22ab31ca5c3eb5a247508eff1d64 100644 (file)
@@ -85,6 +85,7 @@ extern void           ip_rt_flush(struct device *dev);
 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);
index 0169a486dd60125443cfe1074ca8585d6f1ea1b5..f726dddaa1203ddce73237c22b8a614fd3eca85f 100644 (file)
@@ -340,15 +340,19 @@ void allow_interrupts(void)
   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);
index 6ae27e20fb60c3e93c107506104b1f6a91298480..8e01edceae076c073026d5afacb3939c3bf20da9 100644 (file)
@@ -447,6 +447,6 @@ bad_order:
        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);
 }
index b32551e383cff38eb8023ad78b8aa62a01552848..161be3e9587db6888020d6c676046e0c643c2cbb 100644 (file)
@@ -406,11 +406,8 @@ int try_to_free_page(int priority, int dma, int wait)
        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 @@ int kswapd(void *unused)
                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));
        }
 }
 
index a7cb1b8a071733caabb3882e777bdb91a2f8b97e..68fd21737d549f458b8cf8ca9ef596ae36b3e0cb 100644 (file)
@@ -1921,6 +1921,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        {
                /*
                 *      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);
 
index cb22de9afafb2c1200d36daa3ebc665b94d36ab6..0af398144318e08593f2056116533db18541158a 100644 (file)
@@ -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 @@ static void icmp_discard(struct icmphdr *icmph, struct sk_buff *skb, struct devi
  *     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 @@ int icmp_chkaddr(struct sk_buff *skb)
                        {
                        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 @@ int icmp_chkaddr(struct sk_buff *skb)
                        {
                        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;
index 9c76eab0aa3dfeef0745991a8027cc5a8bc92e7e..94322501f963ebbec449ae0edeeecf547c87fbc6 100644 (file)
@@ -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 @@ int ip_alias_print_1(struct net_alias_type *this, struct net_alias *alias, char
                (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 @@ struct device *ip_alias_dev_select(struct net_alias_type *this, struct device *m
         *      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 @@ int ip_alias_done(void)
 
 #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;
index 1bd7275ae9fc2cacc5b4b3d9cb50a81106a72e3e..9fea00c8a56230e06166a83c93dafafef53d0d0e 100644 (file)
@@ -299,10 +299,13 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
         *      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
index 53bbacdcf5e20444ffea240d63fe04dd26fe1aed..88d93aba454d60386241957781299317f24201ba 100644 (file)
@@ -983,8 +983,7 @@ int ip_build_xmit(struct sock *sk,
                }
 #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;
index a45b083637b05c94b3546462ed6fd95b4f3c9750..e2568e23f9ca44055714f5ffd3428202d76f5776 100644 (file)
@@ -193,6 +193,8 @@ static struct mfc_cache *ipmr_cache_alloc(int priority)
        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 @@ int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg)
        struct sioc_sg_req sr;
        struct sioc_vif_req vr;
        struct vif_device *vif;
+       struct mfc_cache *cl;
        
        switch(cmd)
        {
@@ -617,6 +620,19 @@ int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg)
                        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 @@ void ipmr_forward(struct sk_buff *skb, int is_frag)
        
        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 @@ void ipmr_forward(struct sk_buff *skb, int is_frag)
        if(psend==-1)
                kfree_skb(skb, FREE_WRITE);
        else
-       {
                ipmr_queue_xmit(skb, &vif_table[psend], skb->dev, is_frag);
-       }
 }
 
 /*
@@ -907,7 +923,7 @@ done:
  
 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) {
index d44711ec495ed222d7d0ab6ac00c02d61a2b67ec..79661fa7686617839da6d7ac928f49a93f6f753b 100644 (file)
@@ -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 @@ void ip_rt_put(struct rtable * rt)
                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;
index 0f5402f765408c015866c2b8095dfadf316e1419..550e35056d86a7b7dd43286c55f8a97d8de9f6d7 100644 (file)
@@ -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 @@ __inline__ struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport
 }
 
 #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 @@ int tcp_chkaddr(struct sk_buff *skb)
        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 @@ retry_search:
 #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 @@ retry_search:
                        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)
                        {
index a8e367c747ca8059ad68137b43bb81997569d623..406874275ea4c0b5aa41f762338d94b4376d7f20 100644 (file)
@@ -537,6 +537,7 @@ void tcp_do_retransmit(struct sock *sk, int all)
                                        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)
index dc20471d87051b018384e650805b4d094213568b..1f5aff88a8ca14f780e03d7aeae8a2f0fff6c669 100644 (file)
@@ -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 @@ __inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport
 }
 
 #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 @@ int udp_chkaddr(struct sk_buff *skb)
        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 @@ int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
 #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);
index e79546f968cadbfd575023583da87dd8984af9c2..e7727b5e0273165687fa1fa532bfb02ce53c10d8 100644 (file)
@@ -100,6 +100,7 @@ static struct symbol_table net_syms = {
 
        X(init_etherdev),
        X(ip_rt_route),
+       X(ip_rt_dev),
        X(icmp_send),
        X(ip_options_compile),
        X(ip_rt_put),