]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.109pre1 2.1.109pre1
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:15:51 +0000 (15:15 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:15:51 +0000 (15:15 -0500)
21 files changed:
CREDITS
Documentation/filesystems/ncpfs.txt
Makefile
arch/i386/kernel/entry.S
arch/i386/kernel/ldt.c
arch/i386/kernel/process.c
arch/i386/kernel/ptrace.c
arch/i386/kernel/signal.c
arch/i386/kernel/traps.c
arch/i386/mm/fault.c
arch/i386/mm/init.c
drivers/char/console.c
drivers/net/de4x5.c
drivers/net/de4x5.h
fs/ncpfs/Makefile
include/asm-i386/bugs.h
include/asm-i386/processor.h
include/asm-i386/system.h
kernel/fork.c
kernel/printk.c
mm/filemap.c

diff --git a/CREDITS b/CREDITS
index d442fef70bd1887752fb1a0aeac4d3280cb19b03..d9ec510ddfa0e6fb9ff1b39df662773d9b36082f 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1,9 +1,9 @@
        This is at least a partial credits-file of people that have
-       contributed to the linux project.  It is sorted by name, and
-       formatted in a format that allows for easy grepping and
-       beautification by scripts.  The fields are: name (N), email (E),
-       web-address (W), PGP key ID and fingerprint (P), description (D)
-       and snail-mail address (S). 
+       contributed to the Linux project.  It is sorted by name and
+       formatted to allow easy grepping and beautification by
+       scripts.  The fields are: name (N), email (E), web-address
+       (W), PGP key ID and fingerprint (P), description (D), and
+       snail-mail address (S).
        Thanks,
 
                        Linus
@@ -46,8 +46,8 @@ W: http://www.inconnect.com/~andersen
 P: 1024/FC4CFFED 78 3C 6A 19 FA 5D 92 5A  FB AC 7B A5 A5 E1 FF 8E
 D: Maintainer of ide-cd and Uniform CD-ROM driver, 
 D: ATAPI CD-Changer support, Major 2.1.x CD-ROM update.
-S: 4538 South Carnegie Tech St.
-S: West Valley City, UT 84120
+S: 4538 South Carnegie Tech Street
+S: West Valley City, Utah 84120
 S: USA
 
 N: H. Peter Anvin
@@ -56,7 +56,7 @@ W: http://www.zytor.com/~hpa/
 P: 2047/2A960705 BA 03 D3 2C 14 A8 A8 BD  1E DF FE 69 EE 35 BD 74
 D: Author of the SYSLINUX boot loader, maintainer of the linux.* news
 D: hierarchy and the Linux Device List; various kernel hacks
-S: 4390 Albany Dr. #46
+S: 4390 Albany Drive #46
 S: San Jose, California 95129
 S: USA
 
@@ -85,7 +85,8 @@ E: aycock@cpsc.ucalgary.ca
 D: Adaptec 274x driver
 S: Department of Computer Science
 S: University of Calgary
-S: Calgary, Alberta, Canada
+S: Calgary, Alberta
+S: Canada
 
 N: Ralf Baechle
 E: ralf@gnu.ai.mit.edu
@@ -143,7 +144,7 @@ S: Germany
 N: Donald Becker
 E: becker@cesdis.gsfc.nasa.gov
 D: General low-level networking hacker
-D: Most of the ethercard drivers
+D: Most of the Ethernet drivers
 D: Original author of the NFS server
 S: USRA Center of Excellence in Space Data and Information Sciences
 S: Code 930.5, Goddard Space Flight Center
@@ -185,7 +186,8 @@ D: Device driver hacking
 D: Some Linux/ARM stuff
 D: Co-architect of the parallel port sharing system
 S: Nexus Electronics Ltd
-S: 10 St Barnabas Road, Cambridge, UK. CB1 2BY
+S: 10 St Barnabas Road, Cambridge CB1 2BY
+S: United Kingdom
 
 N: Thomas Bogendoerfer
 E: tsbogend@alpha.franken.de
@@ -217,8 +219,9 @@ E: braam@cs.cmu.edu
 W: http://coda.cs.cmu.edu/~braam
 D: Coda Filesystem
 S: Dept of Computer Science
-S: 5000 Forbes Ave
-S: Pittsburgh PA 15213
+S: 5000 Forbes Avenue
+S: Pittsburgh, Pennsylvania 15213
+S: USA
 
 N: Andries Brouwer
 E: aeb@cwi.nl
@@ -273,7 +276,8 @@ E: chihjen@iis.sinica.edu.tw
 D: IGMP(Internet Group Management Protocol) version 2
 S: 3F, 65 Tajen street
 S: Tamsui town, Taipei county,
-S: Taiwan 251, Republic of China
+S: Taiwan 251
+S: Republic of China
 
 N: Raymond Chen
 E: raymondc@microsoft.com
@@ -412,7 +416,8 @@ S: Germany
 N: Tom Dyas
 E: tdyas@eden.rutgers.edu
 D: minor hacks and some sparc port stuff
-S: New Jersey, USA
+S: New Jersey
+S: USA
 
 N: Drew Eckhardt
 E: drew@PoohSticks.ORG
@@ -425,7 +430,7 @@ S: USA
 
 N: Heiko Eissfeldt
 E: heiko@colossus.escape.de heiko@unifix.de
-D: verify_area stuff, generic scsi fixes
+D: verify_area stuff, generic SCSI fixes
 D: SCSI Programming HOWTO
 D: POSIX.1 compliance testing
 S: Unifix Software GmbH
@@ -458,7 +463,7 @@ E: fizban@tin.it
 P: 1024/6E657BB5 AF 22 90 33 78 76 04 8B  AF F9 97 1E B5 E2 65 30
 D: Audio Excel DSP 16 init driver author
 D: libmodem author
-D: Yet Another Micro Monitor port and current mantainer
+D: Yet Another Micro Monitor port and current maintainer
 D: First ELF-HOWTO author
 D: random kernel hacker
 S: Via Paolo VI n.29
@@ -482,7 +487,7 @@ S: Hungary
 
 N: Jürgen Fischer
 E: fischer@et-inf.fho-emden.de (=?iso-8859-1?q?J=FCrgen?= Fischer)
-D: Author of Adaptec AHA-152x scsi driver
+D: Author of Adaptec AHA-152x SCSI driver
 S: Schulstraße 18
 S: 26506 Norden
 S: Germany
@@ -493,7 +498,7 @@ D: Improved mmap and munmap handling
 D: General mm minor tidyups
 S: 67 Surrey St.
 S: Darlinghurst, Sydney
-S: NSW 2010
+S: New South Wales 2010
 S: Australia
 
 N: Ralf Flaxa
@@ -526,7 +531,7 @@ D: Initial GPL'd Frame Relay driver
 D: Dynamic PPP devices
 D: Sundry modularizations (PPP, IPX, ...) and fixes
 S: Caldera, Inc.
-S: 240 West Center St.
+S: 240 West Center Street
 S: Orem, Utah 84059-1920
 S: USA
 
@@ -571,7 +576,7 @@ D: prctl() syscall
 D: /proc/mtrr support to manipulate MTRRs on Pentium Pro's
 S: CSIRO Australia Telescope National Facility
 S: P.O. Box 76, Epping
-S: N.S.W., 2121
+S: New South Wales, 2121
 S: Australia
 
 N: Dmitry S. Gorodchanin
@@ -586,7 +591,7 @@ E: gpg109@rsphy1.anu.edu.au
 W: http://rsphy1.anu.edu.au/~gpg109
 D: Real Time Clock driver author.
 D: 8390 net driver hacker (ne2000, wd8013, smc-ultra, 3c503, etc.) 
-D: Ethernet-HowTo and BootPrompt-HowTo author.
+D: Ethernet-HOWTO and BootPrompt-HOWTO author.
 D: Added many new CONFIG options (modules, ramdisk, generic-serial, etc.)
 D: Implemented 1st "official" kernel thread (moved user bdflush to kflushd)
 D: Various other random hacks, patches and utilities.
@@ -601,7 +606,7 @@ 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
+D: Loopback speedup, qlogic SCSI hacking, VT_LOCKSWITCH
 S: Department of Computer Science
 S: University of California, Riverside
 S: Riverside, California 92521-0304
@@ -613,7 +618,7 @@ W: http://www.torque.net/linux-pp.html
 D: original author of ppa driver for parallel port ZIP drive
 D: original architect of the parallel-port sharing scheme 
 D: PARIDE subsystem: drivers for parallel port IDE & ATAPI devices
-S: 44 St. Joseph St., Suite 506
+S: 44 St. Joseph Street, Suite 506
 S: Toronto, Ontario, M4Y 2W4
 S: Canada
 
@@ -694,7 +699,7 @@ S: Germany
 
 N: Michael Hipp
 E: mhipp@student.uni-tuebingen.de
-D: drivers for the racal ni5210 & ni6510 ethernet-boards
+D: drivers for the racal ni5210 & ni6510 Ethernet-boards
 S: Talstr. 1
 S: D - 72072 Tuebingen
 S: Germany
@@ -716,7 +721,7 @@ N: Kenji Tsutomu Hollis
 E: khollis@bitgate.com
 W: http://www.nurk.org/
 D: Berkshire PC Watchdog Driver
-S: PO Box 15
+S: Post Office Box 15
 S: Grants Pass, Oregon 97526
 S: USA
 
@@ -739,7 +744,7 @@ P: 1024/1FD44539 DF 4B EB 9F 5B 68 38 9A  40 E3 FB 71 D1 C8 0B 56
 D: Kernel development
 D: Minor kernel modifications to support Wabi and Wine
 S: Caldera, Inc.
-S: 240 West Center St.
+S: 240 West Center Street
 S: Orem, Utah 84059-1920
 S: USA
 
@@ -854,7 +859,7 @@ S: Germany
 
 N: Russell King
 E: rmk@arm.uk.linux.org
-D: Linux/arm integrater, maintainer & hacker
+D: Linux/arm integrator, maintainer & hacker
 S: Burgh Heath, Tadworth, Surrey.
 S: England
 
@@ -870,8 +875,8 @@ E: ikluft@thunder.sbay.org
 W: http://www.kluft.com/~ikluft/
 D: NET-1 beta testing & minor patches, original Smail binary packages for
 D: Slackware and Debian, vote-taker for 2nd comp.os.linux reorganization
-S: PO Box 611311
-S: San Jose, CA 95161-1311
+S: Post Office Box 611311
+S: San Jose, California 95161-1311
 S: USA
 
 N: Alain L. Knaff
@@ -991,7 +996,7 @@ S: Australia
 N: Hans Lermen
 E: lermen@elserv.ffm.fgan.de
 D: Author of the LOADLIN Linux loader, hacking on boot stuff
-D: Co-ordinator of DOSEMU releases
+D: Coordinator of DOSEMU releases
 S: Am Muehlenweg 38
 S: D53424 Remagen
 S: Germany
@@ -1000,12 +1005,13 @@ N: Achim Leubner
 E: achim@vortex.de
 D: GDT SCSI Disk Array Controller driver
 S: ICP vortex Computersysteme GmbH
-S: Flein, Germany
+S: Flein
+S: Germany
 
 N: Phil Lewis
 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: Post Office Box 371
 S: North Little Rock, Arkansas 72115
 S: USA
 
@@ -1041,7 +1047,7 @@ S: United Kingdom
 N: Warner Losh
 E: imp@village.org
 D: Linux/MIPS Deskstation support, Provided OI/OB for Linux
-S: 8786 Niwot Rd
+S: 8786 Niwot Road
 S: Niwot, Colorado 80503
 S: USA
 
@@ -1099,7 +1105,7 @@ S: Australia
 N: James B. MacLean
 E: macleajb@ednet.ns.ca
 W: http://www.ednet.ns.ca/~macleajb/dosemu.html
-D: Former Co-ordinator of DOSEMU releases
+D: Former Coordinator of DOSEMU releases
 D: Program in DOSEMU
 S: PO BOX 220, HFX. CENTRAL
 S: Halifax, Nova Scotia
@@ -1138,7 +1144,7 @@ E: mike.mclagan@linux.org
 W: http://www.invlogic.com/~mmclagan
 D: DLCI/FRAD drivers for Sangoma SDLAs
 S: Innovative Logic Corp
-S: P.O. Box 1068
+S: Post Office Box 1068
 S: Laurel, Maryland 20732
 S: USA
 
@@ -1202,7 +1208,7 @@ D: New Linux-Activists maintainer
 D: Linux Emacs elf/qmagic support + other libc/gcc things
 D: Yee bore de yee bore! ;-)
 S: 111 Alta Tierra Court
-S: Los Gatos, CA 95032
+S: Los Gatos, California 95032
 S: USA
 
 N: Rick Miller
