diff -u --recursive --new-file v2.0.31/linux/CREDITS linux/CREDITS --- v2.0.31/linux/CREDITS Wed Sep 17 12:00:48 1997 +++ linux/CREDITS Mon Nov 10 16:12:27 1997 @@ -604,12 +604,13 @@ S: United Kingdom N: Ron Holt -E: ron@novell.com +E: ron@caldera.com +W: http://www.holt.org/ D: Kernel development -D: Contributed to kernel Wabi/Wine support -S: Novell, Inc. -S: 1700 South 122 East, Mailstop CP-1 -S: Provo, Utah 84606 +D: Minor kernel modifications to support Wabi and Wine +S: Caldera, Inc. +S: 240 West Center St. +S: Orem, Utah 84059-1920 S: USA N: Rob W. W. Hooft @@ -987,10 +988,10 @@ S: Germany N: David Mosberger-Tang -E: davidm@azstarnet.com +E: David.Mosberger@acm.org D: Linux/Alpha -S: 2552 E. Copper Street -S: Tucson, Arizona 85716-2406 +S: 35706 Runckel Lane +S: Fremont, CA 94536 S: USA N: Ian A. Murdock @@ -1511,6 +1512,14 @@ S: Geert-Grooteplein Noord 21 S: 6525 EZ Nijmegen S: The Netherlands + +N: Ulrich Windl +E: Ulrich.Windl@rz.uni-regensburg.de +P: 1024/E843660D CF D7 43 A1 5A 49 14 25 7C 04 A0 6E 4C 3A AC 6D +D: Bug fixes for adjtimex() and some other time stuff. +S: Alte Regensburger Str. 11a +S: 93149 Nittenau +S: Germany N: Lars Wirzenius E: liw@iki.fi diff -u --recursive --new-file v2.0.31/linux/Makefile linux/Makefile --- v2.0.31/linux/Makefile Mon Aug 4 15:23:02 1997 +++ linux/Makefile Fri Nov 7 10:51:05 1997 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 0 -SUBLEVEL = 31 +SUBLEVEL = 32 ARCH = i386 diff -u --recursive --new-file v2.0.31/linux/arch/i386/boot/compressed/misc.c linux/arch/i386/boot/compressed/misc.c --- v2.0.31/linux/arch/i386/boot/compressed/misc.c Mon Jul 15 03:47:39 1996 +++ linux/arch/i386/boot/compressed/misc.c Sat Oct 25 06:37:01 1997 @@ -9,10 +9,9 @@ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 */ -#include - #include #include +#include /* * gzip declarations @@ -21,8 +20,13 @@ #define OF(args) args #define STATIC static +void* memset(void* s, int c, size_t n); +void* memcpy(void* __dest, __const void* __src, + size_t __n); + #define memzero(s, n) memset ((s), 0, (n)) + typedef unsigned char uch; typedef unsigned short ush; typedef unsigned long ulg; @@ -113,7 +117,6 @@ static void gzip_mark(void **); static void gzip_release(void **); -#ifndef STANDALONE_DEBUG static void puts(const char *); extern int end; @@ -212,7 +215,7 @@ outb_p(0xff & (pos >> 1), vidport+1); } -__ptr_t memset(__ptr_t s, int c, size_t n) +void* memset(void* s, int c, size_t n) { int i; char *ss = (char*)s; @@ -220,7 +223,7 @@ for (i=0;iused_math) != 0) { - if (last_task_used_math == current) +#ifdef __SMP__ + if (current->flags & PF_USEDFPU) +#else + if (last_task_used_math == current) +#endif __asm__("clts ; fnsave %0": :"m" (*fpu)); else memcpy(fpu,¤t->tss.i387.hard,sizeof(*fpu)); } - } else { - /* we should dump the emulator state here, but we need to - convert it into standard 387 format first.. */ + } else { + /* We dump the emulator state here. + We convert it into standard 387 format first.. */ +#ifdef CONFIG_MATH_EMULATION + int i; + unsigned long top; + char (*hardreg)[10]; + struct i387_soft_struct *soft_fpu = ¤t->tss.i387.soft; + struct fpu_reg* softreg; + long int control_word = soft_fpu->cwd; + + fpu->cwd = soft_fpu->cwd; + fpu->swd = soft_fpu->swd; + fpu->twd = soft_fpu->twd; + fpu->fip = soft_fpu->fip; + fpu->fcs = soft_fpu->fcs; + fpu->foo = soft_fpu->foo; + fpu->fos = soft_fpu->fos; + hardreg = (char (*)[10]) &fpu->st_space[0]; + top = (unsigned long) soft_fpu->top % 8; + softreg = &soft_fpu->regs[top]; + for (i = top ; i < 8; i ++) { + softreg_to_hardreg(softreg, *hardreg, control_word); + hardreg++; + softreg++; + } + softreg = &soft_fpu->regs[0]; + for (i = 0; i < top; i++) { + softreg_to_hardreg(softreg, *hardreg, control_word); + hardreg++; + softreg++; + } + fpvalid = 1; +#else /* defined(CONFIG_MATH_EMULATION) */ fpvalid = 0; +#endif /* !defined(CONFIG_MATH_EMULATION) */ } return fpvalid; diff -u --recursive --new-file v2.0.31/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c --- v2.0.31/linux/arch/i386/kernel/ptrace.c Mon Aug 4 12:12:22 1997 +++ linux/arch/i386/kernel/ptrace.c Fri Nov 7 09:11:42 1997 @@ -294,6 +294,127 @@ put_long(tsk, vma, addr, data); return 0; } +#ifdef CONFIG_MATH_EMULATION +static void write_emulator_word(struct task_struct *child, + unsigned long register_offset, + long data) +{ + int i, j; + struct i387_soft_struct *soft_fpu; + struct fpu_reg *this_fpreg, *next_fpreg; + char hard_reg[2][10]; + int control_word; + unsigned long top; + i = register_offset / 10; + j = register_offset % 10; + soft_fpu = &child->tss.i387.soft; + top = i + (unsigned long) soft_fpu->top; + control_word = soft_fpu->cwd; + this_fpreg = &soft_fpu->regs[(top + i) % 8]; + next_fpreg = &soft_fpu->regs[(top + i + 1) % 8]; + softreg_to_hardreg(this_fpreg, hard_reg[0], control_word); + if (j > 6) + softreg_to_hardreg(next_fpreg, hard_reg[1], control_word); + *(long *) &hard_reg[0][j] = data; + hardreg_to_softreg(hard_reg[0], this_fpreg); + if (j > 6) + hardreg_to_softreg(hard_reg[1], next_fpreg); +} +#endif /* defined(CONFIG_MATH_EMULATION) */ + +/* Put a word to the part of the user structure containing + * floating point registers + * Floating point support added to ptrace by Ramon Garcia, + * ramon@juguete.quim.ucm.es + */ + +static int put_fpreg_word (struct task_struct *child, + unsigned long addr, long data) +{ + struct user *dummy = NULL; + if (addr < (long) (&dummy->i387.st_space)) + return -EIO; + addr -= (long) (&dummy->i387.st_space); + + if (!hard_math) { +#ifdef CONFIG_MATH_EMULATION + write_emulator_word(child, addr, data); +#else + return 0; +#endif + } + else +#ifndef __SMP__ + if (last_task_used_math == child) { + clts(); + __asm__("fsave %0; fwait":"=m" (child->tss.i387)); + last_task_used_math = current; + stts(); + } +#endif + *(long *) + ((char *) (child->tss.i387.hard.st_space) + addr) = data; + return 0; +} + +#ifdef CONFIG_MATH_EMULATION + +static unsigned long get_emulator_word(struct task_struct *child, + unsigned long register_offset) +{ + char hard_reg[2][10]; + int i, j; + struct fpu_reg *this_fpreg, *next_fpreg; + struct i387_soft_struct *soft_fpu; + long int control_word; + unsigned long top; + unsigned long tmp; + i = register_offset / 10; + j = register_offset % 10; + soft_fpu = &child->tss.i387.soft; + top = (unsigned long) soft_fpu->top; + this_fpreg = &soft_fpu->regs[(top + i) % 8]; + next_fpreg = &soft_fpu->regs[(top + i + 1) % 8]; + control_word = soft_fpu->cwd; + softreg_to_hardreg(this_fpreg, hard_reg[0], control_word); + if (j > 6) + softreg_to_hardreg(next_fpreg, hard_reg[1], control_word); + tmp = *(long *) + &hard_reg[0][j]; + return tmp; +} + +#endif /* defined(CONFIG_MATH_EMULATION) */ +/* Get a word from the part of the user structure containing + * floating point registers + */ +static unsigned long get_fpreg_word(struct task_struct *child, + unsigned long addr) +{ + struct user *dummy = NULL; + unsigned long tmp; + addr -= (long) (&dummy->i387.st_space); + if (!hard_math) { +#ifdef CONFIG_MATH_EMULATION + tmp = get_emulator_word(child, addr); +#else + tmp = 0; +#endif /* !defined(CONFIG_MATH_EMULATION) */ + } else { +#ifndef __SMP__ + if (last_task_used_math == child) { + clts(); + __asm__("fsave %0; fwait":"=m" (child->tss.i387)); + last_task_used_math = current; + stts(); + } +#endif + tmp = *(long *) + ((char *) (child->tss.i387.hard.st_space) + + addr); + } + return tmp; +} asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { @@ -367,15 +488,25 @@ case PTRACE_PEEKUSR: { unsigned long tmp; int res; - - if ((addr & 3) || addr < 0 || - addr > sizeof(struct user) - 3) + + if ((addr & 3 && + (addr < (long) (&dummy->i387) || + addr > (long) (&dummy->i387.st_space[20]) )) || + addr < 0 || addr > sizeof(struct user) - 3) return -EIO; - + res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long)); if (res) return res; tmp = 0; /* Default return condition */ + if (addr >= (long) (&dummy->i387) && + addr < (long) (&dummy->i387.st_space[20]) ) { +#ifndef CONFIG_MATH_EMULATION + if (!hard_math) + return -EIO; +#endif /* defined(CONFIG_MATH_EMULATION) */ + tmp = get_fpreg_word(child, addr); + } if(addr < 17*sizeof(long)) { addr = addr >> 2; /* temporary hack. */ @@ -401,12 +532,23 @@ return write_long(child,addr,data); case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ - if ((addr & 3) || addr < 0 || + if ((addr & 3 && + (addr < (long) (&dummy->i387.st_space[0]) || + addr > (long) (&dummy->i387.st_space[20]) )) || + addr < 0 || addr > sizeof(struct user) - 3) return -EIO; - + + if (addr >= (long) (&dummy->i387.st_space[0]) && + addr < (long) (&dummy->i387.st_space[20]) ) { +#ifndef CONFIG_MATH_EMULATION + if (!hard_math) + return -EIO; +#endif /* defined(CONFIG_MATH_EMULATION) */ + return put_fpreg_word(child, addr, data); + } addr = addr >> 2; /* temporary hack. */ - + if (addr == ORIG_EAX) return -EIO; if (addr == DS || addr == ES || diff -u --recursive --new-file v2.0.31/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c --- v2.0.31/linux/arch/i386/kernel/time.c Sun Nov 10 09:40:53 1996 +++ linux/arch/i386/kernel/time.c Fri Nov 7 10:06:21 1997 @@ -12,6 +12,8 @@ * precision CMOS clock update * 1996-05-03 Ingo Molnar * fixed time warps in do_[slow|fast]_gettimeoffset() + * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 + * "A Kernel Model for Precision Timekeeping" by Dave Mills */ #include #include @@ -269,9 +271,11 @@ } xtime = *tv; - time_state = TIME_BAD; - time_maxerror = MAXPHASE; - time_esterror = MAXPHASE; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_state = TIME_ERROR; /* p. 24, (a) */ + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; sti(); } @@ -282,6 +286,9 @@ * nowtime is written into the registers of the CMOS clock, it will * jump to the next second precisely 500 ms later. Check the Motorola * MC146818A or Dallas DS12887 data sheet for details. + * + * BUG: This routine does not handle hour overflow properly; it just + * sets the minutes. Usually you'll only notice that after reboot! */ static int set_rtc_mmss(unsigned long nowtime) { @@ -318,8 +325,12 @@ } CMOS_WRITE(real_seconds,RTC_SECONDS); CMOS_WRITE(real_minutes,RTC_MINUTES); - } else + } else { + printk(KERN_WARNING + "set_rtc_mmss: can't update from %d to %d\n", + cmos_minutes, real_minutes); retval = -1; + } /* The following flags have to be released exactly in this order, * otherwise the DS12887 (popular MC146818A clone with integrated @@ -350,7 +361,8 @@ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be * called as close as possible to 500 ms before the new second starts. */ - if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && + if ((time_status & STA_UNSYNC) == 0 && + xtime.tv_sec > last_rtc_update + 660 && xtime.tv_usec > 500000 - (tick >> 1) && xtime.tv_usec < 500000 + (tick >> 1)) if (set_rtc_mmss(xtime.tv_sec) == 0) diff -u --recursive --new-file v2.0.31/linux/arch/i386/math-emu/Makefile linux/arch/i386/math-emu/Makefile --- v2.0.31/linux/arch/i386/math-emu/Makefile Tue Aug 15 05:07:02 1995 +++ linux/arch/i386/math-emu/Makefile Fri Nov 7 09:11:42 1997 @@ -22,7 +22,8 @@ reg_round.o \ wm_shrx.o wm_sqrt.o \ div_Xsig.o polynom_Xsig.o round_Xsig.o \ - shr_Xsig.o mul_Xsig.o + shr_Xsig.o mul_Xsig.o \ + fpu_debug.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.0.31/linux/arch/i386/math-emu/fpu_debug.c linux/arch/i386/math-emu/fpu_debug.c --- v2.0.31/linux/arch/i386/math-emu/fpu_debug.c Wed Dec 31 16:00:00 1969 +++ linux/arch/i386/math-emu/fpu_debug.c Fri Nov 7 09:11:42 1997 @@ -0,0 +1,230 @@ +/* Interface with ptrace and core-dumping routines */ + + +#include "fpu_system.h" +#include "exception.h" +#include "reg_constant.h" +#include "fpu_emu.h" +#include "control_w.h" +#include "status_w.h" + + +#define EXTENDED_Ebias 0x3fff +#define EXTENDED_Emin (-0x3ffe) /* smallest valid exponent */ + +#define DOUBLE_Emax 1023 /* largest valid exponent */ +#define DOUBLE_Ebias 1023 +#define DOUBLE_Emin (-1022) /* smallest valid exponent */ + +#define SINGLE_Emax 127 /* largest valid exponent */ +#define SINGLE_Ebias 127 +#define SINGLE_Emin (-126) /* smallest valid exponent */ + + +/* Copy and paste from round_to_int. Original comments maintained */ +/*===========================================================================*/ + +/* r gets mangled such that sig is int, sign: + it is NOT normalized */ +/* The return value (in eax) is zero if the result is exact, + if bits are changed due to rounding, truncation, etc, then + a non-zero value is returned */ +/* Overflow is signalled by a non-zero return value (in eax). + In the case of overflow, the returned significand always has the + largest possible value */ + +static int round_to_int_cwd(FPU_REG *r, long int user_control_word) +{ + char very_big; + unsigned eax; + + if (r->tag == TW_Zero) + { + /* Make sure that zero is returned */ + significand(r) = 0; + return 0; /* o.k. */ + } + + if (r->exp > EXP_BIAS + 63) + { + r->sigl = r->sigh = ~0; /* The largest representable number */ + return 1; /* overflow */ + } + + eax = shrxs(&r->sigl, EXP_BIAS + 63 - r->exp); + very_big = !(~(r->sigh) | ~(r->sigl)); /* test for 0xfff...fff */ +#define half_or_more (eax & 0x80000000) +#define frac_part (eax) +#define more_than_half ((eax & 0x80000001) == 0x80000001) + switch (user_control_word & CW_RC) + { + case RC_RND: + if ( more_than_half /* nearest */ + || (half_or_more && (r->sigl & 1)) ) /* odd -> even */ + { + if ( very_big ) return 1; /* overflow */ + significand(r) ++; + return PRECISION_LOST_UP; + } + break; + case RC_DOWN: + if (frac_part && r->sign) + { + if ( very_big ) return 1; /* overflow */ + significand(r) ++; + return PRECISION_LOST_UP; + } + break; + case RC_UP: + if (frac_part && !r->sign) + { + if ( very_big ) return 1; /* overflow */ + significand(r) ++; + return PRECISION_LOST_UP; + } + break; + case RC_CHOP: + break; + } + + return eax ? PRECISION_LOST_DOWN : 0; + +} + + + +/* Conver a number in the emulator format to the + * hardware format. + * Taken from the emulator sources, function reg_load_extended + */ + +/* Get a long double from the debugger */ +void hardreg_to_softreg(const char hardreg[10], + FPU_REG *soft_reg) + +{ + unsigned long sigl, sigh, exp; + + sigl = *((unsigned long *) hardreg); + sigh = *(1 + (unsigned long *) hardreg); + exp = *(4 + (unsigned short *) hardreg); + + soft_reg->tag = TW_Valid; /* Default */ + soft_reg->sigl = sigl; + soft_reg->sigh = sigh; + if (exp & 0x8000) + soft_reg->sign = SIGN_NEG; + else + soft_reg->sign = SIGN_POS; + exp &= 0x7fff; + soft_reg->exp = exp - EXTENDED_Ebias + EXP_BIAS; + + if ( exp == 0 ) + { + if ( !(sigh | sigl) ) + { + soft_reg->tag = TW_Zero; + return; + } + /* The number is a de-normal or pseudodenormal. */ + if (sigh & 0x80000000) + { + /* Is a pseudodenormal. */ + /* Convert it for internal use. */ + /* This is non-80486 behaviour because the number + loses its 'denormal' identity. */ + soft_reg->exp++; + return; + } + else + { + /* Is a denormal. */ + /* Convert it for internal use. */ + soft_reg->exp++; + normalize_nuo(soft_reg); + return; + } + } + else if ( exp == 0x7fff ) + { + if ( !((sigh ^ 0x80000000) | sigl) ) + { + /* Matches the bit pattern for Infinity. */ + soft_reg->exp = EXP_Infinity; + soft_reg->tag = TW_Infinity; + return; + } + + soft_reg->exp = EXP_NaN; + soft_reg->tag = TW_NaN; + if ( !(sigh & 0x80000000) ) + { + /* NaNs have the ms bit set to 1. */ + /* This is therefore an Unsupported NaN data type. */ + /* This is non 80486 behaviour */ + /* This should generate an Invalid Operand exception + later, so we convert it to a SNaN */ + soft_reg->sigh = 0x80000000; + soft_reg->sigl = 0x00000001; + soft_reg->sign = SIGN_NEG; + return; + } + return; + } + + if ( !(sigh & 0x80000000) ) + { + /* Unsupported data type. */ + /* Valid numbers have the ms bit set to 1. */ + /* Unnormal. */ + /* Convert it for internal use. */ + /* This is non-80486 behaviour */ + /* This should generate an Invalid Operand exception + later, so we convert it to a SNaN */ + soft_reg->sigh = 0x80000000; + soft_reg->sigl = 0x00000001; + soft_reg->sign = SIGN_NEG; + soft_reg->exp = EXP_NaN; + soft_reg->tag = TW_NaN; + return; + } + return; +} + +/* Conver a number in the emulator format to the + * hardware format. + * Adapted from function write_to_extended + */ + + +void softreg_to_hardreg(const FPU_REG *rp, char d[10], long int user_control_word) +{ + long e; + FPU_REG tmp; + e = rp->exp - EXP_BIAS + EXTENDED_Ebias; + + /* + All numbers except denormals are stored internally in a + format which is compatible with the extended real number + format. + */ + if (e > 0) { + *(unsigned long *) d = rp->sigl; + *(unsigned long *) (d + 4) = rp->sigh; + } else { + /* + The number is a de-normal stored as a normal using our + extra exponent range, or is Zero. + Convert it back to a de-normal, or leave it as Zero. + */ + reg_move(rp, &tmp); + tmp.exp += -EXTENDED_Emin + 63; /* largest exp to be 63 */ + round_to_int_cwd(&tmp, user_control_word); + e = 0; + *(unsigned long *) d= tmp.sigl; + *(unsigned long *) (d + 4) = tmp.sigh; + } + e |= rp->sign == SIGN_POS ? 0 : 0x8000; + *(unsigned short *) (d + 8) = e; +} + diff -u --recursive --new-file v2.0.31/linux/drivers/char/console.c linux/drivers/char/console.c --- v2.0.31/linux/drivers/char/console.c Tue Aug 12 13:06:54 1997 +++ linux/drivers/char/console.c Mon Nov 3 16:56:30 1997 @@ -60,6 +60,8 @@ * User-defined bell sound, new setterm control sequences and printk * redirection by Martin Mares 19-Nov-95 * + * APM screenblank bug fixed Takashi Manabe + * Backported to 2.0.31 by Adam Bradley */ #define BLANK 0x0020 @@ -2151,12 +2153,14 @@ hide_cursor(); console_blanked = fg_console + 1; + if(!nopowersave) + { #ifdef CONFIG_APM - if (apm_display_blank()) - return; + if (apm_display_blank()) + return; #endif - if(!nopowersave) - vesa_blank(); + vesa_blank(); + } } void do_unblank_screen(void) diff -u --recursive --new-file v2.0.31/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c --- v2.0.31/linux/drivers/net/ibmtr.c Tue Aug 12 13:21:12 1997 +++ linux/drivers/net/ibmtr.c Fri Nov 7 09:55:03 1997 @@ -444,7 +444,7 @@ paging), then only one adapter can be supported. */ /* determine how much of total RAM is mapped into PC space */ - ti->mapped_ram_size=1<<(((readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD)) >>2) +4); + ti->mapped_ram_size=1<<((((readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD)) >>2) & 0x03) + 4); ti->page_mask=0; if (ti->shared_ram_paging == 0xf) { /* No paging in adapter */ ti->mapped_ram_size = ti->avail_shared_ram; @@ -500,7 +500,7 @@ if (cardpresent==TR_ISA) { static unsigned char ram_bndry_mask[]={0xfe, 0xfc, 0xf8, 0xf0}; unsigned char new_base, rrr_32, chk_base, rbm; - rrr_32 = (readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD))>>2; + rrr_32 = ((readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD))>>2) & 0x03; rbm = ram_bndry_mask[rrr_32]; new_base = (Shared_Ram_Base + (~rbm)) & rbm; /* up to boundary */ chk_base = new_base + (ti->mapped_ram_size>>3); diff -u --recursive --new-file v2.0.31/linux/drivers/net/ne.c linux/drivers/net/ne.c --- v2.0.31/linux/drivers/net/ne.c Sun Aug 17 09:44:56 1997 +++ linux/drivers/net/ne.c Tue Nov 11 08:15:27 1997 @@ -77,6 +77,7 @@ {PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_RL2000}, {PCI_VENDOR_ID_KTI, PCI_DEVICE_ID_KTI_ET32P2}, {PCI_VENDOR_ID_NETVIN, PCI_DEVICE_ID_NETVIN_NV5000SC}, + {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C926}, {0,} }; #endif diff -u --recursive --new-file v2.0.31/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.0.31/linux/drivers/pci/pci.c Fri Oct 17 14:05:37 1997 +++ linux/drivers/pci/pci.c Sat Nov 1 10:06:27 1997 @@ -231,8 +231,8 @@ DEVICE( VIA, VIA_82C576, "VT 82C576 3V"), DEVICE( VIA, VIA_82C585, "VT 82C585VP Apollo VP-1"), DEVICE( VIA, VIA_82C586_0, "VT 82C586 Apollo VP-1"), - DEVICE( VIA, VIA_82C416, "VT 82C416MV"), DEVICE( VIA, VIA_82C926, "VT 82C926 Amazon"), + DEVICE( VIA, VIA_82C416, "VT 82C416MV"), DEVICE( VORTEX, VORTEX_GDT60x0, "GDT 60x0"), DEVICE( VORTEX, VORTEX_GDT6000B,"GDT 6000b"), DEVICE( VORTEX, VORTEX_GDT6x10, "GDT 6110/6510"), diff -u --recursive --new-file v2.0.31/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c --- v2.0.31/linux/drivers/scsi/fdomain.c Sat Nov 2 06:41:06 1996 +++ linux/drivers/scsi/fdomain.c Fri Nov 7 10:16:23 1997 @@ -462,6 +462,7 @@ { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 }, { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 }, { "Adaptec AHA-2920 PCI-SCSI Card", 42, 31, 3, -1, 1 }, + { "IBM F1 P264/32", 5, 14, 3, -1, 1 }, /* This next signature may not be a 3.5 bios */ { "Future Domain Corp. V2.0108/18/93", 5, 33, 3, 5, 0 }, { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 }, diff -u --recursive --new-file v2.0.31/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v2.0.31/linux/drivers/scsi/sr.c Mon Aug 11 13:37:24 1997 +++ linux/drivers/scsi/sr.c Fri Nov 7 09:57:30 1997 @@ -601,6 +601,8 @@ if (filp->f_mode & 2) return -EROFS; + if(sr_template.usage_count) (*sr_template.usage_count)++; + sr_ioctl(inode,filp,CDROMCLOSETRAY,0); check_disk_change(inode->i_rdev); @@ -608,7 +610,6 @@ sr_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0); if (scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count) (*scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count)++; - if(sr_template.usage_count) (*sr_template.usage_count)++; sr_photocd(inode); diff -u --recursive --new-file v2.0.31/linux/drivers/sound/ulaw.h linux/drivers/sound/ulaw.h --- v2.0.31/linux/drivers/sound/ulaw.h Sun Jun 30 01:43:40 1996 +++ linux/drivers/sound/ulaw.h Mon Nov 10 10:54:42 1997 @@ -1,69 +1,69 @@ static unsigned char ulaw_dsp[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2, - 5, 9, 13, 17, 21, 25, 29, 33, - 37, 41, 45, 49, 53, 57, 61, 65, - 68, 70, 72, 74, 76, 78, 80, 82, - 84, 86, 88, 90, 92, 94, 96, 98, - 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, - 115, 116, 116, 117, 117, 118, 118, 119, - 119, 120, 120, 121, 121, 122, 122, 123, - 123, 123, 124, 124, 124, 124, 125, 125, - 125, 125, 126, 126, 126, 126, 127, 127, - 127, 127, 127, 127, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 252, 248, 244, 240, 236, 232, 228, 224, - 220, 216, 212, 208, 204, 200, 196, 192, - 189, 187, 185, 183, 181, 179, 177, 175, - 173, 171, 169, 167, 165, 163, 161, 159, - 157, 156, 155, 154, 153, 152, 151, 150, - 149, 148, 147, 146, 145, 144, 143, 142, - 142, 141, 141, 140, 140, 139, 139, 138, - 138, 137, 137, 136, 136, 135, 135, 134, - 134, 134, 133, 133, 133, 133, 132, 132, - 132, 132, 131, 131, 131, 131, 130, 130, - 130, 130, 130, 130, 129, 129, 129, 129, - 129, 129, 129, 129, 128, 128, 128, 128, + 3, 7, 11, 15, 19, 23, 27, 31, + 35, 39, 43, 47, 51, 55, 59, 63, + 66, 68, 70, 72, 74, 76, 78, 80, + 82, 84, 86, 88, 90, 92, 94, 96, + 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, + 113, 114, 114, 115, 115, 116, 116, 117, + 117, 118, 118, 119, 119, 120, 120, 121, + 121, 121, 122, 122, 122, 122, 123, 123, + 123, 123, 124, 124, 124, 124, 125, 125, + 125, 125, 125, 125, 126, 126, 126, 126, + 126, 126, 126, 126, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 253, 249, 245, 241, 237, 233, 229, 225, + 221, 217, 213, 209, 205, 201, 197, 193, + 190, 188, 186, 184, 182, 180, 178, 176, + 174, 172, 170, 168, 166, 164, 162, 160, + 158, 157, 156, 155, 154, 153, 152, 151, + 150, 149, 148, 147, 146, 145, 144, 143, + 143, 142, 142, 141, 141, 140, 140, 139, + 139, 138, 138, 137, 137, 136, 136, 135, + 135, 135, 134, 134, 134, 134, 133, 133, + 133, 133, 132, 132, 132, 132, 131, 131, + 131, 131, 131, 131, 130, 130, 130, 130, + 130, 130, 130, 130, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, }; static unsigned char dsp_ulaw[] = { - 31, 31, 31, 32, 32, 32, 32, 33, - 33, 33, 33, 34, 34, 34, 34, 35, - 35, 35, 35, 36, 36, 36, 36, 37, - 37, 37, 37, 38, 38, 38, 38, 39, - 39, 39, 39, 40, 40, 40, 40, 41, - 41, 41, 41, 42, 42, 42, 42, 43, - 43, 43, 43, 44, 44, 44, 44, 45, - 45, 45, 45, 46, 46, 46, 46, 47, - 47, 47, 47, 48, 48, 49, 49, 50, - 50, 51, 51, 52, 52, 53, 53, 54, - 54, 55, 55, 56, 56, 57, 57, 58, - 58, 59, 59, 60, 60, 61, 61, 62, - 62, 63, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 81, 83, 85, 87, 89, - 91, 93, 95, 99, 103, 107, 111, 119, - 255, 247, 239, 235, 231, 227, 223, 221, - 219, 217, 215, 213, 211, 209, 207, 206, - 205, 204, 203, 202, 201, 200, 199, 198, - 197, 196, 195, 194, 193, 192, 191, 191, - 190, 190, 189, 189, 188, 188, 187, 187, - 186, 186, 185, 185, 184, 184, 183, 183, - 182, 182, 181, 181, 180, 180, 179, 179, - 178, 178, 177, 177, 176, 176, 175, 175, - 175, 175, 174, 174, 174, 174, 173, 173, - 173, 173, 172, 172, 172, 172, 171, 171, - 171, 171, 170, 170, 170, 170, 169, 169, - 169, 169, 168, 168, 168, 168, 167, 167, - 167, 167, 166, 166, 166, 166, 165, 165, - 165, 165, 164, 164, 164, 164, 163, 163, - 163, 163, 162, 162, 162, 162, 161, 161, - 161, 161, 160, 160, 160, 160, 159, 159, + 0, 0, 0, 0, 0, 1, 1, 1, + 1, 2, 2, 2, 2, 3, 3, 3, + 3, 4, 4, 4, 4, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 7, 7, + 7, 8, 8, 8, 8, 9, 9, 9, + 9, 10, 10, 10, 10, 11, 11, 11, + 11, 12, 12, 12, 12, 13, 13, 13, + 13, 14, 14, 14, 14, 15, 15, 15, + 15, 16, 16, 17, 17, 18, 18, 19, + 19, 20, 20, 21, 21, 22, 22, 23, + 23, 24, 24, 25, 25, 26, 26, 27, + 27, 28, 28, 29, 29, 30, 30, 31, + 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, + 47, 49, 51, 53, 55, 57, 59, 61, + 63, 66, 70, 74, 78, 84, 92, 104, + 254, 231, 219, 211, 205, 201, 197, 193, + 190, 188, 186, 184, 182, 180, 178, 176, + 175, 174, 173, 172, 171, 170, 169, 168, + 167, 166, 165, 164, 163, 162, 161, 160, + 159, 159, 158, 158, 157, 157, 156, 156, + 155, 155, 154, 154, 153, 153, 152, 152, + 151, 151, 150, 150, 149, 149, 148, 148, + 147, 147, 146, 146, 145, 145, 144, 144, + 143, 143, 143, 143, 142, 142, 142, 142, + 141, 141, 141, 141, 140, 140, 140, 140, + 139, 139, 139, 139, 138, 138, 138, 138, + 137, 137, 137, 137, 136, 136, 136, 136, + 135, 135, 135, 135, 134, 134, 134, 134, + 133, 133, 133, 133, 132, 132, 132, 132, + 131, 131, 131, 131, 130, 130, 130, 130, + 129, 129, 129, 129, 128, 128, 128, 128, }; diff -u --recursive --new-file v2.0.31/linux/fs/buffer.c linux/fs/buffer.c --- v2.0.31/linux/fs/buffer.c Tue Sep 23 13:23:33 1997 +++ linux/fs/buffer.c Fri Nov 7 09:57:30 1997 @@ -95,7 +95,7 @@ int dummy3; /* unused */ } b_un; unsigned int data[N_PARAM]; -} bdf_prm = {{60, 500, 64, 256, 15, 30*HZ, 5*HZ, 1884, 2}}; +} bdf_prm = {{40, 500, 64, 64, 15, 30*HZ, 5*HZ, 1884, 2}}; /* These are the min and max parameter values that we will allow to be assigned */ int bdflush_min[N_PARAM] = { 0, 10, 5, 25, 0, 100, 100, 1, 1}; @@ -590,6 +590,48 @@ return NULL; } +static void put_unused_buffer_head(struct buffer_head * bh) +{ + if (nr_unused_buffer_heads >= MAX_UNUSED_BUFFERS) { + nr_buffer_heads--; + kfree(bh); + return; + } + memset(bh,0,sizeof(*bh)); + nr_unused_buffer_heads++; + bh->b_next_free = unused_list; + unused_list = bh; + wake_up(&buffer_wait); +} + +/* + * We can't put completed temporary IO buffer_heads directly onto the + * unused_list when they become unlocked, since the device driver + * end_request routines still expect access to the buffer_head's + * fields after the final unlock. So, the device driver puts them on + * the reuse_list instead once IO completes, and we recover these to + * the unused_list here. + * + * The reuse_list receives buffers from interrupt routines, so we need + * to be IRQ-safe here (but note that interrupts only _add_ to the + * reuse_list, never take away. So we don't need to worry about the + * reuse_list magically emptying). + */ +static inline void recover_reusable_buffer_heads(void) +{ + if (reuse_list) { + struct buffer_head *head; + + head = xchg(&reuse_list, NULL); + + do { + struct buffer_head *bh = head; + head = head->b_next_free; + put_unused_buffer_head(bh); + } while (head); + } +} + extern void allow_interrupts(void); static void refill_freelist(int size) @@ -617,6 +659,7 @@ repeat: allow_interrupts(); + recover_reusable_buffer_heads(); if(needed <= 0) return; @@ -661,11 +704,6 @@ goto repeat; } - /* Dirty buffers should not overtake, wakeup_bdflush(1) calls - bdflush and sleeps, therefore kswapd does his important work. */ - if (nr_buffers_type[BUF_DIRTY] > nr_buffers * bdf_prm.b_un.nfract/100) - wakeup_bdflush(1); - /* Too bad, that was not enough. Try a little harder to grow some. */ if (nr_free_pages > limit) { @@ -677,14 +715,14 @@ /* If we are not bdflush we should wake up bdflush and try it again. */ - if (current != bdflush_tsk) { + if (current != bdflush_tsk && + (buffermem >> PAGE_SHIFT) > (MAP_NR(high_memory) >> 2) && + nr_buffers_type[BUF_DIRTY] > bdf_prm.b_un.nref_dirt) { wakeup_bdflush(1); needed -= PAGE_SIZE; goto repeat; } - /* We are bdflush: let's try our best */ - /* * In order to protect our reserved pages, * return now if we got any buffers. @@ -694,7 +732,12 @@ return; /* and repeat until we find something good */ - grow_buffers(GFP_BUFFER, size); + i = grow_buffers(GFP_BUFFER, size); + + if (current != bdflush_tsk && !i && nr_buffers_type[BUF_DIRTY] > 0) + wakeup_bdflush(1); + else if (!i) + grow_buffers(GFP_IO, size); /* decrease needed even if there is no success */ needed -= PAGE_SIZE; @@ -732,26 +775,30 @@ return bh; } - while(!free_list[isize]) { - allow_interrupts(); - refill_freelist(size); - } - - if (find_buffer(dev,block,size)) - goto repeat; - +get_free: bh = free_list[isize]; + if (!bh) + goto refill; remove_from_free_list(bh); -/* OK, FINALLY we know that this buffer is the only one of its kind, */ -/* and that it's unused (b_count=0), unlocked (buffer_locked=0), and clean */ + /* OK, FINALLY we know that this buffer is the only one of its kind, + * and that it's unused (b_count=0), unlocked (buffer_locked=0), + * and clean */ bh->b_count=1; + bh->b_list=BUF_CLEAN; bh->b_flushtime=0; bh->b_state=(1<b_dev=dev; bh->b_blocknr=block; insert_into_queues(bh); return bh; + +refill: + allow_interrupts(); + refill_freelist(size); + if (!find_buffer(dev,block,size)) + goto get_free; + goto repeat; } void set_writetime(struct buffer_head * buf, int flag) @@ -934,48 +981,6 @@ return NULL; } -static void put_unused_buffer_head(struct buffer_head * bh) -{ - if (nr_unused_buffer_heads >= MAX_UNUSED_BUFFERS) { - nr_buffer_heads--; - kfree(bh); - return; - } - memset(bh,0,sizeof(*bh)); - nr_unused_buffer_heads++; - bh->b_next_free = unused_list; - unused_list = bh; - wake_up(&buffer_wait); -} - -/* - * We can't put completed temporary IO buffer_heads directly onto the - * unused_list when they become unlocked, since the device driver - * end_request routines still expect access to the buffer_head's - * fields after the final unlock. So, the device driver puts them on - * the reuse_list instead once IO completes, and we recover these to - * the unused_list here. - * - * The reuse_list receives buffers from interrupt routines, so we need - * to be IRQ-safe here (but note that interrupts only _add_ to the - * reuse_list, never take away. So we don't need to worry about the - * reuse_list magically emptying). - */ -static inline void recover_reusable_buffer_heads(void) -{ - if (reuse_list) { - struct buffer_head *head; - - head = xchg(&reuse_list, NULL); - - do { - struct buffer_head *bh = head; - head = head->b_next_free; - put_unused_buffer_head(bh); - } while (head); - } -} - static void get_more_buffer_heads(void) { struct buffer_head * bh; @@ -1502,6 +1507,7 @@ if (wait) { run_task_queue(&tq_disk); sleep_on(&bdflush_done); + recover_reusable_buffer_heads(); } } diff -u --recursive --new-file v2.0.31/linux/fs/exec.c linux/fs/exec.c --- v2.0.31/linux/fs/exec.c Wed Oct 15 14:56:43 1997 +++ linux/fs/exec.c Fri Nov 7 09:57:30 1997 @@ -320,7 +320,7 @@ for (i = 0 ; i < MAX_ARG_PAGES ; i++) { if (bprm->page[i]) { free_page(bprm->page[i]); - bprm->page[i]=NULL; + bprm->page[i] = 0; } } } @@ -411,8 +411,10 @@ return 0; } + flush_cache_mm(current->mm); exit_mmap(current->mm); clear_page_tables(current); + flush_tlb_mm(current->mm); return 0; } diff -u --recursive --new-file v2.0.31/linux/fs/locks.c linux/fs/locks.c --- v2.0.31/linux/fs/locks.c Mon Sep 1 11:20:42 1997 +++ linux/fs/locks.c Fri Nov 7 15:35:04 1997 @@ -130,8 +130,9 @@ struct task_struct *blocked_task); static void posix_remove_locks(struct file_lock **before, struct task_struct *task); static void flock_remove_locks(struct file_lock **before, struct file *filp); - -static struct file_lock *locks_alloc_lock(struct file_lock *fl); +static struct file_lock *locks_empty_lock(void); +static struct file_lock *locks_init_lock(struct file_lock *, + struct file_lock *); static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl); static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait); static char *lock_get_status(struct file_lock *fl, int id, char *pfx); @@ -142,6 +143,15 @@ static struct file_lock *file_lock_table = NULL; +/* Allocate a new lock, and initialize its fields from fl. + * The lock is not inserted into any lists until locks_insert_lock() or + * locks_insert_block() are called. + */ +static inline struct file_lock *locks_alloc_lock(struct file_lock *fl) +{ + return locks_init_lock(locks_empty_lock(), fl); +} + /* Free lock not inserted in any queue. */ static inline void locks_free_lock(struct file_lock *fl) @@ -281,6 +291,7 @@ if (!filp->f_inode || !posix_make_lock(filp, &file_lock, &flock)) return (-EINVAL); + flock.l_type = F_UNLCK; for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) { if (!(fl->fl_flags & FL_POSIX)) break; @@ -291,12 +302,10 @@ fl->fl_end - fl->fl_start + 1; flock.l_whence = 0; flock.l_type = fl->fl_type; - memcpy_tofs(l, &flock, sizeof(flock)); - return (0); + break; } } - flock.l_type = F_UNLCK; /* no conflict found */ memcpy_tofs(l, &flock, sizeof(flock)); return (0); } @@ -327,6 +336,11 @@ if (!(inode = filp->f_inode)) return (-EINVAL); + /* + * This might block, so we do it before checking the inode. + */ + memcpy_fromfs(&flock, l, sizeof(flock)); + /* Don't allow mandatory locks on files that may be memory mapped * and shared. */ @@ -341,7 +355,6 @@ } while (vma != inode->i_mmap); } - memcpy_fromfs(&flock, l, sizeof(flock)); if (!posix_make_lock(filp, &file_lock, &flock)) return (-EINVAL); @@ -708,19 +721,38 @@ unsigned int wait) { struct file_lock *fl; - struct file_lock *new_fl; + struct file_lock *new_fl = NULL; struct file_lock **before; - int change = 0; + int error; + int change; + int unlock = (caller->fl_type == F_UNLCK); + + /* + * If we need a new lock, get it in advance to avoid races. + */ + if (!unlock) { + error = -ENOLCK; + new_fl = locks_alloc_lock(caller); + if (!new_fl) + goto out; + } + + + error = 0; +search: + change = 0; before = &filp->f_inode->i_flock; - if ((fl = *before) && (fl->fl_flags & FL_POSIX)) - return (-EBUSY); + if ((fl = *before) && (fl->fl_flags & FL_POSIX)) { + error = -EBUSY; + goto out; + } while ((fl = *before) != NULL) { if (caller->fl_file == fl->fl_file) { if (caller->fl_type == fl->fl_type) - return (0); + goto out; change = 1; break; } @@ -729,50 +761,48 @@ /* change means that we are changing the type of an existing lock, or * or else unlocking it. */ - if (change) - locks_delete_lock(before, caller->fl_type != F_UNLCK); - if (caller->fl_type == F_UNLCK) - return (0); - if ((new_fl = locks_alloc_lock(caller)) == NULL) - return (-ENOLCK); -repeat: - if ((fl = filp->f_inode->i_flock) && (fl->fl_flags & FL_POSIX)) { - locks_free_lock(new_fl); - return (-EBUSY); + if (change) { + /* N.B. What if the wait argument is false? */ + locks_delete_lock(before, !unlock); + /* + * If we waited, another lock may have been added ... + */ + if (!unlock) + goto search; } + if (unlock) + goto out; + +repeat: + /* Check signals each time we start */ + error = -ERESTARTSYS; + if (current->signal & ~current->blocked) + goto out; + error = -EBUSY; + if ((fl = filp->f_inode->i_flock) && (fl->fl_flags & FL_POSIX)) + goto out; while (fl != NULL) { if (!flock_locks_conflict(new_fl, fl)) { fl = fl->fl_next; continue; } - if (!wait) { - locks_free_lock(new_fl); - return (-EAGAIN); - } - if (current->signal & ~current->blocked) { - /* Note: new_fl is not in any queue at this - * point, so we must use locks_free_lock() - * instead of locks_delete_lock() - * Dmitry Gorodchanin 09/02/96. - */ - locks_free_lock(new_fl); - return (-ERESTARTSYS); - } + error = -EAGAIN; + if (!wait) + goto out; locks_insert_block(fl, new_fl); interruptible_sleep_on(&new_fl->fl_wait); locks_delete_block(fl, new_fl); - if (current->signal & ~current->blocked) { - /* Awakened by a signal. Free the new - * lock and return an error. - */ - locks_free_lock(new_fl); - return (-ERESTARTSYS); - } goto repeat; } locks_insert_lock(&filp->f_inode->i_flock, new_fl); - return (0); + new_fl = NULL; + error = 0; + +out: + if (new_fl) + locks_free_lock(new_fl); + return (error); } /* Add a POSIX style lock to a file. @@ -791,44 +821,62 @@ unsigned int wait) { struct file_lock *fl; - struct file_lock *new_fl; + struct file_lock *new_fl, *new_fl2; struct file_lock *left = NULL; struct file_lock *right = NULL; struct file_lock **before; + int error; int added = 0; + /* + * We may need two file_lock structures for this operation, + * so we get them in advance to avoid races. + */ + new_fl = locks_empty_lock(); + new_fl2 = locks_empty_lock(); + error = -ENOLCK; /* "no luck" */ + if (!(new_fl && new_fl2)) + goto out; + if (caller->fl_type != F_UNLCK) { repeat: + error = -EBUSY; if ((fl = filp->f_inode->i_flock) && (fl->fl_flags & FL_FLOCK)) - return (-EBUSY); + goto out; while (fl != NULL) { if (!posix_locks_conflict(caller, fl)) { fl = fl->fl_next; continue; } + error = -EAGAIN; if (!wait) - return (-EAGAIN); - if (current->signal & ~current->blocked) - return (-ERESTARTSYS); + goto out; + error = -EDEADLK; if (posix_locks_deadlock(caller->fl_owner, fl->fl_owner)) - return (-EDEADLK); + goto out; + error = -ERESTARTSYS; + if (current->signal & ~current->blocked) + goto out; locks_insert_block(fl, caller); interruptible_sleep_on(&caller->fl_wait); locks_delete_block(fl, caller); - if (current->signal & ~current->blocked) - return (-ERESTARTSYS); goto repeat; } } - /* Find the first old lock with the same owner as the new lock. + /* + * We've allocated the new locks in advance, so there are no + * errors possible (and no blocking operations) from here on. + * + * Find the first old lock with the same owner as the new lock. */ before = &filp->f_inode->i_flock; + error = -EBUSY; if ((*before != NULL) && ((*before)->fl_flags & FL_FLOCK)) - return (-EBUSY); + goto out; /* First skip locks owned by other processes. */ @@ -916,25 +964,23 @@ before = &fl->fl_next; } + error = 0; if (!added) { if (caller->fl_type == F_UNLCK) - return (0); - if ((new_fl = locks_alloc_lock(caller)) == NULL) - return (-ENOLCK); + goto out; + locks_init_lock(new_fl, caller); locks_insert_lock(before, new_fl); + new_fl = NULL; } if (right) { if (left == right) { - /* The new lock breaks the old one in two pieces, so we - * have to allocate one more lock (in this case, even - * F_UNLCK may fail!). + /* The new lock breaks the old one in two pieces, + * so we have to use the second new lock (in this + * case, even F_UNLCK may fail!). */ - if ((left = locks_alloc_lock(right)) == NULL) { - if (!added) - locks_delete_lock(before, 0); - return (-ENOLCK); - } + left = locks_init_lock(new_fl2, right); locks_insert_lock(before, left); + new_fl2 = NULL; } right->fl_start = caller->fl_end + 1; locks_wake_up_blocks(right, 0); @@ -943,32 +989,44 @@ left->fl_end = caller->fl_start - 1; locks_wake_up_blocks(left, 0); } - return (0); +out: + /* + * Free any unused locks. (They haven't + * ever been used, so we use kfree().) + */ + if (new_fl) + kfree(new_fl); + if (new_fl2) + kfree(new_fl2); + return error; } -/* Allocate new lock. - * Initialize its fields from fl. The lock is not inserted into any - * lists until locks_insert_lock() or locks_insert_block() are called. +/* + * Allocate an empty lock structure. We can use GFP_KERNEL now that + * all allocations are done in advance. */ -static struct file_lock *locks_alloc_lock(struct file_lock *fl) +static struct file_lock *locks_empty_lock(void) { - struct file_lock *tmp; - - /* Okay, let's make a new file_lock structure... */ - if ((tmp = (struct file_lock *)kmalloc(sizeof(struct file_lock), - GFP_ATOMIC)) == NULL) - return (tmp); - - memset(tmp, 0, sizeof(*tmp)); - - tmp->fl_flags = fl->fl_flags; - tmp->fl_owner = fl->fl_owner; - tmp->fl_file = fl->fl_file; - tmp->fl_type = fl->fl_type; - tmp->fl_start = fl->fl_start; - tmp->fl_end = fl->fl_end; + return ((struct file_lock *) kmalloc(sizeof(struct file_lock), + GFP_KERNEL)); +} - return (tmp); +/* + * Initialize a new lock from an existing file_lock structure. + */ +static struct file_lock *locks_init_lock(struct file_lock *new, + struct file_lock *fl) +{ + if (new) { + memset(new, 0, sizeof(*new)); + new->fl_owner = fl->fl_owner; + new->fl_file = fl->fl_file; + new->fl_flags = fl->fl_flags; + new->fl_type = fl->fl_type; + new->fl_start = fl->fl_start; + new->fl_end = fl->fl_end; + } + return new; } /* Insert file lock fl into an inode's lock list at the position indicated diff -u --recursive --new-file v2.0.31/linux/fs/proc/fd.c linux/fs/proc/fd.c --- v2.0.31/linux/fs/proc/fd.c Fri Dec 22 03:00:19 1995 +++ linux/fs/proc/fd.c Sat Nov 1 12:30:30 1997 @@ -106,8 +106,8 @@ if (!pid || i >= NR_TASKS) return -ENOENT; - if (fd >= NR_OPEN || !p->files->fd[fd] || !p->files->fd[fd]->f_inode) - return -ENOENT; + if (fd >= NR_OPEN || !p->files || !p->files->fd[fd] || !p->files->fd[fd]->f_inode) + return -ENOENT; ino = (pid << 16) + (PROC_PID_FD_DIR << 8) + fd; diff -u --recursive --new-file v2.0.31/linux/fs/proc/inode.c linux/fs/proc/inode.c --- v2.0.31/linux/fs/proc/inode.c Sat Nov 30 02:21:21 1996 +++ linux/fs/proc/inode.c Sat Nov 1 12:31:17 1997 @@ -236,7 +236,7 @@ switch (ino >> 8) { case PROC_PID_FD_DIR: ino &= 0xff; - if (ino >= NR_OPEN || !p->files->fd[ino]) + if (ino >= NR_OPEN || !p->files || !p->files->fd[ino]) return; inode->i_op = &proc_link_inode_operations; inode->i_size = 64; diff -u --recursive --new-file v2.0.31/linux/fs/proc/link.c linux/fs/proc/link.c --- v2.0.31/linux/fs/proc/link.c Fri Dec 22 03:00:19 1995 +++ linux/fs/proc/link.c Sat Nov 1 12:31:42 1997 @@ -121,7 +121,7 @@ if (!p->files) break; ino &= 0xff; - if (ino < NR_OPEN && p->files->fd[ino]) { + if (ino < NR_OPEN && p->files && p->files->fd[ino]) { new_inode = p->files->fd[ino]->f_inode; } break; diff -u --recursive --new-file v2.0.31/linux/include/asm-alpha/errno.h linux/include/asm-alpha/errno.h --- v2.0.31/linux/include/asm-alpha/errno.h Wed Jul 3 21:28:57 1996 +++ linux/include/asm-alpha/errno.h Sat Nov 1 12:26:17 1997 @@ -136,4 +136,7 @@ #define ERESTART 127 /* Interrupted system call should be restarted */ #define ESTRPIPE 128 /* Streams pipe error */ +#define ENOMEDIUM 129 /* No medium found */ +#define EMEDIUMTYPE 130 /* Wrong medium type */ + #endif diff -u --recursive --new-file v2.0.31/linux/include/asm-alpha/socket.h linux/include/asm-alpha/socket.h --- v2.0.31/linux/include/asm-alpha/socket.h Tue Aug 12 13:57:23 1997 +++ linux/include/asm-alpha/socket.h Sat Oct 25 06:36:08 1997 @@ -1,8 +1,6 @@ #ifndef _ASM_SOCKET_H #define _ASM_SOCKET_H -#include -#include #include /* For setsockoptions(2) */ diff -u --recursive --new-file v2.0.31/linux/include/asm-i386/errno.h linux/include/asm-i386/errno.h --- v2.0.31/linux/include/asm-i386/errno.h Wed Jul 3 21:28:57 1996 +++ linux/include/asm-i386/errno.h Sat Nov 1 12:26:17 1997 @@ -126,4 +126,7 @@ #define EREMOTEIO 121 /* Remote I/O error */ #define EDQUOT 122 /* Quota exceeded */ +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + #endif diff -u --recursive --new-file v2.0.31/linux/include/asm-i386/math_emu.h linux/include/asm-i386/math_emu.h --- v2.0.31/linux/include/asm-i386/math_emu.h Mon May 13 12:35:33 1996 +++ linux/include/asm-i386/math_emu.h Fri Nov 7 09:11:42 1997 @@ -45,4 +45,13 @@ long ___vm86_gs; }; +/* Interface for converting data between the emulator format + * and the hardware format. Used for core dumping and for + * ptrace(2) */ +void hardreg_to_softreg(const char hardreg[10], + struct fpu_reg *soft_reg); + +void softreg_to_hardreg(const struct fpu_reg *rp, char d[10], + long int control_word); + #endif diff -u --recursive --new-file v2.0.31/linux/include/asm-m68k/errno.h linux/include/asm-m68k/errno.h --- v2.0.31/linux/include/asm-m68k/errno.h Wed Dec 27 12:46:55 1995 +++ linux/include/asm-m68k/errno.h Sat Nov 1 12:26:17 1997 @@ -124,4 +124,7 @@ #define EREMOTEIO 121 /* Remote I/O error */ #define EDQUOT 122 /* Quota exceeded */ +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + #endif /* _M68K_ERRNO_H */ diff -u --recursive --new-file v2.0.31/linux/include/asm-mips/errno.h linux/include/asm-mips/errno.h --- v2.0.31/linux/include/asm-mips/errno.h Wed Dec 13 02:39:45 1995 +++ linux/include/asm-mips/errno.h Sat Nov 1 12:26:17 1997 @@ -137,6 +137,8 @@ #define EINPROGRESS 150 /* Operation now in progress */ #define ESTALE 151 /* Stale NFS file handle */ #define ECANCELED 158 /* AIO operation canceled */ +#define ENOMEDIUM 159 /* No medium found */ +#define EMEDIUMTYPE 160 /* Wrong medium type */ #define EDQUOT 1133 /* Quota exceeded */ #define ENFSREMOTE 1134 /* ??? */ diff -u --recursive --new-file v2.0.31/linux/include/asm-ppc/errno.h linux/include/asm-ppc/errno.h --- v2.0.31/linux/include/asm-ppc/errno.h Mon May 27 02:00:59 1996 +++ linux/include/asm-ppc/errno.h Sat Nov 1 12:26:17 1997 @@ -123,6 +123,8 @@ #define EISNAM 120 /* Is a named type file */ #define EREMOTEIO 121 /* Remote I/O error */ #define EDQUOT 122 /* Quota exceeded */ +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ /* Should never be seen by user programs */ #define ERESTARTSYS 512 diff -u --recursive --new-file v2.0.31/linux/include/asm-sparc/errno.h linux/include/asm-sparc/errno.h --- v2.0.31/linux/include/asm-sparc/errno.h Fri Nov 24 18:31:42 1995 +++ linux/include/asm-sparc/errno.h Sat Nov 1 12:26:17 1997 @@ -130,4 +130,7 @@ #define ELIBMAX 123 /* Atmpt to link in too many shared libs */ #define ELIBSCN 124 /* .lib section in a.out corrupted */ +#define ENOMEDIUM 125 /* No medium found */ +#define EMEDIUMTYPE 126 /* Wrong medium type */ + #endif diff -u --recursive --new-file v2.0.31/linux/include/linux/mm.h linux/include/linux/mm.h --- v2.0.31/linux/include/linux/mm.h Wed Oct 15 15:22:05 1997 +++ linux/include/linux/mm.h Fri Nov 7 09:57:31 1997 @@ -304,6 +304,7 @@ #define GFP_KERNEL 0x03 #define GFP_NOBUFFER 0x04 #define GFP_NFS 0x05 +#define GFP_IO 0x06 /* Flag - indicates that the buffer will be suitable for DMA. Ignored on some platforms, used as appropriate on others */ diff -u --recursive --new-file v2.0.31/linux/include/linux/posix_types.h linux/include/linux/posix_types.h --- v2.0.31/linux/include/linux/posix_types.h Mon Aug 5 00:13:54 1996 +++ linux/include/linux/posix_types.h Sat Oct 25 06:35:58 1997 @@ -41,7 +41,7 @@ #undef __FDMASK #define __FDMASK(d) (1UL << ((d) % __NFDBITS)) -typedef struct fd_set { +typedef struct { unsigned long fds_bits [__FDSET_LONGS]; } __kernel_fd_set; diff -u --recursive --new-file v2.0.31/linux/include/linux/timex.h linux/include/linux/timex.h --- v2.0.31/linux/include/linux/timex.h Sat May 4 09:39:22 1996 +++ linux/include/linux/timex.h Fri Nov 7 10:06:21 1997 @@ -38,6 +38,8 @@ * Derived linux/timex.h * 1995-08-13 Torsten Duwe * kernel PLL updated to 1994-12-13 specs (rfc-1589) + * 1997-08-30 Ulrich Windl + * Added new constant NTP_PHASE_LIMIT. Corrected MAXFREQ. */ #ifndef _LINUX_TIMEX_H #define _LINUX_TIMEX_H @@ -91,10 +93,11 @@ #define FINEUSEC (1L << SHIFT_SCALE) /* 1 us in phase units */ #define MAXPHASE 512000L /* max phase error (us) */ -#define MAXFREQ (512L << SHIFT_USEC) /* max frequency error (ppm) */ +#define MAXFREQ (200L << SHIFT_USEC) /* max frequency error (ppm) */ #define MAXTIME (200L << PPS_AVG) /* max PPS error (jitter) (200 us) */ #define MINSEC 16L /* min interval between updates (s) */ #define MAXSEC 1200L /* max interval between updates (s) */ +#define NTP_PHASE_LIMIT (MAXPHASE << 5) /* beyond max. dispersion */ /* * The following defines are used only if a pulse-per-second (PPS) diff -u --recursive --new-file v2.0.31/linux/kernel/fork.c linux/kernel/fork.c --- v2.0.31/linux/kernel/fork.c Wed Oct 15 08:32:00 1997 +++ linux/kernel/fork.c Fri Nov 7 09:57:31 1997 @@ -93,11 +93,6 @@ tmp->vm_flags &= ~VM_LOCKED; tmp->vm_mm = mm; tmp->vm_next = NULL; - if (copy_page_range(mm, current->mm, tmp)) { - kfree(tmp); - exit_mmap(mm); - return -ENOMEM; - } if (tmp->vm_inode) { tmp->vm_inode->i_count++; /* insert tmp into the share list, just after mpnt */ @@ -105,12 +100,22 @@ mpnt->vm_next_share = tmp; tmp->vm_prev_share = mpnt; } + if (copy_page_range(mm, current->mm, tmp)) { + if (mpnt->vm_next_share == tmp) { + tmp->vm_prev_share->vm_next_share = tmp->vm_next_share; + tmp->vm_next_share->vm_prev_share = tmp->vm_prev_share; + } + kfree(tmp); + exit_mmap(mm); + return -ENOMEM; + } if (tmp->vm_ops && tmp->vm_ops->open) tmp->vm_ops->open(tmp); *p = tmp; p = &tmp->vm_next; } build_mmap_avl(mm); + flush_tlb_mm(current->mm); return 0; } @@ -119,7 +124,7 @@ if (!(clone_flags & CLONE_VM)) { struct mm_struct * mm = kmalloc(sizeof(*tsk->mm), GFP_KERNEL); if (!mm) - return -1; + return -ENOMEM; *mm = *current->mm; mm->count = 1; mm->def_flags = 0; @@ -128,13 +133,18 @@ tsk->min_flt = tsk->maj_flt = 0; tsk->cmin_flt = tsk->cmaj_flt = 0; tsk->nswap = tsk->cnswap = 0; - if (new_page_tables(tsk)) + if (new_page_tables(tsk)) { + tsk->mm = NULL; + mm->pgd = NULL; + exit_mmap(mm); goto free_mm; + } if (dup_mmap(mm)) { + tsk->mm = NULL; free_page_tables(mm); free_mm: kfree(mm); - return -1; + return -ENOMEM; } return 0; } diff -u --recursive --new-file v2.0.31/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.0.31/linux/kernel/ksyms.c Fri Sep 5 20:43:59 1997 +++ linux/kernel/ksyms.c Mon Nov 10 10:50:56 1997 @@ -172,6 +172,7 @@ X(generic_file_mmap), X(generic_readpage), X(__fput), + X(make_bad_inode), /* device registration */ X(register_chrdev), @@ -299,6 +300,7 @@ X(sys_call_table), X(hard_reset_now), X(_ctype), + X(get_random_bytes), /* Signal interfaces */ X(send_sig), diff -u --recursive --new-file v2.0.31/linux/kernel/sched.c linux/kernel/sched.c --- v2.0.31/linux/kernel/sched.c Fri Oct 17 13:17:43 1997 +++ linux/kernel/sched.c Fri Nov 7 10:06:21 1997 @@ -7,6 +7,8 @@ * 1996-12-23 Modified by Dave Grothe to fix bugs in semaphores and * make semaphores SMP safe * 1997-01-28 Modified by Finn Arne Gangstad to make timers scale better. + * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 + * "A Kernel Model for Precision Timekeeping" by Dave Mills */ /* @@ -64,8 +66,8 @@ long time_constant = 2; /* pll time constant */ long time_tolerance = MAXFREQ; /* frequency tolerance (ppm) */ long time_precision = 1; /* clock precision (us) */ -long time_maxerror = MAXPHASE; /* maximum error (us) */ -long time_esterror = MAXPHASE; /* estimated error (us) */ +long time_maxerror = NTP_PHASE_LIMIT; /* maximum error (us) */ +long time_esterror = NTP_PHASE_LIMIT; /* estimated error (us) */ long time_phase = 0; /* phase offset (scaled us) */ long time_freq = ((1000000 + HZ/2) % HZ - HZ/2) << SHIFT_USEC; /* frequency offset (scaled ppm) */ long time_adj = 0; /* tick adjust (scaled 1 / HZ) */ @@ -988,8 +990,11 @@ /* Bump the maxerror field */ time_maxerror += time_tolerance >> SHIFT_USEC; - if ( time_maxerror > MAXPHASE ) - time_maxerror = MAXPHASE; + if ( time_maxerror > NTP_PHASE_LIMIT ) { + time_maxerror = NTP_PHASE_LIMIT; + time_state = TIME_ERROR; /* p. 17, sect. 4.3, (b) */ + time_status |= STA_UNSYNC; + } /* * Leap second processing. If in leap-insert state at @@ -1013,7 +1018,7 @@ if (xtime.tv_sec % 86400 == 0) { xtime.tv_sec--; time_state = TIME_OOP; - printk("Clock: inserting leap second 23:59:60 UTC\n"); + printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n"); } break; @@ -1021,7 +1026,7 @@ if ((xtime.tv_sec + 1) % 86400 == 0) { xtime.tv_sec++; time_state = TIME_WAIT; - printk("Clock: deleting leap second 23:59:59 UTC\n"); + printk(KERN_NOTICE "Clock: deleting leap second 23:59:59 UTC\n"); } break; @@ -1069,7 +1074,7 @@ * the pll and the PPS signal. */ pps_valid++; - if (pps_valid == PPS_VALID) { + if (pps_valid == PPS_VALID) { /* PPS signal lost */ pps_jitter = MAXTIME; pps_stabil = MAXFREQ; time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER | @@ -1077,24 +1082,43 @@ } ltemp = time_freq + pps_freq; if (ltemp < 0) - time_adj -= -ltemp >> - (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE); + time_adj -= -ltemp >> (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE); else - time_adj += ltemp >> - (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE); + time_adj += ltemp >> (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE); #if HZ == 100 - /* compensate for (HZ==100) != 128. Add 25% to get 125; => only 3% error */ + /* Compensate for (HZ==100) != (1 << SHIFT_HZ). + * Add 25% and 3.125% to get 128.125; => only 0.125% error (p. 14) + */ if (time_adj < 0) - time_adj -= -time_adj >> 2; + time_adj -= (-time_adj >> 2) + (-time_adj >> 5); else - time_adj += time_adj >> 2; + time_adj += (time_adj >> 2) + (time_adj >> 5); #endif } /* in the NTP reference this is called "hardclock()" */ static void update_wall_time_one_tick(void) { + if ( (time_adjust_step = time_adjust) != 0 ) { + /* We are doing an adjtime thing. + * + * Prepare time_adjust_step to be within bounds. + * Note that a positive time_adjust means we want the clock + * to run faster. + * + * Limit the amount of the step to be in the range + * -tickadj .. +tickadj + */ + if (time_adjust > tickadj) + time_adjust_step = tickadj; + else if (time_adjust < -tickadj) + time_adjust_step = -tickadj; + + /* Reduce by this step the amount of time left */ + time_adjust -= time_adjust_step; + } + xtime.tv_usec += tick + time_adjust_step; /* * Advance the phase, once it gets to one microsecond, then * advance the tick more. @@ -1103,37 +1127,13 @@ if (time_phase <= -FINEUSEC) { long ltemp = -time_phase >> SHIFT_SCALE; time_phase += ltemp << SHIFT_SCALE; - xtime.tv_usec += tick + time_adjust_step - ltemp; + xtime.tv_usec -= ltemp; } else if (time_phase >= FINEUSEC) { long ltemp = time_phase >> SHIFT_SCALE; time_phase -= ltemp << SHIFT_SCALE; - xtime.tv_usec += tick + time_adjust_step + ltemp; - } else - xtime.tv_usec += tick + time_adjust_step; - - if (time_adjust) { - /* We are doing an adjtime thing. - * - * Modify the value of the tick for next time. - * Note that a positive delta means we want the clock - * to run fast. This means that the tick should be bigger - * - * Limit the amount of the step for *next* tick to be - * in the range -tickadj .. +tickadj - */ - if (time_adjust > tickadj) - time_adjust_step = tickadj; - else if (time_adjust < -tickadj) - time_adjust_step = -tickadj; - else - time_adjust_step = time_adjust; - - /* Reduce by this step the amount of time left */ - time_adjust -= time_adjust_step; + xtime.tv_usec += ltemp; } - else - time_adjust_step = 0; } /* diff -u --recursive --new-file v2.0.31/linux/kernel/time.c linux/kernel/time.c --- v2.0.31/linux/kernel/time.c Fri Sep 5 08:53:13 1997 +++ linux/kernel/time.c Fri Nov 7 10:06:21 1997 @@ -16,6 +16,10 @@ * adjtime interface update and CMOS clock write code * 1995-08-13 Torsten Duwe * kernel PLL updated to 1994-12-13 specs (rfc-1589) + * 1996-10-22, 1997-09-13 Ulrich Windl + * support for external PPS signal, error checking in adjtimex() + * Updated NTP code according to technical memorandum Jan '96 + * "A Kernel Model for Precision Timekeeping" by Dave Mills */ #include @@ -75,9 +79,11 @@ cli(); xtime.tv_sec = value; xtime.tv_usec = 0; - time_state = TIME_ERROR; - time_maxerror = MAXPHASE; - time_esterror = MAXPHASE; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_state = TIME_ERROR; /* p. 24, (a) */ + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; sti(); return 0; } @@ -195,14 +201,14 @@ asmlinkage int sys_adjtimex(struct timex *txc_p) { long ltemp, mtemp, save_adjust; - int error; + int error = 0; /* Local copy of parameter */ struct timex txc; error = verify_area(VERIFY_WRITE, txc_p, sizeof(struct timex)); if (error) - return error; + return error; /* do not write results */ /* Copy the user data space into the kernel copy * structure. But bear in mind that the structures @@ -216,124 +222,163 @@ /* Now we validate the data before disabling interrupts */ - if (txc.modes != ADJ_OFFSET_SINGLESHOT && (txc.modes & ADJ_OFFSET)) - /* adjustment Offset limited to +- .512 seconds */ - if (txc.offset <= - MAXPHASE || txc.offset >= MAXPHASE ) - return -EINVAL; - - /* if the quartz is off by more than 10% something is VERY wrong ! */ - if (txc.modes & ADJ_TICK) - if (txc.tick < 900000/HZ || txc.tick > 1100000/HZ) - return -EINVAL; + /* adjustment Offset limited to +- .512 seconds */ + if (txc.offset <= - MAXPHASE || txc.offset >= MAXPHASE ) + return -EINVAL; cli(); - /* Save for later - semantics of adjtime is to return old value */ + /* Save for later - semantics of adjtime() is to return old value */ save_adjust = time_adjust; /* If there are input parameters, then process them */ +#if 0 /* STA_CLOCKERR is never set yet */ + time_status &= ~STA_CLOCKERR; /* reset STA_CLOCKERR */ +#endif if (txc.modes) { - if (time_state == TIME_BAD) - time_state = TIME_OK; + if (time_state == TIME_ERROR) + time_state = TIME_OK; /* reset error -- why? */ - if (txc.modes & ADJ_STATUS) - time_status = txc.status; - - if (txc.modes & ADJ_FREQUENCY) - time_freq = txc.freq; + if (txc.modes & ADJ_STATUS) /* only set allowed bits */ + time_status = (txc.status & ~STA_RONLY) | + (time_status & STA_RONLY); + + if (txc.modes & ADJ_FREQUENCY) { /* p. 22 */ + if (txc.freq > MAXFREQ || txc.freq < -MAXFREQ) { + error = -EINVAL; + goto leave; + } + time_freq = txc.freq - pps_freq; + } - if (txc.modes & ADJ_MAXERROR) + if (txc.modes & ADJ_MAXERROR) { + if (txc.maxerror < 0 || txc.maxerror >= NTP_PHASE_LIMIT) { + error = -EINVAL; + goto leave; + } time_maxerror = txc.maxerror; + } - if (txc.modes & ADJ_ESTERROR) + if (txc.modes & ADJ_ESTERROR) { + if (txc.esterror < 0 || txc.esterror >= NTP_PHASE_LIMIT) { + error = -EINVAL; + goto leave; + } time_esterror = txc.esterror; + } - if (txc.modes & ADJ_TIMECONST) + if (txc.modes & ADJ_TIMECONST) { /* p. 24 */ + if (txc.constant < 0 || txc.constant > MAXTC) { + error = -EINVAL; + goto leave; + } time_constant = txc.constant; + } - if (txc.modes & ADJ_OFFSET) - if ((txc.modes == ADJ_OFFSET_SINGLESHOT) - || !(time_status & STA_PLL)) - { - time_adjust = txc.offset; + if (txc.modes & ADJ_OFFSET) { /* values checked earlier */ + if (txc.modes == ADJ_OFFSET_SINGLESHOT) { + /* adjtime() is independent from ntp_adjtime() */ + time_adjust = txc.offset; } - else if ((time_status & STA_PLL)||(time_status & STA_PPSTIME)) - { - ltemp = (time_status & STA_PPSTIME && - time_status & STA_PPSSIGNAL) ? - pps_offset : txc.offset; - - /* - * Scale the phase adjustment and - * clamp to the operating range. - */ - if (ltemp > MAXPHASE) - time_offset = MAXPHASE << SHIFT_UPDATE; - else if (ltemp < -MAXPHASE) - time_offset = -(MAXPHASE << SHIFT_UPDATE); - else - time_offset = ltemp << SHIFT_UPDATE; - - /* - * Select whether the frequency is to be controlled and in which - * mode (PLL or FLL). Clamp to the operating range. Ugly - * multiply/divide should be replaced someday. - */ - - if (time_status & STA_FREQHOLD || time_reftime == 0) + else if ( time_status & (STA_PLL | STA_PPSTIME) ) { + ltemp = (time_status & (STA_PPSTIME | STA_PPSSIGNAL)) == + (STA_PPSTIME | STA_PPSSIGNAL) ? + pps_offset : txc.offset; + + /* + * Scale the phase adjustment and + * clamp to the operating range. + */ + if (ltemp > MAXPHASE) + time_offset = MAXPHASE << SHIFT_UPDATE; + else if (ltemp < -MAXPHASE) + time_offset = -(MAXPHASE << SHIFT_UPDATE); + else + time_offset = ltemp << SHIFT_UPDATE; + + /* + * Select whether the frequency is to be controlled + * and in which mode (PLL or FLL). Clamp to the operating + * range. Ugly multiply/divide should be replaced someday. + */ + + if (time_status & STA_FREQHOLD || time_reftime == 0) + time_reftime = xtime.tv_sec; + mtemp = xtime.tv_sec - time_reftime; time_reftime = xtime.tv_sec; - mtemp = xtime.tv_sec - time_reftime; - time_reftime = xtime.tv_sec; - if (time_status & STA_FLL) - { - if (mtemp >= MINSEC) - { - ltemp = ((time_offset / mtemp) << (SHIFT_USEC - - SHIFT_UPDATE)); - if (ltemp < 0) - time_freq -= -ltemp >> SHIFT_KH; - else - time_freq += ltemp >> SHIFT_KH; - } - } - else - { - if (mtemp < MAXSEC) - { - ltemp *= mtemp; - if (ltemp < 0) - time_freq -= -ltemp >> (time_constant + - time_constant + SHIFT_KF - - SHIFT_USEC); - else - time_freq += ltemp >> (time_constant + - time_constant + SHIFT_KF - - SHIFT_USEC); - } + if (time_status & STA_FLL) { + if (mtemp >= MINSEC) { + ltemp = (time_offset / mtemp) << (SHIFT_USEC - + SHIFT_UPDATE); + if (ltemp < 0) + time_freq -= -ltemp >> SHIFT_KH; + else + time_freq += ltemp >> SHIFT_KH; + } else /* calibration interval too short (p. 12) */ + time_state = TIME_ERROR; + } else { /* PLL mode */ + if (mtemp < MAXSEC) { + ltemp *= mtemp; + if (ltemp < 0) + time_freq -= -ltemp >> (time_constant + + time_constant + + SHIFT_KF - SHIFT_USEC); + else + time_freq += ltemp >> (time_constant + + time_constant + + SHIFT_KF - SHIFT_USEC); + } else /* calibration interval too long (p. 12) */ + time_state = TIME_ERROR; } - if (time_freq > time_tolerance) - time_freq = time_tolerance; - else if (time_freq < -time_tolerance) - time_freq = -time_tolerance; + if (time_freq > time_tolerance) + time_freq = time_tolerance; + else if (time_freq < -time_tolerance) + time_freq = -time_tolerance; } /* STA_PLL || STA_PPSTIME */ - if (txc.modes & ADJ_TICK) - tick = txc.tick; - + } /* txc.modes & ADJ_OFFSET */ + if (txc.modes & ADJ_TICK) { + /* if the quartz is off by more than 10% something is + VERY wrong ! */ + if (txc.tick < 900000/HZ || txc.tick > 1100000/HZ) { + error = -EINVAL; + goto leave; + } + tick = txc.tick; + } + } /* txc.modes */ +leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0 + || ((time_status & (STA_PPSFREQ|STA_PPSTIME)) != 0 + && (time_status & STA_PPSSIGNAL) == 0) + /* p. 24, (b) */ + || ((time_status & (STA_PPSTIME|STA_PPSJITTER)) + == (STA_PPSTIME|STA_PPSJITTER)) + /* p. 24, (c) */ + || ((time_status & STA_PPSFREQ) != 0 + && (time_status & (STA_PPSWANDER|STA_PPSERROR)) != 0)) + /* p. 24, (d) */ + time_state = TIME_ERROR; + + if ((txc.modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) + txc.offset = save_adjust; + else { + if (time_offset < 0) + txc.offset = -(-time_offset >> SHIFT_UPDATE); + else + txc.offset = time_offset >> SHIFT_UPDATE; } - txc.offset = save_adjust; - txc.freq = time_freq; + txc.freq = time_freq + pps_freq; txc.maxerror = time_maxerror; txc.esterror = time_esterror; txc.status = time_status; txc.constant = time_constant; txc.precision = time_precision; txc.tolerance = time_tolerance; - txc.time = xtime; + do_gettimeofday(&txc.time); txc.tick = tick; txc.ppsfreq = pps_freq; - txc.jitter = pps_jitter; + txc.jitter = pps_jitter >> PPS_AVG; txc.shift = pps_shift; txc.stabil = pps_stabil; txc.jitcnt = pps_jitcnt; @@ -344,5 +389,5 @@ sti(); memcpy_tofs(txc_p, &txc, sizeof(struct timex)); - return time_state; + return(error < 0 ? error : time_state); } diff -u --recursive --new-file v2.0.31/linux/mm/filemap.c linux/mm/filemap.c --- v2.0.31/linux/mm/filemap.c Sat Aug 23 10:54:08 1997 +++ linux/mm/filemap.c Fri Nov 7 09:57:31 1997 @@ -114,7 +114,7 @@ } } -int shrink_mmap(int priority, int dma, int can_do_io) +int shrink_mmap(int priority, int dma, int free_buf) { static int clock = 0; struct page * page; @@ -174,7 +174,7 @@ } /* is it a buffer cache page? */ - if (can_do_io && bh && try_to_free_buffer(bh, &bh, 6)) + if (free_buf && bh && try_to_free_buffer(bh, &bh, 6)) return 1; break; @@ -662,8 +662,15 @@ pos += nr; read += nr; count -= nr; - if (count) + if (count) { + /* + * to prevent hogging the CPU on well-cached systems, + * schedule if needed, it's safe to do it here: + */ + if (need_resched) + schedule(); continue; + } break; } diff -u --recursive --new-file v2.0.31/linux/mm/kmalloc.c linux/mm/kmalloc.c --- v2.0.31/linux/mm/kmalloc.c Tue Sep 23 13:23:33 1997 +++ linux/mm/kmalloc.c Fri Nov 7 09:57:31 1997 @@ -362,7 +362,8 @@ } { static unsigned long last = 0; - if (priority != GFP_BUFFER && (last + 10 * HZ < jiffies)) { + if (priority != GFP_BUFFER && priority != GFP_IO && + (last + 10 * HZ < jiffies)) { last = jiffies; printk("Couldn't get a free page.....\n"); } diff -u --recursive --new-file v2.0.31/linux/mm/mmap.c linux/mm/mmap.c --- v2.0.31/linux/mm/mmap.c Fri Nov 22 06:25:17 1996 +++ linux/mm/mmap.c Fri Nov 7 09:57:31 1997 @@ -55,7 +55,8 @@ long freepages; freepages = buffermem >> PAGE_SHIFT; freepages += page_cache_size; - freepages >>= 1; + if (freepages <= (MAP_NR(high_memory) >> 4) + 48) + freepages >>= 1; freepages += nr_free_pages; freepages += nr_swap_pages; freepages -= MAP_NR(high_memory) >> 4; diff -u --recursive --new-file v2.0.31/linux/mm/page_alloc.c linux/mm/page_alloc.c --- v2.0.31/linux/mm/page_alloc.c Sat Aug 23 10:54:08 1997 +++ linux/mm/page_alloc.c Fri Nov 7 09:57:31 1997 @@ -205,6 +205,8 @@ reserved_pages = 5; if (priority != GFP_NFS) reserved_pages = min_free_pages; + if ((priority == GFP_BUFFER || priority == GFP_IO) && reserved_pages >= 48) + reserved_pages -= (12 + (reserved_pages>>3)); save_flags(flags); repeat: cli(); @@ -214,7 +216,7 @@ return 0; } restore_flags(flags); - if (try_to_free_page(priority, dma, 1)) + if (priority != GFP_BUFFER && try_to_free_page(priority, dma, 1)) goto repeat; return 0; } @@ -264,11 +266,13 @@ /* * select nr of pages we try to keep free for important stuff - * with a minimum of 24 pages. This is totally arbitrary + * with a minimum of 48 pages. This is totally arbitrary */ i = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT+7); if (i < 24) i = 24; + i += 24; /* The limit for buffer pages in __get_free_pages is + * decreased by 12+(i>>3) */ min_free_pages = i; free_pages_low = i + (i>>1); free_pages_high = i + i; diff -u --recursive --new-file v2.0.31/linux/mm/vmscan.c linux/mm/vmscan.c --- v2.0.31/linux/mm/vmscan.c Tue Sep 23 13:23:33 1997 +++ linux/mm/vmscan.c Fri Nov 7 09:57:31 1997 @@ -406,7 +406,7 @@ can_do_io = 1; if (wait) stop = 0; - if (priority == GFP_BUFFER) + if (priority == GFP_IO) can_do_io = 0; switch (state) { do { @@ -453,7 +453,7 @@ */ int kswapd(void *unused) { - int i; + int i, j; current->session = 1; current->pgrp = 1; @@ -491,12 +491,12 @@ swapstats.wakeups++; /* Protect our reserved pages: */ i = 0; - if (nr_free_pages <= min_free_pages) - i = (1+min_free_pages) - nr_free_pages; + j = (min_free_pages >= 48 ? min_free_pages-12 : min_free_pages); + if (nr_free_pages <= j) + i = (1+j) - nr_free_pages; /* Do the background pageout: */ for (i += kswapd_ctl.maxpages; i > 0; i--) - try_to_free_page(GFP_KERNEL, 0, - (nr_free_pages <= min_free_pages)); + try_to_free_page(GFP_KERNEL, 0, (nr_free_pages <= j)); } } diff -u --recursive --new-file v2.0.31/linux/net/core/sock.c linux/net/core/sock.c --- v2.0.31/linux/net/core/sock.c Fri Aug 15 12:23:22 1997 +++ linux/net/core/sock.c Fri Nov 7 09:57:31 1997 @@ -525,7 +525,7 @@ { /* The buffer get won't block, or use the atomic queue. It does produce annoying no free page messages still.... */ - skb = sock_wmalloc(sk, size, 0 , GFP_BUFFER); + skb = sock_wmalloc(sk, size, 0 , GFP_IO); if(!skb) skb=sock_wmalloc(sk, fallback, 0, GFP_KERNEL); } diff -u --recursive --new-file v2.0.31/linux/net/ipv4/ip_masq_quake.c linux/net/ipv4/ip_masq_quake.c --- v2.0.31/linux/net/ipv4/ip_masq_quake.c Tue Apr 8 08:47:47 1997 +++ linux/net/ipv4/ip_masq_quake.c Fri Nov 7 16:58:01 1997 @@ -48,9 +48,9 @@ typedef struct { - __u16 type; // (Little Endian) Type of message. - __u16 length; // (Little Endian) Length of message, header included. - char message[0]; // The contents of the message. + __u16 type; /* (Little Endian) Type of message. */ + __u16 length; /* (Little Endian) Length of message, header included. */ + char message[0]; /* The contents of the message. */ } QUAKEHEADER; struct quake_priv_data { diff -u --recursive --new-file v2.0.31/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.0.31/linux/net/ipv4/tcp_input.c Wed Oct 15 14:47:56 1997 +++ linux/net/ipv4/tcp_input.c Fri Oct 31 11:34:12 1997 @@ -2632,7 +2632,7 @@ dev->pa_addr, skb->redirport, dev); else #endif - sk = NULL; + sk = __tcp_v4_lookup(th, saddr, th->source, daddr, th->dest, dev); /* this is not really correct: we should check sk->users */ if (sk && sk->state==TCP_LISTEN) {