From f613de21294f35d546d9f229c13e8c8cf3c65d66 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:12:56 -0500 Subject: [PATCH] Import 2.1.26 --- CREDITS | 17 +- Documentation/Changes | 57 +++-- Documentation/Configure.help | 10 +- MAINTAINERS | 5 + Makefile | 2 +- arch/alpha/Makefile | 2 +- arch/alpha/kernel/entry.S | 69 +++--- arch/alpha/kernel/head.S | 7 +- arch/alpha/lib/copy_user.S | 1 - arch/alpha/lib/csum_ipv6_magic.S | 4 +- arch/alpha/lib/csum_partial_copy.c | 153 +++++++++---- arch/alpha/lib/strncat.S | 4 +- arch/alpha/lib/strncpy_from_user.S | 108 +++++----- arch/alpha/lib/stxcpy.S | 80 +++---- arch/alpha/lib/stxncpy.S | 102 ++++----- arch/i386/defconfig | 5 +- arch/i386/kernel/ioport.c | 27 +-- arch/i386/kernel/sys_i386.c | 10 +- arch/i386/kernel/time.c | 134 +++++++----- arch/i386/kernel/traps.c | 15 ++ arch/i386/lib/checksum.c | 335 ++++++++++++----------------- drivers/ap1000/apfddi.c | 14 +- drivers/ap1000/apfddi.h | 2 +- drivers/ap1000/bif.c | 14 +- drivers/char/esp.c | 48 +++-- drivers/net/dgrs.c | 2 +- drivers/net/ibmtr.c | 52 ++--- drivers/net/pi2.h | 2 +- drivers/net/seeq8005.c | 6 +- drivers/net/sk_g16.c | 8 +- drivers/net/smc9194.c | 6 +- drivers/pci/pci.c | 8 +- drivers/scsi/scsi.c | 1 - drivers/scsi/scsi_ioctl.c | 1 + fs/nfs/nfsroot.c | 2 + fs/select.c | 67 +++--- include/asm-alpha/checksum.h | 7 + include/asm-alpha/current.h | 6 +- include/asm-alpha/system.h | 4 +- include/asm-i386/checksum.h | 38 +++- include/linux/fs.h | 2 +- include/linux/icmp.h | 3 +- include/linux/if_tr.h | 4 +- include/linux/limits.h | 2 +- include/linux/netdevice.h | 6 - include/linux/pci.h | 12 +- include/linux/proc_fs.h | 1 + include/linux/sched.h | 2 +- include/linux/sysctl.h | 7 + include/net/lapb.h | 15 +- include/scsi/scsi.h | 2 + kernel/ksyms.c | 4 +- kernel/sched.c | 39 ++-- kernel/signal.c | 3 +- kernel/sys.c | 98 ++++----- kernel/time.c | 22 +- net/802/fddi.c | 51 +++-- net/802/p8022.c | 1 + net/802/sysctl_net_802.c | 8 + net/802/tr.c | 168 ++++++++++----- net/core/sock.c | 4 + net/ipv4/Config.in | 10 +- net/ipv4/arp.c | 19 +- net/ipv4/tcp.c | 4 +- net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/udp.c | 2 +- net/ipx/af_ipx.c | 2 +- net/lapb/lapb_iface.c | 18 +- net/lapb/lapb_in.c | 291 +------------------------ net/lapb/lapb_out.c | 19 +- net/lapb/lapb_subr.c | 3 + net/lapb/lapb_timer.c | 54 +++-- net/netrom/nr_dev.c | 17 +- net/rose/rose_dev.c | 17 +- net/socket.c | 7 +- net/sysctl_net.c | 7 + scripts/Configure | 4 +- scripts/Menuconfig | 4 +- 78 files changed, 1165 insertions(+), 1204 deletions(-) diff --git a/CREDITS b/CREDITS index e9d51d7b1c93..9a787a208691 100644 --- a/CREDITS +++ b/CREDITS @@ -960,11 +960,8 @@ S: The White House, Melbourne Street, LEEDS S: LS2 7PS, UK N: Craig Metz -E: cmetz@tjhsst.edu -D: Some of PAS 16 mixer & PCM support -S: 12305 Country Ridge Lane -S: Fairfax, Virginia 22033 -S: USA +E: cmetz@inner.net +D: Some of PAS 16 mixer & PCM support, inet6-apps N: William (Bill) Metzenthen E: billm@suburbia.net @@ -1099,6 +1096,10 @@ S: University of New Mexico S: Albuquerque, NM 87131 S: USA +N: David Parsons +E: orc@pell.chi.il.us +D: improved memory detection code. + N: Avery Pennarun E: apenwarr@foxnet.net D: ARCnet driver @@ -1384,9 +1385,9 @@ E: Linus.Torvalds@Helsinki.FI W: http://www.cs.helsinki.fi/~torvalds/ P: 1024/A86B35C5 96 54 50 29 EC 11 44 7A BE 67 3C 24 03 13 62 C8 D: Original kernel hacker -S: Kalevankatu 55 B 37 -S: 00180 Helsinki -S: Finland +S: 3665 Benton Street #36 +S: Santa Clara, California 95051 +S: USA N: Jeff Tranter E: Jeff_Tranter@Mitel.COM diff --git a/Documentation/Changes b/Documentation/Changes index 571fcede5176..04185b33c30a 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -19,7 +19,14 @@ you don't need to bother doing so in the form of a diff, as this is generated by texinfo so a diff is useless anyway (though I can incorporate one by hand if you insist upon sending it that way ;-). -Last updated: January 9, 1997. + Check out http://www.cviog.uga.edu/Misc/info/LinuxBleed.html for an +HTML-ized shopping list. + + For those of you in Europe, +http://www.datanet.hu/generations/linux/Changes2.html is an +English-language HTML version. + +Last updated: January 29, 1997. Current Author: Chris Ricker (gt1355b@prism.gatech.edu). Current Minimal Requirements @@ -28,7 +35,7 @@ Current Minimal Requirements Upgrade to at *least* these software revisions before thinking you've encountered a bug! -- Kernel modules modutils-970104 +- Kernel modules modutils-2.1.23 - Gnu C 2.7.2.1 - Binutils 2.7.0.3 - Linux C Library 5.4.17 @@ -39,6 +46,7 @@ encountered a bug! - Mount 2.5p - Net-tools 1.32-alpha - Kbd 0.91 +- Loadlin 1.6a Upgrade notes ************* @@ -49,8 +57,8 @@ General Information now performs a cold reboot instead of a warm reboot for increased hardware compatibility. If you want a warm reboot and know it works on your hardware, add a "reboot=warm" command line option -in Lilo. A small number of machines need "reboot=bios" to reboot via the -BIOS. +in Lilo. A small number of machines need "reboot=bios" to reboot via +the BIOS. Libc ==== @@ -75,7 +83,7 @@ widely available, so if you need to upgrade, use it. Modules ======= - You need to upgrade to modutils-970104 for kernels 2.1.8 and later. + You need to upgrade to modutils-2.1.23 for kernels 2.1.18 and later. Gnu C ===== @@ -120,7 +128,13 @@ DOSEMU ====== A new "stable" version of DOSEMU is available for 2.1.x kernels. -Upgrade to 0.64.2 or later. +Upgrade to 0.64.3 or later. + +Loadlin +======= + + Linux 2.1.22 and later releases use a new method of memory size +detection, requiring loadlin users to upgrade to loadlin-1.6a. How to know the version of the installed programs ************************************************* @@ -132,15 +146,14 @@ requires that you be logged in as root. Binutils: ld -v Gnu C: gcc -v or gcc --version Kbd: loadkeys -h -Ld.so: ldd -v +Ld.so: ldd -v Libc: ls -l /lib/libc.so.* Libc++: ls -l /usr/lib/libg++.so.* -modules: /sbin/insmod -V -mount: mount --version -procps: ps --version -SysVinit: (must be logged in as root) - strings `egrep -li INIT_VERSION=sysvinit- /proc/*/environ | head -1` | \ - egrep -i INIT_VERSION=sysvinit- +Modutils: insmod -V +Mount: mount --version +Procps: ps --version +SysVinit: strings `egrep -li INIT_VERSION=sysvinit- /proc/*/environ | head +-1` | egrep -i INIT_VERSION=sysvinit- RPM: rpm --version Where to get the files @@ -196,8 +209,9 @@ ftp://sunsite.unc.edu/pub/Linux/GCC/ld.so-1.8.5.tar.gz Modules utilities ================= -The 970104 release: -ftp://ftp.redhat.com/pub/alphabits/modutils-970104.tar.gz +The 2.1.23 release: +ftp://tsx-11.mit.edu/pub/linux/sources/system/v2.1/modutils-2.1.23.tar.gz +ftp://sunsite.unc.edu/pub/Linux/kernel/v2.1/modutils-2.1.23.tar.gz Procps utilities ================ @@ -229,9 +243,16 @@ ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/i386/rpm-devel-2.2.7-1.sparc. DOSEMU ====== -The 0.64.2 release: -ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/dosemu0.64.2.tgz -ftp://sunsite.unc.edu/pub/Linux/system/Emulators/dosemu0.64.2.tgz +The 0.64.3.1 release: +ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/dosemu0.64.3.1.tgz +ftp://sunsite.unc.edu/pub/Linux/system/Emulators/dosemu0.64.3.1.tgz + +Loadlin +======= + +The 1.6a release: +ftp://ftp.suse.com/pub/loadlin/update-1.6a/loadlin.exe.gz +ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/update-1.6a/loadlin.exe.gz Other Info ========== diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 07886728a2f5..f1da2c453e39 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -2364,17 +2364,17 @@ CONFIG_WAN_ROUTER distances with data transfer rates significantly higher than those achievable with commonly used asynchronous modem connections. Usually, a quite expensive external device called `WAN router' is - needed to connect to WAN. - As an alternative, WAN router can be build into Linux kernel. + needed to connect to a WAN. + As an alternative, WAN routing can be built into the Linux kernel. With relatively inexpensive WAN interface cards available on the - market, a perfectly usable router can be built for less than half a + market, a perfectly usable router can be built for less than half the price of an external router. If you have one of those cards (with appropriate WAN Link Driver) and wish to use your Linux box as a WAN router, you may say 'Y' to this option. You will also need a wan-tools package available via FTP (user: anonymous) from ftp.sangoma.com. Read Documentation/networking/wan-router.txt for more information. - WAN router is always built as a module ( = code which can be + WAN routing is always built as a module ( = code which can be inserted in and removed from the running kernel whenever you want). For general information about modules read Documentation/modules.txt. @@ -2390,7 +2390,7 @@ CONFIG_WAN_DRIVERS Sangoma WANPIPE(tm) multiprotocol cards CONFIG_VENDOR_SANGOMA WANPIPE from Sangoma Technologies Inc. (http://www.sangoma.com) - is a family of intelligent multiprotocol WAN adapter with data + is a family of intelligent multiprotocol WAN adapters with data transfer rates up to T1 (1.544 Mbps). They are also known as Synchronous Data Link Adapters (SDLA) and designated S502E(A), S503 or S508. If you have one of these cards, say 'Y' to this option. diff --git a/MAINTAINERS b/MAINTAINERS index e18c29a0b20d..f054e9cdab94 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -351,6 +351,11 @@ P: Axel Boldt M: boldt@math.ucsb.edu S: Maintained +PCI ID DATABASE +P: Jens Maurer +M: jmaurer@cck.uni-kl.de +S: Maintained + LANCE AND LANCE32 NETWORK DRIVER P: Thomas Bogendoerfer M: tsbogend@bigbug.franken.de diff --git a/Makefile b/Makefile index ccc0309417c0..df09c9700c3f 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 25 +SUBLEVEL = 26 ARCH = i386 diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile index a234e9453662..22f19e76cc0f 100644 --- a/arch/alpha/Makefile +++ b/arch/alpha/Makefile @@ -24,7 +24,7 @@ else CFLAGS := $(CFLAGS) -pipe endif -CFLAGS := $(CFLAGS) -mno-fp-regs +CFLAGS := $(CFLAGS) -mno-fp-regs -ffixed-8 HEAD := arch/alpha/kernel/head.o diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 284cd22a55b2..02f43f9612a2 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -127,8 +127,8 @@ entInt: addq $1,1,$1 stq $1,0($0) /* set up the arguments to the C interrupt handler */ - lda $27,do_entInt - jsr $26,($27),do_entInt + ldq $8,current_set + jsr $26,do_entInt /* ok, return */ lda $0,intr_count ldq $1,0($0) @@ -153,6 +153,7 @@ entMM: stq $15,48($30) addq $30,56,$19 /* handle the fault */ + ldq $8,current_set jsr $26,do_page_fault /* reload the registers after the exception code played. */ ldq $9,0($30) @@ -172,6 +173,9 @@ entMM: .ent entArith entArith: SAVE_ALL + ldq $8,current_set + /* How much of a win is this clockwise? We are, after all, messing + up the call/return prefetch stack. -- rth */ lda $27,do_entArith lda $26,ret_from_sys_call jsr $31,($27),do_entArith @@ -182,6 +186,7 @@ entArith: .ent entIF entIF: SAVE_ALL + ldq $8,current_set lda $27,do_entIF lda $26,ret_from_sys_call jsr $31,($27),do_entIF @@ -210,8 +215,7 @@ kernel_clone: stq $18,40($30) bis $31,2,$0 /* Register v0: syscall nr for fork() */ SAVE_ALL - lda $27,sys_clone - jsr $26,($27),sys_clone + jsr $26,sys_clone stq $0,0($30) br $31,ret_from_sys_call .end kernel_clone @@ -240,11 +244,13 @@ __kernel_thread: ret $31,($26),1 /* this is in child: look out as we don't have any stack here.. */ 1: bis $9,$9,$27 /* get fn */ + br $29,2f +2: ldgp $29,0($29) bis $10,$10,$16 /* get arg */ + ldq $8,current_set jsr $26,($27) bis $0,$0,$16 - lda $27,sys_exit - jsr $26,($27),sys_exit + jsr $26,sys_exit call_pal PAL_halt .end __kernel_thread @@ -382,8 +388,8 @@ entUna: stq $29,232($30) stq $30,240($30) stq $31,248($30) - lda $27,do_entUna - jsr $26,($27),do_entUna + ldq $8,current_set + jsr $26,do_entUna ldq $0,0($30) ldq $1,8($30) ldq $2,16($30) @@ -431,9 +437,9 @@ entUnaUser: stq $13,32($30) stq $14,40($30) stq $15,48($30) - lda $27,do_entUnaUser bis $31,$30,$19 - jsr $26,($27),do_entUnaUser + ldq $8,current_set + jsr $26,do_entUnaUser ldq $9,0($30) ldq $10,8($30) ldq $11,16($30) @@ -457,8 +463,7 @@ sys_fork: bis $31,SIGCHLD,$16 bis $31,$31,$17 bis $30,$30,$18 - lda $27,alpha_clone - jsr $26,($27),alpha_clone + jsr $26,alpha_clone bsr $1,undo_switch_stack ret $31,($26),1 .end sys_fork @@ -470,8 +475,7 @@ sys_clone: bsr $1,do_switch_stack /* arg1 and arg2 come from the user */ bis $30,$30,$18 - lda $27,alpha_clone - jsr $26,($27),alpha_clone + jsr $26,alpha_clone bsr $1,undo_switch_stack ret $31,($26),1 .end sys_clone @@ -499,14 +503,13 @@ alpha_switch_to: .ent entSys entSys: SAVE_ALL - lda $1,current_set + ldq $8,current_set lda $4,NR_SYSCALLS($31) stq $16,SP_OFF+24($30) lda $5,sys_call_table - ldq $2,0($1) lda $27,do_entSys cmpult $0,$4,$4 - ldq $3,TASK_FLAGS($2) + ldq $3,TASK_FLAGS($8) stq $17,SP_OFF+32($30) s8addq $0,$5,$5 and $3,PF_PTRACED,$3 @@ -539,15 +542,13 @@ ret_from_handle_bh: beq $0,restore_all ret_from_reschedule: lda $0,need_resched - lda $1,current_set ldl $2,0($0) lda $4,init_task - ldq $3,0($1) bne $2,reschedule - subq $4,$3,$4 + xor $4,$8,$4 beq $4,restore_all - ldq $4,TASK_SIGNAL($3) - ldq $16,TASK_BLOCKED($3) + ldq $4,TASK_SIGNAL($8) + ldq $16,TASK_BLOCKED($8) bic $4,$16,$4 bne $4,signal_return restore_all: @@ -560,8 +561,7 @@ restore_all: strace: /* set up signal stack, call syscall_trace */ bsr $1,do_switch_stack - lda $27,syscall_trace - jsr $26,($27),syscall_trace + jsr $26,syscall_trace bsr $1,undo_switch_stack /* get the system call number and the arguments back.. */ @@ -590,8 +590,7 @@ strace_success: stq $0,0($30) /* save return value */ bsr $1,do_switch_stack - lda $27,syscall_trace - jsr $26,($27),syscall_trace + jsr $26,syscall_trace bsr $1,undo_switch_stack br $31,ret_from_sys_call @@ -609,8 +608,7 @@ strace_error: bsr $1,do_switch_stack bis $19,$19,$9 /* save old syscall number */ bis $20,$20,$10 /* save old a3 */ - lda $27,syscall_trace - jsr $26,($27),syscall_trace + jsr $26,syscall_trace bis $9,$9,$19 bis $10,$10,$20 bsr $1,undo_switch_stack @@ -628,8 +626,7 @@ handle_bottom_half: subq $30,16,$30 stq $19,0($30) /* save syscall nr */ stq $20,8($30) /* and error indication (a3) */ - lda $27,do_bottom_half - jsr $26,($27),do_bottom_half + jsr $26,do_bottom_half lda $0,intr_count ldq $19,0($30) ldq $20,8($30) @@ -667,8 +664,7 @@ signal_return: bis $30,$30,$17 br $1,do_switch_stack bis $30,$30,$18 - lda $27,do_signal - jsr $26,($27),do_signal + jsr $26,do_signal lda $30,SWITCH_STACK_SIZE($30) br $31,restore_all .end entSys @@ -679,8 +675,7 @@ reschedule: subq $30,16,$30 stq $19,0($30) /* save syscall nr */ stq $20,8($30) /* and error indication (a3) */ - lda $27,schedule - jsr $26,($27),schedule + jsr $26,schedule ldq $19,0($30) ldq $20,8($30) addq $30,16,$30 @@ -693,8 +688,7 @@ sys_sigreturn: bis $30,$30,$17 lda $30,-SWITCH_STACK_SIZE($30) bis $30,$30,$18 - lda $27,do_sigreturn - jsr $26,($27),do_sigreturn + jsr $26,do_sigreturn br $1,undo_switch_stack br $31,ret_from_sys_call .end sys_sigreturn @@ -705,8 +699,7 @@ sys_sigsuspend: bis $30,$30,$17 br $1,do_switch_stack bis $30,$30,$18 - lda $27,do_sigsuspend - jsr $26,($27),do_sigsuspend + jsr $26,do_sigsuspend lda $30,SWITCH_STACK_SIZE($30) br $31,ret_from_sys_call .end sys_sigsuspend diff --git a/arch/alpha/kernel/head.S b/arch/alpha/kernel/head.S index 0c1fc8681ecc..d19e829edeef 100644 --- a/arch/alpha/kernel/head.S +++ b/arch/alpha/kernel/head.S @@ -23,8 +23,11 @@ _stext: __start: br $27,1f 1: ldgp $29,0($27) - lda $27,start_kernel - jsr $26,($27),start_kernel + /* We need to get current loaded up with our first task. */ + lda $8,init_task + stq $8,current_set + /* And then we can start the kernel. */ + jsr $26,start_kernel halt .end __start diff --git a/arch/alpha/lib/copy_user.S b/arch/alpha/lib/copy_user.S index 5dcbbcbb56ae..da57fd6d1ac7 100644 --- a/arch/alpha/lib/copy_user.S +++ b/arch/alpha/lib/copy_user.S @@ -17,7 +17,6 @@ * length in $0 * destination address in $6 * source address in $7 - * exception pointer in $8 * return address in $28 * * Outputs: diff --git a/arch/alpha/lib/csum_ipv6_magic.S b/arch/alpha/lib/csum_ipv6_magic.S index 1042c6904ccd..168590726aed 100644 --- a/arch/alpha/lib/csum_ipv6_magic.S +++ b/arch/alpha/lib/csum_ipv6_magic.S @@ -61,8 +61,8 @@ csum_ipv6_magic: extwl $0,2,$1 # e0 : zapnot $0,3,$0 # .. e1 : addq $0,$1,$0 # e0 : - unop # : - not $0,$0 # e0 : + not $0,$0 # e1 : + zapnot $0,3,$0 # e0 : ret # .. e1 : .end csum_ipv6_magic diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c index b4f1fc03fb43..87cbebc56208 100644 --- a/arch/alpha/lib/csum_partial_copy.c +++ b/arch/alpha/lib/csum_partial_copy.c @@ -7,6 +7,11 @@ * we do for performance.. */ +#include +#include +#include + + #define ldq_u(x,y) \ __asm__ __volatile__("ldq_u %0,%1":"=r" (x):"m" (*(unsigned long *)(y))) @@ -31,17 +36,52 @@ __asm__ __volatile__("insql %1,%2,%0":"=r" (z):"r" (x),"r" (y)) #define insqh(x,y,z) \ __asm__ __volatile__("insqh %1,%2,%0":"=r" (z):"r" (x),"r" (y)) + +#define __get_user_u(x,ptr) \ +({ \ + long __guu_err; \ + __asm__ __volatile__( \ + "1: ldq_u %0,%2\n" \ + "2:\n" \ + ".section __ex_table,\"a\"\n" \ + " .gprel32 1b\n" \ + " lda %0,2b-1b(%1)\n" \ + ".previous" \ + : "=r"(x), "=r"(__guu_err) \ + : "m"(__m(ptr)), "1"(0)); \ + __guu_err; \ +}) + +#define __put_user_u(x,ptr) \ +({ \ + long __puu_err; \ + __asm__ __volatile__( \ + "1: stq_u %2,%1\n" \ + "2:\n" \ + ".section __ex_table,\"a\"\n" \ + " .gprel32 1b" \ + " lda $31,2b-1b(%0)\n" \ + ".previous" \ + : "=r"(__puu_err) \ + : "m"(__m(addr)), "rJ"(x), "0"(0)); \ + __puu_err; \ +}) + + /* * Ok. This isn't fun, but this is the EASY case. */ -static inline unsigned long csum_partial_copy_aligned( - unsigned long *src, unsigned long *dst, - long len, unsigned long checksum) +static inline unsigned long +csum_partial_cfu_aligned(unsigned long *src, unsigned long *dst, + long len, unsigned long checksum, + int *errp) { unsigned long carry = 0; + int err = 0; while (len >= 0) { - unsigned long word = *src; + unsigned long word; + err |= __get_user(word, src); checksum += carry; src++; checksum += word; @@ -54,7 +94,7 @@ static inline unsigned long csum_partial_copy_aligned( checksum += carry; if (len) { unsigned long word, tmp; - word = *src; + err |= __get_user(word, src); tmp = *dst; mskql(word, len, word); checksum += word; @@ -63,28 +103,31 @@ static inline unsigned long csum_partial_copy_aligned( *dst = word | tmp; checksum += carry; } - return checksum; + if (err) *errp = err; + return checksum; } /* * This is even less fun, but this is still reasonably * easy. */ -static inline unsigned long csum_partial_copy_dest_aligned( - unsigned long *src, unsigned long *dst, - unsigned long soff, - long len, unsigned long checksum) +static inline unsigned long +csum_partial_cfu_dest_aligned(unsigned long *src, unsigned long *dst, + unsigned long soff, + long len, unsigned long checksum, + int *errp) { unsigned long first; unsigned long word, carry; unsigned long lastsrc = 7+len+(unsigned long)src; + int err = 0; - ldq_u(first,src); + err |= __get_user_u(first,src); carry = 0; while (len >= 0) { unsigned long second; - ldq_u(second, src+1); + err |= __get_user_u(second, src+1); extql(first, soff, word); len -= 8; src++; @@ -102,7 +145,7 @@ static inline unsigned long csum_partial_copy_dest_aligned( if (len) { unsigned long tmp; unsigned long second; - ldq_u(second, lastsrc); + err |= __get_user_u(second, lastsrc); tmp = *dst; extql(first, soff, word); extqh(second, soff, first); @@ -114,25 +157,28 @@ static inline unsigned long csum_partial_copy_dest_aligned( *dst = word | tmp; checksum += carry; } + if (err) *errp = err; return checksum; } /* * This is slightly less fun than the above.. */ -static inline unsigned long csum_partial_copy_src_aligned( - unsigned long *src, unsigned long *dst, - unsigned long doff, - long len, unsigned long checksum, - unsigned long partial_dest) +static inline unsigned long +csum_partial_cfu_src_aligned(unsigned long *src, unsigned long *dst, + unsigned long doff, + long len, unsigned long checksum, + unsigned long partial_dest, + int *errp) { unsigned long carry = 0; unsigned long word; + int err = 0; mskql(partial_dest, doff, partial_dest); while (len >= 0) { unsigned long second_dest; - word = *src; + err |= __get_user(word, src); len -= 8; insql(word, doff, second_dest); checksum += carry; @@ -147,7 +193,7 @@ static inline unsigned long csum_partial_copy_src_aligned( checksum += carry; if (len >= 0) { unsigned long second_dest; - word = *src; + err |= __get_user(word, src); mskql(word, len-doff, word); checksum += word; insql(word, doff, second_dest); @@ -162,7 +208,7 @@ static inline unsigned long csum_partial_copy_src_aligned( checksum += carry; } else if (len & 7) { unsigned long second_dest; - word = *src; + err |= __get_user(word, src); ldq_u(second_dest, dst); mskql(word, len-doff, word); checksum += word; @@ -172,6 +218,7 @@ static inline unsigned long csum_partial_copy_src_aligned( stq_u(partial_dest | word | second_dest, dst); checksum += carry; } + if (err) *errp = err; return checksum; } @@ -179,24 +226,26 @@ static inline unsigned long csum_partial_copy_src_aligned( * This is so totally un-fun that it's frightening. Don't * look at this too closely, you'll go blind. */ -static inline unsigned long csum_partial_copy_unaligned( - unsigned long * src, unsigned long * dst, - unsigned long soff, unsigned long doff, - long len, unsigned long checksum, - unsigned long partial_dest) +static inline unsigned long +csum_partial_cfu_unaligned(unsigned long * src, unsigned long * dst, + unsigned long soff, unsigned long doff, + long len, unsigned long checksum, + unsigned long partial_dest, + int *errp) { unsigned long carry = 0; unsigned long first; unsigned long lastsrc; + int err = 0; - ldq_u(first, src); + err |= __get_user_u(first, src); lastsrc = 7+len+(unsigned long)src; mskql(partial_dest, doff, partial_dest); while (len >= 0) { unsigned long second, word; unsigned long second_dest; - ldq_u(second, src+1); + err |= __get_user_u(second, src+1); extql(first, soff, word); checksum += carry; len -= 8; @@ -216,8 +265,8 @@ static inline unsigned long csum_partial_copy_unaligned( if (len >= 0) { unsigned long second, word; unsigned long second_dest; - - ldq_u(second, lastsrc); + + err |= __get_user_u(second, lastsrc); extql(first, soff, word); extqh(second, soff, first); word |= first; @@ -233,12 +282,12 @@ static inline unsigned long csum_partial_copy_unaligned( mskqh(second_dest, len, second_dest); stq_u(partial_dest | second_dest, dst+1); } - checksum += carry; + checksum += carry; } else if (len & 7) { unsigned long second, word; unsigned long second_dest; - ldq_u(second, lastsrc); + err |= __get_user_u(second, lastsrc); extql(first, soff, word); extqh(second, soff, first); word |= first; @@ -251,42 +300,51 @@ static inline unsigned long csum_partial_copy_unaligned( stq_u(partial_dest | word | second_dest, dst); checksum += carry; } + if (err) *errp = err; return checksum; } -unsigned int csum_partial_copy(char *src, char *dst, int len, int sum) +unsigned int +csum_partial_copy_from_user(int *errp, char *src, char *dst, + int len, unsigned int sum) { unsigned long checksum = (unsigned) sum; unsigned long soff = 7 & (unsigned long) src; unsigned long doff = 7 & (unsigned long) dst; + if (!access_ok(src, len, VERIFY_READ)) { + *errp = -EFAULT; + memset(dst, 0, len); + return checksum; + } + if (len) { if (!doff) { if (!soff) - checksum = csum_partial_copy_aligned( + checksum = csum_partial_cfu_aligned( (unsigned long *) src, (unsigned long *) dst, - len-8, checksum); + len-8, checksum, errp); else - checksum = csum_partial_copy_dest_aligned( + checksum = csum_partial_cfu_dest_aligned( (unsigned long *) src, (unsigned long *) dst, - soff, len-8, checksum); + soff, len-8, checksum, errp); } else { unsigned long partial_dest; ldq_u(partial_dest, dst); if (!soff) - checksum = csum_partial_copy_src_aligned( + checksum = csum_partial_cfu_src_aligned( (unsigned long *) src, (unsigned long *) dst, doff, len-8, checksum, - partial_dest); + partial_dest, errp); else - checksum = csum_partial_copy_unaligned( + checksum = csum_partial_cfu_unaligned( (unsigned long *) src, (unsigned long *) dst, soff, doff, len-8, checksum, - partial_dest); + partial_dest, errp); } /* 64 -> 33 bits */ checksum = (checksum & 0xffffffff) + (checksum >> 32); @@ -298,3 +356,16 @@ unsigned int csum_partial_copy(char *src, char *dst, int len, int sum) } return checksum; } + +unsigned int +csum_partial_copy (const char *src, char *dst, int len, unsigned int sum) +{ + unsigned int ret; + int error = 0; + + ret = csum_partial_copy_from_user(&error, src, dst, len, sum); + if (error) + printk("csum_partial_copy_old(): tell mingo to convert me!\n"); + + return ret; +} diff --git a/arch/alpha/lib/strncat.S b/arch/alpha/lib/strncat.S index 583cbfae5d61..a8278163c972 100644 --- a/arch/alpha/lib/strncat.S +++ b/arch/alpha/lib/strncat.S @@ -56,11 +56,11 @@ $found: negq $2, $3 # clear all but least set bit /* Worry about the null termination. */ - zapnot $1, $22, $2 # was last byte a null? + zapnot $1, $27, $2 # was last byte a null? bne $2, 0f ret -0: cmplt $22, $24, $2 # did we fill the buffer completely? +0: cmplt $27, $24, $2 # did we fill the buffer completely? or $2, $18, $2 bne $2, 2f diff --git a/arch/alpha/lib/strncpy_from_user.S b/arch/alpha/lib/strncpy_from_user.S index 0c7a04c7ed28..aff7c1d2bf91 100644 --- a/arch/alpha/lib/strncpy_from_user.S +++ b/arch/alpha/lib/strncpy_from_user.S @@ -44,10 +44,10 @@ $aligned: mskqh t1, a1, t3 # e0 : ornot t1, t2, t2 # .. e1 : mskql t0, a1, t0 # e0 : assemble the first output word - cmpbge zero, t2, t7 # .. e1 : bits set iff null found + cmpbge zero, t2, t8 # .. e1 : bits set iff null found or t0, t3, t0 # e0 : beq a2, $a_eoc # .. e1 : - bne t7, $a_eos # .. e1 : + bne t8, $a_eos # .. e1 : /* On entry to this basic block: t0 == a source word not containing a null. */ @@ -58,34 +58,34 @@ $a_loop: EX( ldq_u t0, 0(a1) ) # e0 : addq a1, 8, a1 # .. e1 : subq a2, 1, a2 # e0 : - cmpbge zero, t0, t7 # .. e1 (stall) + cmpbge zero, t0, t8 # .. e1 (stall) beq a2, $a_eoc # e1 : - beq t7, $a_loop # e1 : + beq t8, $a_loop # e1 : /* Take care of the final (partial) word store. At this point - the end-of-count bit is set in t7 iff it applies. + the end-of-count bit is set in t8 iff it applies. On entry to this basic block we have: t0 == the source word containing the null - t7 == the cmpbge mask that found it. */ + t8 == the cmpbge mask that found it. */ $a_eos: - negq t7, t8 # e0 : find low bit set - and t7, t8, t8 # e1 (stall) + negq t8, t12 # e0 : find low bit set + and t8, t12, t12 # e1 (stall) /* For the sake of the cache, don't read a destination word if we're not going to need it. */ - and t8, 0x80, t6 # e0 : + and t12, 0x80, t6 # e0 : bne t6, 1f # .. e1 (zdb) /* We're doing a partial word store and so need to combine our source and original destination words. */ ldq_u t1, 0(a0) # e0 : - subq t8, 1, t6 # .. e1 : - or t8, t6, t7 # e0 : + subq t12, 1, t6 # .. e1 : + or t12, t6, t8 # e0 : unop # - zapnot t0, t7, t0 # e0 : clear src bytes > null - zap t1, t7, t1 # .. e1 : clear dst bytes <= null + zapnot t0, t8, t0 # e0 : clear src bytes > null + zap t1, t8, t1 # .. e1 : clear dst bytes <= null or t0, t1, t0 # e1 : 1: stq_u t0, 0(a0) @@ -93,7 +93,7 @@ $a_eos: /* Add the end-of-count bit to the eos detection bitmask. */ $a_eoc: - or t10, t7, t7 + or t10, t8, t8 br $a_eos /*** The Function Entry Point ***/ @@ -148,18 +148,18 @@ $u_head: mskqh t1, a0, t1 # e0 : mask leading garbage in src or t0, t1, t0 # e0 : first output word complete or t0, t6, t6 # e1 : mask original data for zero test - cmpbge zero, t6, t7 # e0 : + cmpbge zero, t6, t8 # e0 : beq a2, $u_eocfin # .. e1 : - bne t7, $u_final # e1 : + bne t8, $u_final # e1 : lda t6, -1 # e1 : mask out the bits we have mskql t6, a1, t6 # e0 : already seen stq_u t0, 0(a0) # e0 : store first output word or t6, t2, t2 # .. e1 : - cmpbge zero, t2, t7 # e0 : find nulls in second partial + cmpbge zero, t2, t8 # e0 : find nulls in second partial addq a0, 8, a0 # .. e1 : subq a2, 1, a2 # e0 : - bne t7, $u_late_head_exit # .. e1 : + bne t8, $u_late_head_exit # .. e1 : /* Finally, we've got all the stupid leading edge cases taken care of and we can set up to enter the main loop. */ @@ -167,9 +167,9 @@ $u_head: extql t2, a1, t1 # e0 : position hi-bits of lo word EX( ldq_u t2, 8(a1) ) # .. e1 : read next high-order source word addq a1, 8, a1 # e0 : - cmpbge zero, t2, t7 # e1 (stall) + cmpbge zero, t2, t8 # e1 (stall) beq a2, $u_eoc # e1 : - bne t7, $u_eos # e1 : + bne t8, $u_eos # e1 : /* Unaligned copy main loop. In order to avoid reading too much, the loop is structured to detect zeros in aligned source words. @@ -195,9 +195,9 @@ $u_loop: stq_u t0, -8(a0) # e0 : save the current word mov t3, t1 # .. e1 : subq a2, 1, a2 # e0 : - cmpbge zero, t2, t7 # .. e1 : test new word for eos + cmpbge zero, t2, t8 # .. e1 : test new word for eos beq a2, $u_eoc # e1 : - beq t7, $u_loop # e1 : + beq t8, $u_loop # e1 : /* We've found a zero somewhere in the source word we just read. If it resides in the lower half, we have one (probably partial) @@ -211,8 +211,8 @@ $u_eos: extqh t2, a1, t0 # e0 : or t0, t1, t0 # e1 : first (partial) source word complete - cmpbge zero, t0, t7 # e0 : is the null in this first bit? - bne t7, $u_final # .. e1 (zdb) + cmpbge zero, t0, t8 # e0 : is the null in this first bit? + bne t8, $u_final # .. e1 (zdb) stq_u t0, 0(a0) # e0 : the null was in the high-order bits addq a0, 8, a0 # .. e1 : @@ -220,27 +220,27 @@ $u_eos: $u_late_head_exit: extql t2, a1, t0 # .. e0 : - cmpbge zero, t0, t7 # e0 : - or t7, t10, t6 # e1 : - cmoveq a2, t6, t7 # e0 : + cmpbge zero, t0, t8 # e0 : + or t8, t10, t6 # e1 : + cmoveq a2, t6, t8 # e0 : nop # .. e1 : /* Take care of a final (probably partial) result word. On entry to this basic block: t0 == assembled source word - t7 == cmpbge mask that found the null. */ + t8 == cmpbge mask that found the null. */ $u_final: - negq t7, t6 # e0 : isolate low bit set - and t6, t7, t8 # e1 : + negq t8, t6 # e0 : isolate low bit set + and t6, t8, t12 # e1 : - and t8, 0x80, t6 # e0 : avoid dest word load if we can + and t12, 0x80, t6 # e0 : avoid dest word load if we can bne t6, 1f # .. e1 (zdb) ldq_u t1, 0(a0) # e0 : - subq t8, 1, t6 # .. e1 : - or t6, t8, t7 # e0 : - zapnot t0, t7, t0 # .. e1 : kill source bytes > null - zap t1, t7, t1 # e0 : kill dest bytes <= null + subq t12, 1, t6 # .. e1 : + or t6, t12, t8 # e0 : + zapnot t0, t8, t0 # .. e1 : kill source bytes > null + zap t1, t8, t1 # e0 : kill dest bytes <= null or t0, t1, t0 # e1 : 1: stq_u t0, 0(a0) # e0 : @@ -249,10 +249,10 @@ $u_final: $u_eoc: # end-of-count extqh t2, a1, t0 or t0, t1, t0 - cmpbge zero, t0, t7 + cmpbge zero, t0, t8 $u_eocfin: # end-of-count, final word - or t10, t7, t7 + or t10, t8, t8 br $u_final /* Unaligned copy entry point. */ @@ -279,19 +279,19 @@ $unaligned: /* If source misalignment is larger than dest misalignment, we need extra startup checks to avoid SEGV. */ - cmplt t4, t5, t8 # e1 : + cmplt t4, t5, t12 # e1 : extql t1, a1, t1 # .. e0 : shift src into place lda t2, -1 # e0 : for creating masks later - beq t8, $u_head # e1 : + beq t12, $u_head # e1 : mskqh t2, t5, t2 # e0 : begin src byte validity mask - cmpbge zero, t1, t7 # .. e1 : is there a zero? + cmpbge zero, t1, t8 # .. e1 : is there a zero? extql t2, a1, t2 # e0 : - or t7, t10, t6 # .. e1 : test for end-of-count too + or t8, t10, t5 # .. e1 : test for end-of-count too cmpbge zero, t2, t3 # e0 : - cmoveq a2, t6, t7 # .. e1 : - andnot t7, t3, t7 # e0 : - beq t7, $u_head # .. e1 (zdb) + cmoveq a2, t5, t8 # .. e1 : + andnot t8, t3, t8 # e0 : + beq t8, $u_head # .. e1 (zdb) /* At this point we've found a zero in the first partial word of the source. We need to isolate the valid source data and mask @@ -299,26 +299,26 @@ $unaligned: that we'll need at least one byte of that original dest word.) */ ldq_u t0, 0(a0) # e0 : - negq t7, t6 # .. e1 : build bitmask of bytes <= zero + negq t8, t6 # .. e1 : build bitmask of bytes <= zero mskqh t1, t4, t1 # e0 : - and t6, t7, t8 # .. e1 : - subq t8, 1, t6 # e0 : - or t6, t8, t7 # e1 : + and t6, t8, t12 # .. e1 : + subq t12, 1, t6 # e0 : + or t6, t12, t8 # e1 : - zapnot t2, t7, t2 # e0 : prepare source word; mirror changes - zapnot t1, t7, t1 # .. e1 : to source validity mask + zapnot t2, t8, t2 # e0 : prepare source word; mirror changes + zapnot t1, t8, t1 # .. e1 : to source validity mask andnot t0, t2, t0 # e0 : zero place for source to reside or t0, t1, t0 # e1 : and put it there stq_u t0, 0(a0) # e0 : $finish_up: - zapnot t0, t8, t4 # was last byte written null? + zapnot t0, t12, t4 # was last byte written null? cmovne t4, 1, t4 - and t8, 0xf0, t3 # binary search for the address of the - and t8, 0xcc, t2 # last byte written - and t8, 0xaa, t1 + and t12, 0xf0, t3 # binary search for the address of the + and t12, 0xcc, t2 # last byte written + and t12, 0xaa, t1 bic a0, 7, t0 cmovne t3, 4, t3 cmovne t2, 2, t2 diff --git a/arch/alpha/lib/stxcpy.S b/arch/alpha/lib/stxcpy.S index 8efdef9eae31..b7b9da4829b6 100644 --- a/arch/alpha/lib/stxcpy.S +++ b/arch/alpha/lib/stxcpy.S @@ -13,7 +13,7 @@ * a1 = SRC * * On output: - * t8 = bitmask (with one bit set) indicating the last byte written + * t12 = bitmask (with one bit set) indicating the last byte written * a0 = unaligned address of the last *word* written * * Furthermore, v0, a3-a5, t11, and t12 are untouched. @@ -47,9 +47,9 @@ stxcpy_aligned: mskqh t1, a1, t3 # e0 : ornot t1, t2, t2 # .. e1 : mskql t0, a1, t0 # e0 : assemble the first output word - cmpbge zero, t2, t7 # .. e1 : bits set iff null found + cmpbge zero, t2, t8 # .. e1 : bits set iff null found or t0, t3, t1 # e0 : - bne t7, $a_eos # .. e1 : + bne t8, $a_eos # .. e1 : /* On entry to this basic block: t0 == the first destination word for masking back in @@ -60,29 +60,29 @@ $a_loop: addq a0, 8, a0 # .. e1 : ldq_u t1, 0(a1) # e0 : addq a1, 8, a1 # .. e1 : - cmpbge zero, t1, t7 # e0 (stall) - beq t7, $a_loop # .. e1 (zdb) + cmpbge zero, t1, t8 # e0 (stall) + beq t8, $a_loop # .. e1 (zdb) /* Take care of the final (partial) word store. On entry to this basic block we have: t1 == the source word containing the null - t7 == the cmpbge mask that found it. */ + t8 == the cmpbge mask that found it. */ $a_eos: - negq t7, t6 # e0 : find low bit set - and t7, t6, t8 # e1 (stall) + negq t8, t6 # e0 : find low bit set + and t8, t6, t12 # e1 (stall) /* For the sake of the cache, don't read a destination word if we're not going to need it. */ - and t8, 0x80, t6 # e0 : + and t12, 0x80, t6 # e0 : bne t6, 1f # .. e1 (zdb) /* We're doing a partial word store and so need to combine our source and original destination words. */ ldq_u t0, 0(a0) # e0 : - subq t8, 1, t6 # .. e1 : + subq t12, 1, t6 # .. e1 : zapnot t1, t6, t1 # e0 : clear src bytes >= null - or t8, t6, t7 # .. e1 : - zap t0, t7, t0 # e0 : clear dst bytes <= null + or t12, t6, t8 # .. e1 : + zap t0, t8, t0 # e0 : clear dst bytes <= null or t0, t1, t1 # e1 : 1: stq_u t1, 0(a0) # e0 : @@ -138,14 +138,14 @@ $u_head: or t0, t1, t1 # e1 : or t1, t6, t6 # e0 : - cmpbge zero, t6, t7 # .. e1 : + cmpbge zero, t6, t8 # .. e1 : lda t6, -1 # e0 : for masking just below - bne t7, $u_final # .. e1 : + bne t8, $u_final # .. e1 : mskql t6, a1, t6 # e0 : mask out the bits we have or t6, t2, t2 # e1 : already extracted before - cmpbge zero, t2, t7 # e0 : testing eos - bne t7, $u_late_head_exit # .. e1 (zdb) + cmpbge zero, t2, t8 # e0 : testing eos + bne t8, $u_late_head_exit # .. e1 (zdb) /* Finally, we've got all the stupid leading edge cases taken care of and we can set up to enter the main loop. */ @@ -155,9 +155,9 @@ $u_head: extql t2, a1, t0 # e0 : position ho-bits of lo word ldq_u t2, 8(a1) # .. e1 : read next high-order source word addq a1, 8, a1 # e0 : - cmpbge zero, t2, t7 # .. e1 : + cmpbge zero, t2, t8 # .. e1 : nop # e0 : - bne t7, $u_eos # .. e1 : + bne t8, $u_eos # .. e1 : /* Unaligned copy main loop. In order to avoid reading too much, the loop is structured to detect zeros in aligned source words. @@ -182,8 +182,8 @@ $u_loop: ldq_u t2, 0(a1) # .. e1 : load high word for next time stq_u t1, -8(a0) # e0 : save the current word mov t3, t0 # .. e1 : - cmpbge zero, t2, t7 # e0 : test new word for eos - beq t7, $u_loop # .. e1 : + cmpbge zero, t2, t8 # e0 : test new word for eos + beq t8, $u_loop # .. e1 : /* We've found a zero somewhere in the source word we just read. If it resides in the lower half, we have one (probably partial) @@ -197,31 +197,31 @@ $u_eos: extqh t2, a1, t1 # e0 : or t0, t1, t1 # e1 : first (partial) source word complete - cmpbge zero, t1, t7 # e0 : is the null in this first bit? - bne t7, $u_final # .. e1 (zdb) + cmpbge zero, t1, t8 # e0 : is the null in this first bit? + bne t8, $u_final # .. e1 (zdb) $u_late_head_exit: stq_u t1, 0(a0) # e0 : the null was in the high-order bits addq a0, 8, a0 # .. e1 : extql t2, a1, t1 # e0 : - cmpbge zero, t1, t7 # .. e1 : + cmpbge zero, t1, t8 # .. e1 : /* Take care of a final (probably partial) result word. On entry to this basic block: t1 == assembled source word - t7 == cmpbge mask that found the null. */ + t8 == cmpbge mask that found the null. */ $u_final: - negq t7, t6 # e0 : isolate low bit set - and t6, t7, t8 # e1 : + negq t8, t6 # e0 : isolate low bit set + and t6, t8, t12 # e1 : - and t8, 0x80, t6 # e0 : avoid dest word load if we can + and t12, 0x80, t6 # e0 : avoid dest word load if we can bne t6, 1f # .. e1 (zdb) ldq_u t0, 0(a0) # e0 : - subq t8, 1, t6 # .. e1 : - or t6, t8, t7 # e0 : + subq t12, 1, t6 # .. e1 : + or t6, t12, t8 # e0 : zapnot t1, t6, t1 # .. e1 : kill source bytes >= null - zap t0, t7, t0 # e0 : kill dest bytes <= null + zap t0, t8, t0 # e0 : kill dest bytes <= null or t0, t1, t1 # e1 : 1: stq_u t1, 0(a0) # e0 : @@ -251,15 +251,15 @@ $unaligned: /* If source misalignment is larger than dest misalignment, we need extra startup checks to avoid SEGV. */ - cmplt t4, t5, t8 # e0 : - beq t8, $u_head # .. e1 (zdb) + cmplt t4, t5, t12 # e0 : + beq t12, $u_head # .. e1 (zdb) lda t2, -1 # e1 : mask out leading garbage in source mskqh t2, t5, t2 # e0 : nop # e0 : ornot t1, t2, t3 # .. e1 : - cmpbge zero, t3, t7 # e0 : is there a zero? - beq t7, $u_head # .. e1 (zdb) + cmpbge zero, t3, t8 # e0 : is there a zero? + beq t8, $u_head # .. e1 (zdb) /* At this point we've found a zero in the first partial word of the source. We need to isolate the valid source data and mask @@ -268,14 +268,14 @@ $unaligned: ldq_u t0, 0(a0) # e0 : - negq t7, t6 # .. e1 : build bitmask of bytes <= zero - and t6, t7, t8 # e0 : + negq t8, t6 # .. e1 : build bitmask of bytes <= zero + and t6, t8, t12 # e0 : and a1, 7, t5 # .. e1 : - subq t8, 1, t6 # e0 : - or t6, t8, t7 # e1 : - srl t8, t5, t8 # e0 : adjust final null return value + subq t12, 1, t6 # e0 : + or t6, t12, t8 # e1 : + srl t12, t5, t12 # e0 : adjust final null return value - zapnot t2, t7, t2 # .. e1 : prepare source word; mirror changes + zapnot t2, t8, t2 # .. e1 : prepare source word; mirror changes and t1, t2, t1 # e1 : to source validity mask extql t2, a1, t2 # .. e0 : extql t1, a1, t1 # e0 : diff --git a/arch/alpha/lib/stxncpy.S b/arch/alpha/lib/stxncpy.S index cfbfac18b802..5bab622e0134 100644 --- a/arch/alpha/lib/stxncpy.S +++ b/arch/alpha/lib/stxncpy.S @@ -18,9 +18,9 @@ * * On output: * t0 = last word written - * t8 = bitmask (with one bit set) indicating the last byte written * t10 = bitmask (with one bit set) indicating the byte position of * the end of the range specified by COUNT + * t12 = bitmask (with one bit set) indicating the last byte written * a0 = unaligned address of the last *word* written * a2 = the number of full words left in COUNT * @@ -55,10 +55,10 @@ stxncpy_aligned: mskqh t1, a1, t3 # e0 : ornot t1, t2, t2 # .. e1 : mskql t0, a1, t0 # e0 : assemble the first output word - cmpbge zero, t2, t7 # .. e1 : bits set iff null found + cmpbge zero, t2, t8 # .. e1 : bits set iff null found or t0, t3, t0 # e0 : beq a2, $a_eoc # .. e1 : - bne t7, $a_eos # .. e1 : + bne t8, $a_eos # .. e1 : /* On entry to this basic block: t0 == a source word not containing a null. */ @@ -69,34 +69,34 @@ $a_loop: ldq_u t0, 0(a1) # e0 : addq a1, 8, a1 # .. e1 : subq a2, 1, a2 # e0 : - cmpbge zero, t0, t7 # .. e1 (stall) + cmpbge zero, t0, t8 # .. e1 (stall) beq a2, $a_eoc # e1 : - beq t7, $a_loop # e1 : + beq t8, $a_loop # e1 : /* Take care of the final (partial) word store. At this point - the end-of-count bit is set in t7 iff it applies. + the end-of-count bit is set in t8 iff it applies. On entry to this basic block we have: t0 == the source word containing the null - t7 == the cmpbge mask that found it. */ + t8 == the cmpbge mask that found it. */ $a_eos: - negq t7, t8 # e0 : find low bit set - and t7, t8, t8 # e1 (stall) + negq t8, t12 # e0 : find low bit set + and t8, t12, t12 # e1 (stall) /* For the sake of the cache, don't read a destination word if we're not going to need it. */ - and t8, 0x80, t6 # e0 : + and t12, 0x80, t6 # e0 : bne t6, 1f # .. e1 (zdb) /* We're doing a partial word store and so need to combine our source and original destination words. */ ldq_u t1, 0(a0) # e0 : - subq t8, 1, t6 # .. e1 : - or t8, t6, t7 # e0 : + subq t12, 1, t6 # .. e1 : + or t12, t6, t8 # e0 : unop # - zapnot t0, t7, t0 # e0 : clear src bytes > null - zap t1, t7, t1 # .. e1 : clear dst bytes <= null + zapnot t0, t8, t0 # e0 : clear src bytes > null + zap t1, t8, t1 # .. e1 : clear dst bytes <= null or t0, t1, t0 # e1 : 1: stq_u t0, 0(a0) # e0 : @@ -104,7 +104,7 @@ $a_eos: /* Add the end-of-count bit to the eos detection bitmask. */ $a_eoc: - or t10, t7, t7 + or t10, t8, t8 br $a_eos .end stxncpy_aligned @@ -161,18 +161,18 @@ $u_head: mskqh t1, a0, t1 # e0 : mask leading garbage in src or t0, t1, t0 # e0 : first output word complete or t0, t6, t6 # e1 : mask original data for zero test - cmpbge zero, t6, t7 # e0 : + cmpbge zero, t6, t8 # e0 : beq a2, $u_eocfin # .. e1 : - bne t7, $u_final # e1 : + bne t8, $u_final # e1 : lda t6, -1 # e1 : mask out the bits we have mskql t6, a1, t6 # e0 : already seen stq_u t0, 0(a0) # e0 : store first output word or t6, t2, t2 # .. e1 : - cmpbge zero, t2, t7 # e0 : find nulls in second partial + cmpbge zero, t2, t8 # e0 : find nulls in second partial addq a0, 8, a0 # .. e1 : subq a2, 1, a2 # e0 : - bne t7, $u_late_head_exit # .. e1 : + bne t8, $u_late_head_exit # .. e1 : /* Finally, we've got all the stupid leading edge cases taken care of and we can set up to enter the main loop. */ @@ -180,9 +180,9 @@ $u_head: extql t2, a1, t1 # e0 : position hi-bits of lo word ldq_u t2, 8(a1) # .. e1 : read next high-order source word addq a1, 8, a1 # e0 : - cmpbge zero, t2, t7 # e1 (stall) + cmpbge zero, t2, t8 # e1 (stall) beq a2, $u_eoc # e1 : - bne t7, $u_eos # e1 : + bne t8, $u_eos # e1 : /* Unaligned copy main loop. In order to avoid reading too much, the loop is structured to detect zeros in aligned source words. @@ -208,9 +208,9 @@ $u_loop: stq_u t0, -8(a0) # e0 : save the current word mov t3, t1 # .. e1 : subq a2, 1, a2 # e0 : - cmpbge zero, t2, t7 # .. e1 : test new word for eos + cmpbge zero, t2, t8 # .. e1 : test new word for eos beq a2, $u_eoc # e1 : - beq t7, $u_loop # e1 : + beq t8, $u_loop # e1 : /* We've found a zero somewhere in the source word we just read. If it resides in the lower half, we have one (probably partial) @@ -224,8 +224,8 @@ $u_eos: extqh t2, a1, t0 # e0 : or t0, t1, t0 # e1 : first (partial) source word complete - cmpbge zero, t0, t7 # e0 : is the null in this first bit? - bne t7, $u_final # .. e1 (zdb) + cmpbge zero, t0, t8 # e0 : is the null in this first bit? + bne t8, $u_final # .. e1 (zdb) stq_u t0, 0(a0) # e0 : the null was in the high-order bits addq a0, 8, a0 # .. e1 : @@ -233,27 +233,27 @@ $u_eos: $u_late_head_exit: extql t2, a1, t0 # .. e0 : - cmpbge zero, t0, t7 # e0 : - or t7, t10, t6 # e1 : - cmoveq a2, t6, t7 # e0 : + cmpbge zero, t0, t8 # e0 : + or t8, t10, t6 # e1 : + cmoveq a2, t6, t8 # e0 : nop # .. e1 : /* Take care of a final (probably partial) result word. On entry to this basic block: t0 == assembled source word - t7 == cmpbge mask that found the null. */ + t8 == cmpbge mask that found the null. */ $u_final: - negq t7, t6 # e0 : isolate low bit set - and t6, t7, t8 # e1 : + negq t8, t6 # e0 : isolate low bit set + and t6, t8, t12 # e1 : - and t8, 0x80, t6 # e0 : avoid dest word load if we can + and t12, 0x80, t6 # e0 : avoid dest word load if we can bne t6, 1f # .. e1 (zdb) ldq_u t1, 0(a0) # e0 : - subq t8, 1, t6 # .. e1 : - or t6, t8, t7 # e0 : - zapnot t0, t7, t0 # .. e1 : kill source bytes > null - zap t1, t7, t1 # e0 : kill dest bytes <= null + subq t12, 1, t6 # .. e1 : + or t6, t12, t8 # e0 : + zapnot t0, t8, t0 # .. e1 : kill source bytes > null + zap t1, t8, t1 # e0 : kill dest bytes <= null or t0, t1, t0 # e1 : 1: stq_u t0, 0(a0) # e0 : @@ -262,10 +262,10 @@ $u_final: $u_eoc: # end-of-count extqh t2, a1, t0 or t0, t1, t0 - cmpbge zero, t0, t7 + cmpbge zero, t0, t8 $u_eocfin: # end-of-count, final word - or t10, t7, t7 + or t10, t8, t8 br $u_final /* Unaligned copy entry point. */ @@ -292,19 +292,19 @@ $unaligned: /* If source misalignment is larger than dest misalignment, we need extra startup checks to avoid SEGV. */ - cmplt t4, t5, t8 # e1 : + cmplt t4, t5, t12 # e1 : extql t1, a1, t1 # .. e0 : shift src into place lda t2, -1 # e0 : for creating masks later - beq t8, $u_head # e1 : + beq t12, $u_head # e1 : mskqh t2, t5, t2 # e0 : begin src byte validity mask - cmpbge zero, t1, t7 # .. e1 : is there a zero? + cmpbge zero, t1, t8 # .. e1 : is there a zero? extql t2, a1, t2 # e0 : - or t7, t10, t6 # .. e1 : test for end-of-count too + or t8, t10, t5 # .. e1 : test for end-of-count too cmpbge zero, t2, t3 # e0 : - cmoveq a2, t6, t7 # .. e1 : - andnot t7, t3, t7 # e0 : - beq t7, $u_head # .. e1 (zdb) + cmoveq a2, t5, t8 # .. e1 : + andnot t8, t3, t8 # e0 : + beq t8, $u_head # .. e1 (zdb) /* At this point we've found a zero in the first partial word of the source. We need to isolate the valid source data and mask @@ -312,14 +312,14 @@ $unaligned: that we'll need at least one byte of that original dest word.) */ ldq_u t0, 0(a0) # e0 : - negq t7, t6 # .. e1 : build bitmask of bytes <= zero + negq t8, t6 # .. e1 : build bitmask of bytes <= zero mskqh t1, t4, t1 # e0 : - and t6, t7, t8 # .. e1 : - subq t8, 1, t6 # e0 : - or t6, t8, t7 # e1 : + and t6, t8, t12 # .. e1 : + subq t12, 1, t6 # e0 : + or t6, t12, t8 # e1 : - zapnot t2, t7, t2 # e0 : prepare source word; mirror changes - zapnot t1, t7, t1 # .. e1 : to source validity mask + zapnot t2, t8, t2 # e0 : prepare source word; mirror changes + zapnot t1, t8, t1 # .. e1 : to source validity mask andnot t0, t2, t0 # e0 : zero place for source to reside or t0, t1, t0 # e1 : and put it there diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 4ed71aa03ec0..c8d62e92395a 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -68,9 +68,10 @@ CONFIG_BLK_DEV_RZ1000=y # CONFIG_FIREWALL is not set # CONFIG_NET_ALIAS is not set CONFIG_INET=y -# CONFIG_IP_FORWARD is not set # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ACCT is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set # # (it is safe to leave these untouched) @@ -116,9 +117,9 @@ CONFIG_EL3=y # CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_NET_RADIO is not set -# CONFIG_LAPBETHER is not set # CONFIG_SLIP is not set # CONFIG_TR is not set +# CONFIG_LAPBETHER is not set # # ISDN subsystem diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c index 43ad07572a70..8f929f603c5a 100644 --- a/arch/i386/kernel/ioport.c +++ b/arch/i386/kernel/ioport.c @@ -53,19 +53,13 @@ static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_ */ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) { - int ret = -EINVAL; - - lock_kernel(); if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32)) - goto out; - ret = -EPERM; + return -EINVAL; if (!suser()) - goto out; + return -EPERM; + set_bitmap((unsigned long *)current->tss.io_bitmap, from, num, !turn_on); - ret = 0; -out: - unlock_kernel(); - return ret; + return 0; } unsigned int *stack; @@ -80,23 +74,18 @@ unsigned int *stack; * on system-call entry - see also fork() and the signal handling * code. */ + asmlinkage int sys_iopl(long ebx,long ecx,long edx, long esi, long edi, long ebp, long eax, long ds, long es, long orig_eax, long eip, long cs, long eflags, long esp, long ss) { unsigned int level = ebx; - int ret = -EINVAL; - lock_kernel(); if (level > 3) - goto out; - ret = -EPERM; + return -EINVAL; if (!suser()) - goto out; + return -EPERM; *(&eflags) = (eflags & 0xffffcfff) | (level << 12); - ret = 0; -out: - unlock_kernel(); - return ret; + return 0; } diff --git a/arch/i386/kernel/sys_i386.c b/arch/i386/kernel/sys_i386.c index 70c09380437e..5c3d00736594 100644 --- a/arch/i386/kernel/sys_i386.c +++ b/arch/i386/kernel/sys_i386.c @@ -32,11 +32,11 @@ asmlinkage int sys_pipe(unsigned long * fildes) lock_kernel(); error = do_pipe(fd); + unlock_kernel(); if (!error) { if (copy_to_user(fildes, fd, 2*sizeof(int))) error = -EFAULT; } - unlock_kernel(); return error; } @@ -46,6 +46,7 @@ asmlinkage int sys_pipe(unsigned long * fildes) * 4 system call parameters, so these system calls used a memory * block for parameter passing.. */ + struct mmap_arg_struct { unsigned long addr; unsigned long len; @@ -87,13 +88,12 @@ struct sel_arg_struct { asmlinkage int old_select(struct sel_arg_struct *arg) { struct sel_arg_struct a; - int ret = -EFAULT; + int ret; - lock_kernel(); if (copy_from_user(&a, arg, sizeof(a))) - goto out; + return -EFAULT; + lock_kernel(); ret = sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); -out: unlock_kernel(); return ret; } diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index 21024c46ec7e..4c181719b249 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -41,38 +41,33 @@ static struct { unsigned long high; } init_timer_cc, last_timer_cc; -/* - * This is more assembly than C, but it's also rather - * timing-critical and we have to use assembler to get - * reasonable 64-bit arithmetic - */ +extern volatile unsigned long lost_ticks; + +/* change this if you have some constant time drift */ +#define USECS_PER_JIFFY (1000020/HZ) + static unsigned long do_fast_gettimeoffset(void) { register unsigned long eax asm("ax"); register unsigned long edx asm("dx"); - unsigned long tmp, quotient, low_timer, missing_time; + unsigned long tmp, quotient, low_timer; - /* Last jiffy when do_fast_gettimeoffset() was called.. */ + /* Last jiffy when do_fast_gettimeoffset() was called. */ static unsigned long last_jiffies=0; - /* Cached "clocks per usec" value.. */ + /* + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. + */ static unsigned long cached_quotient=0; - /* The "clocks per usec" value is calculated once each jiffy */ tmp = jiffies; + quotient = cached_quotient; low_timer = last_timer_cc.low; - missing_time = 0; + if (last_jiffies != tmp) { last_jiffies = tmp; - /* - * test for hanging bottom handler (this means xtime is not - * updated yet) - */ - if (test_bit(TIMER_BH, &bh_active) ) - { - missing_time = 1000020/HZ; - } /* Get last timer tick in absolute kernel time */ eax = low_timer; @@ -86,14 +81,16 @@ static unsigned long do_fast_gettimeoffset(void) * Divide the 64-bit time with the 32-bit jiffy counter, * getting the quotient in clocks. * - * Giving quotient = "average internal clocks per usec" + * Giving quotient = "1/(average internal clocks per usec)*2^32" + * we do this '1/...' trick to get the 'mull' into the critical + * path. 'mull' is much faster than divl (10 vs. 41 clocks) */ __asm__("divl %2" :"=a" (eax), "=d" (edx) :"r" (tmp), "0" (eax), "1" (edx)); - edx = 1000020/HZ; + edx = USECS_PER_JIFFY; tmp = eax; eax = 0; @@ -114,7 +111,7 @@ static unsigned long do_fast_gettimeoffset(void) eax -= low_timer; /* - * Time offset = (1000020/HZ * time_low) / quotient. + * Time offset = (USECS_PER_JIFFY * time_low) * quotient. */ __asm__("mull %2" @@ -123,15 +120,13 @@ static unsigned long do_fast_gettimeoffset(void) "0" (eax), "1" (edx)); /* - * Due to rounding errors (and jiffies inconsistencies), - * we need to check the result so that we'll get a timer - * that is monotonic. + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. */ - if (edx >= 1000020/HZ) - edx = 1000020/HZ-1; + if (edx >= USECS_PER_JIFFY) + edx = USECS_PER_JIFFY-1; - eax = edx + missing_time; - return eax; + return edx; } #endif @@ -172,8 +167,8 @@ static unsigned long do_fast_gettimeoffset(void) static unsigned long do_slow_gettimeoffset(void) { int count; - static int count_p = 0; - unsigned long offset = 0; + + static int count_p = LATCH; /* for the first call after boot */ static unsigned long jiffies_p = 0; /* @@ -183,53 +178,69 @@ static unsigned long do_slow_gettimeoffset(void) /* timer count may underflow right here */ outb_p(0x00, 0x43); /* latch the count ASAP */ + count = inb_p(0x40); /* read the latched count */ - count |= inb(0x40) << 8; + /* + * We do this guaranteed double memory access instead of a _p + * postfix in the previous port access. Wheee, hackady hack + */ jiffies_t = jiffies; + count |= inb_p(0x40) << 8; + /* * avoiding timer inconsistencies (they are rare, but they happen)... - * there are three kinds of problems that must be avoided here: + * there are two kinds of problems that must be avoided here: * 1. the timer counter underflows * 2. hardware problem with the timer, not giving us continuous time, * the counter does small "jumps" upwards on some Pentium systems, - * thus causes time warps - * 3. we are after the timer interrupt, but the bottom half handler - * hasn't executed yet. + * (see c't 95/10 page 335 for Neptun bug.) */ - if( count > count_p ) { - if( jiffies_t == jiffies_p ) { - if( count > LATCH-LATCH/100 ) - offset = TICK_SIZE; - else + +/* you can safely undefine this if you dont have the Neptun chipset */ + +#define BUGGY_NEPTUN_TIMER + + if( jiffies_t == jiffies_p ) { + if( count > count_p ) { + /* the nutcase */ + + outb_p(0x0A, 0x20); + + /* assumption about timer being IRQ1 */ + if( inb(0x20) & 0x01 ) { /* - * argh, the timer is bugging we cant do nothing - * but to give the previous clock value. + * We cannot detect lost timer interrupts ... + * well, thats why we call them lost, dont we? :) + * [hmm, on the Pentium and Alpha we can ... sort of] */ - count = count_p; - } else { - if( test_bit(TIMER_BH, &bh_active) ) { - /* - * we have detected a counter underflow. - */ - offset = TICK_SIZE; - count_p = count; + count -= LATCH; } else { - count_p = count; - jiffies_p = jiffies_t; +#ifdef BUGGY_NEPTUN_TIMER + /* + * for the Neptun bug we know that the 'latch' + * command doesnt latch the high and low value + * of the counter atomically. Thus we have to + * substract 256 from the counter + * ... funny, isnt it? :) + */ + + count -= 256; +#else + printk("do_slow_gettimeoffset(): hardware timer problem?\n"); +#endif } } - } else { - count_p = count; + } else jiffies_p = jiffies_t; - } + count_p = count; count = ((LATCH-1) - count) * TICK_SIZE; count = (count + LATCH/2) / LATCH; - return offset + count; + return count; } /* @@ -253,11 +264,20 @@ void do_gettimeofday(struct timeval *tv) cli(); *tv = xtime; tv->tv_usec += do_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. lost_ticks is + * nonzero if the timer bottom half hasnt executed yet. + */ + if (lost_ticks) + tv->tv_usec += USECS_PER_JIFFY; + + restore_flags(flags); + if (tv->tv_usec >= 1000000) { tv->tv_usec -= 1000000; tv->tv_sec++; } - restore_flags(flags); } void do_settimeofday(struct timeval *tv) diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index d62c1b3a7286..ec6909548644 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -198,6 +198,21 @@ DO_ERROR(11, SIGBUS, "segment not present", segment_not_present, current) DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current) DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current) DO_ERROR(18, SIGSEGV, "reserved", reserved, current) +/* I don't have documents for this but it does seem to cover the cache + flush from user space exception some people get. */ +DO_ERROR(19, SIGSEGV, "cache flush denied", cache_flush_denied, current) + +asmlinkage void cache_flush_denied(struct pt_regs * regs, long error_code) +{ + if (regs->eflags & VM_MASK) { + handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); + return; + } + die_if_kernel("cache flush denied",regs,error_code); + current->tss.error_code = error_code; + current->tss.trap_no = 19; + force_sig(SIGSEGV, current); +} asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) { diff --git a/arch/i386/lib/checksum.c b/arch/i386/lib/checksum.c index 0ad0c47be4a2..4a0f82440eeb 100644 --- a/arch/i386/lib/checksum.c +++ b/arch/i386/lib/checksum.c @@ -100,225 +100,162 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) /* * Copy from ds while checksumming, otherwise like csum_partial * - * The macros SRC and DST specify wether there should be exception handling - * for the source and/or the destination addresses. + * The macros SRC and DST specify the type of access for the instruction. + * thus we can call a custom exception handler for all access types. * * FIXME: could someone double check wether i havent mixed up some SRC and * DST definitions? It's damn hard to trigger all cases, i hope i got * them all but theres no guarantee ... */ -#define csum_partial_copy_type(type) \ -unsigned int csum_partial_copy ##type (int * __csum_err, const char *src, char *dst, \ - int len, int sum) { \ - __asm__( \ -" testl $2, %%edi # Check alignment. \n" \ -" jz 2f # Jump if alignment is ok. \n" \ -" subl $2, %%ecx # Alignment uses up two bytes. \n" \ -" jae 1f # Jump if we had at least two bytes. \n" \ -" addl $2, %%ecx # ecx was < 2. Deal with it. \n" \ -" jmp 4f \n" \ -" 1000: \n" \ -" 1: movw (%%esi), %%bx \n" \ -" addl $2, %%esi \n" \ -" 1001: \n" \ -" movw %%bx, (%%edi) \n" \ -" addl $2, %%edi \n" \ -" addw %%bx, %%ax \n" \ -" adcl $0, %%eax \n" \ -" 2: \n" \ -" pushl %%ecx \n" \ -" shrl $5, %%ecx \n" \ -" jz 2f \n" \ -" testl %%esi, %%esi \n" \ -" 1002: \n" \ -" 1: movl (%%esi), %%ebx \n" \ -" 1003: \n" \ -" movl 4(%%esi), %%edx \n" \ -" adcl %%ebx, %%eax \n" \ -" 1004: \n" \ -" movl %%ebx, (%%edi) \n" \ -" adcl %%edx, %%eax \n" \ -" 1005: \n" \ -" movl %%edx, 4(%%edi) \n" \ -" \n" \ -" 1006: \n" \ -" movl 8(%%esi), %%ebx \n" \ -" 1007: \n" \ -" movl 12(%%esi), %%edx \n" \ -" adcl %%ebx, %%eax \n" \ -" 1008: \n" \ -" movl %%ebx, 8(%%edi) \n" \ -" adcl %%edx, %%eax \n" \ -" 1009: \n" \ -" movl %%edx, 12(%%edi) \n" \ -" \n" \ -" 1010: \n" \ -" movl 16(%%esi), %%ebx \n" \ -" 1011: \n" \ -" movl 20(%%esi), %%edx \n" \ -" adcl %%ebx, %%eax \n" \ -" 1012: \n" \ -" movl %%ebx, 16(%%edi) \n" \ -" adcl %%edx, %%eax \n" \ -" 1013: \n" \ -" movl %%edx, 20(%%edi) \n" \ -" \n" \ -" 1014: \n" \ -" movl 24(%%esi), %%ebx \n" \ -" 1015: \n" \ -" movl 28(%%esi), %%edx \n" \ -" adcl %%ebx, %%eax \n" \ -" 1016: \n" \ -" movl %%ebx, 24(%%edi) \n" \ -" adcl %%edx, %%eax \n" \ -" 1017: \n" \ -" movl %%edx, 28(%%edi) \n" \ -" \n" \ -" 1018: \n" \ -" lea 32(%%esi), %%esi \n" \ -" 1019: \n" \ -" lea 32(%%edi), %%edi \n" \ -" dec %%ecx \n" \ -" jne 1b \n" \ -" adcl $0, %%eax \n" \ -" 2: popl %%edx \n" \ -" movl %%edx, %%ecx \n" \ -" andl $0x1c, %%edx \n" \ -" je 4f \n" \ -" shrl $2, %%edx # This clears CF \n" \ -" 1020: \n" \ -" 3: movl (%%esi), %%ebx \n" \ -" adcl %%ebx, %%eax \n" \ -" 1021: \n" \ -" movl %%ebx, (%%edi) \n" \ -" 1022: \n" \ -" lea 4(%%esi), %%esi \n" \ -" 1023: \n" \ -" lea 4(%%edi), %%edi \n" \ -" dec %%edx \n" \ -" jne 3b \n" \ -" adcl $0, %%eax \n" \ -" 4: andl $3, %%ecx \n" \ -" jz 7f \n" \ -" cmpl $2, %%ecx \n" \ -" jb 5f \n" \ -" 1024: \n" \ -" movw (%%esi), %%cx \n" \ -" 1025: \n" \ -" leal 2(%%esi), %%esi \n" \ -" 1026: \n" \ -" movw %%cx, (%%edi) \n" \ -" 1027: \n" \ -" leal 2(%%edi), %%edi \n" \ -" je 6f \n" \ -" shll $16,%%ecx \n" \ -" 1028: \n" \ -" 5: movb (%%esi), %%cl \n" \ -" 1029: \n" \ -" movb %%cl, (%%edi) \n" \ -" 6: addl %%ecx, %%eax \n" \ -" adcl $0, %%eax \n" \ -" 7: \n" \ -" 2000: \n" \ -" .section .fixup,\"ax\" \n" \ -" 3000: movl %7,%1 \n" \ -/* FIXME: zero out the rest of the buffer here !!!!!! */ \ -" jmp 2000b \n" \ -" .previous \n" \ -" .section __ex_table,\"a\" \n" \ -" .align 4 \n" \ -" \n" \ -SRC( " .long 1000b,3000b \n " ) \ -DST( " .long 1001b,3000b \n " ) \ -SRC( " .long 1002b,3000b \n " ) \ -SRC( " .long 1003b,3000b \n " ) \ -DST( " .long 1004b,3000b \n " ) \ -DST( " .long 1005b,3000b \n " ) \ -SRC( " .long 1006b,3000b \n " ) \ -SRC( " .long 1007b,3000b \n " ) \ -DST( " .long 1008b,3000b \n " ) \ -DST( " .long 1009b,3000b \n " ) \ -SRC( " .long 1010b,3000b \n " ) \ -SRC( " .long 1011b,3000b \n " ) \ -DST( " .long 1012b,3000b \n " ) \ -DST( " .long 1013b,3000b \n " ) \ -SRC( " .long 1014b,3000b \n " ) \ -SRC( " .long 1015b,3000b \n " ) \ -DST( " .long 1016b,3000b \n " ) \ -DST( " .long 1017b,3000b \n " ) \ -SRC( " .long 1018b,3000b \n " ) \ -DST( " .long 1019b,3000b \n " ) \ -SRC( " .long 1020b,3000b \n " ) \ -DST( " .long 1021b,3000b \n " ) \ -SRC( " .long 1022b,3000b \n " ) \ -DST( " .long 1023b,3000b \n " ) \ -SRC( " .long 1024b,3000b \n " ) \ -SRC( " .long 1025b,3000b \n " ) \ -DST( " .long 1026b,3000b \n " ) \ -DST( " .long 1027b,3000b \n " ) \ -SRC( " .long 1028b,3000b \n " ) \ -DST( " .long 1029b,3000b \n " ) \ -" .previous \n " \ - : "=a" (sum), "=r" (*__csum_err) \ - : "0" (sum), "c" (len), "S" (src), "D" (dst), \ - "1" (*__csum_err), "i" (-EFAULT) \ - : "bx", "cx", "dx", "si", "di" ); \ - \ - return(sum); \ -} +#define SRC(y...) \ +" 9999: "#y"; \n \ + .section __ex_table, \"a\"; \n \ + .long 9999b, src_access_fault \n \ + .previous" -/* - * Currently we need only 2 out of the 4 possible type combinations: - */ +#define DST(y...) \ +" 9999: "#y"; \n \ + .section __ex_table, \"a\"; \n \ + .long 9999b, dst_access_fault \n \ + .previous" -/* - * Generate 'csum_partial_copy_from_user()', we need to do exception - * handling for source addresses. - */ +unsigned int csum_partial_copy_generic (const char *src, char *dst, + int len, int sum, int *src_err_ptr, int *dst_err_ptr) +{ + __asm__ __volatile__ ( " + testl $2, %%edi # Check alignment. + jz 2f # Jump if alignment is ok. + subl $2, %%ecx # Alignment uses up two bytes. + jae 1f # Jump if we had at least two bytes. + addl $2, %%ecx # ecx was < 2. Deal with it. + jmp 4f +"SRC( 1: movw (%%esi), %%bx )" + addl $2, %%esi +"DST( movw %%bx, (%%edi) )" + addl $2, %%edi + addw %%bx, %%ax + adcl $0, %%eax + 2: + pushl %%ecx + shrl $5, %%ecx + jz 2f + testl %%esi, %%esi +"SRC( 1: movl (%%esi), %%ebx )" +"SRC( movl 4(%%esi), %%edx )" + adcl %%ebx, %%eax +"DST( movl %%ebx, (%%edi) )" + adcl %%edx, %%eax +"DST( movl %%edx, 4(%%edi) )" -#define SRC(x) x -#define DST(x) -csum_partial_copy_type(_from_user) -#undef SRC -#undef DST +"SRC( movl 8(%%esi), %%ebx )" +"SRC( movl 12(%%esi), %%edx )" + adcl %%ebx, %%eax +"DST( movl %%ebx, 8(%%edi) )" + adcl %%edx, %%eax +"DST( movl %%edx, 12(%%edi) )" -/* - * Generate 'csum_partial_copy_nocheck()', no need to do exception - * handling. - */ +"SRC( movl 16(%%esi), %%ebx )" +"SRC( movl 20(%%esi), %%edx )" + adcl %%ebx, %%eax +"DST( movl %%ebx, 16(%%edi) )" + adcl %%edx, %%eax +"DST( movl %%edx, 20(%%edi) )" + +"SRC( movl 24(%%esi), %%ebx )" +"SRC( movl 28(%%esi), %%edx )" + adcl %%ebx, %%eax +"DST( movl %%ebx, 24(%%edi) )" + adcl %%edx, %%eax +"DST( movl %%edx, 28(%%edi) )" + +"SRC( lea 32(%%esi), %%esi )" +"DST( lea 32(%%edi), %%edi )" + dec %%ecx + jne 1b + adcl $0, %%eax + 2: popl %%edx + movl %%edx, %%ecx + andl $0x1c, %%edx + je 4f + shrl $2, %%edx # This clears CF +"SRC( 3: movl (%%esi), %%ebx )" + adcl %%ebx, %%eax +"DST( movl %%ebx, (%%edi) )" +"SRC( lea 4(%%esi), %%esi )" +"DST( lea 4(%%edi), %%edi )" + dec %%edx + jne 3b + adcl $0, %%eax + 4: andl $3, %%ecx + jz 7f + cmpl $2, %%ecx + jb 5f +"SRC( movw (%%esi), %%cx )" +"SRC( leal 2(%%esi), %%esi )" +"DST( movw %%cx, (%%edi) )" +"DST( leal 2(%%edi), %%edi )" + je 6f + shll $16,%%ecx +"SRC( 5: movb (%%esi), %%cl )" +"DST( movb %%cl, (%%edi) )" + 6: addl %%ecx, %%eax + adcl $0, %%eax + 7: + +end_of_body: + +# Exception handler: +################################################ + # +.section .fixup, \"a\" # + # +common_fixup: # + # + movl %7, (%%ebx) # + # +# FIXME: do zeroing of rest of the buffer here. # + # + jmp end_of_body # + # +src_access_fault: # + movl %1, %%ebx # + jmp common_fixup # + # +dst_access_fault: # + movl %2, %%ebx # + jmp common_fixup # + # +.previous # + # +################################################ + +" + : "=a" (sum), "=m" (src_err_ptr), "=m" (dst_err_ptr) + : "0" (sum), "c" (len), "S" (src), "D" (dst), + "i" (-EFAULT) + : "bx", "cx", "dx", "si", "di" ); + + return(sum); +} -#define SRC(x) -#define DST(x) -csum_partial_copy_type(_nocheck_generic) #undef SRC #undef DST /* - * Generate 'csum_partial_copy_old()', old and slow compability stuff, - * full checking. - * - * tell us if you see something printk-ing on this. This function will be - * removed soon. + * FIXME: old compatibility stuff, will be removed soon. */ -#define SRC(x) x -#define DST(x) x -csum_partial_copy_type(_old) -#undef SRC -#undef DST - -unsigned int csum_partial_copy ( const char *src, char *dst, - int len, int sum) +unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum) { - int ret; - int error = 0; + int src_err=0, dst_err=0; - ret = csum_partial_copy_old (&error, src, dst, len, sum); + sum = csum_partial_copy_generic ( src, dst, len, sum, &src_err, &dst_err); - if (error) - printk("csum_partial_copy_old(): tell mingo to convert me!\n"); + if (src_err || dst_err) + printk("old csum_partial_copy_fromuser(), tell mingo to convert me.\n"); - return ret; + return sum; } + diff --git a/drivers/ap1000/apfddi.c b/drivers/ap1000/apfddi.c index 89cfef3f87b3..21f609ea2219 100644 --- a/drivers/ap1000/apfddi.c +++ b/drivers/ap1000/apfddi.c @@ -126,7 +126,7 @@ u_char fddi_bitrev[256] = { static u_char apfddi_saddr[6] = { 0x42, 0x9a, 0x08, 0x6e, 0x11, 0x41 }; struct device *apfddi_device = NULL; -struct enet_statistics *apfddi_stats = NULL; +struct net_device_stats *apfddi_stats = NULL; volatile struct apfddi_queue *apfddi_queue_top = NULL; @@ -254,7 +254,7 @@ int apfddi_init(struct device *dev); static void apfddi_interrupt(int irq, void *dev_id, struct pt_regs *regs); static int apfddi_xmit(struct sk_buff *skb, struct device *dev); int apfddi_rx(struct mac_buf *mbuf); -static struct enet_statistics *apfddi_get_stats(struct device *dev); +static struct net_device_stats *apfddi_get_stats(struct device *dev); #if APFDDI_DEBUG void dump_packet(char *action, char *buf, int len, int seq); #endif @@ -496,11 +496,11 @@ int apfddi_init(struct device *dev) dev->stop = apfddi_stop; dev->hard_start_xmit = apfddi_xmit; dev->get_stats = apfddi_get_stats; - dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_ATOMIC); + dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_ATOMIC); if (dev->priv == NULL) return -ENOMEM; - memset(dev->priv, 0, sizeof(struct enet_statistics)); - apfddi_stats = (struct enet_statistics *)apfddi_device->priv; + memset(dev->priv, 0, sizeof(struct net_device_stats)); + apfddi_stats = (struct net_device_stats *)apfddi_device->priv; /* Initialise the fddi device structure */ for (i = 0; i < DEV_NUMBUFFS; i++) @@ -692,9 +692,9 @@ void print_mbuf(struct mac_buf *mbuf) /* * Return statistics of fddi driver. */ -static struct enet_statistics *apfddi_get_stats(struct device *dev) +static struct net_device_stats *apfddi_get_stats(struct device *dev) { - return((struct enet_statistics *)dev->priv); + return((struct net_device_stats *)dev->priv); } diff --git a/drivers/ap1000/apfddi.h b/drivers/ap1000/apfddi.h index 021bd00ace2f..33230186e44f 100644 --- a/drivers/ap1000/apfddi.h +++ b/drivers/ap1000/apfddi.h @@ -138,5 +138,5 @@ void rmt_event(int st); void set_cf_join(int on); extern struct device *apfddi_device; -extern struct enet_statistics *apfddi_stats; +extern struct net_device_stats *apfddi_stats; diff --git a/drivers/ap1000/bif.c b/drivers/ap1000/bif.c index 52ea4a82d2d7..45ae418f4609 100644 --- a/drivers/ap1000/bif.c +++ b/drivers/ap1000/bif.c @@ -46,14 +46,14 @@ static int seq = 0; #define BIF_MTU 10240 static struct device *bif_device = 0; -static struct enet_statistics *bif_stats = 0; +static struct net_device_stats *bif_stats = 0; int bif_init(struct device *dev); int bif_open(struct device *dev); static int bif_xmit(struct sk_buff *skb, struct device *dev); int bif_rx(struct sk_buff *skb); int bif_stop(struct device *dev); -static struct enet_statistics *bif_get_stats(struct device *dev); +static struct net_device_stats *bif_get_stats(struct device *dev); static int bif_hard_header(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr, @@ -128,11 +128,11 @@ int bif_init(struct device *dev) dev->open = bif_open; dev->flags = IFF_NOARP; /* Don't use ARP on this device */ dev->family = AF_INET; - dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL); + dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; - memset(dev->priv, 0, sizeof(struct enet_statistics)); - bif_stats = (struct enet_statistics *)bif_device->priv; + memset(dev->priv, 0, sizeof(struct net_device_stats)); + bif_stats = (struct net_device_stats *)bif_device->priv; dev->stop = bif_stop; @@ -282,8 +282,8 @@ int bif_stop(struct device *dev) /* * Return statistics of bif driver. */ -static struct enet_statistics *bif_get_stats(struct device *dev) +static struct net_device_stats *bif_get_stats(struct device *dev) { - return((struct enet_statistics *)dev->priv); + return((struct net_device_stats *)dev->priv); } diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 2cc76af203e3..30e3ce491057 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -29,19 +29,17 @@ * by Chris Faylor. * * Most recent changes: (Andrew J. Robinson) - * Remove all references to tty->hw_stopped. - * Request a single region for multiple ports if possible. - * Stop a DMA transfer on a port when it is closed. - * Rename esp_init() to espserial_init(). - * Improve validation of IRQ (only accept those allowed by the ESP card). - * Return if a signal is received while wait for a break to start. - * Split NEED_DMA logic into NEED_DMA_RX and NEED_DMA_TX. + * Don't cause a kernel panic if memory could not be allocated or if the + * device couldn't be registered. + * Always set RTS when transitioning away from B0 status (since the + * flow is really being handled by the ESP card). * * This module exports the following rs232 io functions: * * int espserial_init(void); */ +#include #include #include #include @@ -51,7 +49,6 @@ #include #include #include -#include #include #include #include @@ -95,7 +92,7 @@ static int dma_bytes; #define WAKEUP_CHARS 1024 static char *serial_name = "ESP serial driver"; -static char *serial_version = "1.3"; +static char *serial_version = "1.5"; DECLARE_TASK_QUEUE(tq_esp); @@ -1851,9 +1848,7 @@ static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) /* Handle transition away from B0 status */ if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) { - info->MCR |= UART_MCR_DTR; - if (!(tty->termios->c_cflag & CRTSCTS)) - info->MCR |= UART_MCR_RTS; + info->MCR |= (UART_MCR_DTR | UART_MCR_RTS); cli(); serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); serial_out(info, UART_ESI_CMD2, UART_MCR); @@ -2460,14 +2455,29 @@ int espserial_init(void) esp_callout_driver.subtype = SERIAL_TYPE_CALLOUT; if (tty_register_driver(&esp_driver)) - panic("Couldn't register serial driver\n"); + { + printk(KERN_ERR "Couldn't register esp serial driver"); + return 1; + } + if (tty_register_driver(&esp_callout_driver)) - panic("Couldn't register callout driver\n"); + { + printk(KERN_ERR "Couldn't register esp callout driver"); + tty_unregister_driver(&esp_driver); + return 1; + } info = (struct esp_struct *)kmalloc(sizeof(struct esp_struct), GFP_KERNEL); + if (!info) - panic("Could not allocate memory for device information\n"); + { + printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n"); + tty_unregister_driver(&esp_driver); + tty_unregister_driver(&esp_callout_driver); + return 1; + } + memset((void *)info, 0, sizeof(struct esp_struct)); i = 0; @@ -2515,7 +2525,13 @@ int espserial_init(void) info = (struct esp_struct *)kmalloc(sizeof(struct esp_struct), GFP_KERNEL); if (!info) - panic("Could not allocate memory for device information\n"); + { + printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n"); + + /* allow use of the already detected ports */ + return 0; + } + memset((void *)info, 0, sizeof(struct esp_struct)); if (offset == 56) { diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index 7281f52448b7..b3806503093c 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -509,7 +509,7 @@ again: /* * There are three modes here for doing the packet copy. * If we have DMA, and the packet is "long", we use the - * chaining mode of DMA. If its shorter, we use single + * chaining mode of DMA. If it's shorter, we use single * DMA's. Otherwise, we use memcpy(). */ if (priv0->use_dma && priv0->dmadesc_h && len > 64) diff --git a/drivers/net/ibmtr.c b/drivers/net/ibmtr.c index 24041c8a27bf..3f3630841d67 100644 --- a/drivers/net/ibmtr.c +++ b/drivers/net/ibmtr.c @@ -175,19 +175,10 @@ static int tok_open(struct device *dev); static int tok_close(struct device *dev); static int tok_send_packet(struct sk_buff *skb, struct device *dev); static struct net_device_stats * tok_get_stats(struct device *dev); -void tr_readlog(struct device *dev); +void ibmtr_readlog(struct device *dev); +void ibmtr_reset_timer(struct timer_list *tmr, struct device *dev); -/* FIXME: Should use init_timer and friends not assume the structure - is constant! */ - -static struct timer_list tr_timer = -{ - NULL, - NULL, - 0, - 0L, - tok_open_adapter -}; +static struct timer_list tr_timer; static unsigned int ibmtr_portlist[] = { 0xa20, 0xa24, 0 @@ -793,7 +784,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) ti->current_skb=NULL; } dev->tbusy=0; - if (ti->readlog_pending) tr_readlog(dev); + if (ti->readlog_pending) ibmtr_readlog(dev); } } break; @@ -810,7 +801,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) ti->current_skb=NULL; } dev->tbusy=0; - if (ti->readlog_pending) tr_readlog(dev); + if (ti->readlog_pending) ibmtr_readlog(dev); } } break; @@ -867,10 +858,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) open_ret_code); if (ti->open_status != FAILURE) { - tr_timer.expires=jiffies+TR_RETRY_INTERVAL; - tr_timer.data=(unsigned long)dev; - tr_timer.next=tr_timer.prev=NULL; - add_timer(&tr_timer); + ibmtr_reset_timer(&tr_timer, dev); } } @@ -884,10 +872,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) if (readb(ti->srb+offsetof(struct dlc_open_sap, ret_code))) { DPRINTK("open_sap failed: ret_code = %02X,retrying\n", (int)readb(ti->srb+offsetof(struct dlc_open_sap, ret_code))); - tr_timer.expires=jiffies+TR_RETRY_INTERVAL; - tr_timer.data=(unsigned long)dev; - tr_timer.next=tr_timer.prev=NULL; - add_timer(&tr_timer); + ibmtr_reset_timer(&tr_timer, dev); } else { ti->exsap_station_id= readw(ti->srb+offsetof(struct dlc_open_sap, station_id)); @@ -998,11 +983,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) DPRINTK("Signal loss/Lobe fault\n"); DPRINTK("We try to reopen the adapter.\n"); - tr_timer.expires=jiffies+TR_RETRY_INTERVAL; - tr_timer.data=(unsigned long)dev; - tr_timer.next=tr_timer.prev=NULL; - add_timer(&tr_timer); - + ibmtr_reset_timer(&tr_timer, dev); } else if (ring_status & (HARD_ERROR | XMIT_BEACON | AUTO_REMOVAL | REMOVE_RECV | RING_RECOVER)) DPRINTK("New ring status: %02X\n", ring_status); @@ -1011,7 +992,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) if (dev->tbusy) ti->readlog_pending = 1; else - tr_readlog(dev); + ibmtr_readlog(dev); } } break; @@ -1124,7 +1105,8 @@ static void initial_tok_int(struct device *dev) DPRINTK("encoded addr (%04X,%04X,%08X): ", hw_encoded_addr, ntohs(hw_encoded_addr), encoded_addr); #else - DPRINTK("Initial interrupt : shared RAM located at %08x.\n", ti->sram); + DPRINTK("Initial interrupt : %s Mbps, shared RAM base %08x.\n", + (readb(ti->init_srb+offsetof(struct srb_init_response, init_status)) & 0x01) ? "16" : "4", ti->sram); #endif ti->auto_ringspeedsave=readb(ti->init_srb @@ -1342,7 +1324,7 @@ static void tr_tx(struct device *dev) dev_kfree_skb(ti->current_skb,FREE_WRITE); ti->current_skb=NULL; mark_bh(NET_BH); - if (ti->readlog_pending) tr_readlog(dev); + if (ti->readlog_pending) ibmtr_readlog(dev); } static void tr_rx(struct device *dev) @@ -1545,7 +1527,15 @@ static int tok_send_packet(struct sk_buff *skb, struct device *dev) return 0; } -void tr_readlog(struct device *dev) { +void ibmtr_reset_timer(struct timer_list *tmr, struct device *dev) { + tmr->expires = jiffies + TR_RETRY_INTERVAL; + tmr->data = (unsigned long) dev; + tmr->function = tok_open_adapter; + init_timer(tmr); + add_timer(tmr); +} + +void ibmtr_readlog(struct device *dev) { struct tok_info *ti; ti=(struct tok_info *) dev->priv; diff --git a/drivers/net/pi2.h b/drivers/net/pi2.h index aca659f7a687..1740cc0b2ebd 100644 --- a/drivers/net/pi2.h +++ b/drivers/net/pi2.h @@ -82,7 +82,7 @@ struct pi_req { /* Information that needs to be kept for each channel. */ struct pi_local { - struct netstats stats; /* %%%dp*/ + struct net_device_stats stats; long open_time; /* Useless example local info. */ unsigned long xtal; diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c index 24db6171fb6e..4946f1bfe68d 100644 --- a/drivers/net/seeq8005.c +++ b/drivers/net/seeq8005.c @@ -64,7 +64,7 @@ static unsigned int net_debug = NET_DEBUG; /* Information that need to be kept for each board. */ struct net_local { - struct net_driver_stats stats; + struct net_device_stats stats; unsigned short receive_ptr; /* What address in packet memory do we expect a recv_pkt_header? */ long open_time; /* Useless example local info. */ }; @@ -84,7 +84,7 @@ static int seeq8005_send_packet(struct sk_buff *skb, struct device *dev); static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void seeq8005_rx(struct device *dev); static int seeq8005_close(struct device *dev); -static struct net_driver_stats *seeq8005_get_stats(struct device *dev); +static struct net_device_stats *seeq8005_get_stats(struct device *dev); static void set_multicast_list(struct device *dev); /* Example routines you must write ;->. */ @@ -593,7 +593,7 @@ seeq8005_close(struct device *dev) /* Get the current statistics. This may be called with the card open or closed. */ -static struct net_driver_stats *seeq8005_get_stats(struct device *dev) +static struct net_device_stats *seeq8005_get_stats(struct device *dev) { struct net_local *lp = (struct net_local *)dev->priv; diff --git a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c index a288e1e40eeb..abf4ef380d90 100644 --- a/drivers/net/sk_g16.c +++ b/drivers/net/sk_g16.c @@ -457,7 +457,7 @@ struct priv int tmdlast; /* last sent descriptor used for error handling, etc */ void *rmdbufs[RMDNUM]; /* pointer to the receive buffers */ void *tmdbufs[TMDNUM]; /* pointer to the transmit buffers */ - struct net_driver_stats stats; /* Device driver statistics */ + struct net_device_stats stats; /* Device driver statistics */ }; /* global variable declaration */ @@ -491,7 +491,7 @@ static void SK_rxintr(struct device *dev); static void SK_txintr(struct device *dev); static int SK_close(struct device *dev); -static struct net_driver_stats *SK_get_stats(struct device *dev); +static struct net_device_stats *SK_get_stats(struct device *dev); unsigned int SK_rom_addr(void); @@ -1681,14 +1681,14 @@ static int SK_close(struct device *dev) * It is called by sprintf_stats (dev.c). * * Parameters : I : struct device *dev - our device structure - * Return Value : struct net_driver_stats * - our current statistics + * Return Value : struct net_device_stats * - our current statistics * Errors : None * Side Effects : None * Update History : * YY/MM/DD uid Description -*/ -static struct net_driver_stats *SK_get_stats(struct device *dev) +static struct net_device_stats *SK_get_stats(struct device *dev) { struct priv *p = (struct priv *) dev->priv; diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index ac1833e51f62..1e8f5e96f9b8 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -175,7 +175,7 @@ struct smc_local { can find out semi-useless statistics of how well the card is performing */ - struct net_driver_stats stats; + struct net_device_stats stats; /* If I have to wait until memory is available to send @@ -234,7 +234,7 @@ static int smc_close(struct device *dev); . This routine allows the proc file system to query the driver's . statistics. */ -static struct net_driver_stats * smc_query_statistics( struct device *dev); +static struct net_device_stats * smc_query_statistics( struct device *dev); /* . Finally, a call to set promiscuous mode ( for TCPDUMP and related @@ -1643,7 +1643,7 @@ static int smc_close(struct device *dev) . Get the current statistics. . This may be called with the card open or closed. .-------------------------------------------------------------*/ -static struct net_driver_stats* smc_query_statistics(struct device *dev) { +static struct net_device_stats* smc_query_statistics(struct device *dev) { struct smc_local *lp = (struct smc_local *)dev->priv; return &lp->stats; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6c6ffd3f9892..8106ae66189c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -152,6 +152,7 @@ struct pci_dev_info dev_info[] = { DEVICE( 3COM, 3COM_3C595T4, "3C595 100bT4"), DEVICE( 3COM, 3COM_3C595MII, "3C595 100b-MII"), DEVICE( 3COM, 3COM_3C900TPO, "3C900 10bTPO"), + DEVICE( 3COM, 3COM_3C905TX, "3C905 100bTX"), DEVICE( AL, AL_M1445, "M1445"), DEVICE( AL, AL_M1449, "M1449"), DEVICE( AL, AL_M1451, "M1451"), @@ -270,8 +271,9 @@ struct pci_dev_info dev_info[] = { DEVICE( ADAPTEC, ADAPTEC_7883, "AIC-7883U"), DEVICE( ADAPTEC, ADAPTEC_7884, "AIC-7884U"), DEVICE( ATRONICS, ATRONICS_2015, "IDE-2015PL"), - DEVICE( HER, HER_STING, "Stingray"), - DEVICE( HER, HER_STINGARK, "Stingray ARK 2000PV") + DEVICE( ARK, ARK_STING, "Stingray"), + DEVICE( ARK, ARK_STINGARK, "Stingray ARK 2000PV"), + DEVICE( ARK, ARK_2000MT, "2000MT") }; @@ -546,7 +548,7 @@ const char *pci_strvendor(unsigned int vendor) case PCI_VENDOR_ID_INTEL: return "Intel"; case PCI_VENDOR_ID_ADAPTEC: return "Adaptec"; case PCI_VENDOR_ID_ATRONICS: return "Atronics"; - case PCI_VENDOR_ID_HER: return "Hercules"; + case PCI_VENDOR_ID_ARK: return "ARK Logic"; default: return "Unknown vendor"; } } diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 1fb997667a36..916ffd3a7ff8 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -238,7 +238,6 @@ static struct dev_info device_list[] = {"MAXTOR","XT-4170S","B5A", BLIST_NOLUN}, /* Locks-up sometimes when LUN>0 polled. */ {"MAXTOR","XT-8760S","B7B", BLIST_NOLUN}, /* guess what? */ {"MEDIAVIS","RENO CD-ROMX2A","2.03",BLIST_NOLUN},/*Responds to all lun */ -{"HP", "C3725S", "*", BLIST_NOTQ}, /* Buggy Tagged Queuing */ {"MICROP", "4110", "*", BLIST_NOTQ}, /* Buggy Tagged Queuing */ {"NEC","CD-ROM DRIVE:841","1.0", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */ {"RODIME","RO3000S","2.33", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index c552f6cf995a..7d2486b1a252 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -247,6 +247,7 @@ static int ioctl_command(Scsi_Device *dev, Scsi_Ioctl_Command *sic) retries = 1; break; case START_STOP: + case MOVE_MEDIUM: timeout = 60 * HZ; /* 60 seconds */ retries = 1; break; diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index 82fe38e49340..59f4ab8a3fdd 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c @@ -598,6 +598,7 @@ static inline int root_send_udp(struct socket *sock, void *buf, int size) iov.iov_base = buf; iov.iov_len = size; msg.msg_name = NULL; + msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; @@ -624,6 +625,7 @@ static inline int root_recv_udp(struct socket *sock, void *buf, int size) iov.iov_base = buf; iov.iov_len = size; msg.msg_name = NULL; + msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; diff --git a/fs/select.c b/fs/select.c index 8ab7d229f4ab..683865a30fec 100644 --- a/fs/select.c +++ b/fs/select.c @@ -62,25 +62,31 @@ static void free_wait(poll_table * p) } /* - * Due to kernel stack usage, we use a _limited_ fd_set type here, and once - * we really start supporting >256 file descriptors we'll probably have to - * allocate the kernel fd_set copies dynamically.. (The kernel select routines - * are careful to touch only the defined low bits of any fd_set pointer, this - * is important for performance too). + * For the kernel fd_set we use a fixed set-size for allocation purposes. + * This set-size doesn't necessarily bear any relation to the size the user + * uses, but should preferably obviously be larger than any possible user + * size (NR_OPEN bits). + * + * We need 6 bitmaps (in/out/ex for both incoming and outgoing), and we + * allocate one page for all the bitmaps. Thus we have 8*PAGE_SIZE bits, + * to be divided by 6. And we'd better make sure we round to a full + * long-word (in fact, we'll round to 64 bytes). */ -typedef unsigned long limited_fd_set[NR_OPEN/(8*(sizeof(unsigned long)))]; +#define KFDS_64BLOCK ((PAGE_SIZE/(6*64))*64) +#define KFDS_NR (KFDS_64BLOCK*8 > NR_OPEN ? NR_OPEN : KFDS_64BLOCK*8) +typedef unsigned long kernel_fd_set[KFDS_NR/(8*sizeof(unsigned long))]; typedef struct { - limited_fd_set in, out, ex; - limited_fd_set res_in, res_out, res_ex; + kernel_fd_set in, out, ex; + kernel_fd_set res_in, res_out, res_ex; } fd_set_buffer; #define __IN(in) (in) -#define __OUT(in) (in + sizeof(limited_fd_set)/sizeof(unsigned long)) -#define __EX(in) (in + 2*sizeof(limited_fd_set)/sizeof(unsigned long)) -#define __RES_IN(in) (in + 3*sizeof(limited_fd_set)/sizeof(unsigned long)) -#define __RES_OUT(in) (in + 4*sizeof(limited_fd_set)/sizeof(unsigned long)) -#define __RES_EX(in) (in + 5*sizeof(limited_fd_set)/sizeof(unsigned long)) +#define __OUT(in) (in + sizeof(kernel_fd_set)/sizeof(unsigned long)) +#define __EX(in) (in + 2*sizeof(kernel_fd_set)/sizeof(unsigned long)) +#define __RES_IN(in) (in + 3*sizeof(kernel_fd_set)/sizeof(unsigned long)) +#define __RES_OUT(in) (in + 4*sizeof(kernel_fd_set)/sizeof(unsigned long)) +#define __RES_EX(in) (in + 5*sizeof(kernel_fd_set)/sizeof(unsigned long)) #define BITS(in) (*__IN(in)|*__OUT(in)|*__EX(in)) @@ -277,17 +283,20 @@ __zero_fd_set((nr)-1, (unsigned long *) (fdp)) asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp) { int error = -EINVAL; - fd_set_buffer fds; + fd_set_buffer *fds; unsigned long timeout; lock_kernel(); + fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL); + if (!fds) + goto out; if (n < 0) goto out; - if (n > NR_OPEN) - n = NR_OPEN; - if ((error = get_fd_set(n, inp, &fds.in)) || - (error = get_fd_set(n, outp, &fds.out)) || - (error = get_fd_set(n, exp, &fds.ex))) goto out; + if (n > KFDS_NR) + n = KFDS_NR; + if ((error = get_fd_set(n, inp, &fds->in)) || + (error = get_fd_set(n, outp, &fds->out)) || + (error = get_fd_set(n, exp, &fds->ex))) goto out; timeout = ~0UL; if (tvp) { error = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp)); @@ -303,11 +312,11 @@ asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct if (timeout) timeout += jiffies + 1; } - zero_fd_set(n, &fds.res_in); - zero_fd_set(n, &fds.res_out); - zero_fd_set(n, &fds.res_ex); + zero_fd_set(n, &fds->res_in); + zero_fd_set(n, &fds->res_out); + zero_fd_set(n, &fds->res_ex); current->timeout = timeout; - error = do_select(n, &fds); + error = do_select(n, fds); timeout = current->timeout - jiffies - 1; current->timeout = 0; if ((long) timeout < 0) @@ -326,10 +335,11 @@ asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct goto out; error = 0; } - set_fd_set(n, inp, &fds.res_in); - set_fd_set(n, outp, &fds.res_out); - set_fd_set(n, exp, &fds.res_ex); + set_fd_set(n, inp, &fds->res_in); + set_fd_set(n, outp, &fds->res_out); + set_fd_set(n, exp, &fds->res_ex); out: + free_page((unsigned long) fds); unlock_kernel(); return error; } @@ -376,15 +386,12 @@ static int do_poll(unsigned int nfds, struct pollfd *fds, poll_table *wait) asmlinkage int sys_poll(struct pollfd * ufds, unsigned int nfds, int timeout) { - int i, count, fdcount, err = -EINVAL; + int i, count, fdcount, err; struct pollfd * fds, *fds1; poll_table wait_table; struct poll_table_entry *entry; lock_kernel(); - if (nfds > NR_OPEN) - goto out; - err = -ENOMEM; entry = (struct poll_table_entry *) __get_free_page(GFP_KERNEL); if (!entry) diff --git a/include/asm-alpha/checksum.h b/include/asm-alpha/checksum.h index 26c67252122d..4b0b878e10cb 100644 --- a/include/asm-alpha/checksum.h +++ b/include/asm-alpha/checksum.h @@ -44,9 +44,16 @@ unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int /* * the same as csum_partial, but copies from user space (but on the alpha * we have just one address space, so this is identical to the above) + * + * this is obsolete and will go away. */ #define csum_partial_copy_fromuser csum_partial_copy +/* + * this is a new version of the above that records errors it finds in *errp, + * but continues and zeros the rest of the buffer. + */ +unsigned int csum_partial_copy_from_user(int *errp, char *src, char *dst, int len, unsigned int sum); /* * this routine is used for miscellaneous IP-like checksums, mainly diff --git a/include/asm-alpha/current.h b/include/asm-alpha/current.h index 9ade4d8f33be..56d12724b286 100644 --- a/include/asm-alpha/current.h +++ b/include/asm-alpha/current.h @@ -3,10 +3,10 @@ /* Some architectures may want to do something "clever" here since * this is the most frequently accessed piece of data in the entire - * kernel. For an example, see the Sparc implementation where an - * entire register is hard locked to contain the value of current. + * kernel. */ extern struct task_struct *current_set[NR_CPUS]; -#define current (current_set[smp_processor_id()]) /* Current on this processor */ + +register struct task_struct *current __asm__("$8"); #endif /* !(_ALPHA_CURRENT_H) */ diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h index db9c62a7d214..91d78c3f38af 100644 --- a/include/asm-alpha/system.h +++ b/include/asm-alpha/system.h @@ -56,8 +56,8 @@ extern void wrmces (unsigned long); #define halt() __asm__ __volatile__ ("call_pal %0" : : "i" (PAL_halt) : "memory") #define switch_to(prev,next) do { \ - current_set[0] = next; \ - alpha_switch_to((unsigned long) &(next)->tss - 0xfffffc0000000000); \ + current_set[0] = current = next; \ + alpha_switch_to((unsigned long) ¤t->tss - 0xfffffc0000000000); \ } while (0) extern void alpha_switch_to(unsigned long pctxp); diff --git a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h index bec632323a29..284a30ee4bce 100644 --- a/include/asm-i386/checksum.h +++ b/include/asm-i386/checksum.h @@ -23,26 +23,42 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) * better 64-bit) boundary */ -unsigned int csum_partial_copy_from_user( int * err, const char *src, - char *dst, int len, int sum); +unsigned int csum_partial_copy_generic( const char *src, char *dst, int len, int sum, + int *src_err_ptr, int *dst_err_ptr); + +extern __inline__ +unsigned int csum_partial_copy_nocheck ( const char *src, char *dst, + int len, int sum) +{ + int *src_err_ptr=NULL, *dst_err_ptr=NULL; + + return csum_partial_copy_generic ( src, dst, len, sum, src_err_ptr, dst_err_ptr); +} + +extern __inline__ +unsigned int csum_partial_copy_from_user ( const char *src, char *dst, + int len, int sum, int *err_ptr) +{ + int *dst_err_ptr=NULL; + + return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, dst_err_ptr); +} /* - * I hope GCC will optimize 'dummy' away ... + * This combination is currently not used, but possible: */ -unsigned int csum_partial_copy_nocheck_generic( int * err, const char *src, char *dst, - int len, int sum); - -extern __inline__ unsigned int csum_partial_copy_nocheck ( const char *src, char *dst, - int len, int sum) +extern __inline__ +unsigned int csum_partial_copy_to_user ( const char *src, char *dst, + int len, int sum, int *err_ptr) { - int dummy; + int *src_err_ptr=NULL; - return csum_partial_copy_nocheck_generic ( &dummy, src, dst, len, sum); + return csum_partial_copy_generic ( src, dst, len, sum, src_err_ptr, err_ptr); } /* - * These are the 'old' way of doing checksums, a warning message will be + * These are the old (and unsafe) way of doing checksums, a warning message will be * printed if they are used and an exeption occurs. * * these functions should go away after some time. diff --git a/include/linux/fs.h b/include/linux/fs.h index b887ce152318..bd5d8a089b39 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -27,7 +27,7 @@ /* Fixed constants first: */ #undef NR_OPEN -#define NR_OPEN 256 +#define NR_OPEN 1024 #define NR_SUPER 64 #define BLOCK_SIZE 1024 diff --git a/include/linux/icmp.h b/include/linux/icmp.h index 10bed4c34d88..9e5dd8899b0f 100644 --- a/include/linux/icmp.h +++ b/include/linux/icmp.h @@ -80,11 +80,12 @@ struct icmphdr { } un; }; +#ifdef __KERNEL__ struct icmp_err { int errno; unsigned fatal:1; }; - +#endif #endif /* _LINUX_ICMP_H */ diff --git a/include/linux/if_tr.h b/include/linux/if_tr.h index 545f1b7f07a8..985aa062fc07 100644 --- a/include/linux/if_tr.h +++ b/include/linux/if_tr.h @@ -94,8 +94,8 @@ struct tr_statistics { #define TR_RII 0x80 #define TR_RCF_DIR_BIT 0x80 #define TR_RCF_LEN_MASK 0x1f00 -#define TR_RCF_BROADCAST 0x8000 -#define TR_RCF_LIMITED_BROADCAST 0xA000 +#define TR_RCF_BROADCAST 0x8000 /* all-routes broadcast */ +#define TR_RCF_LIMITED_BROADCAST 0xC000 /* single-route broadcast */ #define TR_RCF_FRAME2K 0x20 #define TR_RCF_BROADCAST_MASK 0xC000 diff --git a/include/linux/limits.h b/include/linux/limits.h index 14428592c4f6..b99a12bc053b 100644 --- a/include/linux/limits.h +++ b/include/linux/limits.h @@ -1,7 +1,7 @@ #ifndef _LINUX_LIMITS_H #define _LINUX_LIMITS_H -#define NR_OPEN 256 +#define NR_OPEN 1024 #define NGROUPS_MAX 32 /* supplemental group IDs are available */ #define ARG_MAX 131072 /* # bytes of args + environ for exec() */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 3318c2ae8039..7b27236a9fe5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -185,12 +185,6 @@ struct device unsigned char if_port; /* Selectable AUI, TP,..*/ unsigned char dma; /* DMA channel */ - /* - * FIXME: - * The description 'enet_statistics' is misleading. We - * should change this. - */ - struct net_device_stats* (*get_stats)(struct device *dev); struct iw_statistics* (*get_wireless_stats)(struct device *dev); diff --git a/include/linux/pci.h b/include/linux/pci.h index 37aeb1f84128..30e0001e79fc 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -31,14 +31,14 @@ * PCI-CPU bridge or PCI-ISA bridge. * - If you can't find the actual information in your hardware * booklet, try to read the references of the chip on the board. - * - Send all that to linux-pcisupport@cao-vlsi.ibp.fr, + * - Send all that to linux-pcisupport@cck.uni-kl.de * and I'll add your device to the list as soon as possible * * BEFORE you send a mail, please check the latest linux releases * to be sure it has not been recently added. * * Thanks - * Frederic Potter. + * Jens Maurer */ @@ -418,6 +418,7 @@ #define PCI_DEVICE_ID_3COM_3C595T4 0x5951 #define PCI_DEVICE_ID_3COM_3C595MII 0x5952 #define PCI_DEVICE_ID_3COM_3C900TPO 0x9000 +#define PCI_DEVICE_ID_3COM_3C905TX 0x9050 #define PCI_VENDOR_ID_AL 0x10b9 #define PCI_DEVICE_ID_AL_M1445 0x1445 @@ -607,9 +608,10 @@ #define PCI_VENDOR_ID_ATRONICS 0x907f #define PCI_DEVICE_ID_ATRONICS_2015 0x2015 -#define PCI_VENDOR_ID_HER 0xedd8 -#define PCI_DEVICE_ID_HER_STING 0xa091 -#define PCI_DEVICE_ID_HER_STINGARK 0xa099 +#define PCI_VENDOR_ID_ARK 0xedd8 +#define PCI_DEVICE_ID_ARK_STING 0xa091 +#define PCI_DEVICE_ID_ARK_STINGARK 0xa099 +#define PCI_DEVICE_ID_ARK_2000MT 0xa0a1 /* * The PCI interface treats multi-function devices as independent diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 1bf172b89434..5fd6e6d2f608 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -127,6 +127,7 @@ enum net_directory_inos { PROC_NET_X25_LINKS, PROC_NET_X25_ROUTES, PROC_NET_X25, + PROC_NET_TR_RIF, PROC_NET_LAST }; diff --git a/include/linux/sched.h b/include/linux/sched.h index 590f9b2910a3..af19cbed636e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -127,7 +127,7 @@ struct files_struct { struct fs_struct { int count; - unsigned short umask; + int umask; struct inode * root, * pwd; }; diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index cd5fbb933958..dd323490ea5e 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -84,6 +84,7 @@ struct __sysctl_args { #define NET_IPV6 11 #define NET_ROSE 12 #define NET_X25 13 +#define NET_TR 14 /* /proc/sys/net/core */ @@ -166,6 +167,12 @@ enum { NET_X25_ACK_HOLD_BACK_TIMEOUT }; +/* /proc/sys/net/token-ring */ +enum +{ + NET_TR_RIF_TIMEOUT=1 +}; + /* CTL_PROC names: */ /* CTL_FS names: */ diff --git a/include/net/lapb.h b/include/net/lapb.h index d6c87f7b323d..da2094576bae 100644 --- a/include/net/lapb.h +++ b/include/net/lapb.h @@ -44,11 +44,11 @@ #define LAPB_ADDR_D 0x07 /* Define Link State constants. */ -#define LAPB_STATE_0 0 -#define LAPB_STATE_1 1 -#define LAPB_STATE_2 2 -#define LAPB_STATE_3 3 -#define LAPB_STATE_4 4 +#define LAPB_STATE_0 0 /* Disconnected State */ +#define LAPB_STATE_1 1 /* Awaiting Connection State */ +#define LAPB_STATE_2 2 /* Awaiting Disconnection State */ +#define LAPB_STATE_3 3 /* Data Transfer State */ +#define LAPB_STATE_4 4 /* Frame Reject State */ #define LAPB_DEFAULT_MODE (LAPB_STANDARD | LAPB_SLP | LAPB_DTE) #define LAPB_DEFAULT_WINDOW 7 /* Window=7 */ @@ -69,6 +69,7 @@ typedef struct lapb_cb { unsigned short n2, n2count; unsigned short t1, t2; unsigned short t1timer, t2timer; + struct sk_buff_head input_queue; struct sk_buff_head write_queue; struct sk_buff_head ack_queue; unsigned char window; @@ -77,7 +78,6 @@ typedef struct lapb_cb { } lapb_cb; /* lapb_iface.c */ -extern lapb_cb *lapb_tokentostruct(void *); extern void lapb_connect_confirmation(lapb_cb *, int); extern void lapb_connect_indication(lapb_cb *, int); extern void lapb_disconnect_confirmation(lapb_cb *, int); @@ -86,13 +86,12 @@ extern int lapb_data_indication(lapb_cb *, struct sk_buff *); extern int lapb_data_transmit(lapb_cb *, struct sk_buff *); /* lapb_in.c */ +extern void lapb_data_input(lapb_cb *, struct sk_buff *); /* lapb_out.c */ extern void lapb_kick(lapb_cb *); extern void lapb_transmit_buffer(lapb_cb *, struct sk_buff *, int); -extern void lapb_nr_error_recovery(lapb_cb *); extern void lapb_establish_data_link(lapb_cb *); -extern void lapb_transmit_enquiry(lapb_cb *); extern void lapb_enquiry_response(lapb_cb *); extern void lapb_timeout_response(lapb_cb *); extern void lapb_check_iframes_acked(lapb_cb *, unsigned short); diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 8328210e856c..1020a33b9168 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -74,12 +74,14 @@ #define LOG_SENSE 0x4d #define MODE_SELECT_10 0x55 #define MODE_SENSE_10 0x5a +#define MOVE_MEDIUM 0xa5 #define READ_12 0xa8 #define WRITE_12 0xaa #define WRITE_VERIFY_12 0xae #define SEARCH_HIGH_12 0xb0 #define SEARCH_EQUAL_12 0xb1 #define SEARCH_LOW_12 0xb2 +#define READ_ELEMENT_STATUS 0xb8 #define SEND_VOLUME_TAG 0xb6 #define WRITE_LONG_2 0xea diff --git a/kernel/ksyms.c b/kernel/ksyms.c index c13d728fb2ff..18f8025f3f2b 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -49,7 +49,7 @@ #include #include -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE) extern struct drive_info_struct drive_info; #endif @@ -202,7 +202,7 @@ EXPORT_SYMBOL(gendisk_head); EXPORT_SYMBOL(resetup_one_dev); EXPORT_SYMBOL(unplug_device); -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE) EXPORT_SYMBOL(drive_info); #endif diff --git a/kernel/sched.c b/kernel/sched.c index c4d2726647a7..e24e10e8ab6b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1187,23 +1187,32 @@ static void update_process_times(unsigned long ticks, unsigned long system) #endif } -static unsigned long lost_ticks = 0; +volatile unsigned long lost_ticks = 0; static unsigned long lost_ticks_system = 0; static inline void update_times(void) { unsigned long ticks; + unsigned long flags; - ticks = xchg(&lost_ticks, 0); + save_flags(flags); + cli(); + + ticks = lost_ticks; + lost_ticks = 0; if (ticks) { unsigned long system; - system = xchg(&lost_ticks_system, 0); + calc_load(ticks); update_wall_time(ticks); + restore_flags(flags); + update_process_times(ticks, system); - } + + } else + restore_flags(flags); } static void timer_bh(void) @@ -1349,21 +1358,21 @@ asmlinkage int sys_nice(int increment) { unsigned long newprio; int increase = 0; - int ret = -EPERM; /* - * We need a lock. sys_setpriority can affect other tasks. + * Setpriority might change our priority at the same moment. + * We don't have to worry. Conceptually one call occurs first + * and we have a single winner. */ - lock_kernel(); newprio = increment; if (increment < 0) { if (!suser()) - goto out; + return -EPERM; newprio = -increment; increase = 1; } - ret = 0; + if (newprio > 40) newprio = 40; /* @@ -1377,15 +1386,21 @@ asmlinkage int sys_nice(int increment) increment = newprio; if (increase) increment = -increment; + /* + * Current->priority can change between this point + * and the assignment. We are assigning not doing add/subs + * so thats ok. Conceptually a process might just instantaneously + * read the value we stomp over. I don't think that is an issue + * unless posix makes it one. If so we can loop on changes + * to current->priority. + */ newprio = current->priority - increment; if ((signed) newprio < 1) newprio = 1; if (newprio > DEF_PRIORITY*2) newprio = DEF_PRIORITY*2; current->priority = newprio; -out: - unlock_kernel(); - return ret; + return 0; } #endif diff --git a/kernel/signal.c b/kernel/signal.c index 9e8afe95fd11..8143c9b11318 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -72,9 +72,8 @@ asmlinkage int sys_sgetmask(void) { int ret; - lock_kernel(); + /* SMP safe */ ret = current->blocked; - unlock_kernel(); return ret; } diff --git a/kernel/sys.c b/kernel/sys.c index 105c7bc4429d..94b6cc0fe096 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -205,18 +205,17 @@ extern asmlinkage int sys_kill(int, int); */ asmlinkage int sys_reboot(int magic, int magic_too, int flag) { - int error = -EPERM; - - lock_kernel(); if (!suser()) - goto out; - error = -EINVAL; + return -EPERM; if (magic != 0xfee1dead || (magic_too != 672274793 && magic_too != 85072278)) - goto out; - error = 0; + return -EINVAL; + + if (flag == 0x01234567) { + /* SMP: We need to lock during the shutdown still */ + lock_kernel(); notifier_call_chain(&boot_notifier_list, SYS_DOWN, NULL); hard_reset_now(); } @@ -225,6 +224,8 @@ asmlinkage int sys_reboot(int magic, int magic_too, int flag) else if (!flag) C_A_D = 0; else if (flag == 0xCDEF0123) { + /* SMP: We need to lock during the shutdown still */ + lock_kernel(); printk(KERN_EMERG "System halted\n"); #ifdef __sparc__ halt_now(); @@ -236,10 +237,8 @@ asmlinkage int sys_reboot(int magic, int magic_too, int flag) notifier_call_chain(&boot_notifier_list, SYS_HALT, NULL); do_exit(0); } else - error = -EINVAL; -out: - unlock_kernel(); - return error; + return -EINVAL; + return 0; } /* @@ -659,24 +658,21 @@ asmlinkage int sys_setfsgid(gid_t gid) asmlinkage long sys_times(struct tms * tbuf) { - int error; - - lock_kernel(); - if (tbuf) { - error = put_user(current->utime,&tbuf->tms_utime); - if (!error) - error = put_user(current->stime,&tbuf->tms_stime); - if (!error) - error = put_user(current->cutime,&tbuf->tms_cutime); - if (!error) - error = put_user(current->cstime,&tbuf->tms_cstime); - if (error) - goto out; + /* + * In the SMP world we might just be unlucky and have one of + * the times increment as we use it. Since the value is an + * atomically safe type this is just fine. Conceptually its + * as if the syscall took an instant longer to occur. + */ + if (tbuf) + { + if(put_user(current->utime,&tbuf->tms_utime)|| + put_user(current->stime,&tbuf->tms_stime) || + put_user(current->cutime,&tbuf->tms_cutime) || + put_user(current->cstime,&tbuf->tms_cstime)) + return -EFAULT; } - error = jiffies; -out: - unlock_kernel(); - return error; + return jiffies; } /* @@ -691,6 +687,7 @@ out: * Auch. Had to add the 'did_exec' flag to conform completely to POSIX. * LBT 04.03.94 */ + asmlinkage int sys_setpgid(pid_t pid, pid_t pgid) { struct task_struct * p; @@ -820,45 +817,40 @@ out: */ asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist) { - int i, err = -EINVAL; + int i; + + /* + * SMP: Nobody else can change our grouplist. Thus we are + * safe. + */ - lock_kernel(); if (gidsetsize < 0) - goto out; + return -EINVAL; i = current->ngroups; if (gidsetsize) { - err = -EINVAL; if (i > gidsetsize) - goto out; - err = -EFAULT; + return -EINVAL; if (copy_to_user(grouplist, current->groups, sizeof(gid_t)*i)) - goto out; + return -EFAULT; } - err = i; -out: - unlock_kernel(); - return err; + return i; } +/* + * SMP: Our groups are not shared. We can copy to/from them safely + * without another task interfering. + */ + asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist) { - int err = -EPERM; - - lock_kernel(); if (!suser()) - goto out; - err = -EINVAL; + return -EPERM; if ((unsigned) gidsetsize > NGROUPS) - goto out; - err = copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t)); - if (err) { - gidsetsize = 0; - err = -EFAULT; - } + return -EINVAL; + if(copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t))) + return -EFAULT; current->ngroups = gidsetsize; -out: - unlock_kernel(); - return err; + return 0; } int in_group_p(gid_t grp) diff --git a/kernel/time.c b/kernel/time.c index 6f3cd8d40297..7c0540729aa5 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -66,13 +66,13 @@ asmlinkage int sys_time(int * tloc) { int i; - lock_kernel(); + /* SMP: This is fairly trivial. We grab CURRENT_TIME and + stuff it to user space. No side effects */ i = CURRENT_TIME; if (tloc) { if (put_user(i,tloc)) i = -EFAULT; } - unlock_kernel(); return i; } @@ -82,16 +82,20 @@ asmlinkage int sys_time(int * tloc) * why not move it into the appropriate arch directory (for those * architectures that need it). */ + asmlinkage int sys_stime(int * tptr) { - int value = -EPERM; + int value; - lock_kernel(); if (!suser()) - goto out; - value = -EFAULT; + return -EPERM; if (get_user(value, tptr)) - goto out; + return -EFAULT; + /* + * SMP: We need to lock out everything for the time update + * the new cli/sti semantics will let us drop this lock soon. + */ + lock_kernel(); cli(); xtime.tv_sec = value; xtime.tv_usec = 0; @@ -99,10 +103,8 @@ asmlinkage int sys_stime(int * tptr) time_maxerror = MAXPHASE; time_esterror = MAXPHASE; sti(); - value = 0; -out: unlock_kernel(); - return value; + return 0; } #endif diff --git a/net/802/fddi.c b/net/802/fddi.c index 9b644c8ce56e..78ac08635476 100644 --- a/net/802/fddi.c +++ b/net/802/fddi.c @@ -52,18 +52,23 @@ int fddi_header(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr, void *saddr, unsigned len) { - struct fddihdr *fddi = (struct fddihdr *)skb_push(skb, FDDI_K_SNAP_HLEN); - - /* Fill in frame header - assume 802.2 SNAP frames for now */ - + int hl = FDDI_K_SNAP_HLEN; + struct fddihdr *fddi; + + if(type!=htons(ETH_P_IP)) + hl=FDDI_K_8022_HLEN-3; + fddi = (struct fddihdr *)skb_push(skb, hl); fddi->fc = FDDI_FC_K_ASYNC_LLC_DEF; - fddi->hdr.llc_snap.dsap = FDDI_EXTENDED_SAP; - fddi->hdr.llc_snap.ssap = FDDI_EXTENDED_SAP; - fddi->hdr.llc_snap.ctrl = FDDI_UI_CMD; - fddi->hdr.llc_snap.oui[0] = 0x00; - fddi->hdr.llc_snap.oui[1] = 0x00; - fddi->hdr.llc_snap.oui[2] = 0x00; - fddi->hdr.llc_snap.ethertype = htons(type); + if(type==htons(ETH_P_IP)) + { + fddi->hdr.llc_snap.dsap = FDDI_EXTENDED_SAP; + fddi->hdr.llc_snap.ssap = FDDI_EXTENDED_SAP; + fddi->hdr.llc_snap.ctrl = FDDI_UI_CMD; + fddi->hdr.llc_snap.oui[0] = 0x00; + fddi->hdr.llc_snap.oui[1] = 0x00; + fddi->hdr.llc_snap.oui[2] = 0x00; + fddi->hdr.llc_snap.ethertype = htons(type); + } /* Set the source and destination hardware addresses */ @@ -75,9 +80,9 @@ int fddi_header(struct sk_buff *skb, struct device *dev, unsigned short type, if (daddr != NULL) { memcpy(fddi->daddr, daddr, dev->addr_len); - return(FDDI_K_SNAP_HLEN); + return(hl); } - return(-FDDI_K_SNAP_HLEN); + return(-hl); } @@ -114,15 +119,26 @@ int fddi_rebuild_header(struct sk_buff *skb) unsigned short fddi_type_trans(struct sk_buff *skb, struct device *dev) { struct fddihdr *fddi = (struct fddihdr *)skb->data; - + unsigned short type; + /* * Set mac.raw field to point to FC byte, set data field to point * to start of packet data. Assume 802.2 SNAP frames for now. */ skb->mac.raw = skb->data; /* point to frame control (FC) */ - skb_pull(skb, FDDI_K_SNAP_HLEN); /* adjust for 21 byte header */ - + + if(fddi->hdr.llc_8022_1.dsap==0xe0) + { + skb_pull(skb, FDDI_K_8022_HLEN-3); + type=htons(ETH_P_8022); + } + else + { + skb_pull(skb, FDDI_K_SNAP_HLEN); /* adjust for 21 byte header */ + type=fddi->hdr.llc_snap.ethertype; + } + /* Set packet type based on destination address and flag settings */ if (*fddi->daddr & 0x01) @@ -141,5 +157,6 @@ unsigned short fddi_type_trans(struct sk_buff *skb, struct device *dev) /* Assume 802.2 SNAP frames, for now */ - return(fddi->hdr.llc_snap.ethertype); + return(type); + } diff --git a/net/802/p8022.c b/net/802/p8022.c index c34378d3d7ee..23e6f2fad59f 100644 --- a/net/802/p8022.c +++ b/net/802/p8022.c @@ -55,6 +55,7 @@ int p8022_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) if (proto != NULL) { skb->h.raw += 3; + skb->nh.raw += 3; skb_pull(skb,3); return proto->rcvfunc(skb, dev, pt); } diff --git a/net/802/sysctl_net_802.c b/net/802/sysctl_net_802.c index acfcf3d777bb..63c4917d2138 100644 --- a/net/802/sysctl_net_802.c +++ b/net/802/sysctl_net_802.c @@ -16,3 +16,11 @@ ctl_table e802_table[] = { {0} }; + +#ifdef CONFIG_TR +extern int sysctl_tr_rif_timeout; +ctl_table tr_table[] = { + {NET_TR_RIF_TIMEOUT, "rif_timeout", &sysctl_tr_rif_timeout, sizeof(int), + 0644, NULL, &proc_dointvec}, +}; +#endif diff --git a/net/802/tr.c b/net/802/tr.c index d429cb4d4b84..333aa6c5722c 100644 --- a/net/802/tr.c +++ b/net/802/tr.c @@ -6,7 +6,10 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Fixes: + * Fixes: 3 Feb 97 Paul Norton Minor routing fixes. + * Added rif table to /proc/net/tr_rif and rif timeout to + * /proc/sys/net/token-ring/rif_timeout. + * */ #include @@ -26,31 +29,35 @@ #include #include #include +#include #include -static void tr_source_route(struct trh_hdr *trh,struct device *dev); -static void tr_add_rif_info(struct trh_hdr *trh); +static void tr_source_route(struct trh_hdr *trh, struct device *dev); +static void tr_add_rif_info(struct trh_hdr *trh, struct device *dev); static void rif_check_expire(unsigned long dummy); +#define TR_SR_DEBUG 0 + typedef struct rif_cache_s *rif_cache; /* * Each RIF entry we learn is kept this way */ -struct rif_cache_s -{ - unsigned char addr[TR_ALEN]; - unsigned short rcf; - unsigned short rseg[8]; - rif_cache next; - unsigned long last_used; +struct rif_cache_s { + unsigned char addr[TR_ALEN]; + unsigned char iface[5]; + __u16 rcf; + __u8 rseg[8]; + rif_cache next; + unsigned long last_used; + unsigned char local_ring; }; -#define RIF_TABLE_SIZE 16 +#define RIF_TABLE_SIZE 32 /* - * We hash the RIF cache 16 ways. We do after all have to look it + * We hash the RIF cache 32 ways. We do after all have to look it * up a lot. */ @@ -63,11 +70,9 @@ rif_cache rif_table[RIF_TABLE_SIZE]={ NULL, }; * Garbage disposal timer. */ -static struct timer_list rif_timer= -{ - NULL,NULL,RIF_CHECK_INTERVAL,0L,rif_check_expire -}; +static struct timer_list rif_timer; +int sysctl_tr_rif_timeout = RIF_TIMEOUT; /* * Put the headers on a token ring packet. Token ring source routing @@ -130,7 +135,7 @@ int tr_rebuild_header(struct sk_buff *skb) */ if(trllc->ethertype != htons(ETH_P_IP)) { - printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons( trllc->ethertype)); + printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons(trllc->ethertype)); return 0; } @@ -160,8 +165,7 @@ unsigned short tr_type_trans(struct sk_buff *skb, struct device *dev) skb_pull(skb,dev->hard_header_len); - if(trh->saddr[0] & TR_RII) - tr_add_rif_info(trh); + tr_add_rif_info(trh, dev); if(*trh->daddr & 1) { @@ -214,11 +218,11 @@ static void tr_source_route(struct trh_hdr *trh,struct device *dev) */ if(entry) { -#if 0 +#if TR_SR_DEBUG printk("source routing for %02X %02X %02X %02X %02X %02X\n",trh->daddr[0], trh->daddr[1],trh->daddr[2],trh->daddr[3],trh->daddr[4],trh->daddr[5]); #endif - if((ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8) + if(!entry->local_ring && (ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8) { trh->rcf=entry->rcf; memcpy(&trh->rseg[0],&entry->rseg[0],8*sizeof(unsigned short)); @@ -226,8 +230,15 @@ printk("source routing for %02X %02X %02X %02X %02X %02X\n",trh->daddr[0], trh->rcf&=htons(0x1fff); /* Issam Chehab */ trh->saddr[0]|=TR_RII; - entry->last_used=jiffies; +#if TR_SR_DEBUG + printk("entry found with rcf %04x\n", entry->rcf); + } + else + { + printk("entry found but without rcf length, local=%02x\n", entry->local_ring); +#endif } + entry->last_used=jiffies; } else { @@ -239,6 +250,7 @@ printk("source routing for %02X %02X %02X %02X %02X %02X\n",trh->daddr[0], trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK) | TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST); trh->saddr[0]|=TR_RII; + printk("no entry in rif table found - broadcasting frame\n"); } } } @@ -248,27 +260,36 @@ printk("source routing for %02X %02X %02X %02X %02X %02X\n",trh->daddr[0], * routing. */ -static void tr_add_rif_info(struct trh_hdr *trh) +static void tr_add_rif_info(struct trh_hdr *trh, struct device *dev) { int i; - unsigned int hash; + unsigned int hash, rii_p = 0; rif_cache entry; /* * Firstly see if the entry exists */ - trh->saddr[0]&=0x7f; + + if(trh->saddr[0] & TR_RII) + { + trh->saddr[0]&=0x7f; + if (((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) + { + rii_p = 1; + } + } + for(i=0,hash=0;isaddr[i++]); hash&=RIF_TABLE_SIZE-1; for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);entry=entry->next); if(entry==NULL) { -#if 0 +#if TR_SR_DEBUG printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n", trh->saddr[0],trh->saddr[1],trh->saddr[2], trh->saddr[3],trh->saddr[4],trh->saddr[5], - trh->rcf); + ntohs(trh->rcf)); #endif /* * Allocate our new entry. A failure to allocate loses @@ -278,14 +299,26 @@ printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n", * limiting and adjust the timers to suit. */ entry=kmalloc(sizeof(struct rif_cache_s),GFP_ATOMIC); + if(!entry) { printk(KERN_DEBUG "tr.c: Couldn't malloc rif cache entry !\n"); return; } - entry->rcf=trh->rcf; - memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short)); + + if (rii_p) + { + entry->rcf = trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK); + memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short)); + entry->local_ring = 0; + } + else + { + entry->local_ring = 1; + } + memcpy(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN); + memcpy(&(entry->iface[0]),dev->name,5); entry->next=rif_table[hash]; entry->last_used=jiffies; rif_table[hash]=entry; @@ -295,21 +328,20 @@ printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n", /* * Update existing entries */ - if ( entry->rcf != trh->rcf ) - { - if (!(trh->rcf & htons(TR_RCF_BROADCAST_MASK))) - { -#if 0 + if (!entry->local_ring) + if (entry->rcf != (trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK)) && + !(trh->rcf & htons(TR_RCF_BROADCAST_MASK))) + { +#if TR_SR_DEBUG printk("updating rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n", trh->saddr[0],trh->saddr[1],trh->saddr[2], trh->saddr[3],trh->saddr[4],trh->saddr[5], - trh->rcf); + ntohs(trh->rcf)); #endif - entry->rcf = trh->rcf; - memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short)); - entry->last_used=jiffies; - } - } + entry->rcf = trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK); + memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short)); + } + entry->last_used=jiffies; } } @@ -333,7 +365,7 @@ static void rif_check_expire(unsigned long dummy) /* * Out it goes */ - if((now-entry->last_used) > RIF_TIMEOUT) + if((now-entry->last_used) > sysctl_tr_rif_timeout) { *pentry=entry->next; kfree_s(entry,sizeof(struct rif_cache_s)); @@ -349,7 +381,7 @@ static void rif_check_expire(unsigned long dummy) */ del_timer(&rif_timer); - rif_timer.expires=jiffies+RIF_CHECK_INTERVAL; + rif_timer.expires = jiffies + sysctl_tr_rif_timeout; add_timer(&rif_timer); } @@ -359,27 +391,46 @@ static void rif_check_expire(unsigned long dummy) * routing. */ -int rif_get_info(char *buffer,char **start, off_t offset, int length) +#ifdef CONFIG_PROC_FS +int rif_get_info(char *buffer,char **start, off_t offset, int length, int dummy) { int len=0; off_t begin=0; off_t pos=0; - int size,i; + int size,i,j,rcf_len; + unsigned long now=jiffies; rif_cache entry; size=sprintf(buffer, - " TR address rcf routing segments TTL\n\n"); + "if TR address TTL rcf routing segments\n\n"); pos+=size; len+=size; for(i=0;i < RIF_TABLE_SIZE;i++) { for(entry=rif_table[i];entry;entry=entry->next) { - size=sprintf(buffer+len,"%02X:%02X:%02X:%02X:%02X:%02X %04X %04X %04X %04X %04X %04X %04X %04X %04X %lu\n", - entry->addr[0],entry->addr[1],entry->addr[2],entry->addr[3],entry->addr[4],entry->addr[5], - entry->rcf,entry->rseg[0],entry->rseg[1],entry->rseg[2],entry->rseg[3], - entry->rseg[4],entry->rseg[5],entry->rseg[6],entry->rseg[7],jiffies-entry->last_used); + size=sprintf(buffer+len,"%s %02X:%02X:%02X:%02X:%02X:%02X %7li ", + entry->iface,entry->addr[0],entry->addr[1],entry->addr[2],entry->addr[3],entry->addr[4],entry->addr[5], + sysctl_tr_rif_timeout-(now-entry->last_used)); + len+=size; + pos=begin+len; + if (entry->local_ring) + size=sprintf(buffer+len,"local\n"); + else { + size=sprintf(buffer+len,"%04X", ntohs(entry->rcf)); + rcf_len = ((ntohs(entry->rcf) & TR_RCF_LEN_MASK)>>8)-2; + if (rcf_len) + rcf_len >>= 1; + for(j = 0; j < rcf_len; j++) { + len+=size; + pos=begin+len; + size=sprintf(buffer+len," %04X",ntohs(entry->rseg[j])); + } + len+=size; + pos=begin+len; + size=sprintf(buffer+len,"\n"); + } len+=size; pos=begin+len; @@ -401,15 +452,28 @@ int rif_get_info(char *buffer,char **start, off_t offset, int length) len=length; /* Ending slop */ return len; } +#endif /* * Called during bootup. We don't actually have to initialise - * too much for this. The timer structure is setup statically. Thats - * probably NOT a good thing if we change the structure. + * too much for this. */ void rif_init(struct net_proto *unused) { + + rif_timer.expires = RIF_TIMEOUT; + rif_timer.data = 0L; + rif_timer.function = rif_check_expire; + init_timer(&rif_timer); add_timer(&rif_timer); -} +#ifdef CONFIG_PROC_FS + proc_net_register(&(struct proc_dir_entry) { + PROC_NET_TR_RIF, 6, "tr_rif", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + rif_get_info + }); +#endif +} diff --git a/net/core/sock.c b/net/core/sock.c index 66b76998b5ed..1535cab2aecb 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -185,6 +185,10 @@ int sock_setsockopt(struct socket *sock, int level, int optname, if(val > 65535) val = 65535; sk->sndbuf = val; + /* + * FIXME: Wake up sending tasks if we + * upped the value. + */ break; case SO_RCVBUF: diff --git a/net/ipv4/Config.in b/net/ipv4/Config.in index 2d6042e50de4..4895989946e1 100644 --- a/net/ipv4/Config.in +++ b/net/ipv4/Config.in @@ -18,12 +18,10 @@ if [ "$CONFIG_FIREWALL" = "y" ]; then fi fi bool 'IP: accounting' CONFIG_IP_ACCT -if [ "$CONFIG_IP_FORWARD" = "y" ]; then - bool 'IP: optimize as router not host' CONFIG_IP_ROUTER - tristate 'IP: tunneling' CONFIG_NET_IPIP - if [ "$CONFIG_IP_MULTICAST" = "y" ]; then - bool 'IP: multicast routing' CONFIG_IP_MROUTE - fi +bool 'IP: optimize as router not host' CONFIG_IP_ROUTER +tristate 'IP: tunneling' CONFIG_NET_IPIP +if [ "$CONFIG_IP_MULTICAST" = "y" ]; then + bool 'IP: multicast routing' CONFIG_IP_MROUTE fi if [ "$CONFIG_NET_ALIAS" = "y" ]; then tristate 'IP: aliasing support' CONFIG_IP_ALIAS diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index a913b45b19fb..bf45d901bd3f 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -54,6 +54,10 @@ * Stuart Cheshire : Metricom and grat arp fixes * *** FOR 2.1 clean this up *** * Lawrence V. Stefani: (08/12/96) Added FDDI support. + * Alan Cox : Took the AP1000 nasty FDDI hack and + * folded into the mainstream FDDI code. + * Ack spit, Linus how did you allow that + * one in... */ /* RFC1122 Status: @@ -1383,7 +1387,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) * is not from an IP number. We can't currently handle this, so toss * it. */ -#ifdef CONFIG_FDDI +#if defined(CONFIG_FDDI) || defined(CONFIG_AP1000) if (dev->type == ARPHRD_FDDI) { /* @@ -1415,18 +1419,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) } #else if (arp->ar_hln != dev->addr_len || -#if CONFIG_AP1000 - /* - * ARP from cafe-f was found to use ARPHDR_IEEE802 instead of - * the expected ARPHDR_ETHER. - */ - (strcmp(dev->name,"fddi") == 0 && - arp->ar_hrd != ARPHRD_ETHER && arp->ar_hrd != ARPHRD_IEEE802) || - (strcmp(dev->name,"fddi") != 0 && - dev->type != ntohs(arp->ar_hrd)) || -#else dev->type != ntohs(arp->ar_hrd) || -#endif dev->flags & IFF_NOARP || skb->pkt_type == PACKET_OTHERHOST || arp->ar_pln != 4) { @@ -1491,8 +1484,6 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) tha=arp_ptr; arp_ptr += dev->addr_len; memcpy(&tip, arp_ptr, 4); - - /* * Check for bad requests for 127.x.x.x and requests for multicast * addresses. If this is one such, delete it. diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 79443bfe925d..933b3977bbbb 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1033,8 +1033,8 @@ int tcp_do_sendmsg(struct sock *sk, int iovlen, struct iovec *iov, skb->h.th->urg_ptr = ntohs(copy); } - skb->csum = csum_partial_copy_from_user(&err, from, - skb_put(skb, copy), copy, 0); + skb->csum = csum_partial_copy_from_user(from, + skb_put(skb, copy), copy, 0, &err); from += copy; copied += copy; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index cc707111856c..ad298ad0d641 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -629,7 +629,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 i if (sk->ack_backlog >= sk->max_ack_backlog || tcp_v4_syn_filter(sk, skb, saddr)) { - printk(KERN_DEBUG "droping syn ack:%d max:%d\n", + printk(KERN_DEBUG "dropping syn ack:%d max:%d\n", sk->ack_backlog, sk->max_ack_backlog); #ifdef CONFIG_IP_TCPSF tcp_v4_random_drop(sk); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 961d127c89d2..d5ec97acd3ab 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -627,7 +627,7 @@ int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) sk->ip_tos|sk->localroute); if (err) return err; - if (rt->rt_flags&RTF_BROADCAST && !sk->broadcast) { + if ((rt->rt_flags&RTF_BROADCAST) && !sk->broadcast) { ip_rt_put(rt); return -EACCES; } diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index db2090d0d2f5..f6e2af59f381 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -2103,7 +2103,7 @@ int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) ipx_interface *intrfc; struct ipxhdr *ipx; - skb->h.raw = (void *)ipx = skb->nh.ipxh; + ipx = skb->nh.ipxh; /* Too small? */ if(ntohs(ipx->ipx_pktsize) @@ -104,7 +107,7 @@ static void lapb_insert_cb(lapb_cb *lapb) * Convert the integer token used by the device driver into a pointer * to a LAPB control structure. */ -lapb_cb *lapb_tokentostruct(void *token) +static lapb_cb *lapb_tokentostruct(void *token) { lapb_cb *lapb; @@ -129,6 +132,7 @@ static lapb_cb *lapb_create_cb(void) memset(lapb, 0x00, sizeof(*lapb)); + skb_queue_head_init(&lapb->input_queue); skb_queue_head_init(&lapb->write_queue); skb_queue_head_init(&lapb->ack_queue); @@ -327,6 +331,18 @@ int lapb_data_request(void *token, struct sk_buff *skb) return LAPB_OK; } +int lapb_data_received(void *token, struct sk_buff *skb) +{ + lapb_cb *lapb; + + if ((lapb = lapb_tokentostruct(token)) == NULL) + return LAPB_BADTOKEN; + + skb_queue_tail(&lapb->input_queue, skb); + + return LAPB_OK; +} + void lapb_connect_confirmation(lapb_cb *lapb, int reason) { if (lapb->callbacks.connect_confirmation != NULL) diff --git a/net/lapb/lapb_in.c b/net/lapb/lapb_in.c index cbe51bbf3c93..01f6f3e302f2 100644 --- a/net/lapb/lapb_in.c +++ b/net/lapb/lapb_in.c @@ -312,6 +312,7 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp lapb->condition = 0x00; lapb->t1timer = 0; lapb->t2timer = 0; + lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; @@ -331,6 +332,7 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp lapb->condition = 0x00; lapb->t1timer = 0; lapb->t2timer = 0; + lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; @@ -384,7 +386,7 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n", lapb->token); #endif - lapb_nr_error_recovery(lapb); + lapb_establish_data_link(lapb); lapb->state = LAPB_STATE_1; } break; @@ -401,7 +403,7 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n", lapb->token); #endif - lapb_nr_error_recovery(lapb); + lapb_establish_data_link(lapb); lapb->state = LAPB_STATE_1; } break; @@ -415,12 +417,13 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp if (lapb_validate_nr(lapb, nr)) { lapb_frames_acked(lapb, nr); lapb->t1timer = 0; + lapb->n2count = 0; lapb_requeue_frames(lapb); } else { #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n", lapb->token); #endif - lapb_nr_error_recovery(lapb); + lapb_establish_data_link(lapb); lapb->state = LAPB_STATE_1; } break; @@ -433,7 +436,7 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n", lapb->token); #endif - lapb_nr_error_recovery(lapb); + lapb_establish_data_link(lapb); lapb->state = LAPB_STATE_1; break; } @@ -489,285 +492,12 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp kfree_skb(skb, FREE_READ); } -/* - * State machine for state 4, Timer Recovery State. - * The handling of the timer(s) is in file lapb_timer.c - */ -static void lapb_state4_machine(lapb_cb *lapb, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type) -{ - int queued = 0; - int modulus; - - modulus = (lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS; - - switch (frametype) { - case LAPB_SABM: -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 RX SABM(%d)\n", lapb->token, pf); -#endif - if (lapb->mode & LAPB_EXTENDED) { -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n", lapb->token, pf); -#endif - lapb_send_control(lapb, LAPB_DM, pf, LAPB_RESPONSE); - } else { -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n", lapb->token, pf); -#endif - lapb_send_control(lapb, LAPB_UA, pf, LAPB_RESPONSE); - lapb->condition = 0x00; - lapb->t1timer = 0; - lapb->t2timer = 0; - lapb->vs = 0; - lapb->vr = 0; - lapb->va = 0; - lapb_requeue_frames(lapb); - } - break; - - case LAPB_SABME: -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 RX SABME(%d)\n", lapb->token, pf); -#endif - if (lapb->mode & LAPB_EXTENDED) { -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n", lapb->token, pf); -#endif - lapb_send_control(lapb, LAPB_UA, pf, LAPB_RESPONSE); - lapb->condition = 0x00; - lapb->t1timer = 0; - lapb->t2timer = 0; - lapb->vs = 0; - lapb->vr = 0; - lapb->va = 0; - lapb_requeue_frames(lapb); - } else { -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n", lapb->token, pf); -#endif - lapb_send_control(lapb, LAPB_DM, pf, LAPB_RESPONSE); - } - break; - - case LAPB_DISC: -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 RX DISC(%d)\n", lapb->token, pf); -#endif -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S0\n", lapb->token); -#endif - lapb_clear_queues(lapb); - lapb_send_control(lapb, LAPB_UA, pf, LAPB_RESPONSE); - lapb->state = LAPB_STATE_0; - lapb->t1timer = lapb->t1; - lapb->t2timer = 0; - lapb_disconnect_indication(lapb, LAPB_OK); - break; - - case LAPB_DM: -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 RX DM(%d)\n", lapb->token, pf); -#endif -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S0\n", lapb->token); -#endif - lapb_clear_queues(lapb); - lapb->state = LAPB_STATE_0; - lapb->t1timer = lapb->t1; - lapb->t2timer = 0; - lapb_disconnect_indication(lapb, LAPB_NOTCONNECTED); - break; - - case LAPB_RNR: -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 RX RNR(%d) R%d\n", lapb->token, pf, nr); -#endif - lapb->condition |= LAPB_PEER_RX_BUSY_CONDITION; - if (type == LAPB_RESPONSE && pf) { - lapb->t1timer = 0; - if (lapb_validate_nr(lapb, nr)) { - lapb_frames_acked(lapb, nr); - if (lapb->vs == lapb->va) { -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n", lapb->token); -#endif - lapb->n2count = 0; - lapb->state = LAPB_STATE_3; - } - } else { -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S1\n", lapb->token); -#endif - lapb_nr_error_recovery(lapb); - lapb->state = LAPB_STATE_1; - } - break; - } - - lapb_check_need_response(lapb, type, pf); - if (lapb_validate_nr(lapb, nr)) { - lapb_frames_acked(lapb, nr); - } else { -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S1\n", lapb->token); -#endif - lapb_nr_error_recovery(lapb); - lapb->state = LAPB_STATE_1; - } - break; - - case LAPB_RR: -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 RX RR(%d) R%d\n", lapb->token, pf, nr); -#endif - lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; - if (pf && type == LAPB_RESPONSE) { - lapb->t1timer = 0; - if (lapb_validate_nr(lapb, nr)) { - lapb_frames_acked(lapb, nr); - if (lapb->vs == lapb->va) { -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n", lapb->token); -#endif - lapb->n2count = 0; - lapb->state = LAPB_STATE_3; - } else { - lapb_requeue_frames(lapb); - } - } else { -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S1\n", lapb->token); -#endif - lapb_nr_error_recovery(lapb); - lapb->state = LAPB_STATE_1; - } - break; - } - - lapb_check_need_response(lapb, type, pf); - if (lapb_validate_nr(lapb, nr)) { - lapb_frames_acked(lapb, nr); - } else { -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S1\n", lapb->token); -#endif - lapb_nr_error_recovery(lapb); - lapb->state = LAPB_STATE_1; - } - break; - - case LAPB_REJ: -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 RX REJ(%d) R%d\n", lapb->token, pf, nr); -#endif - lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; - if (pf && type == LAPB_RESPONSE) { - lapb->t1timer = 0; - if (lapb_validate_nr(lapb, nr)) { - lapb_frames_acked(lapb, nr); - if (lapb->vs == lapb->va) { -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n", lapb->token); -#endif - lapb->n2count = 0; - lapb->state = LAPB_STATE_3; - } else { - lapb_requeue_frames(lapb); - } - } else { -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S1\n", lapb->token); -#endif - lapb_nr_error_recovery(lapb); - lapb->state = LAPB_STATE_1; - } - break; - } - - lapb_check_need_response(lapb, type, pf); - if (lapb_validate_nr(lapb, nr)) { - lapb_frames_acked(lapb, nr); - if (lapb->vs != lapb->va) - lapb_requeue_frames(lapb); - } else { -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S1\n", lapb->token); -#endif - lapb_nr_error_recovery(lapb); - lapb->state = LAPB_STATE_1; - } - break; - - case LAPB_I: -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 RX I(%d) S%d R%d\n", lapb->token, pf, ns, nr); -#endif - if (!lapb_validate_nr(lapb, nr)) { -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S1\n", lapb->token); -#endif - lapb_nr_error_recovery(lapb); - lapb->state = LAPB_STATE_1; - break; - } - lapb_frames_acked(lapb, nr); - if (ns == lapb->vr) { - lapb->vr = (lapb->vr + 1) % modulus; - queued = lapb_data_indication(lapb, skb); - lapb->condition &= ~LAPB_REJECT_CONDITION; - if (pf) { - lapb_enquiry_response(lapb); - } else { - if (!(lapb->condition & LAPB_ACK_PENDING_CONDITION)) { - lapb->t2timer = lapb->t2; - lapb->condition |= LAPB_ACK_PENDING_CONDITION; - } - } - } else { - if (lapb->condition & LAPB_REJECT_CONDITION) { - if (pf) - lapb_enquiry_response(lapb); - } else { -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 TX REJ(%d) R%d\n", lapb->token, pf, lapb->vr); -#endif - lapb->condition |= LAPB_REJECT_CONDITION; - lapb_send_control(lapb, LAPB_REJ, pf, LAPB_RESPONSE); - lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; - } - } - break; - - case LAPB_FRMR: - case LAPB_ILLEGAL: -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S4 TX {FRMR,ILLEGAL}(%d)\n", lapb->token, pf); -#endif -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S1\n", lapb->token); -#endif - lapb_establish_data_link(lapb); - lapb->state = LAPB_STATE_1; - break; - - default: - break; - } - - if (!queued) - kfree_skb(skb, FREE_READ); -} - /* * Process an incoming LAPB frame */ -int lapb_data_received(void *token, struct sk_buff *skb) +void lapb_data_input(lapb_cb *lapb, struct sk_buff *skb) { int frametype, ns, nr, pf, type; - lapb_cb *lapb; - - if ((lapb = lapb_tokentostruct(token)) == NULL) - return LAPB_BADTOKEN; del_timer(&lapb->timer); @@ -786,14 +516,9 @@ int lapb_data_received(void *token, struct sk_buff *skb) case LAPB_STATE_3: lapb_state3_machine(lapb, skb, frametype, ns, nr, pf, type); break; - case LAPB_STATE_4: - lapb_state4_machine(lapb, skb, frametype, ns, nr, pf, type); - break; } lapb_set_timer(lapb); - - return LAPB_OK; } #endif diff --git a/net/lapb/lapb_out.c b/net/lapb/lapb_out.c index 1d0f5e5cfac2..1256e3a3c109 100644 --- a/net/lapb/lapb_out.c +++ b/net/lapb/lapb_out.c @@ -167,11 +167,6 @@ void lapb_transmit_buffer(lapb_cb *lapb, struct sk_buff *skb, int type) kfree_skb(skb, FREE_WRITE); } -void lapb_nr_error_recovery(lapb_cb *lapb) -{ - lapb_establish_data_link(lapb); -} - void lapb_establish_data_link(lapb_cb *lapb) { lapb->condition = 0x00; @@ -193,19 +188,6 @@ void lapb_establish_data_link(lapb_cb *lapb) lapb->t1timer = lapb->t1; } -void lapb_transmit_enquiry(lapb_cb *lapb) -{ -#if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S%d TX RR(1) R%d\n", lapb->token, lapb->state, lapb->vr); -#endif - - lapb_send_control(lapb, LAPB_RR, LAPB_POLLON, LAPB_COMMAND); - - lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; - - lapb->t1timer = lapb->t1; -} - void lapb_enquiry_response(lapb_cb *lapb) { #if LAPB_DEBUG > 1 @@ -233,6 +215,7 @@ void lapb_check_iframes_acked(lapb_cb *lapb, unsigned short nr) if (lapb->vs == nr) { lapb_frames_acked(lapb, nr); lapb->t1timer = 0; + lapb->n2count = 0; } else { if (lapb->va != nr) { lapb_frames_acked(lapb, nr); diff --git a/net/lapb/lapb_subr.c b/net/lapb/lapb_subr.c index 271978d76b9b..3902d51a29f5 100644 --- a/net/lapb/lapb_subr.c +++ b/net/lapb/lapb_subr.c @@ -45,6 +45,9 @@ void lapb_clear_queues(lapb_cb *lapb) { struct sk_buff *skb; + while ((skb = skb_dequeue(&lapb->input_queue)) != NULL) + kfree_skb(skb, FREE_READ); + while ((skb = skb_dequeue(&lapb->write_queue)) != NULL) kfree_skb(skb, FREE_WRITE); diff --git a/net/lapb/lapb_timer.c b/net/lapb/lapb_timer.c index d006b0f17b00..dd46eee5fb20 100644 --- a/net/lapb/lapb_timer.c +++ b/net/lapb/lapb_timer.c @@ -67,12 +67,25 @@ void lapb_set_timer(lapb_cb *lapb) static void lapb_timer(unsigned long param) { lapb_cb *lapb = (lapb_cb *)param; - - if (lapb->state == LAPB_STATE_3 || lapb->state == LAPB_STATE_4) + struct sk_buff *skb; + + /* + * Process all packet received since the last clock tick. + */ + while ((skb = skb_dequeue(&lapb->input_queue)) != NULL) + lapb_data_input(lapb, skb); + + /* + * If in a data transfer state, transmit any data. + */ + if (lapb->state == LAPB_STATE_3) lapb_kick(lapb); + /* + * T2 expiry code. + */ if (lapb->t2timer > 0 && --lapb->t2timer == 0) { - if (lapb->state == LAPB_STATE_3 || lapb->state == LAPB_STATE_4) { + if (lapb->state == LAPB_STATE_3) { if (lapb->condition & LAPB_ACK_PENDING_CONDITION) { lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; lapb_timeout_response(lapb); @@ -80,16 +93,30 @@ static void lapb_timer(unsigned long param) } } + /* + * If T1 isn't running, or hasn't timed out yet, keep going. + */ if (lapb->t1timer == 0 || --lapb->t1timer > 0) { lapb_set_timer(lapb); return; } + /* + * T1 has expired. + */ switch (lapb->state) { + + /* + * If we are a DCE, keep going DM .. DM .. DM + */ case LAPB_STATE_0: if (lapb->mode & LAPB_DCE) lapb_send_control(lapb, LAPB_DM, LAPB_POLLOFF, LAPB_RESPONSE); break; + + /* + * Awaiting connection state, send SABM(E), up to N2 times. + */ case LAPB_STATE_1: if (lapb->n2count == lapb->n2) { lapb_clear_queues(lapb); @@ -115,6 +142,9 @@ static void lapb_timer(unsigned long param) } break; + /* + * Awaiting disconnection state, send DISC, up to N2 times. + */ case LAPB_STATE_2: if (lapb->n2count == lapb->n2) { lapb_clear_queues(lapb); @@ -133,27 +163,21 @@ static void lapb_timer(unsigned long param) } break; - case LAPB_STATE_3: - lapb->n2count = 1; - lapb_transmit_enquiry(lapb); - lapb->state = LAPB_STATE_4; -#if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->token); -#endif - break; - - case LAPB_STATE_4: + /* + * Data transfer state, restransmit I frames, up to N2 times. + */ + case LAPB_STATE_3: if (lapb->n2count == lapb->n2) { lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb->t2timer = 0; lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); #if LAPB_DEBUG > 0 - printk(KERN_DEBUG "lapb: (%p) S4 -> S0\n", lapb->token); + printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->token); #endif } else { lapb->n2count++; - lapb_transmit_enquiry(lapb); + lapb_requeue_frames(lapb); } break; } diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index af2dbbb679d6..20e3c3cf7284 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c @@ -59,7 +59,7 @@ int nr_rx_ip(struct sk_buff *skb, struct device *dev) { - struct enet_statistics *stats = (struct enet_statistics *)dev->priv; + struct net_device_stats *stats = (struct net_device_stats *)dev->priv; if (!dev->start) { stats->rx_errors++; @@ -67,6 +67,8 @@ int nr_rx_ip(struct sk_buff *skb, struct device *dev) } stats->rx_packets++; + stats->rx_bytes += skb->len; + skb->protocol = htons(ETH_P_IP); /* Spoof incoming device */ @@ -115,7 +117,7 @@ static int nr_header(struct sk_buff *skb, struct device *dev, unsigned short typ static int nr_rebuild_header(struct sk_buff *skb) { struct device *dev = skb->dev; - struct enet_statistics *stats = (struct enet_statistics *)dev->priv; + struct net_device_stats *stats = (struct net_device_stats *)dev->priv; struct sk_buff *skbn; unsigned char *bp = skb->data; @@ -149,6 +151,7 @@ static int nr_rebuild_header(struct sk_buff *skb) } stats->tx_packets++; + stats->tx_bytes += skbn->len; return 1; } @@ -188,7 +191,7 @@ static int nr_close(struct device *dev) static int nr_xmit(struct sk_buff *skb, struct device *dev) { - struct enet_statistics *stats = (struct enet_statistics *)dev->priv; + struct net_device_stats *stats = (struct net_device_stats *)dev->priv; if (skb == NULL || dev == NULL) return 0; @@ -221,9 +224,9 @@ static int nr_xmit(struct sk_buff *skb, struct device *dev) return 0; } -static struct enet_statistics *nr_get_stats(struct device *dev) +static struct net_device_stats *nr_get_stats(struct device *dev) { - return (struct enet_statistics *)dev->priv; + return (struct net_device_stats *)dev->priv; } int nr_init(struct device *dev) @@ -250,10 +253,10 @@ int nr_init(struct device *dev) dev->pa_mask = 0; dev->pa_alen = sizeof(unsigned long); - if ((dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL)) == NULL) + if ((dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL)) == NULL) return -ENOMEM; - memset(dev->priv, 0, sizeof(struct enet_statistics)); + memset(dev->priv, 0, sizeof(struct net_device_stats)); dev->get_stats = nr_get_stats; diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index 1ba762171dc2..708a1e8cc931 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -55,7 +55,7 @@ int rose_rx_ip(struct sk_buff *skb, struct device *dev) { - struct enet_statistics *stats = (struct enet_statistics *)dev->priv; + struct net_device_stats *stats = (struct net_device_stats *)dev->priv; if (!dev->start) { stats->rx_errors++; @@ -63,6 +63,8 @@ int rose_rx_ip(struct sk_buff *skb, struct device *dev) } stats->rx_packets++; + stats->rx_bytes += skb->len; + skb->protocol = htons(ETH_P_IP); /* Spoof incoming device */ @@ -96,7 +98,7 @@ static int rose_header(struct sk_buff *skb, struct device *dev, unsigned short t static int rose_rebuild_header(struct sk_buff *skb) { struct device *dev = skb->dev; - struct enet_statistics *stats = (struct enet_statistics *)dev->priv; + struct net_device_stats *stats = (struct net_device_stats *)dev->priv; unsigned char *bp = (unsigned char *)skb->data; struct sk_buff *skbn; @@ -121,6 +123,7 @@ static int rose_rebuild_header(struct sk_buff *skb) } stats->tx_packets++; + stats->tx_bytes += skbn->len; return 1; } @@ -160,7 +163,7 @@ static int rose_close(struct device *dev) static int rose_xmit(struct sk_buff *skb, struct device *dev) { - struct enet_statistics *stats = (struct enet_statistics *)dev->priv; + struct net_device_stats *stats = (struct net_device_stats *)dev->priv; if (skb == NULL || dev == NULL) return 0; @@ -193,9 +196,9 @@ static int rose_xmit(struct sk_buff *skb, struct device *dev) return 0; } -static struct enet_statistics *rose_get_stats(struct device *dev) +static struct net_device_stats *rose_get_stats(struct device *dev) { - return (struct enet_statistics *)dev->priv; + return (struct net_device_stats *)dev->priv; } int rose_init(struct device *dev) @@ -222,10 +225,10 @@ int rose_init(struct device *dev) dev->pa_mask = 0; dev->pa_alen = sizeof(unsigned long); - if ((dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL)) == NULL) + if ((dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL)) == NULL) return -ENOMEM; - memset(dev->priv, 0, sizeof(struct enet_statistics)); + memset(dev->priv, 0, sizeof(struct net_device_stats)); dev->get_stats = rose_get_stats; diff --git a/net/socket.c b/net/socket.c index 6f3b019c4ae5..4d26141f1c02 100644 --- a/net/socket.c +++ b/net/socket.c @@ -645,7 +645,7 @@ out: asmlinkage int sys_socketpair(int family, int type, int protocol, int usockvec[2]) { int fd1, fd2, i; - struct socket *sock1, *sock2; + struct socket *sock1=NULL, *sock2=NULL; int err; lock_kernel(); @@ -700,6 +700,10 @@ asmlinkage int sys_socketpair(int family, int type, int protocol, int usockvec[2 } } out: + if(sock1) + sockfd_put(sock1); + if(sock2) + sockfd_put(sock2); unlock_kernel(); return err; } @@ -1114,6 +1118,7 @@ asmlinkage int sys_shutdown(int fd, int how) err=sock->ops->shutdown(sock, how); sockfd_put(sock); } + unlock_kernel(); return err; } diff --git a/net/sysctl_net.c b/net/sysctl_net.c index 8bdb4f2249f1..eb23ea698b96 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c @@ -42,6 +42,10 @@ extern ctl_table bridge_table[]; extern ctl_table ipv6_table[]; #endif +#ifdef CONFIG_TR +extern ctl_table tr_table[]; +#endif + ctl_table net_table[] = { {NET_CORE, "core", NULL, 0, 0555, core_table}, {NET_UNIX, "unix", NULL, 0, 0555, unix_table}, @@ -63,6 +67,9 @@ ctl_table net_table[] = { #endif #ifdef CONFIG_IPV6 {NET_IPV6, "ipv6", NULL, 0, 0555, ipv6_table}, +#endif +#ifdef CONFIG_TR + {NET_TR, "token-ring", NULL, 0, 0555, tr_table}, #endif {0} }; diff --git a/scripts/Configure b/scripts/Configure index e16312920fb6..f685529bd161 100644 --- a/scripts/Configure +++ b/scripts/Configure @@ -288,7 +288,7 @@ function int () { def=${old:-$3} while :; do readln "$1 ($2) [$def] " "$def" "$old" - if expr "$ans" : '0$\|-?[1-9][0-9]*$' > /dev/null; then + if expr "$ans" : '0$\|-\?[1-9][0-9]*$' > /dev/null; then define_int "$2" "$ans" break else @@ -319,7 +319,7 @@ function hex () { while :; do readln "$1 ($2) [$def] " "$def" "$old" ans=${ans#*[x,X]} - if expr "$ans" : '[0-9a-fA-F]+$' > /dev/null; then + if expr "$ans" : '[0-9a-fA-F]\+$' > /dev/null; then define_hex "$2" "$ans" break else diff --git a/scripts/Menuconfig b/scripts/Menuconfig index dc3ba7e4a41c..b835f6b0c0bc 100644 --- a/scripts/Menuconfig +++ b/scripts/Menuconfig @@ -400,7 +400,7 @@ function l_int () { answer="`cat MCdialog.out`" answer="${answer:-$3}" - if expr $answer : '0$\|-?[1-9][0-9]*$' >/dev/null + if expr $answer : '0$\|-\?[1-9][0-9]*$' >/dev/null then eval $2="$answer" else @@ -433,7 +433,7 @@ function l_hex () { answer="${answer:-$3}" answer="${answer##*[x,X]}" - if expr $answer : '[0-9a-fA-F]+$' >/dev/null + if expr $answer : '[0-9a-fA-F]\+$' >/dev/null then eval $2="$answer" else -- 2.39.5