@@ -1242,7 +1248,7 @@ N: David Mosberger-Tang
 E: David.Mosberger@acm.org
 D: Linux/Alpha
 S: 35706 Runckel Lane
-S: Fremont, CA 94536
+S: Fremont, California 94536
 S: USA
 
 N: Ian A. Murdock
@@ -1285,8 +1291,8 @@ W: http://www.crynwr.com/~nelson
 P: 1024/83942741 FF 68 EE 27 A0 5A AA C3  F5 DC 05 62 BD 5B 20 2F
 D: Author of cs89x0, maintainer of kernel changelog through 1.3.3
 D: Wrote many packet drivers, from which some Ethernet drivers are derived.
-S: 521 Pleasant Valley Rd.
-S: Potsdam, NY 13676
+S: 521 Pleasant Valley Road
+S: Potsdam, New York 13676
 S: USA
 
 N: Michael Neuffer
@@ -1402,7 +1408,7 @@ E: quinlan@pathname.com
 W: http://www.pathname.com/~quinlan/
 D: FSSTND coordinator; FHS editor
 D: random Linux documentation, patches, and hacks
-S: 4390 Albany Dr. #41A
+S: 4390 Albany Drive #41A
 S: San Jose, California 95129
 S: USA
 
@@ -1501,7 +1507,7 @@ D: Developed Generic IP Firewalling Chains with Michael Neuling.
 N: Thomas Sailer
 E: sailer@ife.ee.ethz.ch
 E: HB9JNX@HB9W.CHE.EU (packet radio)
-D: hfmodem, Baycom and Soundcard radio modem driver
+D: hfmodem, Baycom and sound card radio modem driver
 S: Weinbergstrasse 76
 S: 8408 Winterthur
 S: Switzerland
@@ -1541,12 +1547,13 @@ D: Random Linux Hacker, Linux Promoter
 D: CD-List, Books-List, Ex-FAQ
 D: Linux-Support, -Mailbox, -Stammtisch
 D: several improvements to system programs
-S: Oldenburg, Germany
+S: Oldenburg
+S: Germany
 
 N: Darren Senn
 E: sinster@darkwater.com
 D: Whatever I notice needs doing (so far: itimers, /proc)
-S: POB 64132
+S: Post Office Box 64132
 S: Sunnyvale, California 94088-4132
 S: USA
 
@@ -1589,11 +1596,11 @@ S: USA
 N: Craig Small
 E: csmall@triode.apana.org.au
 E: vk2xlz@gonzo.vk2xlz.ampr.org (packet radio)
+D: Gracilis PackeTwin device driver
+D: RSPF daemon 
 S: 10 Stockalls Place
 S: Minto, NSW, 2566
 S: Australia
-D: Gracilis PackeTwin device driver
-D: RSPF daemon 
 
 N: Chris Smith
 E: csmith@convex.com
@@ -1681,14 +1688,14 @@ D: Author of several small utilities
 D: (bogomips, scope, eject, statserial)
 S: 1 Laurie Court
 S: Kanata, Ontario
-S: CANADA K2L 1S2
+S: Canada K2L 1S2
 
 N: Andrew Tridgell
 E: Andrew.Tridgell@anu.edu.au
 D: dosemu, networking, samba
 S: 3 Ballow Crescent
-S: MacGregor A.C.T
-S: 2615 Australia
+S: MacGregor A.C.T 2615
+S: Australia
 
 N: Winfried Trümper
 E: winni@xpilot.org
@@ -1720,7 +1727,8 @@ E: tsusheng@scf.usc.edu
 D: IGMP(Internet Group Management Protocol) version 2
 S: 2F 14 ALY 31 LN 166 SEC 1 SHIH-PEI RD
 S: Taipei 
-S: Taiwan 112, Republic of China
+S: Taiwan 112
+S: Republic of China
 S: 24335 Delta Drive
 S: Diamond Bar, California 91765
 S: USA
@@ -1799,7 +1807,7 @@ D: Turtle Beach MultiSound sound driver
 S: USA
 
 N: Dirk Verworner
-D: Co-author of german book ``Linux-Kernel-Programmierung''
+D: Co-author of German book ``Linux-Kernel-Programmierung''
 D: Co-founder of Berlin Linux User Group
 
 N: Patrick Volkerding
@@ -1903,7 +1911,7 @@ S: Finland
 N: Jonathan Woithe
 E: jwoithe@physics.adelaide.edu.au
 W: http://www.physics.adelaide.edu.au/~jwoithe
-D: ALS-007 soundcard extensions to Sound Blaster driver
+D: ALS-007 sound card extensions to Sound Blaster driver
 S: 4/36 Trevelyan St
 S: Wayville SA 5034
 S: Australia
index 8698dba3f0926cfc5164025a2d87a25cef0a8d74..f12c30c93f2fff8408a051446d7bf53cc94a4826 100644 (file)
@@ -1,12 +1,12 @@
-ncpfs is a filesystem which understands the NCP protocol, designed by the
-Novell Corporation for their NetWare(tm) product. NCP is functionally
-similar to the NFS used in the tcp/ip community.
-To mount a Netware-Filesystem, you need a special mount program, which
-can be found in ncpfs package. Homesite for ncpfs is
+The ncpfs filesystem understands the NCP protocol, designed by the
+Novell Corporation for their NetWare(tm) product.  NCP is functionally
+similar to the NFS used in the TCP/IP community.
+To mount a NetWare filesystem, you need a special mount program, which
+can be found in the ncpfs package.  The home site for ncpfs is
 ftp.gwdg.de/pub/linux/misc/ncpfs, but sunsite and its many mirrors
 will have it as well.
 
 Related products are linware and mars_nwe, which will give Linux partial
-NetWare Server functionality.
-Linware's home site is: klokan.sh.cvut.cz/pub/linux/linware,
-Mars_nwe can be found on ftp.gwdg.de/pub/linux/misc/ncpfs.
+NetWare server functionality.  Linware's home site is
+klokan.sh.cvut.cz/pub/linux/linware; mars_nwe can be found on
+ftp.gwdg.de/pub/linux/misc/ncpfs.
index 7719d69fb44b01a5705089572c62c87ba73b885e..88c0d76014c360802e01a500ba6f763dc3361aab 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 108
+SUBLEVEL = 109
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
index fb8dfeb3518f58b543a5681bb3444566a3363a08..c464b684823a1c5d0606851c67cdfbe62638beec 100644 (file)
@@ -94,18 +94,31 @@ ENOSYS = 38
        movl %dx,%ds; \
        movl %dx,%es;
 
-#define RESTORE_ALL \
-       popl %ebx; \
-       popl %ecx; \
-       popl %edx; \
-       popl %esi; \
-       popl %edi; \
-       popl %ebp; \
-       popl %eax; \
-       popl %ds; \
-       popl %es; \
-       addl $4,%esp; \
-       iret
+#define RESTORE_ALL    \
+       popl %ebx;      \
+       popl %ecx;      \
+       popl %edx;      \
+       popl %esi;      \
+       popl %edi;      \
+       popl %ebp;      \
+       popl %eax;      \
+1:     popl %ds;       \
+2:     popl %es;       \
+3:     addl $4,%esp;   \
+       iret;           \
+.section fixup,"ax";   \
+4:     pushl $0;       \
+       popl %ds;       \
+       jmp 2b;         \
+5:     pushl $0;       \
+       popl %es;       \
+       jmp 3b;         \
+.previous;             \
+.section __ex_table,"a";\
+       .align 4;       \
+       .long 1b,4b;    \
+       .long 2b,5b;    \
+.previous
 
 #define GET_CURRENT(reg) \
        movl %esp, reg; \
index 64d4ab1539418bddbecc563aee8fe345c67dbd1a..2a2edffddebabd8ed6f7f89007e4b5b48db3c2d0 100644 (file)
@@ -35,21 +35,29 @@ static int read_ldt(void * ptr, unsigned long bytecount)
 
 static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
 {
+       struct mm_struct * mm = current->mm;
+       void * ldt;
+       __u32 entry_1, entry_2, *lp;
+       __u16 selector, reg_fs, reg_gs;
+       int error;
        struct modify_ldt_ldt_s ldt_info;
-       unsigned long *lp;
-       struct mm_struct * mm;
-       int error, i;
 
+       error = -EINVAL;
        if (bytecount != sizeof(ldt_info))
-               return -EINVAL;
-       error = copy_from_user(&ldt_info, ptr, sizeof(ldt_info));
-       if (error)
-               return -EFAULT;         
-
-       if ((ldt_info.contents == 3 && (oldmode || ldt_info.seg_not_present == 0)) || ldt_info.entry_number >= LDT_ENTRIES)
-               return -EINVAL;
+               goto out;
+       error = -EFAULT;        
+       if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
+               goto out;
 
-       mm = current->mm;
+       error = -EINVAL;
+       if (ldt_info.entry_number >= LDT_ENTRIES)
+               goto out;
+       if (ldt_info.contents == 3) {
+               if (oldmode)
+                       goto out;
+               if (ldt_info.seg_not_present == 0)
+                       goto out;
+       }
 
        /*
         * Horrible dependencies! Try to get rid of this. This is wrong,
@@ -62,60 +70,97 @@ static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
         * For no good reason except historical, the GDT index of the LDT
         * is chosen to follow the index number in the task[] array.
         */
-       if (!mm->segments) {
-               for (i=1 ; i<NR_TASKS ; i++) {
-                       if (task[i] == current) {
-                               if (!(mm->segments = (void *) vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE)))
-                                       return -ENOMEM;
-                               memset(mm->segments, 0, LDT_ENTRIES*LDT_ENTRY_SIZE);
-                               set_ldt_desc(gdt+(i<<1)+FIRST_LDT_ENTRY, mm->segments, LDT_ENTRIES);
-                               load_ldt(i);
-                       }
+       ldt = mm->segments;
+       if (!ldt) {
+               error = -ENOMEM;
+               ldt = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE);
+               if (!ldt)
+                       goto out;
+               memset(ldt, 0, LDT_ENTRIES*LDT_ENTRY_SIZE);
+               /*
+                * Make sure someone else hasn't allocated it for us ...
+                */
+               if (!mm->segments) {
+                       int i = current->tarray_ptr - &task[0];
+                       mm->segments = ldt;
+                       set_ldt_desc(gdt+(i<<1)+FIRST_LDT_ENTRY, ldt, LDT_ENTRIES);
+                       load_ldt(i);
+                       if (mm->count > 1)
+                               printk(KERN_WARNING
+                                       "LDT allocated for cloned task!\n");
+               } else {
+                       vfree(ldt);
                }
        }
-       
-       lp = (unsigned long *) (LDT_ENTRY_SIZE * ldt_info.entry_number + (unsigned long) mm->segments);
+
+       /*
+        * Check whether the entry to be changed is currently in use.
+        * If it is, we may need extra validation checks in case the
+        * kernel is forced to save and restore the selector.
+        *
+        * Note: we check the fs and gs values as well, as these are
+        * loaded by the signal code and during a task switch.
+        */
+       selector = (ldt_info.entry_number << 3) | 4;
+       __asm__("movw %%fs,%0" : "=r"(reg_fs));
+       __asm__("movw %%gs,%0" : "=r"(reg_gs));
+
+       lp = (__u32 *) ((selector & ~7) + (char *) ldt);
+
        /* Allow LDTs to be cleared by the user. */
-       if (ldt_info.base_addr == 0 && ldt_info.limit == 0
-               && (oldmode ||
-                       (  ldt_info.contents == 0
-                       && ldt_info.read_exec_only == 1
-                       && ldt_info.seg_32bit == 0
-                       && ldt_info.limit_in_pages == 0
-                       && ldt_info.seg_not_present == 1
-                       && ldt_info.useable == 0 )) ) {
-               *lp = 0;
-               *(lp+1) = 0;
-               return 0;
+       if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
+               if (oldmode ||
+                   (ldt_info.contents == 0             &&
+                    ldt_info.read_exec_only == 1       &&
+                    ldt_info.seg_32bit == 0            &&
+                    ldt_info.limit_in_pages == 0       &&
+                    ldt_info.seg_not_present == 1      &&
+                    ldt_info.useable == 0 )) {
+                       entry_1 = 0;
+                       entry_2 = 0;
+                       goto out_check;
+               }
        }
-       *lp = ((ldt_info.base_addr & 0x0000ffff) << 16) |
+
+       entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
                  (ldt_info.limit & 0x0ffff);
-       *(lp+1) = (ldt_info.base_addr & 0xff000000) |
-                 ((ldt_info.base_addr & 0x00ff0000)>>16) |
+       entry_2 = (ldt_info.base_addr & 0xff000000) |
+                 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
                  (ldt_info.limit & 0xf0000) |
-                 (ldt_info.contents << 10) |
                  ((ldt_info.read_exec_only ^ 1) << 9) |
+                 (ldt_info.contents << 10) |
+                 ((ldt_info.seg_not_present ^ 1) << 15) |
                  (ldt_info.seg_32bit << 22) |
                  (ldt_info.limit_in_pages << 23) |
-                 ((ldt_info.seg_not_present ^1) << 15) |
                  0x7000;
-       if (!oldmode) *(lp+1) |= (ldt_info.useable << 20);
-       return 0;
+       if (!oldmode)
+               entry_2 |= (ldt_info.useable << 20);
+
+out_check:
+       /* OK to change the entry ...  */
+       *lp     = entry_1;
+       *(lp+1) = entry_2;
+       error = 0;
+out:
+       return error;
 }
 
 asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
 {
-       int ret;
+       int ret = -ENOSYS;
 
        lock_kernel();
-       if (func == 0)
+       switch (func) {
+       case 0:
                ret = read_ldt(ptr, bytecount);
-       else if (func == 1)
+               break;
+       case 1:
                ret = write_ldt(ptr, bytecount, 1);
-       else  if (func == 0x11)
+               break;
+       case 0x11:
                ret = write_ldt(ptr, bytecount, 0);
-       else
-               ret = -ENOSYS;
+               break;
+       }
        unlock_kernel();
        return ret;
 }
