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/setup.c linux/arch/i386/kernel/setup.c --- v2.0.31/linux/arch/i386/kernel/setup.c Fri Sep 20 07:00:34 1996 +++ linux/arch/i386/kernel/setup.c Wed Nov 12 20:40:57 1997 @@ -42,6 +42,7 @@ char x86_mask = 0; /* set by kernel/head.S */ int x86_capability = 0; /* set by kernel/head.S */ int fdiv_bug = 0; /* set if Pentium(TM) with FP bug */ +int pentium_f00f_bug = 0; /* set if Pentium(TM) with F00F bug */ int have_cpuid = 0; /* set if CPUID instruction works */ char x86_vendor_id[13] = "unknown"; @@ -306,6 +307,7 @@ len += sprintf(buffer+len, "fdiv_bug\t: %s\n" "hlt_bug\t\t: %s\n" + "pentium_f00f_bug\t\t: %s\n" "fpu\t\t: %s\n" "fpu_exception\t: %s\n" "cpuid\t\t: %s\n" @@ -313,6 +315,7 @@ "flags\t\t:", CD(fdiv_bug) ? "yes" : "no", CD(hlt_works_ok) ? "no" : "yes", + pentium_f00f_bug ? "yes" : "no", CD(hard_math) ? "yes" : "no", (CD(hard_math) && ignore_irq13) ? "yes" : "no", 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/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.0.31/linux/arch/i386/kernel/traps.c Mon Aug 11 13:37:24 1997 +++ linux/arch/i386/kernel/traps.c Thu Nov 13 16:05:11 1997 @@ -24,6 +24,7 @@ #include #include #include +#include asmlinkage int system_call(void); asmlinkage void lcall7(void); @@ -335,6 +336,49 @@ } #endif /* CONFIG_MATH_EMULATION */ + +struct desc_struct *idt = __idt+0; + +void trap_init_f00f_bug(void) +{ + pgd_t * pgd; + pmd_t * pmd; + pte_t * pte; + unsigned long twopage; + struct desc_struct *new_idt; + struct { + unsigned short limit; + unsigned long addr __attribute__((packed)); + } idt_descriptor; + + printk("moving IDT ... "); + + twopage = (unsigned long) vmalloc (2*PAGE_SIZE); + + new_idt = (void *)(twopage + 4096-7*8); + + memcpy(new_idt,idt,256*8); + + idt_descriptor.limit = 256*8-1; + idt_descriptor.addr = VMALLOC_VMADDR(new_idt); + + __asm__ __volatile__("\tlidt %0": "=m" (idt_descriptor)); + idt = new_idt; + + /* + * Unmap lower page: + */ + twopage = VMALLOC_VMADDR(twopage); + pgd = pgd_offset(current->mm, twopage); + pmd = pmd_offset(pgd, twopage); + pte = pte_offset(pmd, twopage); + + pte_clear(pte); + flush_tlb_all(); + + printk(" ... done\n"); +} + void trap_init(void) { 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/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- v2.0.31/linux/arch/i386/mm/fault.c Sat Aug 16 22:21:20 1997 +++ linux/arch/i386/mm/fault.c Thu Nov 13 16:29:30 1997 @@ -21,6 +21,16 @@ extern void die_if_kernel(const char *,struct pt_regs *,long); +asmlinkage void do_divide_error (struct pt_regs *, unsigned long); +asmlinkage void do_debug (struct pt_regs *, unsigned long); +asmlinkage void do_nmi (struct pt_regs *, unsigned long); +asmlinkage void do_int3 (struct pt_regs *, unsigned long); +asmlinkage void do_overflow (struct pt_regs *, unsigned long); +asmlinkage void do_bounds (struct pt_regs *, unsigned long); +asmlinkage void do_invalid_op (struct pt_regs *, unsigned long); + +extern int pentium_f00f_bug; + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate @@ -117,6 +127,30 @@ force_sig(SIGSEGV, tsk); return; } + + /* + * Pentium F0 0F C7 C8 bug workaround: + */ + if ( pentium_f00f_bug ) { + unsigned long nr; + + nr = (address - TASK_SIZE - (unsigned long) idt) >> 3; + + if (nr < 7) { + static void (*handler[])(struct pt_regs *, unsigned long) = { + do_divide_error, /* 0 - divide overflow */ + do_debug, /* 1 - debug trap */ + do_nmi, /* 2 - NMI */ + do_int3, /* 3 - int 3 */ + do_overflow, /* 4 - overflow */ + do_bounds, /* 5 - bound range */ + do_invalid_op }; /* 6 - invalid opcode */ + handler[nr](regs, error_code); + return; + } + } + + /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. 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/3c59x.c linux/drivers/net/3c59x.c --- v2.0.31/linux/drivers/net/3c59x.c Mon Sep 15 09:45:39 1997 +++ linux/drivers/net/3c59x.c Wed Nov 12 20:36:41 1997 @@ -15,7 +15,7 @@ */ static char *version = -"3c59x.c:v0.44 9/9/97 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n"; +"3c59x.c:v0.46C 10/14/97 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n"; /* "Knobs" that adjust features and parameters. */ /* Set the copy breakpoint for the copy-only-tiny-frames scheme. @@ -24,7 +24,7 @@ /* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */ static const mtu = 1500; /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static const max_interrupt_work = 12; +static int max_interrupt_work = 20; /* Enable the automatic media selection code -- usually set. */ #define AUTOMEDIA 1 @@ -113,6 +113,14 @@ #if (LINUX_VERSION_CODE < 0x20123) #define test_and_set_bit(val, addr) set_bit(val, addr) +#else +MODULE_AUTHOR("Donald Becker "); +MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver"); +MODULE_PARM(debug, "i"); +MODULE_PARM(options, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(rx_copybreak, "i"); +MODULE_PARM(max_interrupt_work, "i"); #endif /* "Knobs" for adjusting internal parameters. */ @@ -717,7 +725,7 @@ /* Read the station address from the EEPROM. */ EL3WINDOW(0); for (i = 0; i < 0x18; i++) { - short *phys_addr = (short *)dev->dev_addr; + u16 *phys_addr = (u16 *)dev->dev_addr; int timer; outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd); /* Pause for at least 162 us. for the read to take place. */ @@ -1076,7 +1084,7 @@ outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ /* Allow status bits to be seen. */ - outw(SetStatusEnb | AdapterFailure|IntReq|StatsFull | + outw(SetStatusEnb | AdapterFailure|IntReq|StatsFull|TxComplete| (vp->full_bus_master_tx ? DownComplete : TxAvailable) | (vp->full_bus_master_rx ? UpComplete : RxComplete) | (vp->bus_master ? DMADone : 0), @@ -1085,7 +1093,7 @@ outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, ioaddr + EL3_CMD); outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull - | AdapterFailure + | AdapterFailure | TxComplete | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete, ioaddr + EL3_CMD); @@ -1389,7 +1397,8 @@ int entry = vp->cur_tx % TX_RING_SIZE; struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE]; - unsigned long flags, i; + unsigned long flags; + int i; if (vortex_debug > 3) printk("%s: Trying to send a packet, Tx index %d.\n", @@ -1492,10 +1501,15 @@ mark_bh(NET_BH); } if (status & TxComplete) { /* Really "TxError" for us. */ + unsigned char tx_status = inb(ioaddr + TxStatus); /* Presumably a tx-timeout. We must merely re-enable. */ - if (vortex_debug > 0) - printk("%s: Host error, Tx status register %2.2x.\n", - dev->name, inb(TxStatus)); + if (vortex_debug > 2 + || (tx_status != 0x88 && vortex_debug > 0)) + printk("%s: Transmit error, Tx status register %2.2x.\n", + dev->name, tx_status); + if (tx_status & 0x04) lp->stats.tx_fifo_errors++; + if (tx_status & 0x38) lp->stats.tx_aborted_errors++; + outb(0, ioaddr + TxStatus); outw(TxEnable, ioaddr + EL3_CMD); } if (status & DownComplete) { @@ -1559,7 +1573,8 @@ } EL3WINDOW(7); outw(SetIntrEnb | TxAvailable | RxComplete | AdapterFailure - | UpComplete | DownComplete, ioaddr + EL3_CMD); + | UpComplete | DownComplete | TxComplete, + ioaddr + EL3_CMD); DoneDidThat++; } } @@ -1590,7 +1605,7 @@ } if (--i < 0) { - printk("%s: Infinite loop in interrupt, status %4.4x. " + printk("%s: Too much work in interrupt, status %4.4x. " "Disabling functions (%4.4x).\n", dev->name, status, SetStatusEnb | ((~status) & 0x7FE)); /* Disable all pending interrupts. */ @@ -1925,7 +1940,7 @@ static void set_rx_mode(struct device *dev) { - short ioaddr = dev->base_addr; + int ioaddr = dev->base_addr; short new_mode; if (dev->flags & IFF_PROMISC) { 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/aic7xxx/aic7xxx.reg linux/drivers/scsi/aic7xxx/aic7xxx.reg --- v2.0.31/linux/drivers/scsi/aic7xxx/aic7xxx.reg Mon Sep 22 14:53:10 1997 +++ linux/drivers/scsi/aic7xxx/aic7xxx.reg Wed Nov 12 20:36:41 1997 @@ -1091,13 +1091,14 @@ * the QOUTFIFO. This is cleared by the * kernel driver every FIFODEPTH commands. * - * NOTE: these scratch RAM registers are *only* used on cards - * that enable SCB paging. The 2742 is unable to page. We - * won't use these on a 2742, and we can't init these registers - * in the kernel driver for 2742 cards because these locations are - * are used by the 2742 cards to control things like bus - * termination. Touching these memory locations is a no-no on all - * non-paging cards as far as we are concerned. + * NOTE: These scratch RAM registers are overlaying SCSICONF + * and SCSICONF2 and are only used on cards that are + * capable of SCB paging. Currently, only the PCI + * controllers can do this, which is good because the + * AIC-7770 based controllers use the SCSICONF register + * to control termination. In other words, do not + * destroy the contents of SCSICONF and SCSICONF2 for + * AIC-7770 based controllers. */ CMDOUTCNT { size 1 diff -u --recursive --new-file v2.0.31/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c --- v2.0.31/linux/drivers/scsi/aic7xxx.c Mon Sep 22 14:53:09 1997 +++ linux/drivers/scsi/aic7xxx.c Wed Nov 12 20:36:41 1997 @@ -147,6 +147,8 @@ #define ALL_TARGETS -1 #define ALL_CHANNELS '\0' #define ALL_LUNS -1 +#define MAX_TARGETS 16 +#define MAX_LUNS 8 #ifndef TRUE # define TRUE 1 #endif @@ -301,7 +303,7 @@ #ifdef AIC7XXX_TAGGED_QUEUEING_BY_DEVICE typedef struct { - char tag_commands[16]; /* Allow for wide/twin channel adapters. */ + unsigned char tag_commands[16]; /* Allow for wide/twin channel adapters. */ } adapter_tag_info_t; /* @@ -871,7 +873,7 @@ long r_total; /* total reads */ long r_total512; /* 512 byte blocks read */ long r_bins[10]; /* binned reads */ - } stats[16][8]; /* channel, target, lun */ + } stats[MAX_TARGETS][MAX_LUNS]; /* [(channel << 3)|target][lun] */ #endif /* AIC7XXX_PROC_STATS */ }; @@ -968,13 +970,8 @@ * These functions are not used yet, but when we do memory mapped * IO, we'll use them then. * - * For now we leave these commented out as the x86 inline assembly causes - * compiles to barf on DEC Alphas. Besides, they aren't even used yet, so - * they constitute wasted .text space right now. ***************************************************************************/ -/*************************************************************************** - static inline unsigned char aic_inb(struct aic7xxx_host *p, long port) { @@ -998,22 +995,30 @@ { if (p->maddr != NULL) { +#ifdef __alpha__ + int i; + + for (i=0; i < size; i++) + { + p->maddr[port] = valp[i]; + } +#else __asm __volatile(" cld; 1: lodsb; movb %%al,(%0); loop 1b" : : - "r" ((p)->maddr + (port)), - "S" ((valp)), "c" ((size)) : + "r" (p->maddr + port), + "S" (valp), "c" (size) : "%esi", "%ecx", "%eax"); +#endif } else { outsb(p->base + port, valp, size); } } - ***************************************************************************/ /*+F************************************************************************* * Function: @@ -1443,10 +1448,10 @@ unsigned char ultra_enb, sxfrctl0; /* - * If the offset is 0, then the device is requesting asynchronous + * If the period is 0, then the device is requesting asynchronous * transfers. */ - if ((*period >= aic7xxx_syncrates[i].period) && *offset != 0) + if (*period != 0) { for (i = 0; i < num_aic7xxx_syncrates; i++) { @@ -1977,15 +1982,38 @@ if ((scb->flags & (SCB_MSGOUT_WDTR | SCB_MSGOUT_SDTR)) != 0) { unsigned short mask; + int message_error = FALSE; mask = 0x01 << TARGET_INDEX(scb->cmd); + + /* + * Check to see if we get an invalid message or a message error + * after failing to negotiate a wide or sync transfer message. + */ + if ((scb->flags & SCB_SENSE) && + ((scb->cmd->sense_buffer[12] == 0x43) || /* INVALID_MESSAGE */ + (scb->cmd->sense_buffer[12] == 0x49))) /* MESSAGE_ERROR */ + { + message_error = TRUE; + } + if (scb->flags & SCB_MSGOUT_WDTR) { p->wdtr_pending &= ~mask; + if (message_error) + { + p->needwdtr &= ~mask; + p->needwdtr_copy &= ~mask; + } } if (scb->flags & SCB_MSGOUT_SDTR) { p->sdtr_pending &= ~mask; + if (message_error) + { + p->needsdtr &= ~mask; + p->needsdtr_copy &= ~mask; + } } } aic7xxx_free_scb(p, scb); @@ -2009,7 +2037,7 @@ long *ptr; int x; - sp = &p->stats[((cmd->channel << 3) | cmd->target) & 0xf][cmd->lun & 0x7]; + sp = &p->stats[TARGET_INDEX(cmd)][cmd->lun & 0x7]; sp->xfers++; if (cmd->request.cmd == WRITE) @@ -3097,6 +3125,8 @@ } else { + int send_reject = FALSE; + /* * Send our own WDTR in reply. */ @@ -3119,14 +3149,25 @@ { bus_width = BUS_8_BIT; scratch &= 0x7F; /* XXX - FreeBSD doesn't do this. */ + send_reject = TRUE; } break; default: break; } - aic7xxx_construct_wdtr(p, /* start byte */ 0, bus_width); - outb(SEND_MSG, p->base + RETURN_1); + if (send_reject) + { + outb(SEND_REJ, p->base + RETURN_1); + printk(KERN_WARNING "scsi%d: Target %d, channel %c, initiating " + "wide negotiation on a narrow bus - rejecting!\n", + p->host_no, target, channel); + } + else + { + aic7xxx_construct_wdtr(p, /* start byte */ 0, bus_width); + outb(SEND_MSG, p->base + RETURN_1); + } } p->needwdtr &= ~target_mask; outb(scratch, p->base + TARG_SCRATCH + scratch_offset); @@ -5314,6 +5355,12 @@ */ outb(p->qcntmask, p->base + QCNTMASK); + /* + * Set FIFO depth and command out count. These are only used when + * paging is enabled and should not be touched for AIC-7770 based + * adapters; FIFODEPTH and CMDOUTCNT overlay SCSICONF and SCSICONF+1 + * which are used to control termination. + */ if (p->flags & PAGE_ENABLED) { outb(p->qfullcount, p->base + FIFODEPTH); @@ -5549,7 +5596,6 @@ { case AIC_7770: /* None of these adapters have seeproms. */ case AIC_7771: - case AIC_7850: case AIC_7855: break; @@ -5557,6 +5603,7 @@ have_seeprom = read_284x_seeprom(p, (struct seeprom_config *) scarray); break; + case AIC_7850: /* The 2910B is a 7850 with a seeprom. */ case AIC_7861: case AIC_7870: case AIC_7871: @@ -5666,7 +5713,11 @@ scsi_conf = (p->scsi_id & 0x7); if (sc->adapter_control & CFSPARITY) scsi_conf |= ENSPCHK; - if (sc->adapter_control & CFRESETB) + /* + * The 7850 controllers with a seeprom, do not honor the CFRESETB + * flag in the seeprom. Assume that we want to reset the SCSI bus. + */ + if ((sc->adapter_control & CFRESETB) || (p->chip_class == AIC_7850)) scsi_conf |= RESET_SCSI; if ((p->chip_class == AIC_786x) || (p->chip_class == AIC_788x)) @@ -5799,6 +5850,14 @@ hcntrl = inb(base + HCNTRL) & IRQMS; /* Default */ outb(hcntrl | PAUSE, base + HCNTRL); + p = aic7xxx_alloc(template, base, 0, chip_type, 0, NULL); + if (p == NULL) + { + printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n"); + continue; + } + aic7xxx_chip_reset(p); + irq = inb(INTDEF + base) & 0x0F; switch (irq) { @@ -5812,19 +5871,14 @@ default: printk(KERN_WARNING "aic7xxx: Host adapter uses unsupported IRQ " - "level, ignoring.\n"); + "level %d, ignoring.\n", irq); irq = 0; + aic7xxx_free(p); break; } if (irq != 0) { - p = aic7xxx_alloc(template, base, 0, chip_type, 0, NULL); - if (p == NULL) - { - printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n"); - continue; - } p->irq = irq & 0x0F; p->chip_class = AIC_777x; #ifdef AIC7XXX_PAGE_ENABLE @@ -5835,7 +5889,6 @@ { p->flags |= EXTENDED_TRANSLATION; } - aic7xxx_chip_reset(p); switch (p->chip_type) { @@ -5997,7 +6050,6 @@ flags = 0; switch (aic7xxx_pci_devices[i].chip_type) { - case AIC_7850: case AIC_7855: flags |= USE_DEFAULTS; break; @@ -6790,17 +6842,43 @@ int aic7xxx_abort(Scsi_Cmnd *cmd) { +#if 0 struct aic7xxx_scb *scb = NULL; +#endif struct aic7xxx_host *p; +#if 0 int base, result; unsigned long processor_flags; +#endif p = (struct aic7xxx_host *) cmd->host->hostdata; +#if 0 scb = (p->scb_data->scb_array[aic7xxx_position(cmd)]); base = p->base; save_flags(processor_flags); cli(); +#endif + +#if 1 + switch (aic7xxx_reset(cmd, 0) & 0x0f) + { + case SCSI_RESET_SNOOZE: + return(SCSI_ABORT_SNOOZE); + case SCSI_RESET_PENDING: + return(SCSI_ABORT_PENDING); + case SCSI_RESET_SUCCESS: + return(SCSI_ABORT_SUCCESS); + case SCSI_RESET_NOT_RUNNING: + return(SCSI_ABORT_NOT_RUNNING); + case SCSI_RESET_ERROR: + return(SCSI_ABORT_ERROR); + default: + printk(KERN_WARNING "scsi%d Unknown abort/reset return state.\n", + p->host_no); + return(SCSI_ABORT_ERROR); + } /* NOT REACHED */ +#else #ifdef AIC7XXX_DEBUG_ABORT if (scb != NULL) @@ -6872,6 +6950,7 @@ } restore_flags(processor_flags); return (result); +#endif } @@ -6899,7 +6978,7 @@ scb = (p->scb_data->scb_array[aic7xxx_position(cmd)]); base = p->base; channel = cmd->channel ? 'B': 'A'; - tindex = (cmd->channel << 3) | cmd->target; + tindex = TARGET_INDEX(cmd); #ifdef 0 /* AIC7XXX_DEBUG_ABORT */ if (scb != NULL) diff -u --recursive --new-file v2.0.31/linux/drivers/scsi/aic7xxx.h linux/drivers/scsi/aic7xxx.h --- v2.0.31/linux/drivers/scsi/aic7xxx.h Thu Jul 31 12:37:17 1997 +++ linux/drivers/scsi/aic7xxx.h Wed Nov 12 20:36:41 1997 @@ -40,7 +40,7 @@ aic7xxx_info, \ NULL, \ aic7xxx_queue, \ - NULL, \ + aic7xxx_abort, \ aic7xxx_reset, \ NULL, \ aic7xxx_biosparam, \ @@ -57,6 +57,7 @@ extern int aic7xxx_biosparam(Disk *, kdev_t, int[]); extern int aic7xxx_detect(Scsi_Host_Template *); extern int aic7xxx_command(Scsi_Cmnd *); +extern int aic7xxx_abort(Scsi_Cmnd *); extern int aic7xxx_reset(Scsi_Cmnd *, unsigned int); extern const char *aic7xxx_info(struct Scsi_Host *); diff -u --recursive --new-file v2.0.31/linux/drivers/scsi/aic7xxx_proc.c linux/drivers/scsi/aic7xxx_proc.c --- v2.0.31/linux/drivers/scsi/aic7xxx_proc.c Mon Sep 22 14:53:09 1997 +++ linux/drivers/scsi/aic7xxx_proc.c Wed Nov 12 20:36:41 1997 @@ -51,6 +51,13 @@ # define proc_debug(fmt, args...) #endif /* PROC_DEBUG */ +static int aic7xxx_buffer_size = 0; +static char *aic7xxx_buffer = NULL; +static const char *bus_names[] = { "Single", "Twin", "Wide" }; +static const char *chip_names[] = { "AIC-777x", "AIC-785x", "AIC-786x", + "AIC-787x", "AIC-788x" }; + + /*+F************************************************************************* * Function: * aic7xxx_set_info @@ -64,7 +71,8 @@ proc_debug("aic7xxx_set_info(): %s\n", buffer); return (-ENOSYS); /* Currently this is a no-op */ } - + + /*+F************************************************************************* * Function: * aic7xxx_proc_info @@ -78,14 +86,9 @@ { struct Scsi_Host *HBAptr; struct aic7xxx_host *p; - static int aic7xxx_buffer_size = 0; int found = FALSE; - static int size = 0; + int size = 0; unsigned char i; - static char *aic7xxx_buffer = NULL; - static char *bus_names[] = { "Single", "Twin", "Wide" }; - static char *chip_names[] = { "AIC-777x", "AIC-785x", "AIC-786x", - "AIC-787x", "AIC-788x" }; #ifdef AIC7XXX_PROC_STATS struct aic7xxx_xferstats *sp; unsigned char target, lun; @@ -100,7 +103,7 @@ { break; } - + while ((HBAptr->hostdata != NULL) && !found && ((HBAptr = ((struct aic7xxx_host *) HBAptr->hostdata)->next) != NULL)) { @@ -109,7 +112,7 @@ found = TRUE; } } - + if (!found) { HBAptr = NULL; @@ -120,49 +123,59 @@ } } } - + if (HBAptr == NULL) { - size += sprintf( buffer, "Can't find adapter for host number %d\n", hostno); - if ( size > length) return size; - return length; + size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno); + if (size > length) + { + return (size); + } + else + { + return (length); + } } - + if (inout == TRUE) /* Has data been written to the file? */ { return (aic7xxx_set_info(buffer, length, HBAptr)); } - + p = (struct aic7xxx_host *) HBAptr->hostdata; - /* It takes roughly 1K of space to hold all relevant card info, not */ - /* counting any proc stats, so we start out with a 1.5k buffer size and */ - /* if proc_stats is defined, then we sweep the stats structure to see */ - /* how many drives we will be printing out for and add 384 bytes per */ - /* device with active stats. */ + /* + * It takes roughly 1K of space to hold all relevant card info, not + * counting any proc stats, so we start out with a 1.5k buffer size and + * if proc_stats is defined, then we sweep the stats structure to see + * how many drives we will be printing out for and add 384 bytes per + * device with active stats. + */ size = 1536; #ifdef AIC7XXX_PROC_STATS - for (target=0; target<16; target++) + for (target = 0; target < MAX_TARGETS; target++) { - for (lun=0; lun<8; lun++) + for (lun = 0; lun < MAX_LUNS; lun++) { if (p->stats[target][lun].xfers != 0) size += 384; } } #endif - if ( aic7xxx_buffer_size != size) { - if ( aic7xxx_buffer != NULL) + if (aic7xxx_buffer_size != size) + { + if (aic7xxx_buffer != NULL) { - kfree ( aic7xxx_buffer); + kfree(aic7xxx_buffer); aic7xxx_buffer_size = 0; } - aic7xxx_buffer = kmalloc ( size, GFP_KERNEL); + aic7xxx_buffer = kmalloc(size, GFP_KERNEL); } - if ( aic7xxx_buffer == NULL) { - size = sprintf ( buffer, "AIC7xxx - kmalloc error at line %d\n", - __LINE__); + if (aic7xxx_buffer == NULL) + { + size = sprintf(buffer, "AIC7xxx - kmalloc error at line %d\n", + __LINE__); return size; } aic7xxx_buffer_size = size; @@ -177,12 +190,10 @@ size += sprintf(BLS, "\n"); size += sprintf(BLS, "Compile Options:\n"); #ifdef AIC7XXX_RESET_DELAY - size += sprintf(BLS, " AIC7XXX_RESET_DELAY : %d\n", - AIC7XXX_RESET_DELAY); + size += sprintf(BLS, " AIC7XXX_RESET_DELAY : %d\n", AIC7XXX_RESET_DELAY); #endif #ifdef AIC7XXX_CMDS_PER_LUN - size += sprintf(BLS, " AIC7XXX_CMDS_PER_LUN : %d\n", - AIC7XXX_CMDS_PER_LUN); + size += sprintf(BLS, " AIC7XXX_CMDS_PER_LUN : %d\n", AIC7XXX_CMDS_PER_LUN); #endif #ifdef AIC7XXX_TAGGED_QUEUEING size += sprintf(BLS, " AIC7XXX_TAGGED_QUEUEING: Enabled\n"); @@ -201,18 +212,17 @@ #endif size += sprintf(BLS, "\n"); size += sprintf(BLS, "Adapter Configuration:\n"); - size += sprintf(BLS, " SCSI Adapter: %s\n", - board_names[p->chip_type]); - size += sprintf(BLS, " (%s chipset)\n", - chip_names[p->chip_class]); - size += sprintf(BLS, " Host Bus: %s\n", - bus_names[p->bus_type]); - size += sprintf(BLS, " Base IO: %#.4x\n", p->base); - size += sprintf(BLS, " Base IO Memory: 0x%x\n", p->mbase); - size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq); - size += sprintf(BLS, " SCBs: Used %d, HW %d, Page %d\n", - p->scb_data->numscbs, p->scb_data->maxhscbs, p->scb_data->maxscbs); - size += sprintf(BLS, " Interrupts: %d", p->isr_count); + size += sprintf(BLS, " SCSI Adapter: %s\n", + board_names[p->chip_type]); + size += sprintf(BLS, " (%s chipset)\n", + chip_names[p->chip_class]); + size += sprintf(BLS, " Host Bus: %s\n", bus_names[p->bus_type]); + size += sprintf(BLS, " Base IO: %#.4x\n", p->base); + size += sprintf(BLS, " Base IO Memory: 0x%x\n", p->mbase); + size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq); + size += sprintf(BLS, " SCBs: Used %d, HW %d, Page %d\n", + p->scb_data->numscbs, p->scb_data->maxhscbs, p->scb_data->maxscbs); + size += sprintf(BLS, " Interrupts: %d", p->isr_count); if (p->chip_class == AIC_777x) { size += sprintf(BLS, " %s\n", @@ -222,23 +232,22 @@ { size += sprintf(BLS, "\n"); } - size += sprintf(BLS, " Serial EEPROM: %s\n", + size += sprintf(BLS, " Serial EEPROM: %s\n", (p->flags & HAVE_SEEPROM) ? "True" : "False"); - size += sprintf(BLS, " Extended Translation: %sabled\n", + size += sprintf(BLS, " Extended Translation: %sabled\n", (p->flags & EXTENDED_TRANSLATION) ? "En" : "Dis"); - size += sprintf(BLS, " SCSI Bus Reset: %sabled\n", + size += sprintf(BLS, " SCSI Bus Reset: %sabled\n", aic7xxx_no_reset ? "Dis" : "En"); - size += sprintf(BLS, " Ultra SCSI: %sabled\n", + size += sprintf(BLS, " Ultra SCSI: %sabled\n", (p->flags & ULTRA_ENABLED) ? "En" : "Dis"); - size += sprintf(BLS, " Target Disconnect: %sabled\n", - p->discenable ? "En" : "Dis"); + size += sprintf(BLS, "Disconnect Enable Flags: 0x%x\n", p->discenable); #ifdef AIC7XXX_PROC_STATS size += sprintf(BLS, "\n"); size += sprintf(BLS, "Statistics:\n"); - for (target = 0; target < 16; target++) + for (target = 0; target < MAX_TARGETS; target++) { - for (lun = 0; lun < 8; lun++) + for (lun = 0; lun < MAX_LUNS; lun++) { sp = &p->stats[target][lun]; if (sp->xfers == 0) @@ -246,42 +255,58 @@ continue; } if (p->bus_type == AIC_TWIN) + { size += sprintf(BLS, "CHAN#%c (TGT %d LUN %d):\n", 'A' + (target >> 3), (target & 0x7), lun); + } else + { size += sprintf(BLS, "CHAN#%c (TGT %d LUN %d):\n", 'A', target, lun); + } size += sprintf(BLS, "nxfers %ld (%ld read;%ld written)\n", - sp->xfers, sp->r_total, sp->w_total); + sp->xfers, sp->r_total, sp->w_total); size += sprintf(BLS, "blks(512) rd=%ld; blks(512) wr=%ld\n", - sp->r_total512, sp->w_total512); + sp->r_total512, sp->w_total512); size += sprintf(BLS, "%s\n", HDRB); size += sprintf(BLS, " Reads:"); - for (i=0; i<10; i++) - size += sprintf(BLS, "%6ld ", sp->r_bins[i]); + for (i = 0; i < NUMBER(sp->r_bins); i++) + { + size += sprintf(BLS, "%6ld ", sp->r_bins[i]); + } size += sprintf(BLS, "\n"); size += sprintf(BLS, "Writes:"); - for (i=0; i<10; i++) - size += sprintf(BLS, "%6ld ", sp->w_bins[i]); + for (i = 0; i < NUMBER(sp->w_bins); i++) + { + size += sprintf(BLS, "%6ld ", sp->w_bins[i]); + } size += sprintf(BLS, "\n\n"); } } #endif /* AIC7XXX_PROC_STATS */ - if ( size >= aic7xxx_buffer_size ) + if (size >= aic7xxx_buffer_size) + { printk(KERN_WARNING "aic7xxx: Overflow in aic7xxx_proc.c\n"); + } - if ( offset > size - 1) { - kfree ( aic7xxx_buffer); - aic7xxx_buffer = NULL; - aic7xxx_buffer_size = length = 0; - *start = NULL; - } else { - *start = &aic7xxx_buffer[offset]; /* Start of wanted data */ - if ( size - offset < length) length = size - offset; + if (offset > size - 1) + { + kfree(aic7xxx_buffer); + aic7xxx_buffer = NULL; + aic7xxx_buffer_size = length = 0; + *start = NULL; } - - return length; + else + { + *start = &aic7xxx_buffer[offset]; /* Start of wanted data */ + if (size - offset < length) + { + length = size - offset; + } + } + + return (length); } /* diff -u --recursive --new-file v2.0.31/linux/drivers/scsi/aic7xxx_reg.h linux/drivers/scsi/aic7xxx_reg.h --- v2.0.31/linux/drivers/scsi/aic7xxx_reg.h Mon Sep 22 14:53:09 1997 +++ linux/drivers/scsi/aic7xxx_reg.h Wed Nov 12 20:36:41 1997 @@ -30,6 +30,13 @@ #define ACTNEGEN 0x02 #define STPWEN 0x01 +#define SCSISIGI 0x03 +#define ATNI 0x10 +#define SELI 0x08 +#define BSYI 0x04 +#define REQI 0x02 +#define ACKI 0x01 + #define SCSISIGO 0x03 #define CDO 0x80 #define IOO 0x40 @@ -40,13 +47,6 @@ #define REQO 0x02 #define ACKO 0x01 -#define SCSISIGI 0x03 -#define ATNI 0x10 -#define SELI 0x08 -#define BSYI 0x04 -#define REQI 0x02 -#define ACKI 0x01 - #define SCSIRATE 0x04 #define WIDEXFER 0x80 #define SXFR 0x70 @@ -262,16 +262,16 @@ #define CMDOUTCNT 0x5a -#define FIFODEPTH 0x5b - #define SCSICONF2 0x5b #define RESET_SCSI 0x40 +#define FIFODEPTH 0x5b + #define HOSTCONF 0x5d #define HA_274_BIOSCTRL 0x5f -#define BIOSMODE 0x30 #define BIOSDISABLED 0x30 +#define BIOSMODE 0x30 #define CHANNEL_B_PRIMARY 0x08 #define SEQCTL 0x60 @@ -315,16 +315,16 @@ #define STACK 0x6f -#define BCTL 0x84 -#define ACE 0x08 -#define ENABLE 0x01 - #define DSCOMMAND 0x84 #define CACHETHEN 0x80 #define DPARCKEN 0x40 #define MPARCKEN 0x20 #define EXTREQLCK 0x10 +#define BCTL 0x84 +#define ACE 0x08 +#define ENABLE 0x01 + #define BUSTIME 0x85 #define BOFF 0xf0 #define BON 0x0f @@ -374,18 +374,18 @@ #define BAD_PHASE 0x01 #define SEQINT 0x01 -#define CLRINT 0x92 -#define CLRBRKADRINT 0x08 -#define CLRSCSIINT 0x04 -#define CLRCMDINT 0x02 -#define CLRSEQINT 0x01 - #define ERROR 0x92 #define PARERR 0x08 #define ILLOPCODE 0x04 #define ILLSADDR 0x02 #define ILLHADDR 0x01 +#define CLRINT 0x92 +#define CLRBRKADRINT 0x08 +#define CLRSCSIINT 0x04 +#define CLRCMDINT 0x02 +#define CLRSEQINT 0x01 + #define DFCNTRL 0x93 #define DFSTATUS 0x94 @@ -410,6 +410,8 @@ #define QOUTCNT 0x9e +#define SCB_BASE 0xa0 + #define SCB_CONTROL 0xa0 #define MK_MESSAGE 0x80 #define DISCENB 0x40 @@ -419,8 +421,6 @@ #define DISCONNECTED 0x04 #define SCB_TAG_TYPE 0x03 -#define SCB_BASE 0xa0 - #define SCB_TCL 0xa1 #define TID 0xf0 #define SELBUSB 0x08 @@ -466,10 +466,10 @@ #define DI_2840 0x01 -#define BUS_8_BIT 0x00 -#define MAX_OFFSET_8BIT 0x0f -#define BUS_16_BIT 0x01 #define MAX_OFFSET_16BIT 0x08 +#define BUS_8_BIT 0x00 #define SCB_LIST_NULL 0xff #define SG_SIZEOF 0x08 +#define MAX_OFFSET_8BIT 0x0f #define BUS_32_BIT 0x02 +#define BUS_16_BIT 0x01 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/inode.c linux/fs/inode.c --- v2.0.31/linux/fs/inode.c Wed Oct 15 10:28:42 1997 +++ linux/fs/inode.c Wed Nov 12 20:36:41 1997 @@ -173,7 +173,25 @@ { struct wait_queue * wait; + /* + * We can clear inodes either when a last deref to the inode + * causes it to be deleted (reference count==1), or when we want to + * reuse it (reference count==0). Any other count is an error. + */ + if (inode->i_count > 1) + panic ("clear_inode: Inode still has references"); + + /* + * We are about to zap this inode. This operation may block, + * and it's imperative that we don't allow another process to + * grab it before it is completely pulled down. The i_count + * will prevent reuse of the inode by get_empty_inode(), but the + * i_condemned flag will also prevent __iget() from finding the + * inode until it is completely dead. + */ + inode->i_condemned = 1; inode->i_count++; + truncate_inode_pages(inode, 0); wait_on_inode(inode); if (IS_WRITABLE(inode)) { @@ -188,6 +206,11 @@ memset(inode,0,sizeof(*inode)); ((volatile struct inode *) inode)->i_wait = wait; insert_inode_free(inode); + /* + * The inode is now reusable again, and the condemned flag is + * clear. Wake up anybody who is waiting on the condemned flag. + */ + wake_up(&inode->i_wait); } int fs_may_mount(kdev_t dev) @@ -428,6 +451,7 @@ } if (inode->i_pipe) wake_up_interruptible(&PIPE_WAIT(*inode)); + repeat: if (inode->i_count>1) { inode->i_count--; @@ -501,7 +525,7 @@ for (i = nr_inodes/2; i > 0; i--,inode = inode->i_next) { if (!inode->i_count) { unsigned long i = 999; - if (!(inode->i_lock | inode->i_dirt)) + if (!(inode->i_lock || inode->i_dirt)) i = inode->i_nrpages; if (i < badness) { best = inode; @@ -615,6 +639,15 @@ goto return_it; found_it: + /* + * The inode may currently be being pulled down by + * clear_inode(). Avoid it if so. If we get past this, then + * the increment of i_count will prevent the inode's reuse. + */ + if (inode->i_condemned) { + sleep_on(&inode->i_wait); + goto repeat; + } if (!inode->i_count) nr_free_inodes--; inode->i_count++; 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 Wed Nov 12 20:36:41 1997 @@ -106,8 +106,9 @@ 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/bugs.h linux/include/asm-i386/bugs.h --- v2.0.31/linux/include/asm-i386/bugs.h Wed Oct 15 15:22:04 1997 +++ linux/include/asm-i386/bugs.h Thu Nov 13 16:12:29 1997 @@ -125,10 +125,32 @@ #endif } +/* + * All current models of Pentium and Pentium with MMX technology CPUs + * have the F0 0F bug, which lets nonpriviledged users lock up the system: + */ +extern int pentium_f00f_bug; +extern void trap_init_f00f_bug(void); + +static void check_pentium_f00f(void) +{ + /* + * Pentium and Pentium MMX + */ + pentium_f00f_bug = 0; + if (x86==5 && !memcmp(x86_vendor_id, "GenuineIntel", 12)) { + printk(KERN_INFO "Intel Pentium with F0 0F bug - workaround enabled.\n"); + pentium_f00f_bug = 1; + trap_init_f00f_bug(); + } +} + + static void check_bugs(void) { check_tlb(); check_fpu(); check_hlt(); + check_pentium_f00f(); system_utsname.machine[1] = '0' + x86; } 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/fs.h linux/include/linux/fs.h --- v2.0.31/linux/include/linux/fs.h Wed Oct 15 15:22:04 1997 +++ linux/include/linux/fs.h Thu Nov 13 16:12:29 1997 @@ -312,6 +312,7 @@ unsigned char i_sock; unsigned char i_seek; unsigned char i_update; + unsigned char i_condemned; unsigned short i_writecount; union { struct pipe_inode_info pipe_i; diff -u --recursive --new-file v2.0.31/linux/include/linux/head.h linux/include/linux/head.h --- v2.0.31/linux/include/linux/head.h Sun Jan 22 04:38:45 1995 +++ linux/include/linux/head.h Thu Nov 13 15:53:58 1997 @@ -5,7 +5,8 @@ unsigned long a,b; } desc_table[256]; -extern desc_table idt,gdt; +extern desc_table __idt,gdt; +extern struct desc_struct *idt; #define GDT_NUL 0 #define GDT_CODE 1 diff -u --recursive --new-file v2.0.31/linux/include/linux/head.h.lock~ linux/include/linux/head.h.lock~ --- v2.0.31/linux/include/linux/head.h.lock~ Wed Dec 31 16:00:00 1969 +++ linux/include/linux/head.h.lock~ Thu Nov 13 15:54:42 1997 @@ -0,0 +1 @@ +torvalds@penguin.transmeta.com \ No newline at end of file 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 Thu Nov 13 16:12:29 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 Wed Nov 12 20:36:41 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; + exit_mmap(mm); goto free_mm; + } if (dup_mmap(mm)) { + tsk->mm = NULL; + exit_mmap(mm); 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_fragment.c linux/net/ipv4/ip_fragment.c --- v2.0.31/linux/net/ipv4/ip_fragment.c Tue Aug 12 11:30:25 1997 +++ linux/net/ipv4/ip_fragment.c Thu Nov 13 05:58:30 1997 @@ -375,7 +375,7 @@ fp = qp->fragments; while(fp != NULL) { - if(count+fp->len > skb->len) + if (fp->len < 0 || count+fp->len > skb->len) { NETDEBUG(printk("Invalid fragment list: Fragment over size.\n")); ip_free(qp); 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/rarp.c linux/net/ipv4/rarp.c --- v2.0.31/linux/net/ipv4/rarp.c Tue Aug 12 11:30:35 1997 +++ linux/net/ipv4/rarp.c Wed Nov 12 20:36:41 1997 @@ -175,6 +175,8 @@ NULL, 0 }; + +static int rarp_pkt_inited=0; static void rarp_init_pkt (void) { @@ -182,8 +184,19 @@ rarp_packet_type.type=htons(ETH_P_RARP); dev_add_pack(&rarp_packet_type); register_netdevice_notifier(&rarp_dev_notifier); + rarp_pkt_inited=1; +} + +static void rarp_end_pkt(void) +{ + if(!rarp_pkt_inited) + return; + dev_remove_pack(&rarp_packet_type); + unregister_netdevice_notifier(&rarp_dev_notifier); + rarp_pkt_inited=0; } + /* * Receive an arp request by the device layer. Maybe it should be * rewritten to use the incoming packet for the reply. The current @@ -574,12 +587,14 @@ void rarp_init(void) { +#ifdef CONFIG_PROC_FS proc_net_register(&(struct proc_dir_entry) { PROC_NET_RARP, 4, "rarp", S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_net_inode_operations, rarp_get_info }); +#endif rarp_ioctl_hook = rarp_ioctl; } @@ -594,7 +609,9 @@ void cleanup_module(void) { struct rarp_table *rt, *rt_next; +#ifdef CONFIG_PROC_FS proc_net_unregister(PROC_NET_RARP); +#endif rarp_ioctl_hook = NULL; cli(); /* Destroy the RARP-table */ @@ -606,5 +623,6 @@ rt_next = rt->next; rarp_release_entry(rt); } + rarp_end_pkt(); } #endif 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) {