index e1433b78c514fb9a56e1497ee8e2bdb6058c8671..966df61758b957aa908765911ec2cba156901ce8 100644 (file)
 
 spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
 
-struct task_struct *last_task_used_math = NULL;
-
 #ifdef __SMP__
-asmlinkage void ret_from_smpfork(void) __asm__("ret_from_smpfork");
+asmlinkage void ret_from_fork(void) __asm__("ret_from_smpfork");
 #else
-asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
+asmlinkage void ret_from_fork(void) __asm__("ret_from_sys_call");
 #endif
 
 #ifdef CONFIG_APM
@@ -427,15 +425,20 @@ void show_regs(struct pt_regs * regs)
 
 void release_segments(struct mm_struct *mm)
 {
-       void * ldt;
+       void * ldt = mm->segments;
+       int nr;
 
        /* forget local segments */
        __asm__ __volatile__("movl %w0,%%fs ; movl %w0,%%gs ; lldt %w0"
                : /* no outputs */
                : "r" (0));
        current->tss.ldt = 0;
+       /*
+        * Set the GDT entry back to the default.
+        */
+       nr = current->tarray_ptr - &task[0];
+       set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY, &default_ldt, 1);
 
-       ldt = mm->segments;
        if (ldt) {
                mm->segments = NULL;
                vfree(ldt);
@@ -447,9 +450,7 @@ void release_segments(struct mm_struct *mm)
  */
 void exit_thread(void)
 {
-       /* forget lazy i387 state */
-       if (last_task_used_math == current)
-               last_task_used_math = NULL;
+       /* nothing to do ... */
 }
 
 void flush_thread(void)
@@ -462,71 +463,103 @@ void flush_thread(void)
        /*
         * Forget coprocessor state..
         */
-#ifdef __SMP__
        if (current->flags & PF_USEDFPU) {
+               current->flags &= ~PF_USEDFPU;
                stts();
        }
-#else
-       if (last_task_used_math == current) {
-               last_task_used_math = NULL;
-               stts();
-       }
-#endif
        current->used_math = 0;
-       current->flags &= ~PF_USEDFPU;
 }
 
 void release_thread(struct task_struct *dead_task)
 {
 }
 
+static inline void unlazy_fpu(struct task_struct *tsk)
+{
+       if (tsk->flags & PF_USEDFPU) {
+               tsk->flags &= ~PF_USEDFPU;
+               __asm__("fnsave %0":"=m" (tsk->tss.i387));
+               stts();
+       }
+}
+
+/*
+ * If new_mm is NULL, we're being called to set up the LDT descriptor
+ * for a clone task. Each clone must have a separate entry in the GDT.
+ */
 void copy_segments(int nr, struct task_struct *p, struct mm_struct *new_mm)
 {
-       int ldt_size = 1;
-       void * ldt = &default_ldt;
        struct mm_struct * old_mm = current->mm;
+       void * old_ldt = old_mm->segments, * ldt = old_ldt;
+       int ldt_size = LDT_ENTRIES;
 
        p->tss.ldt = _LDT(nr);
-       if (old_mm->segments) {
-               new_mm->segments = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE);
-               if (new_mm->segments) {
-                       ldt = new_mm->segments;
-                       ldt_size = LDT_ENTRIES;
-                       memcpy(ldt, old_mm->segments, LDT_ENTRIES*LDT_ENTRY_SIZE);
+       if (old_ldt) {
+               if (new_mm) {
+                       ldt = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE);
+                       new_mm->segments = ldt;
+                       if (!ldt) {
+                               printk(KERN_WARNING "ldt allocation failed\n");
+                               goto no_ldt;
+                       }
+                       memcpy(ldt, old_ldt, LDT_ENTRIES*LDT_ENTRY_SIZE);
                }
+       } else {
+       no_ldt:
+               ldt = &default_ldt;
+               ldt_size = 1;
        }
        set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY, ldt, ldt_size);
 }
 
+/*
+ * Save a segment.
+ */
+#define savesegment(seg,value) \
+       asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
+
+/*
+ * Load a segment. Fall back on loading the zero
+ * segment if something goes wrong..
+ */
+#define loadsegment(seg,value)                 \
+       asm volatile("\n"                       \
+               "1:\t"                          \
+               "movl %0,%%" #seg "\n"          \
+               "2:\n"                          \
+               ".section fixup,\"ax\"\n"       \
+               "3:\t"                          \
+               "pushl $0\n\t"                  \
+               "popl %%" #seg "\n\t"           \
+               "jmp 2b\n"                      \
+               ".previous\n"                   \
+               ".section __ex_table,\"a\"\n\t" \
+               ".align 4\n\t"                  \
+               ".long 1b,3b\n"                 \
+               ".previous"                     \
+               : :"m" (*(unsigned int *)&(value)))
+
 int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
        struct task_struct * p, struct pt_regs * regs)
 {
        struct pt_regs * childregs;
 
        p->tss.tr = _TSS(nr);
-       p->tss.es = __KERNEL_DS;
-       p->tss.cs = __KERNEL_CS;
-       p->tss.ss = __KERNEL_DS;
-       p->tss.ds = __KERNEL_DS;
-       p->tss.fs = __USER_DS;
-       p->tss.gs = __USER_DS;
+       set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
        p->tss.ss0 = __KERNEL_DS;
        p->tss.esp0 = 2*PAGE_SIZE + (unsigned long) p;
+
        childregs = ((struct pt_regs *) (p->tss.esp0)) - 1;
-       p->tss.esp = (unsigned long) childregs;
-#ifdef __SMP__
-       p->tss.eip = (unsigned long) ret_from_smpfork;
-       p->tss.eflags = regs->eflags & 0xffffcdff;  /* iopl always 0 for a new process */
-#else
-       p->tss.eip = (unsigned long) ret_from_sys_call;
-       p->tss.eflags = regs->eflags & 0xffffcfff;  /* iopl always 0 for a new process */
-#endif
-       p->tss.ebx = (unsigned long) p;
        *childregs = *regs;
        childregs->eax = 0;
        childregs->esp = esp;
-       p->tss.back_link = 0;
-       set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
+       childregs->eflags = regs->eflags & 0xffffcfff;  /* iopl always 0 for a new process */
+
+       p->tss.esp = (unsigned long) childregs;
+       p->tss.eip = (unsigned long) ret_from_fork;
+
+       savesegment(fs,p->tss.fs);
+       savesegment(gs,p->tss.gs);
 
        /*
         * a bitmap offset pointing outside of the TSS limit causes a nicely
@@ -535,12 +568,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
         */
        p->tss.bitmap = sizeof(struct thread_struct);
 
-#ifdef __SMP__
-       if (current->flags & PF_USEDFPU)
-#else
-       if (last_task_used_math == current)
-#endif
-               __asm__("clts ; fnsave %0 ; frstor %0":"=m" (p->tss.i387));
+       unlazy_fpu(current);
+       asm volatile("fwait");
+       p->tss.i387 = current->tss.i387;
 
        return 0;
 }
@@ -552,16 +582,11 @@ int dump_fpu (struct pt_regs * regs, struct user_i387_struct* fpu)
 {
        int fpvalid;
 
-       if ((fpvalid = current->used_math) != 0) {
-               if (boot_cpu_data.hard_math) {
-                       if (last_task_used_math == current) {
-                               __asm__("clts ; fsave %0; fwait": :"m" (*fpu));
-                       }
-                       else
-                               memcpy(fpu,&current->tss.i387.hard,sizeof(*fpu));
-               } else {
-                       memcpy(fpu,&current->tss.i387.hard,sizeof(*fpu));
-               }
+       fpvalid = current->used_math;
+       if (fpvalid) {
+               unlazy_fpu(current);
+               asm volatile("fwait");
+               memcpy(fpu,&current->tss.i387.hard,sizeof(*fpu));
        }
 
        return fpvalid;
@@ -597,8 +622,8 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
        dump->regs.eax = regs->eax;
        dump->regs.ds = regs->xds;
        dump->regs.es = regs->xes;
-       __asm__("movl %%fs,%0":"=r" (dump->regs.fs));
-       __asm__("movl %%gs,%0":"=r" (dump->regs.gs));
+       savesegment(fs,dump->regs.fs);
+       savesegment(gs,dump->regs.gs);
        dump->regs.orig_eax = regs->orig_eax;
        dump->regs.eip = regs->eip;
        dump->regs.cs = regs->xcs;
@@ -609,6 +634,89 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
        dump->u_fpvalid = dump_fpu (regs, &dump->i387);
 }
 
+/*
+ * This special macro can be used to load a debugging register
+ */
+#define loaddebug(tsk,register) \
+               __asm__("movl %0,%%db" #register  \
+                       : /* no output */ \
+                       :"r" (tsk->debugreg[register]))
+
+
+/*
+ *     switch_to(x,yn) should switch tasks from x to y.
+ *
+ * We fsave/fwait so that an exception goes off at the right time
+ * (as a call from the fsave or fwait in effect) rather than to
+ * the wrong process. Lazy FP saving no longer makes any sense
+ * with modern CPU's, and this simplifies a lot of things (SMP
+ * and UP become the same).
+ *
+ * NOTE! We used to use the x86 hardware context switching. The
+ * reason for not using it any more becomes apparent when you
+ * try to recover gracefully from saved state that is no longer
+ * valid (stale segment register values in particular). With the
+ * hardware task-switch, there is no way to fix up bad state in
+ * a reasonable manner.
+ *
+ * The fact that Intel documents the hardware task-switching to
+ * be slow is a fairly red herring - this code is not noticeably
+ * faster. However, there _is_ some room for improvement here,
+ * so the performance issues may eventually be a valid point.
+ * More important, however, is the fact that this allows us much
+ * more flexibility.
+ */
+void __switch_to(struct task_struct *prev, struct task_struct *next)
+{
+       /* Do the FPU save and set TS if it wasn't set before.. */
+       unlazy_fpu(prev);
+
+       /*
+        * Reload TR, LDT and the page table pointers..
+        *
+        * We need TR for the IO permission bitmask (and
+        * the vm86 bitmasks in case we ever use enhanced
+        * v86 mode properly).
+        *
+        * We could do LDT things lazily if this turns out
+        * to be a win. Most processes will have the default
+        * LDT.
+        *
+        * We want to get rid of the TR register some day,
+        * and copy the bitmaps around by hand. Oh, well.
+        * In the meantime we have to clear the busy bit
+        * in the TSS entry, ugh.
+        */
+       gdt_table[next->tss.tr >> 3].b &= 0xfffffdff;
+       asm volatile("ltr %0": :"g" (*(unsigned short *)&next->tss.tr));
+       asm volatile("lldt %0": :"g" (*(unsigned short *)&next->tss.ldt));
+       if (next->tss.cr3 != prev->tss.cr3)
+               asm volatile("movl %0,%%cr3": :"r" (next->tss.cr3));
+
+       /*
+        * Save away %fs and %gs. No need to save %es and %ds, as
+        * those are always kernel segments while inside the kernel.
+        * Restore the new values.
+        */
+       asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->tss.fs));
+       asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->tss.gs));
+
+       loadsegment(fs,next->tss.fs);
+       loadsegment(gs,next->tss.gs);
+
+       /*
+        * Now maybe reload the debug registers
+        */
+       if (next->debugreg[7]){
+               loaddebug(next,0);
+               loaddebug(next,1);
+               loaddebug(next,2);
+               loaddebug(next,3);
+               loaddebug(next,6);
+               loaddebug(next,7);
+       }
+}
+
 asmlinkage int sys_fork(struct pt_regs regs)
 {
        int ret;
index 294043faf33b886ffe6aaeedb18dfc4b5a399a44..446816d043fc989b3e2c42b484ebe0f624c9ca10 100644 (file)
@@ -624,14 +624,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 #ifdef CONFIG_MATH_EMULATION
                        if ( boot_cpu_data.hard_math ) {
 #endif
-                         if (last_task_used_math == child) {
-                           clts();
-                           __asm__("fnsave %0; fwait":"=m" (child->tss.i387.hard));
-                           last_task_used_math = NULL;
-                           stts();
-                         }
-                         __copy_to_user((void *)data, &child->tss.i387.hard,
-                                        sizeof(struct user_i387_struct));
+                               __copy_to_user((void *)data, &child->tss.i387.hard,
+                                               sizeof(struct user_i387_struct));
 #ifdef CONFIG_MATH_EMULATION
                        } else {
                          save_i387_soft(&child->tss.i387.soft,
@@ -652,13 +646,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 #ifdef CONFIG_MATH_EMULATION
                        if ( boot_cpu_data.hard_math ) {
 #endif
-                         if (last_task_used_math == child) {
-                           /* Discard the state of the FPU */
-                           last_task_used_math = NULL;
-                         }
                          __copy_from_user(&child->tss.i387.hard, (void *)data,
                                           sizeof(struct user_i387_struct));
                          child->flags &= ~PF_USEDFPU;
+                         stts();
 #ifdef CONFIG_MATH_EMULATION
                        } else {
                          restore_i387_soft(&child->tss.i387.soft,
index 8432a45fefe1cfb45bc25f9735c227a2fba59694..08462e328129fd721bd07ea2268ff9d2f90bd38e 100644 (file)
@@ -153,17 +153,10 @@ struct rt_sigframe
 
 static inline int restore_i387_hard(struct _fpstate *buf)
 {
-#ifdef __SMP__
        if (current->flags & PF_USEDFPU) {
+               current->flags &= ~PF_USEDFPU;
                stts();
        }
-#else
-       if (current == last_task_used_math) {
-               last_task_used_math = NULL;
-               stts();
-       }
-#endif
-       current->flags &= ~PF_USEDFPU;
        return __copy_from_user(&current->tss.i387.hard, buf, sizeof(*buf));
 }
 
@@ -315,20 +308,12 @@ badframe:
 
 static inline int save_i387_hard(struct _fpstate * buf)
 {
-#ifdef __SMP__
        if (current->flags & PF_USEDFPU) {
-               __asm__ __volatile__("fnsave %0":"=m"(current->tss.i387.hard));
-               stts();
                current->flags &= ~PF_USEDFPU;
-       }
-#else
-       if (current == last_task_used_math) {
                __asm__ __volatile__("fnsave %0":"=m"(current->tss.i387.hard));
-               last_task_used_math = NULL;
-               __asm__ __volatile__("fwait");  /* not needed on 486+ */
                stts();
        }
-#endif
+       asm volatile("fwait");
        current->tss.i387.hard.status = current->tss.i387.hard.swd;
        if (__copy_to_user(buf, &current->tss.i387.hard, sizeof(*buf)))
                return -1;
index 0f17f98acf1b3d19394cdf03a96671725b9613c6..faed1755d25d2de489073e1fd28620e27039a568 100644 (file)
@@ -66,23 +66,6 @@ out: \
        unlock_kernel(); \
 }
 
-#define get_seg_byte(seg,addr) ({ \
-register unsigned char __res; \
-__asm__("pushl %%fs;movl %%ax,%%fs;movb %%fs:%2,%%al;popl %%fs" \
-       :"=a" (__res):"0" (seg),"m" (*(addr))); \
-__res;})
-
-#define get_seg_long(seg,addr) ({ \
-register unsigned long __res; \
-__asm__("pushl %%fs;movl %%ax,%%fs;movl %%fs:%2,%%eax;popl %%fs" \
-       :"=a" (__res):"0" (seg),"m" (*(addr))); \
-__res;})
-
-#define _fs() ({ \
-register unsigned short __res; \
-__asm__("movl %%fs,%%ax":"=a" (__res):); \
-__res;})
-
 void page_exception(void);
 
 asmlinkage void divide_error(void);
@@ -118,6 +101,7 @@ int kstack_depth_to_print = 24;
 static void show_registers(struct pt_regs *regs)
 {
        int i;
+       int in_kernel = 1;
        unsigned long esp;
        unsigned short ss;
        unsigned long *stack, addr, module_start, module_end;
@@ -126,6 +110,7 @@ static void show_registers(struct pt_regs *regs)
        esp = (unsigned long) &regs->esp;
        ss = __KERNEL_DS;
        if (regs->xcs & 3) {
+               in_kernel = 0;
                esp = regs->esp;
                ss = regs->xss & 0xffff;
        }
@@ -138,53 +123,59 @@ static void show_registers(struct pt_regs *regs)
        printk("ds: %04x   es: %04x   ss: %04x\n",
                regs->xds & 0xffff, regs->xes & 0xffff, ss);
        store_TR(i);
-       printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)\nStack: ",
+       printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)",
                current->comm, current->pid, 0xffff & i, 4096+(unsigned long)current);
-       stack = (unsigned long *) esp;
-       for(i=0; i < kstack_depth_to_print; i++) {
-               if (((long) stack & 4095) == 0)
-                       break;
-               if (i && ((i % 8) == 0))
-                       printk("\n       ");
-               printk("%08lx ", get_seg_long(ss,stack++));
-       }
-       printk("\nCall Trace: ");
-       stack = (unsigned long *) esp;
-       i = 1;
-       module_start = PAGE_OFFSET + (max_mapnr << PAGE_SHIFT);
-       module_start = ((module_start + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1));
-       module_end = module_start + MODULE_RANGE;
-       while (((long) stack & 4095) != 0) {
-               addr = get_seg_long(ss, stack++);
-               /*
-                * If the address is either in the text segment of the
-                * kernel, or in the region which contains vmalloc'ed
-                * memory, it *may* be the address of a calling
-                * routine; if so, print it so that someone tracing
-                * down the cause of the crash will be able to figure
-                * out the call path that was taken.
-                */
-               if (((addr >= (unsigned long) &_stext) &&
-                    (addr <= (unsigned long) &_etext)) ||
-                   ((addr >= module_start) && (addr <= module_end))) {
+
+       /*
+        * When in-kernel, we also print out the stack and code at the
+        * time of the fault..
+        */
+       if (in_kernel) {
+               printk("\nStack: ");
+               stack = (unsigned long *) esp;
+               for(i=0; i < kstack_depth_to_print; i++) {
+                       if (((long) stack & 4095) == 0)
+                               break;
                        if (i && ((i % 8) == 0))
                                printk("\n       ");
-                       printk("[<%08lx>] ", addr);
-                       i++;
+                       printk("%08lx ", *stack++);
                }
+               printk("\nCall Trace: ");
+               stack = (unsigned long *) esp;
+               i = 1;
+               module_start = PAGE_OFFSET + (max_mapnr << PAGE_SHIFT);
+               module_start = ((module_start + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1));
+               module_end = module_start + MODULE_RANGE;
+               while (((long) stack & 4095) != 0) {
+                       addr = *stack++;
+                       /*
+                        * If the address is either in the text segment of the
+                        * kernel, or in the region which contains vmalloc'ed
+                        * memory, it *may* be the address of a calling
+                        * routine; if so, print it so that someone tracing
+                        * down the cause of the crash will be able to figure
+                        * out the call path that was taken.
+                        */
+                       if (((addr >= (unsigned long) &_stext) &&
+                            (addr <= (unsigned long) &_etext)) ||
+                           ((addr >= module_start) && (addr <= module_end))) {
+                               if (i && ((i % 8) == 0))
+                                       printk("\n       ");
+                               printk("[<%08lx>] ", addr);
+                               i++;
+                       }
+               }
+               printk("\nCode: ");
+               for(i=0;i<20;i++)
+                       printk("%02x ", ((unsigned char *)regs->eip)[i]);
+               printk("\n");
        }
-       printk("\nCode: ");
-       for(i=0;i<20;i++)
-               printk("%02x ",0xff & get_seg_byte(regs->xcs & 0xffff,(i+(char *)regs->eip)));
-       printk("\n");
 }      
 
 spinlock_t die_lock;
 
-void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+void die(const char * str, struct pt_regs * regs, long err)
 {
-       if ((regs->eflags & VM_MASK) || (3 & regs->xcs) == 3)
-               return;
        console_verbose();
        spin_lock_irq(&die_lock);
        printk("%s: %04lx\n", str, err & 0xffff);
@@ -193,6 +184,12 @@ void die_if_kernel(const char * str, struct pt_regs * regs, long err)
        do_exit(SIGSEGV);
 }
 
+static void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+{
+       if (!(regs->eflags & VM_MASK) && !(3 & regs->xcs))
+               die(str, regs, err);
+}
+
 DO_VM86_ERROR( 0, SIGFPE,  "divide error", divide_error, current)
 DO_VM86_ERROR( 3, SIGTRAP, "int3", int3, current)
 DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow, current)
@@ -200,7 +197,7 @@ DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds, current)
 DO_ERROR( 6, SIGILL,  "invalid operand", invalid_op, current)
 DO_VM86_ERROR( 7, SIGSEGV, "device not available", device_not_available, current)
 DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current)
-DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun, last_task_used_math)
+DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun, current)
 DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current)
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present, current)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment, current)
@@ -224,17 +221,34 @@ asmlinkage void cache_flush_denied(struct pt_regs * regs, long error_code)
 
 asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
 {
+       if (regs->eflags & VM_MASK)
+               goto gp_in_vm86;
+
+       if (!(regs->xcs & 3))
+               goto gp_in_kernel;
+
        lock_kernel();
-       if (regs->eflags & VM_MASK) {
-               handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
-               goto out;
-       }
-       die_if_kernel("general protection",regs,error_code);
        current->tss.error_code = error_code;
        current->tss.trap_no = 13;
        force_sig(SIGSEGV, current);    
-out:
+       return;
+
+gp_in_vm86:
+       lock_kernel();
+       handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
        unlock_kernel();
+       return;
+
+gp_in_kernel:
+       {
+               unsigned long fixup;
+               fixup = search_exception_table(regs->eip);
+               if (fixup) {
+                       regs->eip = fixup;
+                       return;
+               }
+               die("general protection fault", regs, error_code);
+       }
 }
 
 static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
@@ -295,9 +309,7 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
                __asm__("movl %0,%%db7"
                        : /* no output */
                        : "r" (0));
-               goto out;
        }
-       die_if_kernel("debug",regs,error_code);
 out:
        unlock_kernel();
 }
@@ -313,16 +325,7 @@ void math_error(void)
 
        lock_kernel();
        clts();
-#ifdef __SMP__
        task = current;
-#else
-       task = last_task_used_math;
-       last_task_used_math = NULL;
-       if (!task) {
-               __asm__("fnclex");
-               goto out;
-       }
-#endif
        /*
         *      Save the info for the exception handler
         */
@@ -333,9 +336,6 @@ void math_error(void)
        force_sig(SIGFPE, task);
        task->tss.trap_no = 16;
        task->tss.error_code = 0;
-#ifndef __SMP__
-out:
-#endif
        unlock_kernel();
 }
 
@@ -373,15 +373,6 @@ asmlinkage void math_state_restore(void)
  *     case we swap processors. We also don't use the coprocessor
  *     timer - IRQ 13 mode isn't used with SMP machines (thank god).
  */
-#ifndef __SMP__
-       if (last_task_used_math == current)
-               return;
-       if (last_task_used_math)
-               __asm__("fnsave %0":"=m" (last_task_used_math->tss.i387));
-       else
-               __asm__("fnclex");
-       last_task_used_math = current;
-#endif
 
        if(current->used_math)
                __asm__("frstor %0": :"m" (current->tss.i387));
index 30af71475d6671f275806f5fdd0a80c9968abfed..6995bb35cee195610abb5a349a6825c19e02d54c 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/pgtable.h>
 #include <asm/hardirq.h>
 
-extern void die_if_kernel(const char *,struct pt_regs *,long);
+extern void die(const char *,struct pt_regs *,long);
 
 /*
  * Ugly, ugly, but the goto's result in better assembly..
@@ -101,7 +101,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
        __asm__("movl %%cr2,%0":"=r" (address));
 
        if (local_irq_count[smp_processor_id()])
-               die_if_kernel("page fault from irq handler",regs,error_code);
+               die("page fault from irq handler",regs,error_code);
        tsk = current;
        mm = tsk->mm;
 
@@ -235,7 +235,7 @@ bad_area:
                printk(KERN_ALERT "*pte = %08lx\n", page);
        }
        lock_kernel();
-       die_if_kernel("Oops", regs, error_code);
+       die("Oops", regs, error_code);
        do_exit(SIGKILL);
        unlock_kernel();
 }
index ba36ad0025a31a88b59d1f822ad88da907d6765f..45d159bb035c4f5b55ab02923141ced0e85fb66a 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 
-extern void die_if_kernel(char *,struct pt_regs *,long);
 extern void show_net_buffers(void);
 
 void __bad_pte_kernel(pmd_t *pmd)
index e326b968724bc900760322f62b166dfdbc31e209..c62300923b7ee650f6709f52168ae84436995164 100644 (file)
@@ -2316,7 +2316,6 @@ __initfunc(unsigned long con_init(unsigned long kmem_start))
 {
        const char *display_desc = NULL;
        unsigned int currcons = 0;
-       char q[2] = { 0, 1 };
 
        if (conswitchp)
                kmem_start = conswitchp->con_startup(kmem_start,
@@ -2397,11 +2396,15 @@ __initfunc(unsigned long con_init(unsigned long kmem_start))
 
 #if 0
 /* The logo is too ugly to live */
+{
+       char q[2] = { 0, 1 };
+
        if (console_show_logo)
            q[1] += console_show_logo();
        conswitchp->con_putcs(vc_cons[fg_console].d, linux_logo_banner,
                              sizeof(linux_logo_banner)-1, q[1]-1, q[0]);
        putconsxy(0, q);
+}
 #endif
        sw->con_cursor(vc_cons[currcons].d, CM_DRAW);
        printk("Console: %s %s %ldx%ld",
index c0b7a6942588cf8e18e6fbd5fe130c565c777466..dec9ac256056186d046a8fe0d086fabfdef419b1 100644 (file)
 
         insmod de4x5 args='eth1:fdx autosense=BNC eth0:autosense=100Mb'.
 
-    For a compiled in driver, somewhere in this file, place e.g.
+    For a compiled in driver, at or above line 548, place e.g.
        #define DE4X5_PARM "eth0:fdx autosense=AUI eth2:autosense=TP"
 
-    Yes,  I know full duplex  isn't permissible on BNC  or AUI; they're just
-    examples. By default, full duplex is turned  off and AUTO is the default
-    autosense setting. In  reality, I expect only the  full duplex option to
+    Yes,  I know full duplex isn't  permissible on BNC  or AUI; they're just
+    examples. By default, full duplex is turned off and  AUTO is the default
+    autosense setting.  In reality, I expect only  the full duplex option to
     be used. Note the use of single quotes in the two examples above and the
-    lack of commas to separate items.
+    lack of commas to separate items. ALSO, you must get the requested media
+    correct in relation to what the adapter SROM says it has. There's no way
+    to  determine this in  advance other than by  trial and error and common
+    sense, e.g. call a BNC connectored port 'BNC', not '10Mb'.
 
     TO DO:
     ------
       0.535  21-Feb-98    Fix Ethernet Address PROM reset bug for DC21040.
       0.536  21-Mar-98    Change pci_probe() to use the pci_dev structure.
                          **Incompatible with 2.0.x from here.**
+      0.540   5-Jul-98    Atomicize assertion of dev->interrupt for SMP
+                           from <lma@varesearch.com>
+                         Add TP, AUI and BNC cases to 21140m_autoconf() for
+                          case where a 21140 under SROM control uses, e.g. AUI
+                          from problem report by <delchini@lpnp09.in2p3.fr>
+                         Add MII parallel detection to 2114x_autoconf() for
+                          case where no autonegotiation partner exists from
+                          problem report by <mlapsley@ndirect.co.uk>.
+                         Add ability to force connection type directly even
+                          when using SROM control from problem report by
+                          <earl@exis.net>.
+                         Updated the PCI interface to conform with the latest
+                          version. I hope nothing is broken...
+                         Add TX done interrupt modification from suggestion
+                          by <Austin.Donnelly@cl.cam.ac.uk>.
+                         Fix is_anc_capable() bug reported by 
+                          <Austin.Donnelly@cl.cam.ac.uk>.
+                         Fix type[13]_infoblock() bug: during MII search, PHY
+                          lp->rst not run because lp->ibn not initialised -
+                          from report & fix by <paubert@iram.es>.
+                         Fix probe bug with EISA & PCI cards present from
+                           report by <eirik@netcom.com>.
 
     =========================================================================
 */
 
-static const char *version = "de4x5.c:V0.536 1998/3/5 davies@maniac.ultranet.com\n";
+static const char *version = "de4x5.c:V0.540 1998/7/5 davies@maniac.ultranet.com\n";
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -933,7 +958,7 @@ static int     test_bad_enet(struct device *dev, int status);
 static void    eisa_probe(struct device *dev, u_long iobase);
 #endif
 static void    pci_probe(struct device *dev, u_long iobase);
-static void    srom_search(int index);
+static void    srom_search(struct pci_dev *pdev);
 static char    *build_setup_frame(struct device *dev, int mode);
 static void    disable_ast(struct device *dev);
 static void    enable_ast(struct device *dev, u32 time_out);
@@ -980,12 +1005,12 @@ static int loading_module = 0;
 static char name[DE4X5_NAME_LENGTH + 1];
 #if !defined(__sparc_v9__) && !defined(__powerpc__)
 static u_char de4x5_irq[] = EISA_ALLOWED_IRQ_LIST;
+static int lastEISA = 0;
+#else
+static int lastEISA = MAX_EISA_SLOTS;           /* Only PCI probes */
 #endif
 static int num_de4x5s = 0;
 static int cfrv = 0, useSROM = 0;
-#if !defined(__sparc_v9__) && !defined(__powerpc__)
-static int lastEISA = 0;
-#endif
 static int lastPCI = -1;
 static struct device *lastModule = NULL;
 
@@ -1036,9 +1061,9 @@ static int (*dc_infoblock[])(struct device *dev, u_char, u_char *) = {
 
 #define PHY_HARD_RESET {\
     outl(GEP_HRST, DE4X5_GEP);           /* Hard RESET the PHY dev. */\
-    mdelay(1);                        /* Assert for 1ms */\
+    mdelay(1);                           /* Assert for 1ms */\
     outl(0x00, DE4X5_GEP);\
-    mdelay(2);                        /* Wait for 2ms */\
+    mdelay(2);                           /* Wait for 2ms */\
 }
 
 \f
@@ -1054,7 +1079,9 @@ de4x5_probe(struct device *dev))
 #if !defined(__sparc_v9__) && !defined(__powerpc__)
     eisa_probe(dev, iobase);
 #endif
-    pci_probe(dev, iobase);
+    if (lastEISA == MAX_EISA_SLOTS) {
+       pci_probe(dev, iobase);
+    }
     
     return (dev->priv ? 0 : -ENODEV);
 }
@@ -1151,21 +1178,15 @@ de4x5_hw_init(struct device *dev, u_long iobase))
        /*
        ** Choose correct autosensing in case someone messed up
        */
-       if ((lp->params.autosense & AUTO) || lp->useSROM) {
-           lp->autosense = AUTO;
-       } else {
-           if (lp->chipset != DC21140) {
-               if ((lp->chipset==DC21040) && (lp->params.autosense&TP_NW)) {
-                   lp->params.autosense = TP;
-               }
-               if ((lp->chipset==DC21041) && (lp->params.autosense&BNC_AUI)) {
-                   lp->params.autosense = BNC;
-               }
-               lp->autosense = lp->params.autosense & 0x001f;
-           } else {
-               lp->autosense = lp->params.autosense & 0x00c0;
-           }
-       }
+        lp->autosense = lp->params.autosense;
+        if (lp->chipset != DC21140) {
+            if ((lp->chipset==DC21040) && (lp->params.autosense&TP_NW)) {
+                lp->params.autosense = TP;
+            }
+            if ((lp->chipset==DC21041) && (lp->params.autosense&BNC_AUI)) {
+                lp->params.autosense = BNC;
+            }
+        }
        lp->fdx = lp->params.fdx;
        sprintf(lp->adapter_name,"%s (%s)", name, dev->name);
        
@@ -1308,8 +1329,9 @@ de4x5_open(struct device *dev)
     
     lp->state = OPEN;
     de4x5_dbg_open(dev);
+    
     if (request_irq(dev->irq, (void *)de4x5_interrupt, SA_SHIRQ, 
-           lp->adapter_name, dev)) {
+                                                    lp->adapter_name, dev)) {
        printk("de4x5_open(): Requested IRQ%d is busy - attemping FAST/SHARE...", dev->irq);
        if (request_irq(dev->irq, de4x5_interrupt, SA_INTERRUPT | SA_SHIRQ,
                                                     lp->adapter_name, dev)) {
@@ -1448,7 +1470,7 @@ de4x5_sw_reset(struct device *dev)
 }
 
 /* 
-** Writes a socket buffer address to the next available transmit descriptor
+** Writes a socket buffer address to the next available transmit descriptor.
 */
 static int
 de4x5_queue_pkt(struct sk_buff *skb, struct device *dev)
@@ -1542,12 +1564,11 @@ de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     lp = (struct de4x5_private *)dev->priv;
     iobase = dev->base_addr;
        
-    if (dev->interrupt)
-      printk("%s: Re-entering the interrupt handler.\n", dev->name);
+    if (test_and_set_bit(MASK_INTERRUPTS, (void*) &dev->interrupt))
+       printk("%s: Re-entering the interrupt handler.\n", dev->name);
        
     DISABLE_IRQs;                        /* Ensure non re-entrancy */
     synchronize_irq();
-    dev->interrupt = MASK_INTERRUPTS;
        
     for (limit=0; limit<8; limit++) {
        sts = inl(DE4X5_STS);            /* Read IRQ status */
@@ -1868,16 +1889,27 @@ de4x5_local_stats(struct device *dev, char *buf, int pkt_len)
     return;
 }
 
+/*
+** Removes the TD_IC flag from previous descriptor to improve TX performance.
+** If the flag is changed on a descriptor that is being read by the hardware,
+** I assume PCI transaction ordering will mean you are either successful or
+** just miss asserting the change to the hardware. Anyway you're messing with
+** a descriptor you don't own, but this shouldn't kill the chip provided
+** the descriptor register is read only to the hardware.
+*/
 static void
 load_packet(struct device *dev, char *buf, u32 flags, struct sk_buff *skb)
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
-    
+    int entry = (lp->tx_new ? lp->tx_new-1 : lp->txRingSize-1);
+
     lp->tx_ring[lp->tx_new].buf = cpu_to_le32(virt_to_bus(buf));
     lp->tx_ring[lp->tx_new].des1 &= cpu_to_le32(TD_TER);
     lp->tx_ring[lp->tx_new].des1 |= cpu_to_le32(flags);
     lp->tx_skb[lp->tx_new] = skb;
+    lp->tx_ring[entry].des1 &= cpu_to_le32(~TD_IC);
     barrier();
+
     lp->tx_ring[lp->tx_new].status = cpu_to_le32(T_OWN);
     barrier();
     
@@ -2044,7 +2076,7 @@ eisa_probe(struct device *dev, u_long ioaddr))
 
     return;
 }
-#endif                         /* !(__sparc_v9__) */
+#endif                         /* !(__sparc_v9__) && !(__powerpc__) */
 
 /*
 ** PCI bus I/O device probe
@@ -2057,22 +2089,25 @@ eisa_probe(struct device *dev, u_long ioaddr))
 ** bit. Here, check for I/O accesses and then set BM. If you put the card in
 ** a non BM slot, you're on your own (and complain to the PC vendor that your
 ** PC doesn't conform to the PCI standard)!
+**
+** This function is only compatible with the *latest* 2.1.x kernels. For 2.0.x
+** kernels use the V0.535[n] drivers.
 */
-#define PCI_DEVICE    (dev_num << 3)
 #define PCI_LAST_DEV  32
 
 __initfunc(static void
 pci_probe(struct device *dev, u_long ioaddr))
 {
-    u_char pb, pbus, dev_num, dnum, dev_fn, timer;
-    u_short dev_id, vendor, index, status;
+    u_char pb, pbus, dev_num, dnum, timer;
+    u_short vendor, index, status;
     u_int irq = 0, device, class = DE4X5_CLASS_CODE;
     u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
     struct bus_type *lp = &bus;
+    struct pci_dev *pdev = NULL;
 
     if (lastPCI == NO_MORE_PCI) return;
 
-    if (!pci_present()) {
+    if (!pcibios_present()) {
        lastPCI = NO_MORE_PCI;
        return;          /* No PCI bus in this machine! */
     }
@@ -2088,96 +2123,77 @@ pci_probe(struct device *dev, u_long ioaddr))
        dnum = 0;
     }
 
-    for (index=lastPCI+1; 
-        (pcibios_find_class(class, index, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND);
-        index++) {
-       dev_num = PCI_SLOT(dev_fn);
-       if ((!pbus && !dnum) || ((pbus == pb) && (dnum == dev_num))) {
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,85)
-           struct pci_dev *pdev = pci_find_slot(pb, dev_fn);
-#else
-           u_char tirq;
-           u_int tmp;
-#endif
-           device = 0;
-           pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor);
-           pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id);
-           device = dev_id;
-           device <<= 8;
-           if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) {
-               continue;
-           }
-
-           /* Search for an SROM on this bus */
-           if (lp->bus_num != pb) {
-               lp->bus_num = pb;
-               srom_search(index);
-           }
+    for (index=lastPCI+1; (pdev=pci_find_class(class, pdev))!=NULL; index++) {
+       dev_num = PCI_SLOT(pdev->devfn);
+       pb = pdev->bus->number;
+       if ((pbus || dnum) && ((pbus != pb) || (dnum != dev_num))) continue;
 
-           /* Get the chip configuration revision register */
-           pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv);
+       vendor = pdev->vendor;
+       device = pdev->device << 8;
+       if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue;
 
-           /* Set the device number information */
-           lp->device = dev_num;
+       /* Search for an SROM on this bus */
+       if (lp->bus_num != pb) {
            lp->bus_num = pb;
-           
-           /* Set the chipset information */
-           if (is_DC2114x) device |= (cfrv & CFRV_RN);
-           lp->chipset = device;
+           srom_search(pdev);
+       }
 
-           /* Get the board I/O address and IRQ */
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,85)
-           pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp);
-           iobase = tmp;
-           pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq);
-           irq = tirq;
-#else
-           iobase = pdev->base_address[0];
-           irq = pdev->irq;
-#endif
-           iobase &= CBIO_MASK;
+       /* Get the chip configuration revision register */
+       pcibios_read_config_dword(pb, pdev->devfn, PCI_REVISION_ID, &cfrv);
+
+       /* Set the device number information */
+       lp->device = dev_num;
+       lp->bus_num = pb;
+           
+       /* Set the chipset information */
+       if (is_DC2114x) device |= (cfrv & CFRV_RN);
+       lp->chipset = device;
 
-           if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
+       /* Get the board I/O address (64 bits on sparc64) */
+       iobase = pdev->base_address[0] & CBIO_MASK;
 
-           /* Check if I/O accesses and Bus Mastering are enabled */
-           pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
+       /* Fetch the IRQ to be used */
+       irq = pdev->irq;
+       if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
+           
+       /* Check if I/O accesses and Bus Mastering are enabled */
+       pcibios_read_config_word(pb, pdev->devfn, PCI_COMMAND, &status);
 #ifdef __powerpc__
-           if (!(status & PCI_COMMAND_IO)) {
-               status |= PCI_COMMAND_IO;
-               pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
-               pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
-           }
+       if (!(status & PCI_COMMAND_IO)) {
+           status |= PCI_COMMAND_IO;
+           pcibios_write_config_word(pb, pdev->devfn, PCI_COMMAND, status);
+           pcibios_read_config_word(pb, pdev->devfn, PCI_COMMAND, &status);
+       }
 #endif /* __powerpc__ */
-           if (!(status & PCI_COMMAND_IO)) continue;
+       if (!(status & PCI_COMMAND_IO)) continue;
 
-           if (!(status & PCI_COMMAND_MASTER)) {
-               status |= PCI_COMMAND_MASTER;
-               pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
-               pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
-           }
-           if (!(status & PCI_COMMAND_MASTER)) continue;
+       if (!(status & PCI_COMMAND_MASTER)) {
+           status |= PCI_COMMAND_MASTER;
+           pcibios_write_config_word(pb, pdev->devfn, PCI_COMMAND, status);
+           pcibios_read_config_word(pb, pdev->devfn, PCI_COMMAND, &status);
+       }
+       if (!(status & PCI_COMMAND_MASTER)) continue;
 
-           /* Check the latency timer for values >= 0x60 */
-           pcibios_read_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, &timer);
-           if (timer < 0x60) {
-               pcibios_write_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, 0x60);
-           }
+       /* Check the latency timer for values >= 0x60 */
+       pcibios_read_config_byte(pb, pdev->devfn, PCI_LATENCY_TIMER, &timer);
+       if (timer < 0x60) {
+           pcibios_write_config_byte(pb, pdev->devfn, PCI_LATENCY_TIMER, 0x60);
+       }
 
-           DevicePresent(DE4X5_APROM);
-           if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) {
-               dev->irq = irq;
-               if ((status = de4x5_hw_init(dev, iobase)) == 0) {
-                   num_de4x5s++;
-                   if (loading_module) {
-                       link_modules(lastModule, dev);
-                       lastPCI = index;
-                   }
-                   return;
+       DevicePresent(DE4X5_APROM);
+       if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) {
+           dev->irq = irq;
+           if ((status = de4x5_hw_init(dev, iobase)) == 0) {
+               num_de4x5s++;
+               if (loading_module) {
+                   link_modules(lastModule, dev);
+                   lastPCI = index;
                }
-           } else if (ioaddr != 0) {
-               printk("%s: region already allocated at 0x%04lx.\n", dev->name,
-                      iobase);
+               return;
            }
+       } else if (ioaddr != 0) {
+           printk("%s: region already allocated at 0x%04lx.\n", dev->name,
+                  iobase);
        }
     }
 
@@ -2193,44 +2209,27 @@ pci_probe(struct device *dev, u_long ioaddr))
 ** For single port cards this is a time waster...
 */
 __initfunc(static void
-srom_search(int index))
+srom_search(struct pci_dev *pdev))
 {
-    u_char pb, dev_fn;
-    u_short dev_id, dev_num, vendor, status;
+    u_char pb;
+    u_short vendor, status;
     u_int irq = 0, device, class = DE4X5_CLASS_CODE;
     u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
     int i, j;
     struct bus_type *lp = &bus;
-#ifndef __sparc_v9__
-    u_char tirq;
-    u_int tmp;
-#endif
 
-    for (; 
-        (pcibios_find_class(class, index, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND);
-        index++) {
-#ifdef __sparc_v9__
-       struct pci_dev *pdev;
-       for (pdev = pci_devices; pdev; pdev = pdev->next) {
-           if ((pdev->bus->number == pb) && (pdev->devfn == dev_fn)) break;
-       }
-#endif
-       if (lp->bus_num != pb) return;
-       dev_num = PCI_SLOT(dev_fn);
-       device = 0;
-       pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor);
-       pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id);
-       device = dev_id;
-       device <<= 8;
-       if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) {
-           continue;
-       }
+    while ((pdev = pci_find_class(class, pdev))!= NULL) {
+       if (lp->bus_num != pdev->bus->number) return;
+       pb = pdev->bus->number;
+       vendor = pdev->vendor;
+       device = pdev->device << 8;
+       if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue;
 
        /* Get the chip configuration revision register */
-       pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv);
+       pcibios_read_config_dword(pb, pdev->devfn, PCI_REVISION_ID, &cfrv);
 
        /* Set the device number information */
-       lp->device = dev_num;
+       lp->device = PCI_SLOT(pdev->devfn);
        lp->bus_num = pb;
            
        /* Set the chipset information */
@@ -2238,25 +2237,14 @@ srom_search(int index))
        lp->chipset = device;
 
        /* Get the board I/O address (64 bits on sparc64) */
-#ifndef __sparc_v9__
-       pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp);
-       iobase = tmp;
-#else
-       iobase = pdev->base_address[0];
-#endif
-       iobase &= CBIO_MASK;
+       iobase = pdev->base_address[0] & CBIO_MASK;
 
        /* Fetch the IRQ to be used */
-#ifndef __sparc_v9__
-       pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq);
-       irq = tirq;
-#else
        irq = pdev->irq;
-#endif
        if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
            
        /* Check if I/O accesses are enabled */
-       pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
+       pcibios_read_config_word(pb, pdev->devfn, PCI_COMMAND, &status);
        if (!(status & PCI_COMMAND_IO)) continue;
 
        /* Search for a valid SROM attached to this DECchip */
@@ -2709,9 +2697,9 @@ dc21140m_autoconf(struct device *dev)
     int ana, anlpa, cap, cr, slnk, sr;
     int next_tick = DE4X5_AUTOSENSE_MS;
     u_long imr, omr, iobase = dev->base_addr;
-
+    
     switch(lp->media) {
-      case INIT: 
+    case INIT: 
         if (lp->timeout < 0) {
            DISABLE_IRQs;
            lp->tx_enable = FALSE;
@@ -2757,9 +2745,9 @@ dc21140m_autoconf(struct device *dev)
        }
        break;
        
-      case ANS:
+    case ANS:
        switch (lp->local_state) {
-         case 0:
+       case 0:
            if (lp->timeout < 0) {
                mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
            }
@@ -2777,7 +2765,7 @@ dc21140m_autoconf(struct device *dev)
            }
            break;
            
-         case 1:
+       case 1:
            if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
                next_tick = sr & ~TIMER_CB;
            } else {
@@ -2805,7 +2793,7 @@ dc21140m_autoconf(struct device *dev)
        }
        break;
        
-      case SPD_DET:                              /* Choose 10Mb/s or 100Mb/s */
+    case SPD_DET:                              /* Choose 10Mb/s or 100Mb/s */
         if (lp->timeout < 0) {
            lp->tmp = (lp->phy[lp->active].id ? MII_SR_LKS : 
                                                  (~gep_rd(dev) & GEP_LNP));
@@ -2825,7 +2813,7 @@ dc21140m_autoconf(struct device *dev)
        }
        break;
        
-      case _100Mb:                               /* Set 100Mb/s */
+    case _100Mb:                               /* Set 100Mb/s */
         next_tick = 3000;
        if (!lp->tx_enable) {
            SET_100Mb;
@@ -2840,8 +2828,10 @@ dc21140m_autoconf(struct device *dev)
            }
        }
        break;
-       
-      case _10Mb:                                /* Set 10Mb/s */
+
+    case BNC:
+    case AUI:
+    case _10Mb:                                /* Set 10Mb/s */
         next_tick = 3000;
        if (!lp->tx_enable) {
            SET_10Mb;
@@ -2857,7 +2847,7 @@ dc21140m_autoconf(struct device *dev)
        }
        break;
        
-      case NC:
+    case NC:
         if (lp->media != lp->c_media) {
            de4x5_dbg_media(dev);
            lp->c_media = lp->media;
@@ -2893,33 +2883,54 @@ dc2114x_autoconf(struct device *dev)
     int next_tick = DE4X5_AUTOSENSE_MS;
 
     switch (lp->media) {
-      case INIT:
+    case INIT:
         if (lp->timeout < 0) {
            DISABLE_IRQs;
            lp->tx_enable = FALSE;
            lp->linkOK = 0;
             lp->timeout = -1;
-           de4x5_save_skbs(dev);          /* Save non transmitted skb's */
+           de4x5_save_skbs(dev);            /* Save non transmitted skb's */
+           if (lp->params.autosense & ~AUTO) {
+               srom_map_media(dev);         /* Fixed media requested      */
+               if (lp->media != lp->params.autosense) {
+                   lp->tcount++;
+                   lp->media = INIT;
+                   return next_tick;
+               }
+               lp->media = INIT;
+           }
        }
        if ((next_tick = de4x5_reset_phy(dev)) < 0) {
            next_tick &= ~TIMER_CB;
        } else {
-            lp->media = SPD_DET;
-           if ((lp->infoblock_media == ANS) && 
+           if (lp->autosense == _100Mb) {
+               lp->media = _100Mb;
+           } else if (lp->autosense == _10Mb) {
+               lp->media = _10Mb;
+           } else if (lp->autosense == TP) {
+               lp->media = TP;
+           } else if (lp->autosense == BNC) {
+               lp->media = BNC;
+           } else if (lp->autosense == AUI) {
+               lp->media = AUI;
+           } else {
+               lp->media = SPD_DET;
+               if ((lp->infoblock_media == ANS) && 
                                    ((sr=is_anc_capable(dev)) & MII_SR_ANC)) {
                    ana = (((sr >> 6) & MII_ANA_TAF) | MII_ANA_CSMA);
                    ana &= (lp->fdx ? ~0 : ~MII_ANA_FDAM);
                    mii_wr(ana, MII_ANA, lp->phy[lp->active].addr, DE4X5_MII);
                    lp->media = ANS;
+               }
            }
            lp->local_state = 0;
            next_tick = dc2114x_autoconf(dev);
         }
        break;
        
-      case ANS:
+    case ANS:
        switch (lp->local_state) {
-         case 0:
+       case 0:
            if (lp->timeout < 0) {
                mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
            }
@@ -2937,7 +2948,7 @@ dc2114x_autoconf(struct device *dev)
            }
            break;
            
-         case 1:
+       case 1:
            if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
                next_tick = sr & ~TIMER_CB;
            } else {
@@ -2959,15 +2970,15 @@ dc2114x_autoconf(struct device *dev)
                    }
                }                       /* Auto Negotiation failed to finish */
                next_tick = dc2114x_autoconf(dev);
-           }                           /* Auto Negotiation failed to start */
+           }                           /* Auto Negotiation failed to start  */
            break;
        }
        break;
-       
-      case AUI:
+
+    case AUI:
        if (!lp->tx_enable) {
            if (lp->timeout < 0) {
-               omr = inl(DE4X5_OMR);          /* Set up half duplex for AUI */
+               omr = inl(DE4X5_OMR);   /* Set up half duplex for AUI        */
                outl(omr & ~OMR_FDX, DE4X5_OMR);
            }
            irqs = 0;
@@ -2990,13 +3001,13 @@ dc2114x_autoconf(struct device *dev)
        }
        break;
        
-      case AUI_SUSPECT:
+    case AUI_SUSPECT:
        next_tick = de4x5_suspect_state(dev, 1000, AUI, ping_media, dc2114x_autoconf);
        break;
        
-      case BNC:
+    case BNC:
        switch (lp->local_state) {
-         case 0:
+       case 0:
            if (lp->timeout < 0) {
                omr = inl(DE4X5_OMR);          /* Set up half duplex for BNC */
                outl(omr & ~OMR_FDX, DE4X5_OMR);
@@ -3012,7 +3023,7 @@ dc2114x_autoconf(struct device *dev)
            }
            break;
            
-         case 1:
+       case 1:
            if (!lp->tx_enable) {
                if ((sts = ping_media(dev, 3000)) < 0) {
                    next_tick = sts & ~TIMER_CB;
@@ -3033,11 +3044,11 @@ dc2114x_autoconf(struct device *dev)
        }
        break;
        
-      case BNC_SUSPECT:
+    case BNC_SUSPECT:
        next_tick = de4x5_suspect_state(dev, 1000, BNC, ping_media, dc2114x_autoconf);
        break;
        
-      case SPD_DET:                              /* Choose 10Mb/s or 100Mb/s */
+    case SPD_DET:                              /* Choose 10Mb/s or 100Mb/s */
          if (srom_map_media(dev) < 0) {
              lp->tcount++;
              lp->media = INIT;
@@ -3053,9 +3064,17 @@ dc2114x_autoconf(struct device *dev)
                  lp->media = SPD_DET;
                  return PDET_LINK_WAIT;
              }
-         } 
-         if (((lp->media == _100Mb) && is_100_up(dev)) ||
+         }
+         if (lp->media == ANS) {           /* Do MII parallel detection */
+             if (is_spd_100(dev)) {
+                 lp->media = _100Mb;
+             } else {
+                 lp->media = _10Mb;
+             }
+             next_tick = dc2114x_autoconf(dev);
+         } else if (((lp->media == _100Mb) && is_100_up(dev)) ||
              ((lp->media == _10Mb)  && is_10_up(dev)) ||
+              (lp->media == TP) ||
               (lp->media == BNC) || (lp->media == AUI)) {
              next_tick = dc2114x_autoconf(dev);
          } else {
@@ -3064,7 +3083,7 @@ dc2114x_autoconf(struct device *dev)
          }
          break;
        
-      case _10Mb:
+    case _10Mb:
         next_tick = 3000;
        if (!lp->tx_enable) {
            SET_10Mb;
@@ -3080,7 +3099,7 @@ dc2114x_autoconf(struct device *dev)
        }
        break;
 
-      case _100Mb:
+    case _100Mb:
         next_tick = 3000;
        if (!lp->tx_enable) {
            SET_100Mb;
@@ -3096,7 +3115,7 @@ dc2114x_autoconf(struct device *dev)
        }
        break;
 
-      default:
+    default:
        lp->tcount++;
 printk("Huh?: media:%02x\n", lp->media);
        lp->media = INIT;
@@ -3466,7 +3485,7 @@ is_anc_capable(struct device *dev)
     if (lp->phy[lp->active].id && (!lp->useSROM || lp->useMII)) {
        return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII));
     } else if ((lp->chipset & ~0x00ff) == DC2114x) {
-       return (inl(DE4X5_SISR) & SISR_LPN) >> 11;
+       return (inl(DE4X5_SISR) & SISR_LPN) >> 12;
     } else {
        return 0;
     }
@@ -4415,7 +4434,7 @@ srom_exec(struct device *dev, u_char *p)
     while (count--) {
        gep_wr(((lp->chipset==DC21140) && (lp->ibn!=5) ? 
                                                   *p++ : TWIDDLE(w++)), dev);
-       mdelay(2);                       /* 2ms per action */
+       mdelay(2);                          /* 2ms per action */
     }
 
     if (lp->chipset != DC21140) {
@@ -4645,6 +4664,7 @@ type1_infoblock(struct device *dev, u_char count, u_char *p)
 
     p += 2;
     if (lp->state == INITIALISED) {
+        lp->ibn = 1;
        lp->active = *p++;
        lp->phy[lp->active].gep = (*p ? p : 0); p += (*p + 1);
        lp->phy[lp->active].rst = (*p ? p : 0); p += (*p + 1);
@@ -4724,6 +4744,7 @@ type3_infoblock(struct device *dev, u_char count, u_char *p)
 
     p += 2;
     if (lp->state == INITIALISED) {
+        lp->ibn = 3;
         lp->active = *p++;
        lp->phy[lp->active].gep = (*p ? p : 0); p += (2 * (*p) + 1);
        lp->phy[lp->active].rst = (*p ? p : 0); p += (2 * (*p) + 1);
@@ -5471,24 +5492,24 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
     } tmp;
     
     switch(ioc->cmd) {
-      case DE4X5_GET_HWADDR:           /* Get the hardware address */
+    case DE4X5_GET_HWADDR:           /* Get the hardware address */
        ioc->len = ETH_ALEN;
        status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len);
        if (status)
-         break;
+           break;
        for (i=0; i<ETH_ALEN; i++) {
            tmp.addr[i] = dev->dev_addr[i];
        }
        copy_to_user(ioc->data, tmp.addr, ioc->len);
        
        break;
-      case DE4X5_SET_HWADDR:           /* Set the hardware address */
+    case DE4X5_SET_HWADDR:           /* Set the hardware address */
        status = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN);
        if (status)
-         break;
+           break;
        status = -EPERM;
        if (!capable(CAP_NET_ADMIN))
-         break;
+           break;
        status = 0;
        copy_from_user(tmp.addr, ioc->data, ETH_ALEN);
        for (i=0; i<ETH_ALEN; i++) {
@@ -5498,13 +5519,13 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        /* Set up the descriptor and give ownership to the card */
        while (test_and_set_bit(0, (void *)&dev->tbusy) != 0);
        load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | 
-                                                       SETUP_FRAME_LEN, NULL);
+                                                      SETUP_FRAME_LEN, NULL);
        lp->tx_new = (++lp->tx_new) % lp->txRingSize;
        outl(POLL_DEMAND, DE4X5_TPD);                /* Start the TX */
        dev->tbusy = 0;                              /* Unlock the TX ring */
        
        break;
-      case DE4X5_SET_PROM:             /* Set Promiscuous Mode */
+    case DE4X5_SET_PROM:             /* Set Promiscuous Mode */
        if (capable(CAP_NET_ADMIN)) {
            omr = inl(DE4X5_OMR);
            omr |= OMR_PR;
@@ -5515,7 +5536,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        }
        
        break;
-      case DE4X5_CLR_PROM:             /* Clear Promiscuous Mode */
+    case DE4X5_CLR_PROM:             /* Clear Promiscuous Mode */
        if (capable(CAP_NET_ADMIN)) {
            omr = inl(DE4X5_OMR);
            omr &= ~OMR_PR;
@@ -5526,11 +5547,11 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        }
        
        break;
-      case DE4X5_SAY_BOO:              /* Say "Boo!" to the kernel log file */
+    case DE4X5_SAY_BOO:              /* Say "Boo!" to the kernel log file */
        printk("%s: Boo!\n", dev->name);
        
        break;
-      case DE4X5_MCA_EN:               /* Enable pass all multicast addressing */
+    case DE4X5_MCA_EN:               /* Enable pass all multicast addressing */
        if (capable(CAP_NET_ADMIN)) {
            omr = inl(DE4X5_OMR);
            omr |= OMR_PM;
@@ -5540,18 +5561,18 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        }
        
        break;
-      case DE4X5_GET_STATS:            /* Get the driver statistics */
+    case DE4X5_GET_STATS:            /* Get the driver statistics */
        ioc->len = sizeof(lp->pktStats);
        status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len);
        if (status)
-         break;
+           break;
        
        cli();
        copy_to_user(ioc->data, &lp->pktStats, ioc->len); 
        sti();
        
        break;
-      case DE4X5_CLR_STATS:            /* Zero out the driver statistics */
+    case DE4X5_CLR_STATS:            /* Zero out the driver statistics */
        if (capable(CAP_NET_ADMIN)) {
            cli();
            memset(&lp->pktStats, 0, sizeof(lp->pktStats));
@@ -5561,14 +5582,14 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        }
        
        break;
-      case DE4X5_GET_OMR:              /* Get the OMR Register contents */
+    case DE4X5_GET_OMR:              /* Get the OMR Register contents */
        tmp.addr[0] = inl(DE4X5_OMR);
        if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, 1))) {
            copy_to_user(ioc->data, tmp.addr, 1);
        }
        
        break;
-      case DE4X5_SET_OMR:              /* Set the OMR Register contents */
+    case DE4X5_SET_OMR:              /* Set the OMR Register contents */
        if (capable(CAP_NET_ADMIN)) {
            if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, 1))) {
                copy_from_user(tmp.addr, ioc->data, 1);
@@ -5579,7 +5600,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        }
        
        break;
-      case DE4X5_GET_REG:              /* Get the DE4X5 Registers */
+    case DE4X5_GET_REG:              /* Get the DE4X5 Registers */
        j = 0;
        tmp.lval[0] = inl(DE4X5_STS); j+=4;
        tmp.lval[1] = inl(DE4X5_BMR); j+=4;
@@ -5687,7 +5708,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        
        break;
 */
-      default:
+    default:
        status = -EOPNOTSUPP;
     }
     
@@ -5766,30 +5787,32 @@ unlink_modules(struct device *p)
 static int
 count_adapters(void)
 {
-    int i, j;
+    int i, j=0;
     char name[DE4X5_STRLEN];
-    u_char pb, dev_fn, dev_num;
-    u_short dev_id, vendor;
+    u_char pb, dev_fn;
+    u_short vendor;
     u_int class = DE4X5_CLASS_CODE;
     u_int device;
+    struct pci_dev *pdev;
+
 #if !defined(__sparc_v9__) && !defined(__powerpc__)
     u_long iobase = 0x1000;
 
-    for (j=0, i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) {
+    for (i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) {
        if (EISA_signature(name, EISA_ID)) j++;
     }
 #endif
-    if (!pci_present()) return j;
+    if (!pcibios_present()) return j;
 
     for (i=0; 
         (pcibios_find_class(class, i, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND);
         i++) {
-       dev_num = PCI_SLOT(dev_fn);
-       device = 0;
-       pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor);
-       pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id);
-       device = dev_id;
-       device <<= 8;
+       for (pdev = pci_devices; pdev; pdev = pdev->next) {
+           if ((pdev->bus->number==pb) && (pdev->devfn==dev_fn)) break;
+       }
+
+       vendor = pdev->vendor;
+       device = pdev->device << 8;
        if (is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x) j++;
     }
 
index c0c58ccf4beb3dc15aa9b90f1031b62934e5f801..24ab3387386b34eb062adbf1c8e9119826006517 100644 (file)
 ** Media / mode state machine definitions
 ** User selectable:
 */
-#define TP              0x0001     /* 10Base-T                             */
+#define TP              0x0040     /* 10Base-T (now equiv to _10Mb)        */
 #define TP_NW           0x0002     /* 10Base-T with Nway                   */
 #define BNC             0x0004     /* Thinwire                             */
 #define AUI             0x0008     /* Thickwire                            */
index 9c33bc515a530ce86d94e6a4e5ab058f65af39a7..109091ef0b5976ace45b6dd715caecb775e3b5e4 100644 (file)
@@ -1,11 +1,11 @@
 #
-# Makefile for the linux ncp-filesystem routines.
+# Makefile for the linux ncp filesystem routines.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
 # removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
+# unless it's something special (not a .c file).
 #
-# Note 2! The CFLAGS definitions are now in the main makefile...
+# Note 2! The CFLAGS definitions are now in the main makefile.
 
 O_TARGET := ncpfs.o
 O_OBJS   := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \
index fbaab052ac3b874a4d9b60234e63f5a3c2533e44..a0ecb75531a60b3032d08e7653b98fe82275cb50 100644 (file)
@@ -41,7 +41,7 @@ __initfunc(static void copro_timeout(void))
        timer_table[COPRO_TIMER].expires = jiffies+100;
        timer_active |= 1<<COPRO_TIMER;
        printk(KERN_ERR "387 failed: trying to reset\n");
-       send_sig(SIGFPE, last_task_used_math, 1);
+       send_sig(SIGFPE, current, 1);
        outb_p(0,0xf1);
        outb_p(0,0xf0);
 }
@@ -156,7 +156,7 @@ __initfunc(static void check_popad(void))
  *     misexecution of code under Linux. Owners of such processors should
  *     contact AMD for precise details and a CPU swap.
  *
- *     See     http://www.chorus.com/~poulot/k6bug.html
+ *     See     http://www.mygale.com/~poulot/k6bug.html
  *             http://www.amd.com/K6/k6docs/revgd.html
  *
  *     The following test is erm.. interesting. AMD neglected to up
@@ -202,7 +202,7 @@ __initfunc(static void check_amd_k6(void))
                        printk("system stability may be impaired when more than 32 MB are used.\n");
                else 
                        printk("probably OK (after B9730xxxx).\n");
-               printk(KERN_INFO "Please see http://www.chorus.com/poulot/k6bug.html\n");
+               printk(KERN_INFO "Please see http://www.mygale.com/~poulot/k6bug.html\n");
        }
 }
 
index 0d642dc277d79574956a367b3d420b93deb8e14c..d75c55605a9586f821e182b4667dc36d3c7d98d1 100644 (file)
@@ -74,9 +74,6 @@ extern unsigned int machine_id;
 extern unsigned int machine_submodel_id;
 extern unsigned int BIOS_revision;
 
-/* Lazy FPU handling on uni-processor */
-extern struct task_struct *last_task_used_math;
-
 /*
  * User space process size: 3GB (default).
  */
@@ -166,33 +163,34 @@ struct thread_struct {
 #define INIT_MMAP \
 { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
 
-#define INIT_TSS  { \
-       0,0, \
-       sizeof(init_stack) + (long) &init_stack, \
-       __KERNEL_DS, 0, \
-       0,0,0,0,0,0, \
-       (long) &swapper_pg_dir - PAGE_OFFSET, \
-       0,0,0,0,0,0,0,0,0,0, \
-       __USER_DS,0,__USER_DS,0,__USER_DS,0, \
-       __USER_DS,0,__USER_DS,0,__USER_DS,0, \
-       _LDT(0),0, \
-       0, 0x8000, \
-       {~0, }, /* ioperm */ \
-       _TSS(0), 0, 0, 0, (mm_segment_t) { 0 } /* obsolete */ , \
-       { { 0, }, },  /* 387 state */ \
-       NULL, 0, 0, 0, 0, 0 /* vm86_info */, \
+#define INIT_TSS  {                                            \
+       0,0, /* back_link, __blh */                             \
+       sizeof(init_stack) + (long) &init_stack, /* esp0 */     \
+       __KERNEL_DS, 0, /* ss0 */                               \
+       0,0,0,0,0,0, /* stack1, stack2 */                       \
+       (long) &swapper_pg_dir - PAGE_OFFSET, /* cr3 */         \
+       0,0, /* eip,eflags */                                   \
+       0,0,0,0, /* eax,ecx,edx,ebx */                          \
+       0,0,0,0, /* esp,ebp,esi,edi */                          \
+       0,0,0,0,0,0, /* es,cs,ss */                             \
+       0,0,0,0,0,0, /* ds,fs,gs */                             \
+       _LDT(0),0, /* ldt */                                    \
+       0, 0x8000, /* tace, bitmap */                           \
+       {~0, }, /* ioperm */                                    \
+       _TSS(0), 0, 0, 0, (mm_segment_t) { 0 }, /* obsolete */  \
+       { { 0, }, },  /* 387 state */                           \
+       NULL, 0, 0, 0, 0, 0, /* vm86_info */                    \
 }
 
-#define start_thread(regs, new_eip, new_esp) do {\
-       unsigned long seg = __USER_DS; \
-       __asm__("movl %w0,%%fs ; movl %w0,%%gs":"=r" (seg) :"0" (seg)); \
-       set_fs(USER_DS); \
-       regs->xds = seg; \
-       regs->xes = seg; \
-       regs->xss = seg; \
-       regs->xcs = __USER_CS; \
-       regs->eip = new_eip; \
-       regs->esp = new_esp; \
+#define start_thread(regs, new_eip, new_esp) do {              \
+       __asm__("movl %w0,%%fs ; movl %w0,%%gs": :"r" (0));     \
+       set_fs(USER_DS);                                        \
+       regs->xds = __USER_DS;                                  \
+       regs->xes = __USER_DS;                                  \
+       regs->xss = __USER_DS;                                  \
+       regs->xcs = __USER_CS;                                  \
+       regs->eip = new_eip;                                    \
+       regs->esp = new_esp;                                    \
 } while (0)
 
 /* Forward declaration, a strange C thing */
index 88c8ebc99754e9ab010c09c5d326ecd416d9e2ab..722374b032d412b04a3ce0b7ee90f73b3549e8b4 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __ASM_SYSTEM_H
 #define __ASM_SYSTEM_H
 
+#include <linux/kernel.h>
 #include <asm/segment.h>
 
 /*
@@ -35,84 +36,35 @@ __asm__("str %%ax\n\t" \
        :"=a" (n) \
        :"0" (0),"i" (FIRST_TSS_ENTRY<<3))
 
-/* This special macro can be used to load a debugging register */
-
-#define loaddebug(tsk,register) \
-               __asm__("movl %0,%%db" #register  \
-                       : /* no output */ \
-                       :"r" (tsk->debugreg[register]))
-
+struct task_struct;    /* one of the stranger aspects of C forward declarations.. */
+extern void FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
 
 /*
- *     switch_to(n) should switch tasks to task nr n, first
- * checking that n isn't the current task, in which case it does nothing.
- * This also clears the TS-flag if the task we switched to has used
- * the math co-processor latest.
- *
- * It also reloads the debug regs if necessary..
+ * We do most of the task switching in C, but we need
+ * to do the EIP/ESP switch in assembly..
  */
-
-#ifdef __SMP__
-       /*
-        *      Keep the lock depth straight. If we switch on an interrupt from
-        *      kernel->user task we need to lose a depth, and if we switch the
-        *      other way we need to gain a depth. Same layer switches come out
-        *      the same.
-        *
-        *      We spot a switch in user mode because the kernel counter is the
-        *      same as the interrupt counter depth. (We never switch during the
-        *      message/invalidate IPI).
-        *
-        *      We fsave/fwait so that an exception goes off at the right time
-        *      (as a call from the fsave or fwait in effect) rather than to
-        *      the wrong process.
-        */
-
-#define switch_to(prev,next) do { \
-       if(prev->flags&PF_USEDFPU) \
-       { \
-               __asm__ __volatile__("fnsave %0":"=m" (prev->tss.i387.hard)); \
-               __asm__ __volatile__("fwait"); \
-               prev->flags&=~PF_USEDFPU;        \
-       } \
-__asm__("ljmp %0\n\t" \
-       : /* no output */ \
-       :"m" (*(((char *)&next->tss.tr)-4)), \
-        "c" (next)); \
-       /* Now maybe reload the debug registers */ \
-       if(prev->debugreg[7]){ \
-               loaddebug(prev,0); \
-               loaddebug(prev,1); \
-               loaddebug(prev,2); \
-               loaddebug(prev,3); \
-               loaddebug(prev,6); \
-               loaddebug(prev,7); \
-       } \
+#define switch_to(prev,next) do {                                      \
+       unsigned long eax, edx, ecx;                                    \
+       asm volatile("pushl %%edi\n\t"                                  \
+                    "pushl %%esi\n\t"                                  \
+                    "pushl %%ebp\n\t"                                  \
+                    "pushl %%ebx\n\t"                                  \
+                    "movl %%esp,%0\n\t"        /* save ESP */          \
+                    "movl %5,%%esp\n\t"        /* restore ESP */       \
+                    "movl $1f,%1\n\t"          /* save EIP */          \
+                    "pushl %6\n\t"             /* restore EIP */       \
+                    "jmp __switch_to\n"                                \
+                    "1:\t"                                             \
+                    "popl %%ebx\n\t"                                   \
+                    "popl %%ebp\n\t"                                   \
+                    "popl %%esi\n\t"                                   \
+                    "popl %%edi"                                       \
+                    :"=m" (prev->tss.esp),"=m" (prev->tss.eip),        \
+                     "=a" (eax), "=d" (edx), "=c" (ecx)                \
+                    :"m" (next->tss.esp),"m" (next->tss.eip),          \
+                     "a" (prev), "d" (next));                          \
 } while (0)
 
-#else
-#define switch_to(prev,next) do { \
-__asm__("ljmp %0\n\t" \
-       "cmpl %1,"SYMBOL_NAME_STR(last_task_used_math)"\n\t" \
-       "jne 1f\n\t" \
-       "clts\n" \
-       "1:" \
-       : /* no outputs */ \
-       :"m" (*(((char *)&next->tss.tr)-4)), \
-        "r" (prev), "r" (next)); \
-       /* Now maybe reload the debug registers */ \
-       if(prev->debugreg[7]){ \
-               loaddebug(prev,0); \
-               loaddebug(prev,1); \
-               loaddebug(prev,2); \
-               loaddebug(prev,3); \
-               loaddebug(prev,6); \
-               loaddebug(prev,7); \
-       } \
-} while (0)
-#endif
-
 #define _set_base(addr,base) \
 __asm__("movw %%dx,%0\n\t" \
        "rorl $16,%%edx\n\t" \
index fef329881b98afd6551433952fa434d9e3082050..0c66e1d3551976019600748ff668897ff70b42d7 100644 (file)
@@ -308,6 +308,10 @@ static inline int copy_mm(int nr, unsigned long clone_flags, struct task_struct
 
        if (clone_flags & CLONE_VM) {
                mmget(current->mm);
+               /*
+                * Set up the LDT descriptor for the clone task.
+                */
+               copy_segments(nr, tsk, NULL);
                SET_PAGE_DIR(tsk, current->mm->pgd);
                return 0;
        }
index 9060da3ef2822d7d8a857c20d44bda3d5d551cc0..dca98441d03f9c9ca067991f2830723e2551e3a5 100644 (file)
@@ -14,8 +14,6 @@
 
 #include <stdarg.h>
 
-#include <asm/system.h>
-
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -27,6 +25,7 @@
 #include <linux/console.h>
 #include <linux/init.h>
 
+#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #define LOG_BUF_LEN    8192
index 26cea095ee10434ad8cbe19fb6650799fdba3699..ff6bca2b029195010a32ea72e78caa97a4a359bf 100644 (file)
@@ -851,7 +851,7 @@ static int file_send_actor(read_descriptor_t * desc, const char *area, unsigned
        return written;
 }
 
-asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, size_t count)
+asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
 {
        ssize_t retval;
        struct file * in_file, * out_file;
@@ -900,16 +900,27 @@ asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, size_t count)
        retval = 0;
        if (count) {
                read_descriptor_t desc;
+               loff_t pos = 0, *ppos;
+
+               retval = -EFAULT;
+               ppos = &in_file->f_pos;
+               if (offset) {
+                       if (get_user(pos, offset))
+                               goto fput_out;
+                       ppos = &pos;
+               }
 
                desc.written = 0;
                desc.count = count;
                desc.buf = (char *) out_file;
                desc.error = 0;
-               do_generic_file_read(in_file, &in_file->f_pos, &desc, file_send_actor);
+               do_generic_file_read(in_file, ppos, &desc, file_send_actor);
 
                retval = desc.written;
                if (!retval)
                        retval = desc.error;
+               if (offset)
+                       put_user(pos, offset);
        }